Compare commits
5 Commits
f52d89ad24
...
72e916c764
Author | SHA1 | Date |
---|---|---|
Bauke | 72e916c764 | |
Bauke | 8fa4607456 | |
Bauke | 0b5e5def96 | |
Bauke | 8605c20dfc | |
Bauke | a4e31998e0 |
|
@ -17,6 +17,15 @@ version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "0.7.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atty"
|
name = "atty"
|
||||||
version = "0.2.14"
|
version = "0.2.14"
|
||||||
|
@ -446,6 +455,23 @@ dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.6.27"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ring"
|
name = "ring"
|
||||||
version = "0.16.20"
|
version = "0.16.20"
|
||||||
|
@ -532,6 +558,7 @@ dependencies = [
|
||||||
"color-eyre",
|
"color-eyre",
|
||||||
"indicatif",
|
"indicatif",
|
||||||
"opml",
|
"opml",
|
||||||
|
"regex",
|
||||||
"ureq",
|
"ureq",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ path = "source/main.rs"
|
||||||
color-eyre = "0.6.2"
|
color-eyre = "0.6.2"
|
||||||
indicatif = "0.17.1"
|
indicatif = "0.17.1"
|
||||||
opml = "1.1.4"
|
opml = "1.1.4"
|
||||||
|
regex = "1.6.0"
|
||||||
ureq = "2.5.0"
|
ureq = "2.5.0"
|
||||||
|
|
||||||
[dependencies.clap]
|
[dependencies.clap]
|
||||||
|
|
|
@ -13,6 +13,7 @@ use {
|
||||||
clap::Parser,
|
clap::Parser,
|
||||||
color_eyre::{install, Result},
|
color_eyre::{install, Result},
|
||||||
indicatif::{ProgressBar, ProgressStyle},
|
indicatif::{ProgressBar, ProgressStyle},
|
||||||
|
regex::Regex,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// CLI arguments struct using [`clap`]'s Derive API.
|
/// CLI arguments struct using [`clap`]'s Derive API.
|
||||||
|
@ -34,11 +35,18 @@ pub struct Args {
|
||||||
/// Verify potential feeds by downloading them and checking if they return XML.
|
/// Verify potential feeds by downloading them and checking if they return XML.
|
||||||
#[clap(short, long)]
|
#[clap(short, long)]
|
||||||
pub verify: bool,
|
pub verify: bool,
|
||||||
|
|
||||||
|
/// A game's store URL, can be used multiple times.
|
||||||
|
#[clap(long)]
|
||||||
|
pub url: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A simple feed struct.
|
/// A simple feed struct.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Feed {
|
pub struct Feed {
|
||||||
|
/// The CLI option that was used for this feed.
|
||||||
|
pub option: FeedOption,
|
||||||
|
|
||||||
/// The text to use for the feed in the OPML output.
|
/// The text to use for the feed in the OPML output.
|
||||||
pub text: Option<String>,
|
pub text: Option<String>,
|
||||||
|
|
||||||
|
@ -46,6 +54,16 @@ pub struct Feed {
|
||||||
pub url: String,
|
pub url: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An enum for [`Feed`]s for which option was used in the CLI.
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum FeedOption {
|
||||||
|
/// `-a, --appid <APPID>` was used.
|
||||||
|
AppID,
|
||||||
|
|
||||||
|
/// `--url <URL>` was used.
|
||||||
|
Url,
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
install()?;
|
install()?;
|
||||||
|
|
||||||
|
@ -58,29 +76,56 @@ fn main() -> Result<()> {
|
||||||
let mut potential_feeds = vec![];
|
let mut potential_feeds = vec![];
|
||||||
let mut feeds_to_output = vec![];
|
let mut feeds_to_output = vec![];
|
||||||
|
|
||||||
|
let store_url_regex =
|
||||||
|
Regex::new(r"(?i)^https?://store.steampowered.com/app/(?P<appid>\d+)")?;
|
||||||
|
|
||||||
for appid in args.appid {
|
for appid in args.appid {
|
||||||
potential_feeds.push(Feed {
|
potential_feeds.push(Feed {
|
||||||
|
option: FeedOption::AppID,
|
||||||
text: Some(format!("Steam AppID {appid}")),
|
text: Some(format!("Steam AppID {appid}")),
|
||||||
url: format!("https://steamcommunity.com/games/{appid}/rss/"),
|
url: appid_to_rss_url(appid),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for url in args.url {
|
||||||
|
let appid = store_url_regex
|
||||||
|
.captures(&url)
|
||||||
|
.and_then(|captures| captures.name("appid"))
|
||||||
|
.and_then(|appid_match| appid_match.as_str().parse::<usize>().ok());
|
||||||
|
if let Some(appid) = appid {
|
||||||
|
potential_feeds.push(Feed {
|
||||||
|
option: FeedOption::Url,
|
||||||
|
text: Some(format!("Steam AppID {appid}")),
|
||||||
|
url: appid_to_rss_url(appid),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if args.verify {
|
if args.verify {
|
||||||
let progress = ProgressBar::new(potential_feeds.len().try_into()?)
|
let progress = ProgressBar::new(potential_feeds.len().try_into()?)
|
||||||
.with_style(ProgressStyle::with_template("Verifying {pos}/{len} {bar}")?);
|
.with_style(ProgressStyle::with_template("Verifying {pos}/{len} {bar}")?);
|
||||||
|
|
||||||
for potential_feed in potential_feeds {
|
for potential_feed in potential_feeds {
|
||||||
|
let potential_feed = if [FeedOption::AppID, FeedOption::Url]
|
||||||
|
.contains(&potential_feed.option)
|
||||||
|
{
|
||||||
let response = ureq_agent.get(&potential_feed.url).call()?;
|
let response = ureq_agent.get(&potential_feed.url).call()?;
|
||||||
if response.content_type() == "text/xml" {
|
if response.content_type() == "text/xml" {
|
||||||
let body = response.into_string()?;
|
let body = response.into_string()?;
|
||||||
let title_start = body.find("<title>").unwrap() + 7;
|
let title_start = body.find("<title>").unwrap() + 7;
|
||||||
let title_end = body.find("</title>").unwrap();
|
let title_end = body.find("</title>").unwrap();
|
||||||
feeds_to_output.push(Feed {
|
Feed {
|
||||||
text: Some(body[title_start..title_end].to_string()),
|
text: Some(body[title_start..title_end].to_string()),
|
||||||
url: potential_feed.url,
|
..potential_feed
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
feeds_to_output.push(potential_feed);
|
||||||
sleep(timeout);
|
sleep(timeout);
|
||||||
progress.inc(1);
|
progress.inc(1);
|
||||||
}
|
}
|
||||||
|
@ -106,3 +151,8 @@ fn main() -> Result<()> {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a Steam RSS URL from a given AppID.
|
||||||
|
fn appid_to_rss_url<D: std::fmt::Display>(appid: D) -> String {
|
||||||
|
format!("https://steamcommunity.com/games/{appid}/rss/")
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue