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 ¶ms
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}