Add an admin based table dump and change buy_it_now_price to cents
All checks were successful
Cargo Build & Test / Rust project - latest (1.86) (push) Successful in 3m32s
Cargo Build & Test / Rust project - latest (1.87) (push) Successful in 3m57s
Cargo Build & Test / Rust project - latest (1.88) (push) Successful in 4m2s
Cargo Build & Test / Rust project - latest (1.85.1) (push) Successful in 9m17s

This commit is contained in:
2025-06-28 15:49:26 -04:00
parent e3b018b046
commit bbca1f3bcb
10 changed files with 256 additions and 209 deletions

119
src/db.rs
View File

@@ -4,7 +4,7 @@ use serde::Serialize;
use std::path::Path;
use tracing::info;
trait DBTable {
pub trait DBTable {
const TABLE_NAME: &'static str;
const TABLE_SCHEMA: &'static str;
fn initialize(conn: &Connection) {
@@ -19,6 +19,10 @@ trait DBTable {
info!("{} ({})", Self::TABLE_NAME, Self::TABLE_SCHEMA);
conn.execute(create_table, ()).unwrap();
}
fn get_all(conn: &Connection) -> rusqlite::Result<Vec<Self>>
where
Self: Sized;
}
#[derive(Serialize, Debug, PartialEq, Clone)]
@@ -32,6 +36,22 @@ impl DBTable for SearchURL {
id INTEGER PRIMARY KEY,
url TEXT NOT NULL UNIQUE,
name TEXT NOT NULL UNIQUE";
fn get_all(conn: &Connection) -> rusqlite::Result<Vec<Self>> {
let mut stmt = conn.prepare(&format!("SELECT url, name FROM {}", Self::TABLE_NAME))?;
let iter = stmt.query_map([], |row| {
Ok(SearchURL {
full_url: row.get(0)?,
name: row.get(1)?,
})
})?;
let mut result = Vec::new();
for item in iter {
result.push(item?);
}
Ok(result)
}
}
impl SearchURL {
pub fn lookup(conn: &Connection, name: &str) -> Option<Self> {
@@ -91,6 +111,25 @@ impl DBTable for ParsedPage {
UNIQUE(category, timestamp)
FOREIGN KEY(category) REFERENCES SearchURLs(name)
";
fn get_all(conn: &Connection) -> rusqlite::Result<Vec<Self>> {
let mut stmt = conn.prepare(&format!(
"SELECT category, timestamp FROM {}",
Self::TABLE_NAME
))?;
let iter = stmt.query_map([], |row| {
Ok(ParsedPage {
category: row.get(0)?,
timestamp: row.get(1)?,
})
})?;
let mut result = Vec::new();
for item in iter {
result.push(item?);
}
Ok(result)
}
}
impl ParsedPage {
pub fn lookup(conn: &Connection, timestamp: DateTime<Utc>) -> Option<Self> {
@@ -146,6 +185,30 @@ impl DBTable for ParsedStorage {
UNIQUE(item, parse_engine)
FOREIGN KEY(item) REFERENCES Listings(item_id)
";
fn get_all(conn: &Connection) -> rusqlite::Result<Vec<Self>> {
let mut stmt = conn.prepare(&format!("SELECT id, item, total_gigabytes, quantity, sizes_gigabytes, parse_engine, need_description_check FROM {}", Self::TABLE_NAME))?;
let iter = stmt.query_map([], |row| {
Ok(ParsedStorage {
id: row.get(0)?,
item: row.get(1)?,
total_gigabytes: row.get(2)?,
quantity: row.get(3)?,
individual_size_gigabytes: {
let r: String = row.get(4)?;
r.parse().unwrap_or(0)
},
parse_engine: row.get(5)?,
needed_description_check: row.get(6)?,
})
})?;
let mut result = Vec::new();
for item in iter {
result.push(item?);
}
Ok(result)
}
}
impl ParsedStorage {
pub fn lookup(conn: &Connection, item: i64) -> Vec<ParsedStorage> {
@@ -211,6 +274,27 @@ impl DBTable for ItemAppearances {
FOREIGN KEY(item) REFERENCES Listings(item_id),
FOREIGN KEY(category, timestamp) REFERENCES Pages_Parsed(category, timestamp)
";
fn get_all(conn: &Connection) -> rusqlite::Result<Vec<Self>> {
let mut stmt = conn.prepare(&format!(
"SELECT item, category, timestamp, current_bid_usd_cents FROM {}",
Self::TABLE_NAME
))?;
let iter = stmt.query_map([], |row| {
Ok(ItemAppearances {
item: row.get(0)?,
category: row.get(1)?,
timestamp: row.get(2)?,
current_bid_usd_cents: row.get(3)?,
})
})?;
let mut result = Vec::new();
for item in iter {
result.push(item?);
}
Ok(result)
}
}
impl ItemAppearances {
pub fn add_or_update(&self, conn: &Connection) {
@@ -267,7 +351,7 @@ pub struct Listing {
pub id: i64,
pub item_id: i64,
pub title: String,
pub buy_it_now_price: Option<f64>,
pub buy_it_now_price_cents: Option<i64>,
pub has_best_offer: bool,
pub image_url: String,
}
@@ -281,6 +365,29 @@ impl DBTable for Listing {
has_best_offer INTEGER NOT NULL,
image_url TEXT NOT NULL
";
fn get_all(conn: &Connection) -> rusqlite::Result<Vec<Self>> {
let mut stmt = conn.prepare(&format!(
"SELECT id, item_id, title, buy_it_now_usd_cents, has_best_offer, image_url FROM {}",
Self::TABLE_NAME
))?;
let iter = stmt.query_map([], |row| {
Ok(Listing {
id: row.get(0)?,
item_id: row.get(1)?,
title: row.get(2)?,
buy_it_now_price_cents: row.get(3)?,
has_best_offer: row.get(4)?,
image_url: row.get(5)?,
})
})?;
let mut result = Vec::new();
for item in iter {
result.push(item?);
}
Ok(result)
}
}
impl Listing {
pub fn lookup(conn: &Connection, item_id: i64) -> Option<Listing> {
@@ -295,7 +402,7 @@ impl Listing {
id: row.get(0)?,
item_id: row.get(1)?,
title: row.get(2)?,
buy_it_now_price: row.get(3)?,
buy_it_now_price_cents: row.get(3)?,
has_best_offer: row.get(4)?,
image_url: row.get(5)?,
})
@@ -329,7 +436,7 @@ impl Listing {
id: row.get(0)?,
item_id: row.get(1)?,
title: row.get(2)?,
buy_it_now_price: row.get(3)?,
buy_it_now_price_cents: row.get(3)?,
has_best_offer: row.get(4)?,
image_url: row.get(5)?,
})
@@ -377,7 +484,7 @@ impl Listing {
(
self.item_id,
&self.title,
self.buy_it_now_price,
self.buy_it_now_price_cents,
self.has_best_offer,
self.image_url.clone(),
),
@@ -424,7 +531,7 @@ mod tests {
id: 1,
item_id: 1234,
title: "Some Title".to_string(),
buy_it_now_price: Some(1.23),
buy_it_now_price_cents: Some(123),
has_best_offer: false,
image_url: "google.com".to_string(),
};