Implement newsreader counting
This commit is contained in:
parent
abaaddae3a
commit
9746c9912b
10
server/sql/count.sql
Normal file
10
server/sql/count.sql
Normal file
@ -0,0 +1,10 @@
|
||||
SELECT
|
||||
COUNT(*) count
|
||||
FROM
|
||||
post
|
||||
WHERE
|
||||
site = $1
|
||||
AND (
|
||||
NOT $2
|
||||
OR NOT is_read
|
||||
)
|
||||
@ -1,4 +1,4 @@
|
||||
use std::{str::Utf8Error, string::FromUtf8Error};
|
||||
use std::{convert::Infallible, str::Utf8Error, string::FromUtf8Error};
|
||||
|
||||
use mailparse::MailParseError;
|
||||
use thiserror::Error;
|
||||
@ -27,4 +27,6 @@ pub enum ServerError {
|
||||
FromUtf8Error(#[from] FromUtf8Error),
|
||||
#[error("error")]
|
||||
StringError(String),
|
||||
#[error("impossible")]
|
||||
InfaillibleError(#[from] Infallible),
|
||||
}
|
||||
|
||||
@ -209,7 +209,14 @@ pub struct QueryRoot;
|
||||
impl QueryRoot {
|
||||
async fn count<'ctx>(&self, ctx: &Context<'ctx>, query: String) -> Result<usize, Error> {
|
||||
let nm = ctx.data_unchecked::<Notmuch>();
|
||||
Ok(nm.count(&query)?)
|
||||
let pool = ctx.data_unchecked::<PgPool>();
|
||||
|
||||
// TODO: make this search both copra and merge results
|
||||
if newsreader::is_newsreader_search(&query) {
|
||||
Ok(newsreader::count(pool, &query).await?)
|
||||
} else {
|
||||
Ok(nm::count(nm, &query).await?)
|
||||
}
|
||||
}
|
||||
|
||||
async fn search<'ctx>(
|
||||
|
||||
@ -1,4 +1,8 @@
|
||||
use std::hash::{DefaultHasher, Hash, Hasher};
|
||||
use std::{
|
||||
convert::Infallible,
|
||||
hash::{DefaultHasher, Hash, Hasher},
|
||||
str::FromStr,
|
||||
};
|
||||
|
||||
use async_graphql::connection::{self, Connection, Edge};
|
||||
use log::info;
|
||||
@ -20,6 +24,15 @@ pub fn is_newsreader_thread(query: &str) -> bool {
|
||||
query.starts_with(THREAD_PREFIX)
|
||||
}
|
||||
|
||||
pub async fn count(pool: &PgPool, query: &str) -> Result<usize, ServerError> {
|
||||
let query: Query = query.parse()?;
|
||||
let site = query.site.expect("search has no site");
|
||||
let row = sqlx::query_file!("sql/count.sql", site, query.unread_only)
|
||||
.fetch_one(pool)
|
||||
.await?;
|
||||
Ok(row.count.unwrap_or(0).try_into().unwrap_or(0))
|
||||
}
|
||||
|
||||
pub async fn search(
|
||||
pool: &PgPool,
|
||||
after: Option<String>,
|
||||
@ -28,27 +41,16 @@ pub async fn search(
|
||||
last: Option<i32>,
|
||||
query: String,
|
||||
) -> Result<Connection<usize, ThreadSummary>, async_graphql::Error> {
|
||||
let mut unread_only = false;
|
||||
let mut site = None;
|
||||
let site_prefix = format!("tag:{TAG_PREFIX}");
|
||||
for word in query.split_whitespace() {
|
||||
if word == "is:unread" {
|
||||
unread_only = true
|
||||
};
|
||||
if word.starts_with(&site_prefix) {
|
||||
site = Some(word[site_prefix.len()..].to_string())
|
||||
}
|
||||
}
|
||||
let site = site.expect("search has no site");
|
||||
info!("news search unread_only {unread_only} site {site:?}");
|
||||
let query: Query = query.parse()?;
|
||||
info!("news search query {query:?}");
|
||||
let site = query.site.expect("search has no site");
|
||||
connection::query(
|
||||
after,
|
||||
before,
|
||||
first,
|
||||
last,
|
||||
|after, before, first, last| async move {
|
||||
// TODO: handle `unread_only`
|
||||
let rows = sqlx::query_file!("sql/threads.sql", site)
|
||||
let rows = sqlx::query_file!("sql/threads.sql", site, query.unread_only)
|
||||
.fetch_all(pool)
|
||||
.await?;
|
||||
|
||||
@ -160,3 +162,27 @@ pub async fn thread(pool: &PgPool, thread_id: String) -> Result<Thread, ServerEr
|
||||
}],
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Query {
|
||||
unread_only: bool,
|
||||
site: Option<String>,
|
||||
}
|
||||
|
||||
impl FromStr for Query {
|
||||
type Err = Infallible;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let mut unread_only = false;
|
||||
let mut site = None;
|
||||
let site_prefix = format!("tag:{TAG_PREFIX}");
|
||||
for word in s.split_whitespace() {
|
||||
if word == "is:unread" {
|
||||
unread_only = true
|
||||
};
|
||||
if word.starts_with(&site_prefix) {
|
||||
site = Some(word[site_prefix.len()..].to_string())
|
||||
}
|
||||
}
|
||||
Ok(Query { unread_only, site })
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,6 +41,10 @@ pub fn threadset_to_messages(thread_set: notmuch::ThreadSet) -> Result<Vec<Messa
|
||||
Ok(Vec::new())
|
||||
}
|
||||
|
||||
pub async fn count(nm: &Notmuch, query: &str) -> Result<usize, ServerError> {
|
||||
Ok(nm.count(query)?)
|
||||
}
|
||||
|
||||
pub async fn search(
|
||||
nm: &Notmuch,
|
||||
after: Option<String>,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user