diff --git a/.gitea/issue_template/bug_report.md b/.gitea/issue_template/bug_report.md index c450e3d..1aa97a1 100644 --- a/.gitea/issue_template/bug_report.md +++ b/.gitea/issue_template/bug_report.md @@ -1,6 +1,6 @@ --- -name: "Bug report" -about: "This template is for reporting a bug" +name: "🐛 Bug report" +about: "For reporting bugs" title: "" labels: - "type::bug" diff --git a/.gitea/issue_template/design_discussion.md b/.gitea/issue_template/design_discussion.md index d5a006a..1d68831 100644 --- a/.gitea/issue_template/design_discussion.md +++ b/.gitea/issue_template/design_discussion.md @@ -1,5 +1,5 @@ --- -name: "Design discussion" +name: "🗣 Design discussion" about: "For discussion about the design of features in the application, when there are several possibilities for implementation" title: "" labels: diff --git a/.gitea/issue_template/feature_request.md b/.gitea/issue_template/feature_request.md index 3746dda..3f8a60b 100644 --- a/.gitea/issue_template/feature_request.md +++ b/.gitea/issue_template/feature_request.md @@ -1,6 +1,6 @@ --- -name: "Feature request" -about: "This template is for requesting a new feature" +name: "💡 Feature request" +about: "For requesting a new feature, with an implementation plan" title: "" labels: - "type::enhancement" @@ -11,4 +11,4 @@ labels: *describe what you would like to be able to do, or what solution you would like* -*(optional) additional context, comments or implementation propositions* +*(optional) additional context, comments diff --git a/.gitea/issue_template/question.md b/.gitea/issue_template/question.md index 92d384d..be3c3d3 100644 --- a/.gitea/issue_template/question.md +++ b/.gitea/issue_template/question.md @@ -1,5 +1,5 @@ --- -name: "Ask a question" +name: "❓ Ask a question" about: "If you have a question about the usage of the libraries or the tool" title: "" labels: diff --git a/.gitea/issue_template/refactor.md b/.gitea/issue_template/refactor.md index 6eb7486..e0155dd 100644 --- a/.gitea/issue_template/refactor.md +++ b/.gitea/issue_template/refactor.md @@ -1,5 +1,5 @@ --- -name: "Refactor" +name: "🚧 Refactor" about: "For refactoring propositions" title: "" labels: diff --git a/crieur-chatbot/src/chatbot.rs b/crieur-chatbot/src/chatbot.rs index cad6b1c..4052944 100644 --- a/crieur-chatbot/src/chatbot.rs +++ b/crieur-chatbot/src/chatbot.rs @@ -46,18 +46,18 @@ impl Builder { user: &impl AsRef, password: &impl AsRef, ) -> &mut Self { - self.user = String::from(user.as_ref()); - self.password = String::from(password.as_ref()); + self.user = user.as_ref().into(); + self.password = password.as_ref().into(); self } pub(crate) fn homeserver(&mut self, homeserver: &impl AsRef) -> &mut Self { - self.homeserver = String::from(homeserver.as_ref()); + self.homeserver = homeserver.as_ref().into(); self } pub(crate) fn room(&mut self, room: &impl AsRef) -> &mut Self { - self.room = String::from(room.as_ref()); + self.room = room.as_ref().into(); self } } diff --git a/crieur-chatbot/src/handlers/html.rs b/crieur-chatbot/src/handlers/html.rs index 5cad197..a8a0f83 100644 --- a/crieur-chatbot/src/handlers/html.rs +++ b/crieur-chatbot/src/handlers/html.rs @@ -1,8 +1,7 @@ use std::convert::TryInto; use std::env; -use anyhow::Result; -use log::info; +use log::{error, info}; use matrix_sdk::{ self, async_trait, events::{ @@ -13,7 +12,7 @@ use matrix_sdk::{ Client, ClientConfig, EventHandler, SyncSettings, }; -use crieur_retrieve::{ArticleLocation, Url}; +use crieur_retrieve::{article_location::Error, article_location::Result, ArticleLocation, Url}; pub(crate) struct Html {} @@ -48,12 +47,43 @@ where //TODO: replace occurences ok() by async and logging block when async block is stable let article_html = match article_html(url).await { Ok(url) => url, - Err(_) => { - room.send(text_message("Can't download the file"), None) + Err(Error::MalformedUrl) => { + room.send(text_message("Error: Given url is malformed"), None) .await .ok(); return; } + Err(Error::UnknownNewspaper) => { + room.send( + text_message("Error: Given url is do not correspond to a known newspaper"), + None, + ) + .await + .ok(); + return; + } + Err(Error::Misconfiguration(key)) => { + error!( + "Error in configuration : {} key is missing or malformed", + &key + ); + room.send( + text_message("Error: configuration error, please contact your admin"), + None, + ) + .await + .ok(); + return; + } + Err(_) => { + room.send( + text_message("Unknown error =/, can't download the file"), + None, + ) + .await + .ok(); + return; + } }; room.send_attachment( diff --git a/crieur-retrieve/src/article_location.rs b/crieur-retrieve/src/article_location.rs index 1cd6178..d6a177a 100644 --- a/crieur-retrieve/src/article_location.rs +++ b/crieur-retrieve/src/article_location.rs @@ -2,17 +2,42 @@ use std::boxed::Box; use std::convert::TryInto; use std::env; -use anyhow::{anyhow, Result}; +use anyhow::anyhow; use log::info; use url::{Host, Url}; use crate::newspaper::Newspaper; use crate::newspapers::mediapart::{self, Mediapart}; +/// Enumerate all errors that can be encountered when using ArticleLocation +#[derive(thiserror::Error, Debug)] +pub enum Error { + /// The url was not set. Therefore, the article location can't be deduced + #[error("No url set")] + NoUrl, + /// The given URL isn't an accepted Url + #[error("Malformed URL")] + MalformedUrl, + /// The given url doesn't correspond to a newspaper. + #[error("The given url doesn't link to a known newspaper")] + UnknownNewspaper, + /// Error in configuration : used for missing or malformed configuration + #[error("Error in configuration (configuration key {0} malformed or missing)")] + Misconfiguration(String), + /// Other errors + #[error(transparent)] + Other(#[from] anyhow::Error), +} + type Newspapers = Vec>; +pub type Result = core::result::Result; fn default_newpapers() -> Result { - let mpruiid = env::var("MEDIAPART_COOKIE")?.into(); + let config_key = "MEDIAPART_COOKIE".to_string(); + let mpruiid = env::var(&config_key) + .map_err(|_| Error::Misconfiguration(config_key))? + .into(); + let mediapart = Mediapart::builder() .login(mediapart::Login::MPRUUID(mpruiid)) .build()?; @@ -36,13 +61,12 @@ impl Builder { /// # Errors /// /// An error is returned if the could not be converted into an url - // TODO: move this to a defined error, remove anyhow ! pub fn url(mut self, url: U) -> Result where U: TryInto + Send, E: std::error::Error + Sync + Send + 'static, { - let url = url.try_into()?; + let url = url.try_into().map_err(|_| Error::MalformedUrl)?; self.url = Some(url); Ok(self) } @@ -60,18 +84,13 @@ impl Builder { } /// Adds several newspapers to the list of accepted newspapers - //fn newspapers(&mut self, newspapers: Newspapers) -> Result<&mut Self> { - // let newspapers = match &self.newspapers { - // Some(current_newspapers) => newspapers - // .iter() - // .chain(current_newspapers.iter()) - // .map(|s| *(s.clone())) - // .collect::(), - // None => newspapers.into_iter().collect::>(), - // }; - // self.newspapers = Some(newspapers); - // Ok(self) - //} + pub fn newspapers(mut self, newspapers: Newspapers) -> Self { + match &mut self.newspapers { + Some(current_newspapers) => current_newspapers.extend(newspapers), + None => self.newspapers = Some(newspapers.into_iter().collect::>()), + }; + self + } /// Builds the ArticleLocation by looking which newspaper /// @@ -82,19 +101,16 @@ impl Builder { /// - no newpspaper is given /// - the url is not set /// - the given url has no host - // TODO: move this to a defined error, remove anyhow ! pub fn build(self) -> Result { - let url = Clone::clone(self.url.as_ref().ok_or(anyhow!( - "No url set. You can set it with the url() function" - ))?); - let host = url.host_str().ok_or(anyhow!("Given url has no host"))?; - let host = Host::parse(host)?; + let url = Clone::clone(self.url.as_ref().ok_or(Error::NoUrl)?); + let host = url.host_str().ok_or(Error::MalformedUrl)?; + let host = Host::parse(host).map_err(|_| Error::MalformedUrl)?; let newspaper = self .newspapers .unwrap_or(default_newpapers()?) .into_iter() .find(|c| c.metadata().hosts.contains(&host)) - .ok_or(anyhow!("Newspaper couldn't be found"))?; + .ok_or(Error::UnknownNewspaper)?; Ok(ArticleLocation { newspaper, url }) } } @@ -111,6 +127,7 @@ impl ArticleLocation { pub async fn retrieve_html(&self) -> Result { info!("It will download from {}", self.url); - self.newspaper.retrieve_html(&self.url).await + // TODO: modify when retrieve_html returns a specific Error type + Ok(self.newspaper.retrieve_html(&self.url).await?) } } diff --git a/crieur-retrieve/src/lib.rs b/crieur-retrieve/src/lib.rs index 31dc3a8..a9f783d 100644 --- a/crieur-retrieve/src/lib.rs +++ b/crieur-retrieve/src/lib.rs @@ -10,7 +10,7 @@ pub mod newspaper; // TODO: move to another crate pub mod newspapers; -mod article_location; +pub mod article_location; pub use article_location::ArticleLocation; mod consts; diff --git a/src/bin/crieur-chatbot.rs b/src/bin/crieur-chatbot.rs index d0179be..ab4853e 100644 --- a/src/bin/crieur-chatbot.rs +++ b/src/bin/crieur-chatbot.rs @@ -4,6 +4,7 @@ use dotenv::dotenv; #[tokio::main] async fn main() -> Result<()> { + env_logger::init(); dotenv().ok(); run().await?; Ok(())