diff --git a/server/sql/thread.sql b/server/sql/thread.sql new file mode 100644 index 0000000..af4b319 --- /dev/null +++ b/server/sql/thread.sql @@ -0,0 +1,6 @@ +SELECT + * +FROM + post +WHERE + uid = $1 diff --git a/server/src/graphql.rs b/server/src/graphql.rs index df85a3f..9b8e97d 100644 --- a/server/src/graphql.rs +++ b/server/src/graphql.rs @@ -243,13 +243,19 @@ impl QueryRoot { } async fn thread<'ctx>(&self, ctx: &Context<'ctx>, thread_id: String) -> Result { let nm = ctx.data_unchecked::(); + let pool = ctx.data_unchecked::(); let debug_content_tree = ctx .look_ahead() .field("messages") .field("body") .field("contentTree") .exists(); - Ok(nm::thread(nm, thread_id, debug_content_tree).await?) + // TODO: look at thread_id and conditionally load newsreader + if newsreader::is_newsreader_thread(&thread_id) { + Ok(newsreader::thread(pool, thread_id).await?) + } else { + Ok(nm::thread(nm, thread_id, debug_content_tree).await?) + } } } diff --git a/server/src/newsreader.rs b/server/src/newsreader.rs index 5b48763..cec7239 100644 --- a/server/src/newsreader.rs +++ b/server/src/newsreader.rs @@ -5,16 +5,21 @@ use log::info; use sqlx::postgres::PgPool; const TAG_PREFIX: &'static str = "News/"; +const THREAD_PREFIX: &'static str = "news:"; use crate::{ - error, - graphql::{Tag, ThreadSummary}, + error::ServerError, + graphql::{Body, Email, Html, Message, Tag, Thread, ThreadSummary}, }; pub fn is_newsreader_search(query: &str) -> bool { query.contains(TAG_PREFIX) } +pub fn is_newsreader_thread(query: &str) -> bool { + query.starts_with(THREAD_PREFIX) +} + pub async fn search( pool: &PgPool, after: Option, @@ -54,7 +59,7 @@ pub async fn search( vec!["unread".to_string(), site.clone()] }; ThreadSummary { - thread: format!("news:{}", r.uid), + thread: format!("{THREAD_PREFIX}{}", r.uid), timestamp: r .date .expect("post missing date") @@ -84,7 +89,7 @@ pub async fn search( .await } -pub async fn tags(pool: &PgPool, needs_unread: bool) -> Result, error::ServerError> { +pub async fn tags(pool: &PgPool, needs_unread: bool) -> Result, ServerError> { // TODO: write separate query for needs_unread. let tags = sqlx::query_file!("sql/tags.sql").fetch_all(pool).await?; let tags = tags @@ -105,3 +110,53 @@ pub async fn tags(pool: &PgPool, needs_unread: bool) -> Result, error:: .collect(); Ok(tags) } + +pub async fn thread(pool: &PgPool, thread_id: String) -> Result { + let id = thread_id + .strip_prefix(THREAD_PREFIX) + .expect("news thread doesn't start with '{THREAD_PREFIX}'") + .to_string(); + + let r = sqlx::query_file!("sql/thread.sql", id) + .fetch_one(pool) + .await?; + + let site = r.site.unwrap_or("NO SITE".to_string()); + let tags = if r.is_read.unwrap_or(false) { + vec![site.clone()] + } else { + vec!["unread".to_string(), site.clone()] + }; + let body = Body::Html(Html { + html: r.summary.unwrap_or("NO SUMMARY".to_string()), + content_tree: "".to_string(), + }); + let title = r.title.unwrap_or("NO TITLE".to_string()); + let from = Some(Email { + name: Some(site.clone()), + addr: r.link, + }); + Ok(Thread { + thread_id, + subject: title.clone(), + messages: vec![Message { + id, + // TODO: join with feed for pretty site name + from, + to: Vec::new(), + cc: Vec::new(), + subject: Some(title), + timestamp: Some( + r.date + .expect("post missing date") + .assume_utc() + .unix_timestamp(), + ), + headers: Vec::new(), + body, + path: "".to_string(), + attachments: Vec::new(), + tags, + }], + }) +}