diff --git a/Cargo.lock b/Cargo.lock index 9ed9502..7f25dad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -189,6 +189,7 @@ name = "gemention" version = "0.1.0" dependencies = [ "anyhow", + "async-trait", "fluffer", "germ", "thiserror", diff --git a/Cargo.toml b/Cargo.toml index 7258d57..f26c184 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" [dependencies] anyhow = "1.0.81" +async-trait = "0.1.79" fluffer = "4" germ = "0.4" thiserror = "1.0.58" diff --git a/src/comments.rs b/src/comments.rs index f1284b8..75a33c9 100644 --- a/src/comments.rs +++ b/src/comments.rs @@ -5,6 +5,7 @@ use fluffer::Client; // - Make Gemini request to see if target page supports gemention. // - If so, store mention in DB. pub(crate) async fn receive_mention(client: Client) -> String { + // TODO change to return MentionResponse or something like that. let titan = match client.titan { Some(ref titan) => titan, _ => return "".to_string(), diff --git a/src/error.rs b/src/error.rs index e0bf26e..959186e 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,3 +1,5 @@ +use std::str::Utf8Error; + use thiserror::Error; #[derive(Error, Debug)] @@ -8,6 +10,9 @@ pub(crate) enum GementionError { #[error("url parsing error: {0}")] UrlParsingError(#[from] url::ParseError), + #[error("value was not utf8: {0}")] + Utf8Error(#[from] Utf8Error), + #[error("generic error: {0}")] UnclassifiedError(#[from] anyhow::Error), } diff --git a/src/models/mentions.rs b/src/models/mentions.rs new file mode 100644 index 0000000..17d9c2c --- /dev/null +++ b/src/models/mentions.rs @@ -0,0 +1,56 @@ +use async_trait::async_trait; +use fluffer::GemBytes; +use std::fmt::Display; + +use crate::error::GementionError; +pub(crate) enum MentionType { + Reply, + Like, +} + +pub(crate) struct Mention { + mention_type: MentionType, + user: String, + content: Option, +} + +// This is for converting an incoming Titan request into a mention. It +// is very flexible: If the incoming value matches a specific format, +// it'll accurately convert the stringi nto a proper mention. +// Otherwise, it just assumes comment. An error is returned only if +// input is not utf8. +impl TryFrom> for Mention { + type Error = GementionError; + + fn try_from(content: Vec) -> Result { + let content = std::str::from_utf8(&content)?; + Ok(Mention { + mention_type: MentionType::Reply, + user: "".to_string(), + content: None, + }) + } +} + +impl Display for MentionType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Reply => write!(f, "Reply"), + Self::Like => write!(f, "Like"), + } + } +} + +#[async_trait] +impl GemBytes for Mention { + async fn gem_bytes(self) -> Vec { + // TODO change output based on mention type: + // Reply/comment = current format. + // Like = " liked this" + + let headline = format!("## {} from {}", self.mention_type, self.user); + let content = self.content.unwrap_or(String::from("[no content]")); + + format!("20 text/gemini\r\n{}\n\n{}", headline, content).into_bytes() + } +} diff --git a/src/models/mod.rs b/src/models/mod.rs new file mode 100644 index 0000000..c9142f1 --- /dev/null +++ b/src/models/mod.rs @@ -0,0 +1,2 @@ +pub(crate) mod verification; +pub(crate) mod mentions; diff --git a/src/models.rs b/src/models/verification.rs similarity index 100% rename from src/models.rs rename to src/models/verification.rs diff --git a/src/verification/mod.rs b/src/verification/mod.rs index bf4f4b7..b0c915d 100644 --- a/src/verification/mod.rs +++ b/src/verification/mod.rs @@ -4,7 +4,7 @@ use germ::request::request as germ_request; use url::Url; use crate::error::GementionError; -use crate::models::*; +use crate::models::verification::*; const OUR_ENDPOINT: &'static str = "titan://localhost/receive/";