mirror of
https://github.com/SkyfallWasTaken/arcade-monitor.git
synced 2024-11-10 03:49:40 +00:00
Add real price ratio
This commit is contained in:
parent
ca2acbffe6
commit
17c19361ab
5 changed files with 64 additions and 14 deletions
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -37,6 +37,7 @@ dependencies = [
|
|||
"console_error_panic_hook",
|
||||
"getrandom",
|
||||
"indoc",
|
||||
"maplit",
|
||||
"pretty_assertions",
|
||||
"reqwest",
|
||||
"scraper",
|
||||
|
@ -631,6 +632,12 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
|
||||
|
||||
[[package]]
|
||||
name = "maplit"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
|
||||
|
||||
[[package]]
|
||||
name = "markup5ever"
|
||||
version = "0.11.0"
|
||||
|
|
|
@ -25,6 +25,7 @@ reqwest = "0.12.5"
|
|||
|
||||
[dev-dependencies]
|
||||
pretty_assertions = "1.4.0"
|
||||
maplit = "1.0.2"
|
||||
|
||||
[package.metadata.cargo-machete]
|
||||
ignored = ["getrandom"]
|
||||
|
|
|
@ -12,6 +12,10 @@
|
|||
- `NTFY_URL` - URL for ntfy
|
||||
- `SLACK_GROUP_ID` - ID of the Slack group to ping
|
||||
|
||||
## Key-value keys
|
||||
- `real_prices` - stores the real-world prices of items. equivalent to a `HashMap<String, i32>`, where `String` is the `id` parameter. prices are in USD.
|
||||
- `items` - stores old items (you don't need to worry about this one)
|
||||
|
||||
## Tech Stack
|
||||
- **Cloudflare Workers** for running the monitor on the edge.
|
||||
- **Rust** for the monitor's code. I love its type safety, as well as libraries such as `serde`.
|
||||
|
|
|
@ -3,7 +3,11 @@ use serde_json::json;
|
|||
|
||||
use crate::items::ShopItem;
|
||||
|
||||
pub fn format_item_diff(old: &ShopItem, new: &ShopItem) -> Option<String> {
|
||||
pub fn format_item_diff(
|
||||
old: &ShopItem,
|
||||
new: &ShopItem,
|
||||
real_price: Option<&i32>,
|
||||
) -> Option<String> {
|
||||
if old == new {
|
||||
// The items are the exact same
|
||||
return None;
|
||||
|
@ -19,13 +23,21 @@ pub fn format_item_diff(old: &ShopItem, new: &ShopItem) -> Option<String> {
|
|||
|
||||
if old.price != new.price {
|
||||
result.push(format!(
|
||||
"*Price:* {} → {} {}",
|
||||
"*Price:* {} → {} {}{}",
|
||||
old.price,
|
||||
new.price,
|
||||
if old.price > new.price {
|
||||
"🔽"
|
||||
} else {
|
||||
"🔼"
|
||||
},
|
||||
if let Some(real_price) = real_price {
|
||||
format!(
|
||||
" _(${real_price} - ${}/hr)_",
|
||||
(*real_price as f32) / (new.price as f32)
|
||||
)
|
||||
} else {
|
||||
"".into()
|
||||
}
|
||||
));
|
||||
}
|
||||
|
@ -257,21 +269,23 @@ mod diff_tests {
|
|||
let old = ShopItem {
|
||||
full_name: "Test".into(),
|
||||
price: 1,
|
||||
id: "1".into(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let new = ShopItem {
|
||||
full_name: "Test".into(),
|
||||
price: 2,
|
||||
id: "1".into(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
format_item_diff(&old, &new),
|
||||
format_item_diff(&old, &new, Some(&50)), // Let's say it's $50
|
||||
Some(
|
||||
indoc! {"
|
||||
*Name:* Test
|
||||
*Price:* 1 → 2 🔼"}
|
||||
*Price:* 1 → 2 🔼 _($50 - $25/hr)_"}
|
||||
.into()
|
||||
)
|
||||
);
|
||||
|
@ -282,17 +296,19 @@ mod diff_tests {
|
|||
let old = ShopItem {
|
||||
full_name: "Test".into(),
|
||||
description: Some("Lorem ipsum".into()),
|
||||
price: 2,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let new = ShopItem {
|
||||
full_name: "Test".into(),
|
||||
description: Some("Dolor sit amet".into()),
|
||||
price: 2,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
format_item_diff(&old, &new),
|
||||
format_item_diff(&old, &new, Some(&50)),
|
||||
Some(
|
||||
indoc! {"
|
||||
*Name:* Test
|
||||
|
@ -317,7 +333,7 @@ mod diff_tests {
|
|||
};
|
||||
|
||||
assert_eq!(
|
||||
format_item_diff(&old, &new),
|
||||
format_item_diff(&old, &new, Some(&50)),
|
||||
Some(
|
||||
indoc! {"
|
||||
*Name:* Test
|
||||
|
@ -332,17 +348,19 @@ mod diff_tests {
|
|||
let old = ShopItem {
|
||||
full_name: "Test".into(),
|
||||
stock: Some(10),
|
||||
price: 2,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let new = ShopItem {
|
||||
full_name: "Test".into(),
|
||||
stock: None,
|
||||
price: 2,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
format_item_diff(&old, &new),
|
||||
format_item_diff(&old, &new, Some(&50)),
|
||||
Some(
|
||||
indoc! {"
|
||||
*Name:* Test
|
||||
|
@ -367,7 +385,7 @@ mod diff_tests {
|
|||
};
|
||||
|
||||
assert_eq!(
|
||||
format_item_diff(&old, &new),
|
||||
format_item_diff(&old, &new, Some(&50)),
|
||||
Some(
|
||||
indoc! {"
|
||||
*Name:* Test
|
||||
|
@ -392,7 +410,7 @@ mod diff_tests {
|
|||
};
|
||||
|
||||
assert_eq!(
|
||||
format_item_diff(&old, &new),
|
||||
format_item_diff(&old, &new, Some(&50)),
|
||||
Some(
|
||||
indoc! {"
|
||||
*Name:* Test
|
||||
|
@ -410,6 +428,6 @@ mod diff_tests {
|
|||
..Default::default()
|
||||
};
|
||||
|
||||
assert_eq!(format_item_diff(&item, &item), None);
|
||||
assert_eq!(format_item_diff(&item, &item, Some(&50)), None);
|
||||
}
|
||||
}
|
||||
|
|
28
src/lib.rs
28
src/lib.rs
|
@ -1,3 +1,5 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use items::ShopItems;
|
||||
use reqwest::Client;
|
||||
use worker::*;
|
||||
|
@ -48,9 +50,13 @@ async fn run_scrape(env: Env) -> Result<String> {
|
|||
kv.put("items", &available_items)?.execute().await?;
|
||||
return Ok("No old items found, storing new items".into());
|
||||
};
|
||||
let Some(real_prices) = kv.get("real_prices").json::<HashMap<String, i32>>().await? else {
|
||||
console_debug!("No real prices found!");
|
||||
return Err("No real prices found! This is a bug.".into());
|
||||
};
|
||||
|
||||
// Compare the old items with the new items.
|
||||
let result = diff_old_new_items(&old_items, &available_items);
|
||||
let result = diff_old_new_items(&old_items, &available_items, real_prices);
|
||||
|
||||
// Check if there are any updates.
|
||||
if result.is_empty() {
|
||||
|
@ -89,7 +95,11 @@ async fn run_scrape(env: Env) -> Result<String> {
|
|||
Ok(result.join("\n\n"))
|
||||
}
|
||||
|
||||
fn diff_old_new_items(old_items: &ShopItems, new_items: &ShopItems) -> Vec<String> {
|
||||
fn diff_old_new_items(
|
||||
old_items: &ShopItems,
|
||||
new_items: &ShopItems,
|
||||
real_prices: HashMap<String, i32>,
|
||||
) -> Vec<String> {
|
||||
let mut result: Vec<String> = Vec::new();
|
||||
for item in new_items {
|
||||
// TODO: not very efficient.
|
||||
|
@ -97,7 +107,7 @@ fn diff_old_new_items(old_items: &ShopItems, new_items: &ShopItems) -> Vec<Strin
|
|||
|
||||
match old_item {
|
||||
Some(old) => {
|
||||
if let Some(diff) = format::format_item_diff(old, item) {
|
||||
if let Some(diff) = format::format_item_diff(old, item, real_prices.get(&item.id)) {
|
||||
result.push(diff);
|
||||
}
|
||||
}
|
||||
|
@ -123,6 +133,7 @@ mod diff_old_new_items_tests {
|
|||
|
||||
use indoc::formatdoc;
|
||||
use items::ShopItem;
|
||||
use maplit::hashmap;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
|
@ -130,12 +141,14 @@ mod diff_old_new_items_tests {
|
|||
let item_1 = ShopItem {
|
||||
full_name: "Item 1".into(),
|
||||
description: Some("Description 1".into()),
|
||||
price: 200,
|
||||
id: "1".into(),
|
||||
..Default::default()
|
||||
};
|
||||
let item_2 = ShopItem {
|
||||
full_name: "Item 2".into(),
|
||||
description: Some("Description 2".into()),
|
||||
price: 50,
|
||||
id: "2".into(),
|
||||
..Default::default()
|
||||
};
|
||||
|
@ -143,7 +156,14 @@ mod diff_old_new_items_tests {
|
|||
let old_items = vec![item_1.clone(), item_2.clone()];
|
||||
let new_items = vec![item_1.clone()];
|
||||
|
||||
let result = diff_old_new_items(&old_items, &new_items);
|
||||
let result = diff_old_new_items(
|
||||
&old_items,
|
||||
&new_items,
|
||||
hashmap! {
|
||||
"1".into() => 100,
|
||||
"2".into() => 200,
|
||||
},
|
||||
);
|
||||
|
||||
assert_eq!(result.len(), 1);
|
||||
assert_eq!(
|
||||
|
|
Loading…
Reference in a new issue