url_bot_rs/
sqlite.rs

1use rusqlite::Connection;
2use failure::{Error, SyncFailure};
3use std::path::Path;
4use serde_rusqlite::{from_rows, to_params_named};
5use chrono::Utc;
6use serde_derive::{Serialize, Deserialize};
7
8pub struct Database {
9    db: Connection,
10}
11
12impl Database {
13    pub fn open(path: impl AsRef<Path>) -> Result<Self, Error> {
14        let db = Connection::open(path)?;
15        Self::from_connection(db)
16    }
17
18    pub fn open_in_memory() -> Result<Self, Error> {
19        let db = Connection::open_in_memory()?;
20        Self::from_connection(db)
21    }
22
23    fn from_connection(db: Connection) -> Result<Self, Error> {
24        db.execute("CREATE TABLE IF NOT EXISTS posts (
25            id              INTEGER PRIMARY KEY,
26            title           TEXT NOT NULL,
27            url             TEXT NOT NULL,
28            user            TEXT NOT NULL,
29            channel         TEXT NOT NULL,
30            time_created    TEXT NOT NULL
31            )",
32            &[]
33        )?;
34        db.execute("CREATE TABLE IF NOT EXISTS errors (
35            id              INTEGER PRIMARY KEY,
36            url             TEXT NOT NULL,
37            error_info      TEXT NOT NULL
38            )",
39            &[]
40        )?;
41
42        Ok(Self { db })
43    }
44
45    pub fn add_log(&self, entry: &NewLogEntry) -> Result<(), Error> {
46        let time_created = Utc::now().format("%a %b %-d %H:%M:%S %-Y").to_string();
47        let params = to_params_named(entry).map_err(SyncFailure::new)?;
48        let mut params = params.to_slice();
49        params.push((":time_created", &time_created));
50
51        self.db.execute_named("
52            INSERT INTO posts ( title,  url,  user,  channel,  time_created)
53            VALUES            (:title, :url, :user, :channel, :time_created)",
54            &params
55        )?;
56
57        Ok(())
58    }
59
60    pub fn check_prepost(&self, url: &str) -> Result<Option<PrevPost>, Error> {
61        let mut st = self.db.prepare("
62            SELECT user, time_created, channel
63            FROM posts
64            WHERE url LIKE :url
65        ")?;
66        let rows = st.query_named(&[(":url", &url)])?;
67        let mut rows = from_rows::<PrevPost>(rows);
68
69        Ok(rows.next())
70    }
71}
72
73#[derive(Debug, Serialize)]
74pub struct NewLogEntry<'a> {
75    pub title: &'a str,
76    pub url: &'a str,
77    pub user: &'a str,
78    pub channel: &'a str,
79}
80
81#[derive(Debug, Default, Deserialize)]
82pub struct PrevPost {
83    pub user: String,
84    pub time_created: String,
85    pub channel: String
86}