server: more news title/body cleanup, and don't search news so much
This commit is contained in:
@@ -3,14 +3,21 @@ pub mod graphql;
|
||||
pub mod newsreader;
|
||||
pub mod nm;
|
||||
|
||||
use std::{convert::Infallible, str::FromStr};
|
||||
|
||||
use css_inline::{CSSInliner, InlineError, InlineOptions};
|
||||
use linkify::{LinkFinder, LinkKind};
|
||||
use log::error;
|
||||
use lol_html::{element, errors::RewritingError, rewrite_str, RewriteStrSettings};
|
||||
use log::{error, info};
|
||||
use lol_html::{element, errors::RewritingError, rewrite_str, text, RewriteStrSettings};
|
||||
use maplit::{hashmap, hashset};
|
||||
use thiserror::Error;
|
||||
use url::Url;
|
||||
|
||||
use crate::newsreader::{
|
||||
extract_thread_id, is_newsreader_search, is_newsreader_thread, make_news_tag,
|
||||
};
|
||||
const NON_EXISTENT_SITE_NAME: &'static str = "NO-SUCH-SITE";
|
||||
|
||||
// TODO: figure out how to use Cow
|
||||
trait Transformer {
|
||||
fn should_run(&self, _html: &str) -> bool {
|
||||
@@ -46,13 +53,38 @@ struct EscapeHtml;
|
||||
|
||||
impl Transformer for EscapeHtml {
|
||||
fn should_run(&self, html: &str) -> bool {
|
||||
html.starts_with("<")
|
||||
html.contains("&")
|
||||
}
|
||||
fn transform(&self, html: &str) -> Result<String, TransformError> {
|
||||
Ok(html_escape::decode_html_entities(html).to_string())
|
||||
}
|
||||
}
|
||||
|
||||
struct StripHtml;
|
||||
|
||||
impl Transformer for StripHtml {
|
||||
fn should_run(&self, html: &str) -> bool {
|
||||
// Lame test
|
||||
html.contains("<")
|
||||
}
|
||||
fn transform(&self, html: &str) -> Result<String, TransformError> {
|
||||
let mut text = String::new();
|
||||
let element_content_handlers = vec![text!("*", |t| {
|
||||
text += t.as_str();
|
||||
Ok(())
|
||||
})];
|
||||
let _ = rewrite_str(
|
||||
html,
|
||||
RewriteStrSettings {
|
||||
element_content_handlers,
|
||||
..RewriteStrSettings::default()
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok(text)
|
||||
}
|
||||
}
|
||||
|
||||
struct InlineStyle;
|
||||
|
||||
impl Transformer for InlineStyle {
|
||||
@@ -381,3 +413,83 @@ fn compute_offset_limit(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Query {
|
||||
pub unread_only: bool,
|
||||
pub tag: Option<String>,
|
||||
pub uid: Option<String>,
|
||||
pub remainder: Vec<String>,
|
||||
pub is_notmuch: bool,
|
||||
pub is_newsreader: bool,
|
||||
}
|
||||
|
||||
impl Query {
|
||||
// Converts the internal state of Query to something suitable for notmuch queries. Removes and
|
||||
// letterbox specific '<key>:<value' tags
|
||||
fn to_notmuch(&self) -> String {
|
||||
let mut parts = Vec::new();
|
||||
if !self.is_notmuch {
|
||||
return String::new();
|
||||
}
|
||||
|
||||
if self.unread_only {
|
||||
parts.push("is:unread".to_string());
|
||||
}
|
||||
if let Some(site) = &self.tag {
|
||||
parts.push(format!("tag:{site}"));
|
||||
}
|
||||
if let Some(uid) = &self.uid {
|
||||
parts.push(uid.clone());
|
||||
}
|
||||
parts.extend(self.remainder.clone());
|
||||
parts.join(" ")
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Query {
|
||||
type Err = Infallible;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let mut unread_only = false;
|
||||
let mut tag = None;
|
||||
let mut uid = None;
|
||||
let mut remainder = Vec::new();
|
||||
let site_prefix = make_news_tag("");
|
||||
let mut is_notmuch = false;
|
||||
let mut is_newsreader = false;
|
||||
for word in s.split_whitespace() {
|
||||
if word == "is:unread" {
|
||||
unread_only = true
|
||||
} else if word.starts_with("tag:") {
|
||||
tag = Some(word["tag:".len()..].to_string())
|
||||
/*
|
||||
} else if word.starts_with("tag:") {
|
||||
// Any tag that doesn't match site_prefix should explicitly set the site to something not in the
|
||||
// database
|
||||
site = Some(NON_EXISTENT_SITE_NAME.to_string());
|
||||
*/
|
||||
} else if is_newsreader_thread(word) {
|
||||
uid = Some(extract_thread_id(word).to_string())
|
||||
} else if word == "is:mail" || word == "is:email" || word == "is:notmuch" {
|
||||
is_notmuch = true;
|
||||
} else if word == "is:news" || word == "is:newsreader" {
|
||||
is_newsreader = true;
|
||||
} else {
|
||||
remainder.push(word.to_string());
|
||||
}
|
||||
}
|
||||
// If we don't see any explicit filters for a corpus, flip them all on
|
||||
if !(is_notmuch || is_newsreader) {
|
||||
is_newsreader = true;
|
||||
is_notmuch = true;
|
||||
}
|
||||
Ok(Query {
|
||||
unread_only,
|
||||
tag,
|
||||
uid,
|
||||
remainder,
|
||||
is_notmuch,
|
||||
is_newsreader,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user