commit dbe5fd72c2d972c018d7784ba7669b25e40fd81d
parent 1880a8594d24dc8bc630a20cd5acea2da7dcb1f0
Author: devnibo <kroekerrobin@gmail.com>
Date: Tue, 19 Sep 2023 14:36:41 +0200
Refactor and improve /report response msgs
Diffstat:
| A | src/i18n.rs | | | 139 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| D | src/langs.rs | | | 109 | ------------------------------------------------------------------------------- |
| M | src/main.rs | | | 119 | ++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------- |
3 files changed, 215 insertions(+), 152 deletions(-)
diff --git a/src/i18n.rs b/src/i18n.rs
@@ -0,0 +1,139 @@
+use std::fs;
+
+#[derive(Clone)]
+pub struct ReportMsgs {
+ pub msg: String,
+ pub error_msg: String,
+ pub success_msg: String,
+ pub cancel_msg: String
+}
+
+#[derive(Clone)]
+pub struct I18n {
+ lang: String,
+ pub start_msg: String,
+ pub song_not_found: String,
+ pub report: ReportMsgs
+}
+
+impl I18n {
+ pub fn new(lang: String, songs_path: String) -> Self {
+ match lang.as_str() {
+ "de" => {
+ Self {
+ lang,
+ start_msg: String::from(format!(
+ "Hallo. Dies ist ein digitales Liederbuch. :)\n\
+ Befehle:\n\
+ /list - Listet alle Lieder auf\n\
+ {}\
+ Ansonsten tippe einfach den Titel oder Teile des Titels \
+ des Liedes ein und du bekommst dein Lied zugeschickt.",
+ get_commands(songs_path).as_str()
+ )),
+ song_not_found: String::from("Kein Lied mit diesem Titel gefunden."),
+ report: ReportMsgs{
+ msg: String::from("Bitte sende einen gefundenen Fehler \
+ entweder als Text oder Sprachnachricht."),
+ error_msg: String::from("Das hat nicht funktioniert. Versuche es nochmal oder /cancel."),
+ success_msg: String::from("Deine Korrektur wurde erfolgreich gemeldet."),
+ cancel_msg: String::from("Das Fehlermelden wurde abgebrochen.")
+ }
+ }
+ },
+ "md" => {
+ Self {
+ lang,
+ start_msg: String::from(format!(
+ "Salut! Această e o carte de cântari digitală. :)\n\
+ Comenzi:\n\
+ /list - Listează toate cântările\n\
+ {}\
+ Deasemenea puteți introduce titlul sau cuvinte din titlul \
+ cântării iar bot-ul va găsi piesa corespondentă.",
+ get_commands(songs_path).as_str()
+ )),
+ song_not_found: String::from("Niciun cântec găsit cu acest nume"),
+ report: ReportMsgs{
+ msg: String::from("Vă rugăm să trimiteți eroare pe care \
+ ați găsit-o fie ca mesaj text sau vocal."),
+ error_msg: String::from("Asta nu a mers. Încercați din nou sau /cancel"),
+ success_msg: String::from("A raportat corect corectia."),
+ cancel_msg: String::from("Raportarea a fost anulată.")
+ }
+ }
+ },
+ _ => {
+ Self {
+ lang,
+ start_msg: String::from(format!(
+ "Hello. This is a digital song book. :)\n\
+ Commands:\n\
+ /list - Lists all songs\n\
+ {}\
+ Otherwise simply type the title or parts of the title \
+ of the song and you will receive the song.",
+ get_commands(songs_path).as_str()
+ )),
+ song_not_found: String::from("Didn't find any song with this title."),
+ report: ReportMsgs{
+ msg: String::from("Please send an error you found \
+ either as text or voice message."),
+ error_msg: String::from("That didn't work. Try again or /cancel."),
+ success_msg: String::from("Successfully reported your correction."),
+ cancel_msg: String::from("Reporting canceled.")
+ }
+ }
+ }
+ }
+ }
+ pub fn format(&self, name: &String) -> String {
+ let mut formatted_name = name.to_string();
+ match self.lang.as_str() {
+ "de" => {
+ formatted_name = formatted_name.replace("Ö", "Oe");
+ formatted_name = formatted_name.replace("ö", "oe");
+ formatted_name = formatted_name.replace("Ü", "Ue");
+ formatted_name = formatted_name.replace("ü", "ue");
+ formatted_name = formatted_name.replace("Ä", "Ae");
+ formatted_name = formatted_name.replace("ä", "ae");
+ formatted_name = formatted_name.replace("ß", "ss");
+ },
+ "md" => {
+ formatted_name = formatted_name.replace("ă", "a");
+ formatted_name = formatted_name.replace("â", "a");
+ formatted_name = formatted_name.replace("î", "i");
+ formatted_name = formatted_name.replace("ș", "s");
+ formatted_name = formatted_name.replace("ț", "t");
+ },
+ _ => {}
+ }
+ formatted_name = formatted_name.replace("-", "_");
+ formatted_name = formatted_name.replace(" ", "_");
+ return formatted_name;
+ }
+}
+
+fn get_commands(songs_path: String) -> String {
+ let mut commands: String = String::new();
+ for name in get_folder_names(&songs_path) {
+ commands.push_str(&("/".to_owned() + name.as_str() + "\n"));
+ }
+ return commands;
+}
+
+pub fn get_folder_names(songs_path: &String) -> Vec<String> {
+ let songs_dir = fs::read_dir(songs_path).unwrap();
+ let mut folder_names: Vec<String> = vec![];
+ let mut is_dir: bool;
+ let mut dir_entry;
+ for f in songs_dir {
+ dir_entry = f.expect("Error: f");
+ is_dir = dir_entry.file_type().unwrap().is_dir();
+ if is_dir {
+ let name: String = dir_entry.file_name().to_str().unwrap().to_string();
+ folder_names.push(name)
+ }
+ }
+ return folder_names;
+}
diff --git a/src/langs.rs b/src/langs.rs
@@ -1,109 +0,0 @@
-use std::{str, fs};
-
-#[derive(Clone)]
-pub struct Strings {
- lang: String,
- pub start_msg: String,
- pub song_not_found: String
-}
-
-impl Strings {
- pub fn new(lang: String, songs_path: String) -> Self {
- let start_msg: String;
- let song_not_found: String;
- let l: &str = lang.as_str();
- match l {
- "de" => {
- start_msg = String::from(format!(
- "Hallo. Dies ist ein digitales Liederbuch. :)\n\
- Befehle:\n\
- /list - Listet alle Lieder auf\n\
- {}\
- Ansonsten tippe einfach den Titel oder Teile des Titels \
- des Liedes ein und du bekommst dein Lied zugeschickt.",
- get_commands(songs_path).as_str()
- ));
- song_not_found = String::from("Kein Lied mit diesem Titel gefunden.");
- },
- "md" => {
- start_msg = String::from(format!(
- "Salut! Această e o carte de cântari digitală. :)\n\
- Comenzi:\n\
- /list - Listează toate cântările\n\
- {}\
- Deasemenea puteți introduce titlul sau cuvinte din titlul \
- cântării iar bot-ul va găsi piesa corespondentă.",
- get_commands(songs_path).as_str()
- ));
- song_not_found = String::from("Niciun cântec găsit cu acest nume");
- },
- _ => {
- start_msg = String::from(format!(
- "Hello. This is a digital song book. :)\n\
- Commands:\n\
- /list - Lists all songs\n\
- {}\
- Otherwise simply type the title or parts of the title \
- of the song and you will receive the song.",
- get_commands(songs_path).as_str()
- ));
- song_not_found = String::from("Didn't find any song with this title.");
- }
- }
- Self {
- lang: lang,
- start_msg: start_msg,
- song_not_found: song_not_found
- }
- }
- pub fn format(&self, name: &String) -> String {
- let mut formatted_name = name.to_string();
- let l: &str = self.lang.as_str();
- match l {
- "de" => {
- formatted_name = formatted_name.replace("Ö", "Oe");
- formatted_name = formatted_name.replace("ö", "oe");
- formatted_name = formatted_name.replace("Ü", "Ue");
- formatted_name = formatted_name.replace("ü", "ue");
- formatted_name = formatted_name.replace("Ä", "Ae");
- formatted_name = formatted_name.replace("ä", "ae");
- formatted_name = formatted_name.replace("ß", "ss");
- },
- "md" => {
- formatted_name = formatted_name.replace("ă", "a");
- formatted_name = formatted_name.replace("â", "a");
- formatted_name = formatted_name.replace("î", "i");
- formatted_name = formatted_name.replace("ș", "s");
- formatted_name = formatted_name.replace("ț", "t");
- },
- _ => {}
- }
- formatted_name = formatted_name.replace("-", "_");
- formatted_name = formatted_name.replace(" ", "_");
- return formatted_name;
- }
-}
-
-fn get_commands(songs_path: String) -> String {
- let mut commands: String = String::new();
- for name in get_folder_names(&songs_path) {
- commands.push_str(&("/".to_owned() + name.as_str() + "\n"));
- }
- return commands;
-}
-
-pub fn get_folder_names(songs_path: &String) -> Vec<String> {
- let songs_dir = fs::read_dir(songs_path).unwrap();
- let mut folder_names: Vec<String> = vec![];
- let mut is_dir: bool;
- let mut dir_entry;
- for f in songs_dir {
- dir_entry = f.expect("Error: f");
- is_dir = dir_entry.file_type().unwrap().is_dir();
- if is_dir {
- let name: String = dir_entry.file_name().to_str().unwrap().to_string();
- folder_names.push(name)
- }
- }
- return folder_names;
-}
diff --git a/src/main.rs b/src/main.rs
@@ -15,8 +15,8 @@ use std::fs::DirEntry;
use std::{fs, thread, time};
use std::io::Write;
use bytes::Bytes;
-
-mod langs;
+mod i18n;
+use i18n::I18n;
/*
* 4096 is the max character length
@@ -27,7 +27,7 @@ mod langs;
*/
const MAX_TEXT_LEN: usize = 4096;
-struct ErrNotFound {
+struct SongNotFound {
message: String
}
@@ -45,14 +45,20 @@ struct Args {
reports_path: Option<String>
}
-struct IncomingTextMsg {
+struct HandleArg {
api: Api,
msg: Option<Message>,
- strings: langs::Strings,
+ token: String,
+ reports_path: Option<String>,
+ i18n: I18n,
songs_path: String,
search_file: Option<String>
}
+struct HandleResult {
+ wait_for_report: bool
+}
+
enum OutgoingTextMsg {
DirEntry(Vec<DirEntry>),
String(Vec<String>)
@@ -60,7 +66,7 @@ enum OutgoingTextMsg {
struct FindSongArgs {
songs_path: String,
- strings: langs::Strings,
+ i18n: I18n,
search_string: String,
search_type: SearchType,
search_file: String
@@ -77,11 +83,7 @@ struct SearchResult {
ss_in_lyrics: Vec<String>
}
-struct HandleResult {
- wait_for_report: bool
-}
-
-enum FileType {
+enum ReportFileType {
Voice(Bytes),
Text(String)
}
@@ -91,10 +93,12 @@ fn main() {
let api = Api::new(&args.token.as_str());
let is_reports_path = args.reports_path.is_some();
let songs_path: String = add_ending_slash(args.songs_path);
- let mut incoming_text_msg = IncomingTextMsg {
+ let mut handle_arg = HandleArg {
api: api.clone(),
msg: None,
- strings: langs::Strings::new(args.lang, songs_path.clone()),
+ token: args.token.clone(),
+ reports_path: args.reports_path.clone(),
+ i18n: I18n::new(args.lang, songs_path.clone()),
songs_path: songs_path.clone(),
search_file: args.search_file.clone()
};
@@ -113,16 +117,16 @@ fn main() {
updates_params.offset = Some(i64::from(update.update_id) + 1);
match &update.content {
UpdateContent::Message(msg) => {
+ handle_arg.msg = Some(msg.clone());
if is_reports_path && res.wait_for_report {
- handle_res = handle_report(&api, &msg, &args.token, &args.reports_path.as_ref().unwrap());
+ handle_res = handle_report(&handle_arg);
if handle_res.is_some() {
res = handle_res.unwrap();
}
continue;
}
if msg.text.is_some() {
- incoming_text_msg.msg = Some(msg.clone());
- handle_res = handle_text_message(&incoming_text_msg);
+ handle_res = handle_text_message(&handle_arg);
if handle_res.is_some() {
res = handle_res.unwrap();
}
@@ -150,11 +154,11 @@ fn add_ending_slash(path: String) -> String {
}
}
-fn handle_text_message(args: &IncomingTextMsg) -> Option<HandleResult> {
+fn handle_text_message(args: &HandleArg) -> Option<HandleResult> {
let mut find_song_args = FindSongArgs {
search_string: String::new(),
songs_path: args.songs_path.clone(),
- strings: args.strings.clone(),
+ i18n: args.i18n.clone(),
search_type: SearchType::Title,
search_file: String::new()
};
@@ -174,7 +178,7 @@ fn handle_text_message(args: &IncomingTextMsg) -> Option<HandleResult> {
.build();
match text {
"/start" => {
- params.text = (args.strings.start_msg).to_string();
+ params.text = (args.i18n.start_msg).to_string();
send_message(&args.api, &mut params);
},
"/list" => {
@@ -183,13 +187,13 @@ fn handle_text_message(args: &IncomingTextMsg) -> Option<HandleResult> {
send_message(&args.api, &mut params);
},
"/report" => {
- params.text = String::from("Please send an error you found.");
+ params.text = args.i18n.report.msg.clone();
send_message(&args.api, &mut params);
return Some(HandleResult{ wait_for_report: true });
},
_ => {
if text.starts_with("/") {
- for name in langs::get_folder_names(&args.songs_path) {
+ for name in i18n::get_folder_names(&args.songs_path) {
if text == "/".to_owned() + name.as_str() {
let songs = get_songs(&args.songs_path, Some(&name));
params.text = form_msg(OutgoingTextMsg::DirEntry(songs));
@@ -213,7 +217,7 @@ fn handle_text_message(args: &IncomingTextMsg) -> Option<HandleResult> {
},
Err(err) => {
println!("{}", err.message);
- params.text = (args.strings.song_not_found).to_string();
+ params.text = (args.i18n.song_not_found).to_string();
send_message(&args.api, &mut params);
}
}
@@ -229,7 +233,7 @@ fn handle_text_message(args: &IncomingTextMsg) -> Option<HandleResult> {
},
Err(err) => {
println!("{}", err.message);
- params.text = (args.strings.song_not_found).to_string();
+ params.text = (args.i18n.song_not_found).to_string();
send_message(&args.api, &mut params);
}
}
@@ -245,7 +249,7 @@ fn handle_text_message(args: &IncomingTextMsg) -> Option<HandleResult> {
},
Err(err) => {
println!("{}", err.message);
- params.text = (args.strings.song_not_found).to_string();
+ params.text = (args.i18n.song_not_found).to_string();
send_message(&args.api, &mut params);
}
}
@@ -257,38 +261,60 @@ fn handle_text_message(args: &IncomingTextMsg) -> Option<HandleResult> {
return None;
}
-fn handle_report(api: &Api, msg: &Message, token: &String, reports_path: &String) -> Option<HandleResult> {
+fn handle_report(args: &HandleArg) -> Option<HandleResult> {
+ let msg = args.msg.clone().unwrap();
+ let reports_path = args.reports_path.clone().unwrap();
+ let chat_id: u64 = msg.from.as_ref().unwrap().id;
+ let mut params = SendMessageParams::builder()
+ .chat_id(ChatId::Integer(chat_id.try_into().unwrap()))
+ .text("")
+ .build();
if msg.voice.is_some() {
let voice = msg.voice.clone().unwrap();
- match api.get_file(&GetFileParams{ file_id: voice.file_id }) {
+ match args.api.get_file(&GetFileParams{ file_id: voice.file_id }) {
Ok(file) => {
let file_path = file.result.file_path.unwrap();
- match download_file(token, &file_path) {
- Ok(bytes) => save_file(FileType::Voice(bytes), reports_path),
+ match download_file(&args.token, &file_path) {
+ Ok(bytes) => save_file(ReportFileType::Voice(bytes), &reports_path),
Err(_) => {}
}
},
Err(_) => {}
}
+ params.text = args.i18n.report.success_msg.clone();
+ send_message(&args.api, &mut params);
+ return Some(HandleResult{ wait_for_report: false });
}
else if msg.text.is_some() {
let text = msg.text.clone().unwrap();
- save_file(FileType::Text(text), reports_path);
+ if text == String::from("/cancel") {
+ params.text = String::from(args.i18n.report.cancel_msg.clone());
+ send_message(&args.api, &mut params);
+ return Some(HandleResult{ wait_for_report: false });
+ }
+ params.text = args.i18n.report.success_msg.clone();
+ send_message(&args.api, &mut params);
+ save_file(ReportFileType::Text(text), &reports_path);
+ return Some(HandleResult{ wait_for_report: false });
+ }
+ else {
+ params.text = args.i18n.report.error_msg.clone();
+ send_message(&args.api, &mut params);
+ return Some(HandleResult{ wait_for_report: true });
}
- return Some(HandleResult{ wait_for_report: false });
}
fn download_file(token: &String, file_path: &String) -> Result<Bytes, reqwest::Error> {
- let url = format!("https://api.telegram.org/file/bot{}/{}", token, file_path);
+ let url = format!("https://api.telegram.org/file/bot{token}/{file_path}");
let bytes = reqwest::blocking::get(url)?.bytes()?;
return Ok(bytes);
}
-fn save_file(t: FileType, reports_path: &String) {
+fn save_file(t: ReportFileType, reports_path: &String) {
let timestamp = chrono::offset::Utc::now().timestamp_millis();
let filepath = reports_path.to_owned() + "/" + ×tamp.to_string();
match t {
- FileType::Voice(bytes) => {
+ ReportFileType::Voice(bytes) => {
match fs::File::create(filepath + ".ogg") {
Ok(mut file) => {
let _res = file.write(&bytes);
@@ -296,7 +322,7 @@ fn save_file(t: FileType, reports_path: &String) {
Err(_) => {}
}
},
- FileType::Text(mut text) => {
+ ReportFileType::Text(mut text) => {
match fs::File::create(filepath + ".txt") {
Ok(mut file) => {
text = text + "\n";
@@ -417,16 +443,17 @@ fn form_msg(songs: OutgoingTextMsg) -> String {
return message;
}
-fn title_search(args: &FindSongArgs) -> Result<Vec<DirEntry>, ErrNotFound> {
+fn title_search(args: &FindSongArgs) -> Result<Vec<DirEntry>, SongNotFound> {
let mut result: Vec<DirEntry> = vec![];
let mut filename: String;
- let ss = args.strings.format(&args.search_string).to_lowercase();
+ let ss = args.i18n.format(&args.search_string).to_lowercase();
for file in get_songs(&args.songs_path, None) {
filename = file.file_name().to_str().unwrap().to_string();
let f: Vec<&str> = filename.split(".").collect();
let mut name: String = f.get(0).unwrap().to_string();
name = name.to_lowercase();
- if name == ss {
+ if name.starts_with(&ss) {
+ // move found song to the beginning
let mut one = vec![file];
one.append(&mut result);
result = one;
@@ -437,21 +464,27 @@ fn title_search(args: &FindSongArgs) -> Result<Vec<DirEntry>, ErrNotFound> {
if result.len() > 0 {
return Ok(result);
} else {
- return Err(ErrNotFound { message: String::from("Didn't find any song.") });
+ return Err(SongNotFound { message: String::from("Didn't find any song.") });
}
}
-fn full_text_search(args: &FindSongArgs) -> Result<SearchResult, ErrNotFound> {
+fn full_text_search(args: &FindSongArgs) -> Result<SearchResult, SongNotFound> {
let mut ss_in_title: Vec<String> = vec![];
let mut ss_in_lyrics: Vec<String> = vec![];
- let ss = prepare_for_search(&args.search_string);
+ let ss = prepare_for_fulltext_search(&args.search_string);
let content = fs::read_to_string(&args.search_file).unwrap();
for line in content.lines() {
let s_line: Vec<&str> = line.split(':').collect();
let name = s_line.get(0).unwrap();
let song_title = s_line.get(1).unwrap();
let song_lyrics = s_line.get(2).unwrap();
- if song_title.contains(&ss) {
+ if song_title.starts_with(&ss) {
+ // move found song to the beginning
+ let mut temp = vec![name.to_string()];
+ temp.append(&mut ss_in_title);
+ ss_in_title = temp;
+ }
+ else if song_title.contains(&ss) {
ss_in_title.push(name.to_string());
}
else if song_lyrics.contains(&ss) {
@@ -459,13 +492,13 @@ fn full_text_search(args: &FindSongArgs) -> Result<SearchResult, ErrNotFound> {
}
}
if ss_in_title.len() == 0 && ss_in_lyrics.len() == 0 {
- return Err(ErrNotFound { message: String::from("Didn't find any song.") });
+ return Err(SongNotFound { message: String::from("Didn't find any song.") });
} else {
return Ok(SearchResult { ss_in_title, ss_in_lyrics });
}
}
-fn prepare_for_search(string: &String) -> String {
+fn prepare_for_fulltext_search(string: &String) -> String {
let mut res = String::new();
// let mut is_last_line_break = false;
for c in string.chars() {