wordle_cli/db/
db_dictionary.rs1use chrono::NaiveDate;
2use diesel::dsl::sql;
3use diesel::{Connection, ExpressionMethods, OptionalExtension, SqliteConnection, QueryDsl, RunQueryDsl};
4use diesel::result::Error;
5
6use crate::db::model::{DbDictionaryEntry, NewDbDictionaryEntry};
7use crate::db::schema::dictionary;
8use crate::dictionary::{Dictionary, DictionaryEntry};
9
10pub struct DbDictionary{
11 conn: SqliteConnection,
12 lang: String
13}
14
15impl DbDictionary {
16 pub fn new(db_url: String, lang: &str) -> DbDictionary {
17 DbDictionary {
18 conn: SqliteConnection::establish(&db_url)
19 .expect(&format!("Error connecting to database {}", db_url)),
20 lang: String::from(lang)
21 }
22 }
23
24 fn update_entry(&self, entry: &DbDictionaryEntry) {
26 match diesel::update(dictionary::dsl::dictionary
27 .filter(dictionary::id.eq(entry.id)))
28 .set((dictionary::used_at.eq(entry.used_at), dictionary::guessed.eq(entry.guessed)))
29 .execute(&self.conn) {
30 Ok(affected_rows) => if affected_rows <= 0 { println!("No rows were affected when updating {}", entry.id) },
31 Err(error) => println!("Error when updating entry with id {}:\n{}", entry.id, error)
32 }
33 }
34
35 fn get_word_of_today(&self, current_day: NaiveDate) -> Result<Option<DbDictionaryEntry>, Error> {
37 match dictionary::dsl::dictionary
38 .filter(dictionary::used_at.eq(current_day))
39 .filter(dictionary::language.eq(&self.lang))
40 .limit(1)
41 .get_result::<DbDictionaryEntry>(&self.conn)
42 .optional() {
43 Err(error) => Err(error),
44 Ok(result) => match result {
45 Some(entry) => Ok(Some(entry)),
46 None => dictionary::dsl::dictionary
47 .filter(dictionary::used_at.is_null())
48 .filter(dictionary::language.eq(&self.lang))
49 .order(sql::<()>("RANDOM()"))
50 .limit(1)
51 .get_result::<DbDictionaryEntry>(&self.conn)
52 .optional()
53 }
54 }
55 }
56}
57
58impl Dictionary for DbDictionary {
59 fn get_random_word(&self) -> Option<DictionaryEntry> {
62 let current_day = chrono::Utc::now();
63 let current_day: NaiveDate = current_day.naive_utc().date();
64
65 match self.get_word_of_today(current_day) {
66 Ok(result) => match result {
67 None => None,
68 Some(mut entry) => {
69 entry.used_at = Some(current_day);
70
71 self.update_entry(&entry);
72 Some(DictionaryEntry{
73 word: entry.word,
74 guessed: entry.guessed
75 })
76 }
77 }
78 Err(error) => {
79 println!("Error when getting today's word.\n{}", error);
80
81 None
82 }
83 }
84 }
85
86 fn find_word(&self, text: &str) -> Option<DictionaryEntry> {
88 let db_result = dictionary::dsl::dictionary
89 .filter(dictionary::word.eq(text))
90 .filter(dictionary::language.eq(&self.lang))
91 .get_result::<DbDictionaryEntry>(&self.conn)
92 .optional();
93
94 match db_result {
95 Ok(db_word) => match db_word {
96 Some(entry) => Some(DictionaryEntry {
97 word: entry.word,
98 guessed: entry.guessed
99 }),
100 None => None
101 },
102 Err(error) => {
103 println!("Error when looking for '{}' in the database:\n{}", text, error);
104
105 None
106 }
107 }
108 }
109
110 fn create_word(&self, word_entry: DictionaryEntry) -> Option<DictionaryEntry> {
112 match self.find_word(&word_entry.word) {
113 None => {
114 let new_word = NewDbDictionaryEntry {
115 word: String::from(&word_entry.word),
116 language: String::from(&self.lang)
117 };
118
119 let db_result = diesel::insert_into(dictionary::table)
120 .values(&new_word)
121 .execute(&self.conn);
122
123 match db_result {
124 Ok(_) => {
125 Some(word_entry)
126 },
127 Err(e) => {
128 println!("Error when writing '{}' to the database:\n{}", &new_word.word, e);
129 None
130 }
131 }
132 },
133 Some (_) => None
134 }
135 }
136
137 fn guessed_word(&self, word_entry: DictionaryEntry) {
139 match diesel::update(dictionary::dsl::dictionary
140 .filter(dictionary::word.eq(word_entry.word)))
141 .filter(dictionary::language.eq(&self.lang))
142 .set(dictionary::guessed.eq(true))
143 .execute(&self.conn) {
144 Ok(_) => {},
145 Err(error) => { println!("Error updating the solution.\n{}", error) }
146 }
147 }
148}