diff options
Diffstat (limited to 'fun/tvldb/src/keyword.rs')
-rw-r--r-- | fun/tvldb/src/keyword.rs | 210 |
1 files changed, 0 insertions, 210 deletions
diff --git a/fun/tvldb/src/keyword.rs b/fun/tvldb/src/keyword.rs deleted file mode 100644 index 9c5ea47ea523..000000000000 --- a/fun/tvldb/src/keyword.rs +++ /dev/null @@ -1,210 +0,0 @@ -use crate::models::{Entry, Keyword, NewEntry, NewKeyword}; -use diesel::pg::PgConnection; -use diesel::prelude::*; -use failure::Error; -use std::borrow::Cow; - -/// Maximum number of times we'll follow a `see: ` pointer. -const RECURSION_LIMIT: usize = 5; - -pub struct KeywordDetails { - pub keyword: Keyword, - pub entries: Vec<Entry>, -} - -impl KeywordDetails { - pub fn learn(&mut self, nick: &str, text: &str, dbc: &PgConnection) -> Result<usize, Error> { - let now = ::chrono::Utc::now().naive_utc(); - let ins = NewEntry { - keyword_id: self.keyword.id, - idx: (self.entries.len() + 1) as _, - text, - creation_ts: now, - created_by: nick, - }; - let new = { - use crate::schema::entries; - ::diesel::insert_into(entries::table) - .values(ins) - .get_result(dbc)? - }; - self.entries.push(new); - Ok(self.entries.len()) - } - - pub fn process_moves(&mut self, moves: &[(i32, i32)], dbc: &PgConnection) -> Result<(), Error> { - for (oid, new_idx) in moves { - { - use crate::schema::entries::dsl::*; - ::diesel::update(entries.filter(id.eq(oid))) - .set(idx.eq(new_idx)) - .execute(dbc)?; - } - } - self.entries = Self::get_entries(self.keyword.id, dbc)?; - Ok(()) - } - - pub fn swap(&mut self, idx_a: usize, idx_b: usize, dbc: &PgConnection) -> Result<(), Error> { - let mut moves = vec![]; - for ent in self.entries.iter() { - if ent.idx == idx_a as i32 { - moves.push((ent.id, idx_b as i32)); - } - if ent.idx == idx_b as i32 { - moves.push((ent.id, idx_a as i32)); - } - } - if moves.len() != 2 { - Err(format_err!("Invalid swap operation."))?; - } - self.process_moves(&moves, dbc)?; - Ok(()) - } - - pub fn update(&mut self, idx: usize, val: &str, dbc: &PgConnection) -> Result<(), Error> { - let ent = self - .entries - .get_mut(idx.saturating_sub(1)) - .ok_or(format_err!("No such element to update."))?; - { - use crate::schema::entries::dsl::*; - ::diesel::update(entries.filter(id.eq(ent.id))) - .set(text.eq(val)) - .execute(dbc)?; - } - ent.text = val.to_string(); - Ok(()) - } - - pub fn delete(&mut self, idx: usize, dbc: &PgConnection) -> Result<(), Error> { - // step 1: delete the element - { - let ent = self - .entries - .get(idx.saturating_sub(1)) - .ok_or(format_err!("No such element to delete."))?; - { - use crate::schema::entries::dsl::*; - ::diesel::delete(entries.filter(id.eq(ent.id))).execute(dbc)?; - } - } - // step 2: move all the elements in front of it back one - let mut moves = vec![]; - for ent in self.entries.iter() { - if idx > ent.idx as _ { - moves.push((ent.id, ent.idx.saturating_sub(1))); - } - } - self.process_moves(&moves, dbc)?; - Ok(()) - } - - pub fn add_zwsp_to_name(name: &str) -> Option<String> { - let second_index = name.char_indices().nth(1).map(|(i, _)| i)?; - let (start, end) = name.split_at(second_index); - Some(format!("{}{}", start, end)) - } - - pub fn format_entry(&self, idx: usize) -> Option<String> { - if let Some(ent) = self.entries.get(idx.saturating_sub(1)) { - let gen_clr = if self.keyword.chan == "*" { - "\x0307" - } else { - "" - }; - let zwsp_name = Self::add_zwsp_to_name(&self.keyword.name) - .unwrap_or_else(|| self.keyword.name.clone()); - Some(format!( - "\x02{}{}\x0f\x0315[{}/{}]\x0f: {} \x0f\x0314[{}]\x0f", - gen_clr, - zwsp_name, - idx, - self.entries.len(), - ent.text, - ent.creation_ts.date() - )) - } else { - None - } - } - - pub fn get_or_create(word: &str, c: &str, dbc: &PgConnection) -> Result<Self, Error> { - if let Some(ret) = Self::get(word, c, dbc)? { - Ok(ret) - } else { - Ok(Self::create(word, c, dbc)?) - } - } - - pub fn create(word: &str, c: &str, dbc: &PgConnection) -> Result<Self, Error> { - let val = NewKeyword { - name: word, - chan: c, - }; - let ret: Keyword = { - use crate::schema::keywords; - ::diesel::insert_into(keywords::table) - .values(val) - .get_result(dbc)? - }; - Ok(KeywordDetails { - keyword: ret, - entries: vec![], - }) - } - - fn get_entries(kid: i32, dbc: &PgConnection) -> Result<Vec<Entry>, Error> { - let entries: Vec<Entry> = { - use crate::schema::entries::dsl::*; - entries - .filter(keyword_id.eq(kid)) - .order_by(idx.asc()) - .load(dbc)? - }; - Ok(entries) - } - - fn get_inner<'a, T: Into<Cow<'a, str>>>( - word: T, - c: &str, - dbc: &PgConnection, - recursion_count: usize, - ) -> Result<Option<Self>, Error> { - let word = word.into(); - let keyword: Option<Keyword> = { - use crate::schema::keywords::dsl::*; - keywords - .filter(name.ilike(word).and(chan.eq(c).or(chan.eq("*")))) - .first(dbc) - .optional()? - }; - if let Some(k) = keyword { - let entries = Self::get_entries(k.id, dbc)?; - if let Some(e0) = entries.get(0) { - if e0.text.starts_with("see: ") { - if recursion_count > RECURSION_LIMIT { - // Oh dear. - Err(format_err!("Halt. You're having a bit too much fun."))? - } - let new_word = e0.text.replace("see: ", ""); - return Self::get_inner(new_word, c, dbc, recursion_count + 1); - } - } - Ok(Some(KeywordDetails { - keyword: k, - entries, - })) - } else { - Ok(None) - } - } - - pub fn get<'a, T: Into<Cow<'a, str>>>( - word: T, - c: &str, - dbc: &PgConnection, - ) -> Result<Option<Self>, Error> { - Self::get_inner(word, c, dbc, 0) - } -} |