123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- use anyhow::{Context, Result};
- use clap::{Parser, Subcommand};
- use rand::prelude::IndexedRandom;
- use reqwest;
- use std::{
- string::String,
- };
- use std::fs::File;
- use std::io::Write;
- mod config;
- mod fetch;
- mod parse;
- // Setup the command line options
- #[derive(Parser)]
- #[command(about = "Retrieve the latest UserAgent strings", long_about=None, arg_required_else_help = true, after_help = "This is very specific to the website's HTML.\nIf it changes, this program might no longer work.")]
- struct Cli {
- // Update UserAgent versions
- // #[arg(short, long, action=clap::ArgAction::SetTrue)]
- // update: bool,
- #[command(subcommand)]
- command: Option<Commands>,
- }
- #[derive(Subcommand)]
- enum Commands {
- /// Display the latest UserAgents
- Display {},
- /// Fetch the latest UserAgents
- Fetch {},
- }
- /// Configuration filename
- const CONFIG_FILE: &str = "latest.config";
- const FIREFOX_URL: &str = "https://www.whatismybrowser.com/guides/the-latest-user-agent/firefox";
- const GCHROME_URL: &str = "https://www.whatismybrowser.com/guides/the-latest-user-agent/chrome";
- fn random_user_agent(config: &config::Config) -> String {
- // Pick a random user_agent, or default to something "sane"...
- if config.user_agents.len() == 0 {
- // No sensible defaults.
- return String::from(
- "Mozilla/5.0 (X11; Linux x86_64; rv:135.0) Gecko/20100101 Firefox/135.0",
- );
- }
- // Ok, do this!
- config.user_agents.choose(&mut rand::rng()).unwrap().clone()
- }
- fn save_html(filename: &str, html: &str) -> Result<()> {
- let mut file = File::create(filename)
- .with_context(|| format!("Failed to write file [{:?}].", filename))?;
- file.write_all(html.as_bytes())
- .with_context(|| format!("Failed to write all to [{:?}].", filename))?;
- Ok(())
- }
- fn main() -> Result<()> {
- let mut config = config::read_config(CONFIG_FILE)?;
- let cli = Cli::parse();
- match &cli.command {
- Some(Commands::Fetch {}) => {
- let ua = random_user_agent(&config);
- let client = reqwest::blocking::Client::builder()
- .user_agent(&ua)
- .build()?;
- let result = fetch::fetch(&client, FIREFOX_URL)?;
- let filename = fetch::filename_from_url(FIREFOX_URL)?;
- save_html(&filename, &result)?;
- let mut agents = parse::find_useragents(&result)?;
- config.user_agents.clear();
- config.user_agents.append(&mut agents);
- let result = fetch::fetch(&client, GCHROME_URL)?;
- let filename = fetch::filename_from_url(GCHROME_URL)?;
- save_html(&filename, &result)?;
- agents = parse::find_useragents(&result)?;
- config.user_agents.append(&mut agents);
- config::write_config(CONFIG_FILE, &config)?;
- println!("Ok! {} agents found.", config.user_agents.len());
- }
- Some(Commands::Display {}) => {
- println!("Display...");
- for ua in config.user_agents {
- println!(" {}", ua);
- }
- return Ok(());
- }
- None => {
- println!("I didn't see a command. Displaying help.\n");
- let _show_help: Cli = Cli::parse_from(["--help"]);
- }
- }
- Ok(())
- }
|