summaryrefslogtreecommitdiffstats
path: root/src/plugins/factoids/database.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/factoids/database.rs')
-rw-r--r--src/plugins/factoids/database.rs151
1 files changed, 151 insertions, 0 deletions
diff --git a/src/plugins/factoids/database.rs b/src/plugins/factoids/database.rs
new file mode 100644
index 0000000..b612d6f
--- /dev/null
+++ b/src/plugins/factoids/database.rs
@@ -0,0 +1,151 @@
+#[cfg(feature = "mysql")]
+extern crate dotenv;
+
+use std::collections::HashMap;
+
+#[cfg(feature = "mysql")]
+use diesel::prelude::*;
+
+#[cfg(feature = "mysql")]
+use diesel::mysql::MysqlConnection;
+
+use chrono::NaiveDateTime;
+
+pub enum DbResponse {
+ Success,
+ Failed(&'static str),
+}
+
+#[cfg_attr(feature = "mysql", derive(Queryable))]
+#[derive(Clone, Debug)]
+pub struct Factoid {
+ pub name: String,
+ pub idx: i32,
+ pub content: String,
+ pub author: String,
+ pub created: NaiveDateTime,
+}
+
+#[cfg(feature = "mysql")]
+use self::mysql::factoids;
+#[cfg_attr(feature = "mysql", derive(Insertable))]
+#[cfg_attr(feature = "mysql", table_name="factoids")]
+pub struct NewFactoid<'a> {
+ pub name: &'a str,
+ pub idx: i32,
+ pub content: &'a str,
+ pub author: &'a str,
+ pub created: NaiveDateTime,
+}
+
+
+pub trait Database: Send {
+ fn insert(&mut self, factoid: &NewFactoid) -> DbResponse;
+ fn get(&self, name: &str, idx: i32) -> Option<Factoid>;
+ fn delete(&mut self, name: &str, idx: i32) -> DbResponse;
+ fn count(&self, name: &str) -> Result<i32, &'static str>;
+}
+
+// HashMap
+impl Database for HashMap<(String, i32), Factoid> {
+ fn insert(&mut self, factoid: &NewFactoid) -> DbResponse {
+ let factoid = Factoid {
+ name: String::from(factoid.name),
+ idx: factoid.idx,
+ content: factoid.content.to_string(),
+ author: factoid.author.to_string(),
+ created: factoid.created,
+ };
+
+ let name = String::from(factoid.name.clone());
+ match self.insert((name, factoid.idx), factoid) {
+ None => DbResponse::Success,
+ Some(_) => DbResponse::Failed("Factoid was overwritten"),
+ }
+ }
+
+ fn get(&self, name: &str, idx: i32) -> Option<Factoid> {
+ self.get(&(String::from(name), idx)).map(|f| f.clone())
+ }
+
+ fn delete(&mut self, name: &str, idx: i32) -> DbResponse {
+ match self.remove(&(String::from(name), idx)) {
+ Some(_) => DbResponse::Success,
+ None => DbResponse::Failed("Factoid not found"),
+ }
+ }
+
+ fn count(&self, name: &str) -> Result<i32, &'static str> {
+ Ok(self.iter()
+ .filter(|&(&(ref n, _), _)| n == name)
+ .count() as i32)
+ }
+}
+
+// Diesel automatically define the factoids module as public.
+// For now this is how we keep it private.
+#[cfg(feature = "mysql")]
+mod mysql {
+ table! {
+ factoids (name, idx) {
+ name -> Varchar,
+ idx -> Integer,
+ content -> Text,
+ author -> Varchar,
+ created -> Timestamp,
+ }
+ }
+}
+
+#[cfg(feature = "mysql")]
+impl Database for MysqlConnection {
+ fn insert(&mut self, factoid: &NewFactoid) -> DbResponse {
+ use diesel;
+ match diesel::insert_into(factoids::table)
+ .values(factoid)
+ .execute(self) {
+ Ok(_) => DbResponse::Success,
+ Err(e) => {
+ error!("DB Insertion Error: \"{}\"", e);
+ DbResponse::Failed("Failed to add factoid")
+ }
+ }
+ }
+
+ fn get(&self, name: &str, idx: i32) -> Option<Factoid> {
+ factoids::table.find((name, idx)).first(self).ok()
+ }
+
+ fn delete(&mut self, name: &str, idx: i32) -> DbResponse {
+ use diesel;
+ use self::factoids::columns;
+ match diesel::delete(factoids::table
+ .filter(columns::name.eq(name))
+ .filter(columns::idx.eq(idx)))
+ .execute(self) {
+ Ok(v) => {
+ if v > 0 {
+ DbResponse::Success
+ } else {
+ DbResponse::Failed("Could not find any factoid with that name")
+ }
+ }
+ Err(e) => {
+ error!("DB Deletion Error: \"{}\"", e);
+ DbResponse::Failed("Failed to delete factoid")
+ }
+ }
+ }
+
+ fn count(&self, name: &str) -> Result<i32, &'static str> {
+ let count: Result<i64, _> = factoids::table
+ .filter(factoids::columns::name.eq(name))
+ .count()
+ .first(self);
+
+ match count {
+ Ok(c) => Ok(c as i32),
+ Err(_) => Err("Database Error"),
+ }
+ }
+}