diff options
| author | Fuwn <[email protected]> | 2022-08-16 17:33:49 -0700 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2022-08-16 17:33:49 -0700 |
| commit | 633f32e3c06aa0eed7133b6cd7ffe61bf5937ca8 (patch) | |
| tree | 40c9e7fb2f5420a804e961074a69481f798f79bf /src/modules | |
| parent | feat(remarks.json): add new remark (diff) | |
| download | locus-633f32e3c06aa0eed7133b6cd7ffe61bf5937ca8.tar.xz locus-633f32e3c06aa0eed7133b6cd7ffe61bf5937ca8.zip | |
feat(modules): stocks
Diffstat (limited to 'src/modules')
| -rw-r--r-- | src/modules/stocks.rs | 191 | ||||
| -rw-r--r-- | src/modules/uptime.rs | 8 |
2 files changed, 197 insertions, 2 deletions
diff --git a/src/modules/stocks.rs b/src/modules/stocks.rs new file mode 100644 index 0000000..e066dce --- /dev/null +++ b/src/modules/stocks.rs @@ -0,0 +1,191 @@ +// This file is part of Locus <https://github.com/gemrest/locus>. +// Copyright (C) 2022-2022 Fuwn <[email protected]> +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU 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 +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// +// Copyright (C) 2022-2022 Fuwn <[email protected]> +// SPDX-License-Identifier: GPL-3.0-only + +use std::lazy::SyncLazy; + +use serde::Deserialize; + +use crate::{route::track_mount, success}; + +static REFERRALS: SyncLazy<Vec<Referral>> = SyncLazy::new(|| { + serde_json::from_str(include_str!("../../content/json/stock_referrals.json")) + .unwrap() +}); + +#[derive(Deserialize)] +struct Referral { + name: String, + description: String, + url: String, +} + +#[derive(Deserialize, Debug)] +struct Quote { + c: f64, + d: Option<f64>, + dp: Option<f64>, + h: f64, + l: f64, + o: f64, + pc: f64, + #[allow(unused)] + t: i64, +} + +impl Quote { + pub fn try_to_string(&self) -> Result<String, ()> { + 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, + )) + } +} + +fn symbol_to_string(symbol: &str) -> String { + let mut quote = None; + + if let Ok(response) = reqwest::blocking::get(format!( + "https://finnhub.io/api/v1/quote?symbol={}&token={}", + symbol, + std::env::var("FINNHUB_TOKEN") + .expect("could not locate FINNHUB_TOKEN environment variable") + )) { + if let Ok(response_content) = response.json::<Quote>() { + 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... Take \ + this up with Finnhub.", + symbol + ) + }, + |quote| quote.try_to_string().unwrap(), + ) +} + +pub fn module(router: &mut windmark::Router) { + track_mount( + router, + "/stocks/referrals", + "Want to start investing? Support me by using one of my referral links!", + Box::new(|context| { + success!( + format!( + "# Referrals\n\n=> /stocks Home\n=> /stocks/search?action=go \ + 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::<Vec<String>>() + .join("\n") + ), + context + ) + }), + ); + + track_mount( + router, + "/stocks", + "Explore and search the stock market using Gemini!", + Box::new(|context| { + success!( + format!( + "# Stocks\n\n=> /stocks/search Symbol Search\n=> /stocks/referrals Referrals\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"), + symbol_to_string("TSLA") + ), + context + ) + }), + ); + + track_mount( + router, + "/stocks/search", + "Search for a specific symbol", + Box::new(|context| { + let mut symbol = context.url.query().unwrap_or("Symbol Search"); + + if symbol.is_empty() { + symbol = "Symbol Search"; + } + + let mut response = format!( + "# {}\n\n=> /stocks Home\n=> /stocks/search?action=go Search!", + symbol + ); + + if symbol != "Symbol Search" { + if let Some(query) = context.url.query_pairs().next() { + if query.0 == "action" && query.1 == "go" { + return windmark::Response::Input( + "Which symbol would you like to explore?".to_string(), + ); + } + + 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) + ); + } + } + } + + success!( + format!( + "{}\n\n## Credits\n\nFinancial data provided by\n\n=> https://finnhub.io/ Finnhub", + response + ), + context + ) + }), + ); +} diff --git a/src/modules/uptime.rs b/src/modules/uptime.rs index 51da496..c0b09cb 100644 --- a/src/modules/uptime.rs +++ b/src/modules/uptime.rs @@ -30,7 +30,7 @@ pub fn module(router: &mut windmark::Router) { "/uptime", "The uptime of Locus (A.K.A., The Locus Epoch). (\\?[s|ms|mu|ns]?)?", Box::new(move |context| { - windmark::Response::Success(context.url.query().map_or_else( + let response = context.url.query().map_or_else( || UPTIME.elapsed().as_nanos().to_string(), |query| { match query { @@ -42,7 +42,11 @@ pub fn module(router: &mut windmark::Router) { _ => UPTIME.elapsed().as_nanos().to_string(), } }, - )) + ); + + crate::route::cache(&context, &response); + + windmark::Response::Success(response) }), ); } |