use { crate::{response::success, route::track_mount}, serde::Deserialize, }; // static REFERRALS: LazyLock> = LazyLock::new(|| { // serde_json::from_str(include_str!( // "../../content/json/stock_market_referrals.json" // )) // .unwrap() // }); // #[derive(Deserialize)] // struct Referral { // name: String, // description: String, // url: String, // } #[derive(Deserialize, Debug)] struct Quote { c: f64, d: Option, dp: Option, h: f64, l: f64, o: f64, pc: f64, #[allow(unused)] t: i64, } impl Quote { pub fn try_to_string(&self) -> Result { Ok(format!( "Current Price: ${}\nDaily Change: ${} ({}%)\nHigh of the Day: ${}\nLow \ of the Day: ${}\nOpening Price: ${}\nYesterday's Closing Price: ${}", self.c, if let Some(d) = self.d { d } else { return Err(()); }, if let Some(dp) = self.dp { dp } else { return Err(()); }, self.l, self.h, self.o, self.pc, )) } } async fn symbol_to_string(symbol: &str) -> String { let mut quote = None; // https://github.com/seanmonstar/reqwest/issues/1017#issuecomment-1157260218 if let Ok(response) = reqwest::get(&format!( "https://finnhub.io/api/v1/quote?symbol={}&token={}", symbol, std::env::var("FINNHUB_TOKEN") .expect("could not locate FINNHUB_TOKEN environment variable") )) .await { if let Ok(response_content) = response.json::().await { if response_content.dp.is_some() { quote = Some(response_content); } else { return "You have searched for an invalid symbol.".to_string(); } } } quote.as_ref().map_or_else( || { format!( "An API error has occurred while looking up the {symbol} symbol... \ Take this up with Finnhub.", ) }, |quote| quote.try_to_string().unwrap(), ) } pub fn module(router: &mut windmark::router::Router) { // track_mount( // router, // "/stocks/referrals", // "Want to start investing in the stock market? Support me by using one of // \ my referral links!", // |context| { // success( // &format!( // "# Referrals\n\n=> /stocks Dashboard\n=> /cryptocurrency \ // Cryptocurrency Dashboard\n=> /stocks/telegram Telegram Groups\n=> // \ /stocks/search Search\n\nWant to start investing? Support me // by \ using one of my referral links!\n\n{}", // REFERRALS // .iter() // .map(|r| { // format!("## {}\n\n{}\n\n=> {} {0}", r.name, r.description, // r.url) }) // .collect::>() // .join("\n") // ), // &context, // ) // }, // ); track_mount( router, "/stocks", "Explore and search the stock market using Gemini!", |context| async move { success( &format!( "# The Stock Market\n\n=> /stocks/search Symbol Search\n=> /stocks/referrals Referrals\n=> /cryptocurrency Cryptocurrency Dashboard\n=> /stocks/telegram Telegram Groups\n\n## Popular \ Symbols\n\n### AAPL\n\n{}\n\n### TSLA\n\n{}\n\n## Credits\n\nFinancial data provided by\n\n=> https://finnhub.io/ Finnhub", symbol_to_string("AAPL").await, symbol_to_string("TSLA").await ), &context ) }, ); track_mount( router, "/stocks/search", "Search for a specific symbol", |context| async move { let mut symbol = context.url.query().unwrap_or("Symbol Search"); if symbol.is_empty() { symbol = "Symbol Search"; } let mut response = format!( "# {symbol}\n\n=> /stocks Dashboard\n=> /cryptocurrency \ Cryptocurrency Dashboard\n=> /stocks/telegram Telegram Groups\n=> \ /stocks/search Search", ); if symbol != "Symbol Search" { if let Some(query) = context.url.query_pairs().next() { if query.0 == "action" && query.1 == "go" { return windmark::response::Response::input( "Which symbol would you like to explore?", ); } let symbol = query.0; if symbol != "Symbol Search" { response = format!( "{}\n\nYou searched for \"{}\"!\n\n## Key Statistics\n\n{}", response, symbol, symbol_to_string(&symbol).await ); } } } success( &format!( "{response}\n\n## Credits\n\nFinancial data provided by\n\n=> https://finnhub.io/ Finnhub", ), &context ) }, ); }