feat: add multi-account ability

This commit is contained in:
VC
2022-11-03 16:14:25 +01:00
parent 44ec3edfe2
commit dad49da090
11 changed files with 341 additions and 163 deletions

View File

@@ -1,10 +1,13 @@
use log::debug;
use rusqlite::{params, Connection, OptionalExtension};
use std::error::Error;
use log::debug;
use rusqlite::{params, Connection, OptionalExtension};
/// Struct for each query line
#[derive(Debug)]
pub struct TweetToToot {
pub twitter_screen_name: String,
pub tweet_id: u64,
pub toot_id: String,
}
@@ -13,12 +16,13 @@ pub struct TweetToToot {
/// if a tweet_id is passed, read this particular tweet from DB
pub fn read_state(
conn: &Connection,
n: &str,
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 tweet_id = {}", i),
None => "SELECT * FROM tweet_to_toot ORDER BY tweet_id DESC LIMIT 1".to_string(),
Some(i) => format!("SELECT * FROM tweet_to_toot WHERE tweet_id = {} and twitter_screen_name = \"{}\"", i, n),
None => format!("SELECT * FROM tweet_to_toot WHERE twitter_screen_name = \"{}\" ORDER BY tweet_id DESC LIMIT 1", n),
};
let mut stmt = conn.prepare(&query)?;
@@ -26,8 +30,9 @@ pub fn read_state(
let t = stmt
.query_row([], |row| {
Ok(TweetToToot {
tweet_id: row.get(0)?,
toot_id: row.get(1)?,
twitter_screen_name: row.get("twitter_screen_name")?,
tweet_id: row.get("tweet_id")?,
toot_id: row.get("toot_id")?,
})
})
.optional()?;
@@ -39,8 +44,8 @@ pub fn read_state(
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],
"INSERT INTO tweet_to_toot (twitter_screen_name, tweet_id, toot_id) VALUES (?1, ?2, ?3)",
params![t.twitter_screen_name, t.tweet_id, t.toot_id],
)?;
Ok(())
@@ -53,8 +58,9 @@ pub fn init_db(d: &str) -> Result<(), Box<dyn Error>> {
conn.execute(
"CREATE TABLE IF NOT EXISTS tweet_to_toot (
tweet_id INTEGER PRIMARY KEY,
toot_id TEXT UNIQUE
twitter_screen_name TEXT NOT NULL,
tweet_id INTEGER PRIMARY KEY,
toot_id TEXT UNIQUE
)",
[],
)?;
@@ -62,6 +68,31 @@ pub fn init_db(d: &str) -> Result<(), Box<dyn Error>> {
Ok(())
}
/// Migrate DB from 0.6.x to 0.7.x
pub fn migrate_db(d: &str, s: &str) -> Result<(), Box<dyn Error>> {
debug!("Migrating DB for Scootaloo");
let conn = Connection::open(d)?;
let res = conn.execute(
&format!(
"ALTER TABLE tweet_to_toot
ADD COLUMN twitter_screen_name TEXT NOT NULL
DEFAULT \"{}\"",
s
),
[],
);
match res {
Err(e) => match e.to_string().as_str() {
"duplicate column name: twitter_screen_name" => Ok(()),
_ => Err(Box::new(e)),
},
_ => Ok(()),
}
}
#[cfg(test)]
mod tests {
use super::*;
@@ -93,9 +124,9 @@ mod tests {
let conn = Connection::open(d).unwrap();
conn.execute(
"INSERT INTO tweet_to_toot
"INSERT INTO tweet_to_toot (twitter_screen_name, tweet_id, toot_id)
VALUES
(100, 'A');",
('tamerelol', 100, 'A');",
[],
)
.unwrap();
@@ -114,6 +145,7 @@ mod tests {
let conn = Connection::open(d).unwrap();
let t_in = TweetToToot {
twitter_screen_name: "tamerelol".to_string(),
tweet_id: 123456789,
toot_id: "987654321".to_string(),
};
@@ -125,14 +157,16 @@ mod tests {
let t_out = stmt
.query_row([], |row| {
Ok(TweetToToot {
tweet_id: row.get(0).unwrap(),
toot_id: row.get(1).unwrap(),
twitter_screen_name: row.get("twitter_screen_name").unwrap(),
tweet_id: row.get("tweet_id").unwrap(),
toot_id: row.get("toot_id").unwrap(),
})
})
.unwrap();
assert_eq!(&t_out.twitter_screen_name, "tamerelol");
assert_eq!(t_out.tweet_id, 123456789);
assert_eq!(t_out.toot_id, "987654321".to_string());
assert_eq!(&t_out.toot_id, "987654321");
remove_file(d).unwrap();
}
@@ -146,15 +180,15 @@ mod tests {
let conn = Connection::open(d).unwrap();
conn.execute(
"INSERT INTO tweet_to_toot (tweet_id, toot_id)
"INSERT INTO tweet_to_toot (twitter_screen_name, tweet_id, toot_id)
VALUES
(101, 'A'),
(102, 'B');",
('tamerelol', 101, 'A'),
('tamerelol', 102, 'B');",
[],
)
.unwrap();
let t_out = read_state(&conn, None).unwrap().unwrap();
let t_out = read_state(&conn, "tamerelol", None).unwrap().unwrap();
remove_file(d).unwrap();
@@ -170,7 +204,7 @@ mod tests {
let conn = Connection::open(d).unwrap();
let t_out = read_state(&conn, None).unwrap();
let t_out = read_state(&conn, "tamerelol", None).unwrap();
remove_file(d).unwrap();
@@ -186,14 +220,14 @@ mod tests {
let conn = Connection::open(d).unwrap();
conn.execute(
"INSERT INTO tweet_to_toot (tweet_id, toot_id)
"INSERT INTO tweet_to_toot (twitter_screen_name, tweet_id, toot_id)
VALUES
(100, 'A');",
('tamerelol', 100, 'A');",
[],
)
.unwrap();
let t_out = read_state(&conn, Some(101)).unwrap();
let t_out = read_state(&conn, "tamerelol", Some(101)).unwrap();
remove_file(d).unwrap();
@@ -209,18 +243,62 @@ mod tests {
let conn = Connection::open(d).unwrap();
conn.execute(
"INSERT INTO tweet_to_toot (tweet_id, toot_id)
"INSERT INTO tweet_to_toot (twitter_screen_name, tweet_id, toot_id)
VALUES
(100, 'A');",
('tamerelol', 100, 'A');",
[],
)
.unwrap();
let t_out = read_state(&conn, Some(100)).unwrap().unwrap();
let t_out = read_state(&conn, "tamerelol", Some(100)).unwrap().unwrap();
remove_file(d).unwrap();
assert_eq!(t_out.tweet_id, 100);
assert_eq!(t_out.toot_id, "A");
}
#[test]
fn test_migrate_db_add_column() {
let d = "/tmp/test_migrate_db_add_column.sqlite";
let conn = Connection::open(d).unwrap();
conn.execute(
"CREATE TABLE IF NOT EXISTS tweet_to_toot (
tweet_id INTEGER PRIMARY KEY,
toot_id TEXT UNIQUE
)",
[],
)
.unwrap();
migrate_db(d, "tamerelol").unwrap();
let mut stmt = conn.prepare("PRAGMA table_info(tweet_to_toot);").unwrap();
let mut t = stmt.query([]).unwrap();
while let Some(row) = t.next().unwrap() {
if row.get::<usize, u8>(0).unwrap() == 2 {
assert_eq!(
row.get::<usize, String>(1).unwrap(),
"twitter_screen_name".to_string()
);
}
}
remove_file(d).unwrap();
}
#[test]
fn test_migrate_db_no_add_column() {
let d = "/tmp/test_migrate_db_no_add_column.sqlite";
init_db(d).unwrap();
migrate_db(d, "tamerelol").unwrap();
remove_file(d).unwrap();
}
}