extern crate serde; extern crate ureq; use serde::{Deserialize, Serialize}; use std::fs; use std::path::Path; use ureq::get; #[derive(Deserialize, Serialize, Debug, Default)] pub struct ApiResult { /// user agent string id agent: String, } /// bump the minor fn increment_version(version: &str) -> String { let mut parts: Vec = version.split('.').map(String::from).collect(); // Collect into Vec to handle owned strings if let Some(last) = parts.last_mut() { if let Ok(num) = last.parse::() { *last = (num + 1).to_string(); // Create a new owned String and assign that } } parts.join(".") } fn bump_version_in_cargo_toml() -> Result<(), Box> { use serde_json::Value; use std::io::Read; let cargo_toml_path = Path::new("Cargo.toml"); let mut cargo_toml_content = String::new(); crate::fs::OpenOptions::new() .read(true) .open(&cargo_toml_path)? .read_to_string(&mut cargo_toml_content)?; if !cargo_toml_content.is_empty() { let mut parsed_toml: Value = cargo_toml_content.parse()?; if let Some(version) = parsed_toml .get_mut("package") .and_then(|pkg| pkg.get_mut("version")) { if let Some(version_str) = version.as_str() { let new_version = increment_version(version_str); *version = Value::String(new_version.clone()); println!("Bumped version to: {}", new_version); } } let new_cargo_toml_content = toml::to_string(&parsed_toml)?; fs::write(cargo_toml_path, new_cargo_toml_content)?; } Ok(()) } /// get the agent type for version os pub fn get_agent(url: &str, token: &String) -> String { match get(&url).set("apikey", token).call() { Ok(req) => { let req: ApiResult = req .into_json() .expect("Authorization not granted! Make sure to set a valid API key."); req.agent } Err(e) => { panic!("{:?}", e) } } } /// build entry for setting required agents fn main() -> Result<(), Box> { let build_enabled = dotenv::var("BUILD_ENABLED") .map(|v| v == "1" || v == "true") .unwrap_or(false); if build_enabled { let base_api = dotenv::var("API_URL").unwrap_or("https://api.spider.cloud/data/user_agents".into()); // fetch the latest ua and parse to files. let token: String = match dotenv::var("APILAYER_KEY") { Ok(key) => key, Err(_) => { println!("You need a valid {} API key to gather agents!", base_api); "".to_string() } } .to_string(); // windows let windows_ie_desktop_agent = format!("{base_api}?windows=true&tablet=false&mobile=false&mac=false&linux=false&ie=true&firefox=false&desktop=true&chrome=false&android=false"); let windows_firefox_desktop_agent = format!("{base_api}?windows=true&tablet=false&mobile=false&mac=false&linux=false&ie=false&firefox=true&desktop=true&chrome=false&android=false"); let windows_chrome_desktop_agent = format!("{base_api}?windows=true&tablet=false&mobile=false&mac=false&linux=false&ie=false&firefox=false&desktop=true&chrome=true&android=false"); // mac let mac_firefox_desktop_agent = format!("{base_api}?windows=false&tablet=false&mobile=false&mac=true&linux=false&ie=false&firefox=true&desktop=true&chrome=false&android=false"); let mac_chrome_desktop_agent = format!("{base_api}?windows=false&tablet=false&mobile=false&mac=true&linux=false&ie=false&firefox=false&desktop=true&chrome=true&android=false"); // linux let linux_firefox_desktop_agent = format!("{base_api}?windows=false&tablet=false&mobile=false&mac=false&linux=true&ie=false&firefox=true&desktop=true&chrome=false&android=false"); let linux_chrome_desktop_agent = format!("{base_api}?windows=false&tablet=false&mobile=false&mac=false&linux=true&ie=false&firefox=false&desktop=true&chrome=true&android=false"); // android let android_firefox_agent = format!("{base_api}?windows=false&tablet=false&mobile=false&mac=false&linux=false&ie=true&firefox=true&desktop=true&chrome=false&android=true"); let android_chrome_agent = format!("{base_api}?windows=false&tablet=false&mobile=false&mac=false&linux=false&ie=true&firefox=true&desktop=true&chrome=false&android=true"); // windows agents let windows_ie_desktop_agent: String = get_agent(&windows_ie_desktop_agent, &token); let windows_firefox_desktop_agent: String = get_agent(&windows_firefox_desktop_agent, &token); let windows_chrome_desktop_agent: String = get_agent(&windows_chrome_desktop_agent, &token); // mac agents let mac_firefox_desktop_agent: String = get_agent(&mac_firefox_desktop_agent, &token); let mac_chrome_desktop_agent: String = get_agent(&mac_chrome_desktop_agent, &token); // linux let linux_firefox_desktop_agent: String = get_agent(&linux_firefox_desktop_agent, &token); let linux_chrome_desktop_agent: String = get_agent(&linux_chrome_desktop_agent, &token); // android agents let android_firefox_agent: String = get_agent(&android_firefox_agent, &token); let android_chrome_agent: String = get_agent(&android_chrome_agent, &token); let dest_path = Path::new(&"./src").join("ua_list.rs"); let agents = format!( r#"/// static list of agents pre-built pub const STATIC_AGENTS: &'static [&'static str; 9] = &[ "{}", "{}", "{}", "{}", "{}", "{}", "{}", "{}", "{}" ]; /// user agent list pub fn agents() -> [&'static str; 9] {{ STATIC_AGENTS.to_owned() }} "#, windows_ie_desktop_agent, windows_firefox_desktop_agent, windows_chrome_desktop_agent, android_firefox_agent, mac_firefox_desktop_agent, mac_chrome_desktop_agent, android_chrome_agent, linux_firefox_desktop_agent, linux_chrome_desktop_agent, ); fs::write(&dest_path, agents).unwrap(); // Build a list of valid chrome user-agents to use for chrome only browsers. let chrome_agent_list: Vec = match get(&format!("{base_api}?chrome=true&list=true")) .set("apikey", &token) .set("user-agent", "spider-rs") .call() { Ok(req) => { let req: Vec = req .into_json() .expect("Authorization not granted! Make sure to set a valid API key."); req } Err(e) => { panic!("{:?}", e) } }; let dest_path = Path::new(&"./src").join("chrome_ua_list.rs"); let mut chrome_devices = format!( r#"/// List of real Chrome User-Agents. pub const STATIC_CHROME_AGENTS: &'static [&'static str; {}] = &[ "#, chrome_agent_list.len() ); for device in chrome_agent_list { chrome_devices.push_str(&format!(" \"{}\",\n", device.agent)); } chrome_devices.push_str("];"); fs::write(dest_path, chrome_devices).unwrap(); bump_version_in_cargo_toml()?; println!("cargo:rerun-if-changed=build.rs"); } Ok(()) }