mirror of
https://framagit.org/veretcle/oolatoocs.git
synced 2025-07-20 20:41:17 +02:00
Initial commit
This commit is contained in:
226
src/state.rs
Normal file
226
src/state.rs
Normal file
@@ -0,0 +1,226 @@
|
||||
use log::debug;
|
||||
use rusqlite::{params, Connection, OptionalExtension};
|
||||
use std::error::Error;
|
||||
|
||||
/// Struct for each query line
|
||||
#[derive(Debug)]
|
||||
pub struct TweetToToot {
|
||||
pub tweet_id: u64,
|
||||
pub toot_id: u64,
|
||||
}
|
||||
|
||||
/// if None is passed, read the last tweet from DB
|
||||
/// if a tweet_id is passed, read this particular tweet from DB
|
||||
pub fn read_state(
|
||||
conn: &Connection,
|
||||
s: Option<u64>,
|
||||
) -> Result<Option<TweetToToot>, Box<dyn Error>> {
|
||||
debug!("Reading tweet_id {:?}", s);
|
||||
let query: String = match s {
|
||||
Some(i) => format!("SELECT * FROM tweet_to_toot WHERE toot_id = {i}"),
|
||||
None => "SELECT * FROM tweet_to_toot ORDER BY toot_id DESC LIMIT 1".to_string(),
|
||||
};
|
||||
|
||||
let mut stmt = conn.prepare(&query)?;
|
||||
|
||||
let t = stmt
|
||||
.query_row([], |row| {
|
||||
Ok(TweetToToot {
|
||||
tweet_id: row.get("tweet_id")?,
|
||||
toot_id: row.get("toot_id")?,
|
||||
})
|
||||
})
|
||||
.optional()?;
|
||||
|
||||
Ok(t)
|
||||
}
|
||||
|
||||
/// Writes last treated tweet id and toot id to the db
|
||||
pub fn write_state(conn: &Connection, t: TweetToToot) -> Result<(), Box<dyn Error>> {
|
||||
debug!("Write struct {:?}", t);
|
||||
conn.execute(
|
||||
"INSERT INTO tweet_to_toot (tweet_id, toot_id) VALUES (?1, ?2)",
|
||||
params![t.tweet_id, t.toot_id],
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Initiates the DB from path
|
||||
pub fn init_db(d: &str) -> Result<(), Box<dyn Error>> {
|
||||
debug!("Initializing DB for Scootaloo");
|
||||
let conn = Connection::open(d)?;
|
||||
|
||||
conn.execute(
|
||||
"CREATE TABLE IF NOT EXISTS tweet_to_toot (
|
||||
tweet_id INTEGER,
|
||||
toot_id INTEGER PRIMARY KEY
|
||||
)",
|
||||
[],
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::{fs::remove_file, path::Path};
|
||||
|
||||
#[test]
|
||||
fn test_init_db() {
|
||||
let d = "/tmp/test_init_db.sqlite";
|
||||
|
||||
init_db(d).unwrap();
|
||||
|
||||
// check that file exist
|
||||
assert!(Path::new(d).exists());
|
||||
|
||||
// open said file
|
||||
let conn = Connection::open(d).unwrap();
|
||||
conn.execute("SELECT * from tweet_to_toot;", []).unwrap();
|
||||
|
||||
remove_file(d).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_init_init_db() {
|
||||
// init_db fn should be idempotent so let’s test that
|
||||
let d = "/tmp/test_init_init_db.sqlite";
|
||||
|
||||
init_db(d).unwrap();
|
||||
|
||||
let conn = Connection::open(d).unwrap();
|
||||
|
||||
conn.execute(
|
||||
"INSERT INTO tweet_to_toot (tweet_id, toot_id)
|
||||
VALUES
|
||||
(100, 1001);",
|
||||
[],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
init_db(d).unwrap();
|
||||
|
||||
remove_file(d).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_state() {
|
||||
let d = "/tmp/test_write_state.sqlite";
|
||||
|
||||
init_db(d).unwrap();
|
||||
|
||||
let conn = Connection::open(d).unwrap();
|
||||
|
||||
let t_in = TweetToToot {
|
||||
tweet_id: 123456789,
|
||||
toot_id: 987654321,
|
||||
};
|
||||
|
||||
write_state(&conn, t_in).unwrap();
|
||||
|
||||
let mut stmt = conn.prepare("SELECT * FROM tweet_to_toot;").unwrap();
|
||||
|
||||
let t_out = stmt
|
||||
.query_row([], |row| {
|
||||
Ok(TweetToToot {
|
||||
tweet_id: row.get("tweet_id").unwrap(),
|
||||
toot_id: row.get("toot_id").unwrap(),
|
||||
})
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(t_out.tweet_id, 123456789);
|
||||
assert_eq!(t_out.toot_id, 987654321);
|
||||
|
||||
remove_file(d).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_none_to_tweet_id_read_state() {
|
||||
let d = "/tmp/test_none_to_tweet_id_read_state.sqlite";
|
||||
|
||||
init_db(d).unwrap();
|
||||
|
||||
let conn = Connection::open(d).unwrap();
|
||||
|
||||
conn.execute(
|
||||
"INSERT INTO tweet_to_toot (tweet_id, toot_id)
|
||||
VALUES
|
||||
(101, 1001),
|
||||
(102, 1002);",
|
||||
[],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let t_out = read_state(&conn, None).unwrap().unwrap();
|
||||
|
||||
remove_file(d).unwrap();
|
||||
|
||||
assert_eq!(t_out.tweet_id, 102);
|
||||
assert_eq!(t_out.toot_id, 1002);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_none_to_none_read_state() {
|
||||
let d = "/tmp/test_none_to_none_read_state.sqlite";
|
||||
|
||||
init_db(d).unwrap();
|
||||
|
||||
let conn = Connection::open(d).unwrap();
|
||||
|
||||
let t_out = read_state(&conn, None).unwrap();
|
||||
|
||||
remove_file(d).unwrap();
|
||||
|
||||
assert!(t_out.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tweet_id_to_none_read_state() {
|
||||
let d = "/tmp/test_tweet_id_to_none_read_state.sqlite";
|
||||
|
||||
init_db(d).unwrap();
|
||||
|
||||
let conn = Connection::open(d).unwrap();
|
||||
|
||||
conn.execute(
|
||||
"INSERT INTO tweet_to_toot (tweet_id, toot_id)
|
||||
VALUES
|
||||
(100, 1000);",
|
||||
[],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let t_out = read_state(&conn, Some(1200)).unwrap();
|
||||
|
||||
remove_file(d).unwrap();
|
||||
|
||||
assert!(t_out.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tweet_id_to_tweet_id_read_state() {
|
||||
let d = "/tmp/test_tweet_id_to_tweet_id_read_state.sqlite";
|
||||
|
||||
init_db(d).unwrap();
|
||||
|
||||
let conn = Connection::open(d).unwrap();
|
||||
|
||||
conn.execute(
|
||||
"INSERT INTO tweet_to_toot (tweet_id, toot_id)
|
||||
VALUES
|
||||
(100, 1000);",
|
||||
[],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let t_out = read_state(&conn, Some(1000)).unwrap().unwrap();
|
||||
|
||||
remove_file(d).unwrap();
|
||||
|
||||
assert_eq!(t_out.tweet_id, 100);
|
||||
assert_eq!(t_out.toot_id, 1000);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user