/* * googleservice main.rs * - entrypoint for the asklyphe google backend * * Copyright (C) 2025 Real Microsoft, LLC * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, version 3. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ mod google; mod process; pub mod proxy; use std::io::Read; use std::str::FromStr; use std::sync::Arc; use std::sync::atomic::{AtomicI64, AtomicU64, AtomicUsize, Ordering}; use asklyphe_common::nats::authservice::AuthServiceResponse; use asklyphe_common::nats::bingservice::BingServiceResponse; use asklyphe_common::nats::comms; use async_nats::jetstream; use isahc::{Request, RequestExt}; use log::{debug, error, info}; use once_cell::sync::{Lazy, OnceCell}; use crate::proxy::Proxy; pub static PROXIES: Lazy> = Lazy::new(|| { if let Ok(proxy_file) = std::env::var("PROXY_FILE") { let contents = std::fs::read_to_string(proxy_file); let mut proxies = vec![]; for line in contents.expect("FAILED TO READ FILE").lines() { proxies.push(Proxy::from_str(line).expect("INVALID PROXY")); } info!("loaded {} proxies", proxies.len()); proxies } else { vec![] } }); pub static NEXT_PROXY: AtomicUsize = AtomicUsize::new(0); pub static NATS_URL: Lazy = Lazy::new(|| std::env::var("NATS_URL").expect("NO NATS DEFINED")); pub static NATS_CERT: Lazy = Lazy::new(|| std::env::var("NATS_CERT").expect("NO NATS_CERT DEFINED")); pub static NATS_KEY: Lazy = Lazy::new(|| std::env::var("NATS_KEY").expect("NO NATS_KEY DEFINED")); pub static DB_URL: Lazy = Lazy::new(|| std::env::var("DB_URL").expect("NO DB_URL DEFINED")); pub static PROCESSES_HANDLED: AtomicU64 = AtomicU64::new(0); pub static LAST_MESSAGE: AtomicI64 = AtomicI64::new(0); //#[tokio::main] //async fn main() { // env_logger::init(); // let mut args: Vec = std::env::args().collect(); // // remove first argument (path) // args.remove(0); // let query = args.join(" "); // // let res = query_bing(query).await; // if let Err(e) = res { // match e { // BingQueryError::CouldNotSendRequest => { // error!("EXITING DUE TO FAILED BING QUERY: COULDN'T SEND REQUEST"); // } // BingQueryError::CouldNotDeserialize => { // error!("EXITING DUE TO FAILED BING QUERY: COULDN'T FIND BING QUERY"); // } // } // return; // } // if let Ok(res) = res { // for res in res { // println!("# {} ({})", res.title.unwrap_or_default(), res.url); // println!(" {}", res.description.unwrap_or_default()); // } // } //} #[tokio::main] async fn main() { env_logger::init(); info!("googleservice began at {}", chrono::Utc::now().to_string()); let nats = async_nats::ConnectOptions::new() .add_client_certificate(NATS_CERT.as_str().into(), NATS_KEY.as_str().into()) .connect(NATS_URL.as_str()) .await; if let Err(e) = nats { error!("FATAL ERROR, COULDN'T CONNECT TO NATS: {}", e); return; } let nats = nats.unwrap(); let nats = jetstream::new(nats); async fn on_recv(query: comms::Query) -> comms::ServiceResponse { debug!("recv"); let now = chrono::Utc::now().timestamp(); LAST_MESSAGE.store(now, Ordering::Relaxed); let response = match query { comms::Query::GoogleService(query) => { process::process(query).await } _ => { BingServiceResponse::InvalidRequest } }; if PROCESSES_HANDLED.load(Ordering::Relaxed) % 100 == 0 { info!("handled {} requests!", PROCESSES_HANDLED.load(Ordering::Relaxed)); } PROCESSES_HANDLED.fetch_add(1, Ordering::Relaxed); comms::ServiceResponse::BingService(response) } if let Err(e) = comms::subscribe_service(comms::Service::GoogleService, &nats, Arc::new(on_recv)).await { error!("failed to subscribe to bingservice nats! reason {:?}", e); } }