Merge commit 'c14dbac8b26249fd56319259c195c1bf41a75d30'

This commit is contained in:
Mike Dilger 2023-03-28 20:17:17 +13:00
commit 26f5dc3140
8 changed files with 169 additions and 138 deletions

2
Cargo.lock generated
View File

@ -2430,7 +2430,7 @@ dependencies = [
[[package]]
name = "nostr-types"
version = "0.5.0-unstable"
source = "git+https://github.com/mikedilger/nostr-types#a9bb464cb5dfe93b3921ef97249725c415845b00"
source = "git+https://github.com/mikedilger/nostr-types#7ac6a3fb8692f56976ecff1b38a405cb2ef8b820"
dependencies = [
"aes",
"base64 0.21.0",

View File

@ -104,23 +104,15 @@ impl DbEvent {
Some(pk) => pk.into(),
};
let mut kinds = vec![EventKind::TextNote, EventKind::EventDeletion];
if GLOBALS.settings.read().direct_messages {
kinds.push(EventKind::EncryptedDirectMessage);
}
if GLOBALS.settings.read().reposts {
kinds.push(EventKind::Repost);
}
if GLOBALS.settings.read().reactions {
kinds.push(EventKind::Reaction);
}
let kinds: Vec<String> = kinds
let kinds: String = GLOBALS
.settings
.read()
.feed_related_event_kinds()
.iter()
.map(|e| <EventKind as Into<u64>>::into(*e))
.map(|e| e.to_string())
.collect();
let kinds = kinds.join(",");
.collect::<Vec<String>>()
.join(",");
let sql = format!(
"SELECT id, raw, pubkey, created_at, kind, content, ots FROM event \
@ -228,21 +220,96 @@ impl DbEvent {
Ok(())
}
/*
pub async fn delete(criteria: &str) -> Result<(), Error> {
let sql = format!("DELETE FROM event WHERE {}", criteria);
// This is for replaceable (not parameterized!) events only.
// Returns true if it inserted something, false if it didn't have to.
pub async fn replace(event: DbEvent) -> Result<bool, Error> {
// Delete anything older
let sql = "DELETE FROM event WHERE pubkey=? and kind=? and created_at<?".to_owned();
let pubkey: String = event.pubkey.as_str().to_owned();
let kind: u64 = event.kind;
let created_at: u64 = event.created_at as u64;
spawn_blocking(move || {
let maybe_db = GLOBALS.db.blocking_lock();
let db = maybe_db.as_ref().unwrap();
db.execute(&sql, [])?;
db.execute(&sql, (&pubkey, &kind, &created_at))?;
Ok::<(), Error>(())
})
.await??;
Ok(())
// Check if anything remains (which must then be newer)
let sql = "SELECT count(*) FROM event WHERE pubkey=? and kind=?".to_owned();
let pubkey: String = event.pubkey.as_str().to_owned();
let kind: u64 = event.kind;
let count: usize = spawn_blocking(move || {
let maybe_db = GLOBALS.db.blocking_lock();
let db = maybe_db.as_ref().unwrap();
let mut stmt = db.prepare(&sql)?;
stmt.raw_bind_parameter(1, &pubkey)?;
stmt.raw_bind_parameter(2, kind)?;
let mut rows = stmt.raw_query();
if let Some(row) = rows.next()? {
return Ok(row.get(0)?);
}
Ok::<usize, Error>(0)
})
.await??;
// If nothing is newer, save this event
if count == 0 {
Self::insert(event).await?;
Ok(true)
} else {
Ok(false)
}
}
// Returns true if it inserted something, false if it didn't have to.
pub async fn replace_parameterized(event: DbEvent, parameter: String) -> Result<bool, Error> {
// Delete anything older
let sql = "DELETE FROM event WHERE pubkey=? and kind=? and created_at<? and id IN (SELECT event FROM event_tag WHERE event=? and label='d' AND field0=?)".to_owned();
let pubkey: String = event.pubkey.as_str().to_owned();
let kind: u64 = event.kind;
let created_at: u64 = event.created_at as u64;
let id: String = event.id.as_str().to_owned();
let param: String = parameter.clone();
spawn_blocking(move || {
let maybe_db = GLOBALS.db.blocking_lock();
let db = maybe_db.as_ref().unwrap();
db.execute(&sql, (&pubkey, &kind, &created_at, &id, &param))?;
Ok::<(), Error>(())
})
.await??;
// Check if anything remains (which must then be newer)
let sql = "SELECT count(*) FROM event WHERE pubkey=? and kind=? AND id IN (SELECT event FROM event_tag WHERE event=? AND label='d' AND field0=?)".to_owned();
let pubkey: String = event.pubkey.as_str().to_owned();
let kind: u64 = event.kind;
let id: String = event.id.as_str().to_owned();
let param: String = parameter.clone();
let count: usize = spawn_blocking(move || {
let maybe_db = GLOBALS.db.blocking_lock();
let db = maybe_db.as_ref().unwrap();
let mut stmt = db.prepare(&sql)?;
stmt.raw_bind_parameter(1, &pubkey)?;
stmt.raw_bind_parameter(2, kind)?;
stmt.raw_bind_parameter(3, &id)?;
stmt.raw_bind_parameter(4, &param)?;
let mut rows = stmt.raw_query();
if let Some(row) = rows.next()? {
return Ok(row.get(0)?);
}
Ok::<usize, Error>(0)
})
.await??;
// If nothing is newer, save this event
if count == 0 {
Self::insert(event).await?;
Ok(true)
} else {
Ok(false)
}
}
*/
/*
pub async fn get_author(id: IdHex) -> Result<Option<PublicKeyHex>, Error> {

View File

@ -207,14 +207,9 @@ impl Feed {
*self.last_computed.write() = Some(Instant::now());
// Copy some values from settings
let (feed_recompute_interval_ms, reposts, long_form) = {
let settings = GLOBALS.settings.read();
(
settings.feed_recompute_interval_ms,
settings.reposts,
settings.show_long_form,
)
};
let feed_recompute_interval_ms = GLOBALS.settings.read().feed_recompute_interval_ms;
let kinds = GLOBALS.settings.read().feed_related_event_kinds();
// We only need to set this the first time, but has to be after
// settings is loaded (can't be in new()). Doing it every time is
@ -238,12 +233,9 @@ impl Feed {
.iter()
.map(|r| r.value().to_owned())
.filter(|e| e.created_at <= now) // no future events
.filter(|e| {
// feed related
e.kind == EventKind::TextNote
|| (reposts && (e.kind == EventKind::Repost))
|| (long_form && (e.kind == EventKind::LongFormContent))
})
.filter(|e| kinds.contains(&e.kind)) // feed related
.filter(|e| e.kind != EventKind::EncryptedDirectMessage) // except DMs
.filter(|e| !e.kind.augments_feed_related()) // not augmenting another event
.filter(|e| !dismissed.contains(&e.id)) // not dismissed
.filter(|e| {
if !with_replies {
@ -276,13 +268,8 @@ impl Feed {
.events
.iter()
.filter(|e| e.value().created_at <= now) // no future events
.filter(|e| {
// feed related
e.value().kind == EventKind::TextNote
|| e.value().kind == EventKind::EncryptedDirectMessage
|| (reposts && (e.value().kind == EventKind::Repost))
|| (long_form && (e.value().kind == EventKind::LongFormContent))
})
.filter(|e| kinds.contains(&e.kind)) // feed related
.filter(|e| !e.kind.augments_feed_related()) // not augmenting another event
.filter(|e| !dismissed.contains(&e.value().id)) // not dismissed
.filter(|e| e.value().pubkey != my_pubkey) // not self-authored
.filter(|e| {
@ -335,12 +322,8 @@ impl Feed {
let mut events: Vec<(Unixtime, Id)> = GLOBALS
.events
.iter()
.filter(|e| {
e.value().kind == EventKind::TextNote
|| e.value().kind == EventKind::EncryptedDirectMessage
|| (reposts && (e.value().kind == EventKind::Repost))
|| (long_form && (e.value().kind == EventKind::LongFormContent))
})
.filter(|e| kinds.contains(&e.kind)) // feed related
.filter(|e| !e.kind.augments_feed_related()) // not augmenting another event
.filter(|e| e.value().pubkey.as_hex_string() == person_pubkey.as_str())
.filter(|e| !dismissed.contains(&e.value().id)) // not dismissed
.map(|e| (e.value().created_at, e.value().id))

View File

@ -66,21 +66,6 @@ impl Minion {
Some(handle),
)
.await?;
/*
if event.kind == EventKind::TextNote {
// Just store text notes in incoming
GLOBALS
.incoming_events
.write()
.await
.push((*event, self.url.clone(), handle));
} else {
// Process everything else immediately
crate::process::process_new_event(&event, true, Some(self.url.clone()))
.await?;
}
*/
}
}
RelayMessage::Notice(msg) => {

View File

@ -405,9 +405,10 @@ impl Minion {
}
};
// Exclude DMs in general feed.
// Allow textnote, deletion, reaction, repost, and long form (if set in settings)
let event_kinds = Self::event_kinds(&[EventKind::EncryptedDirectMessage]);
// Allow all feed related event kinds
let mut event_kinds = GLOBALS.settings.read().feed_related_event_kinds();
// But exclude DMs in the general feed
event_kinds.retain(|f| *f != EventKind::EncryptedDirectMessage);
if let Some(pubkey) = GLOBALS.signer.public_key() {
// feed related by me
@ -521,7 +522,8 @@ impl Minion {
replies_since.max(one_replieschunk_ago)
};
let event_kinds = Self::event_kinds(&[]);
// Allow all feed related event kinds
let event_kinds = GLOBALS.settings.read().feed_related_event_kinds();
if let Some(pubkey) = GLOBALS.signer.public_key() {
// Any mentions of me
@ -581,9 +583,11 @@ impl Minion {
async fn subscribe_person_feed(&mut self, pubkey: PublicKeyHex) -> Result<(), Error> {
// NOTE we do not unsubscribe to the general feed
// Allow all feed related event kinds
let mut event_kinds = GLOBALS.settings.read().feed_related_event_kinds();
// Exclude DMs and reactions (we wouldn't see the post it reacted to) in person feed
let event_kinds =
Self::event_kinds(&[EventKind::EncryptedDirectMessage, EventKind::Reaction]);
event_kinds
.retain(|f| *f != EventKind::EncryptedDirectMessage && *f != EventKind::Reaction);
let filters: Vec<Filter> = vec![Filter {
authors: vec![pubkey.clone().into()],
@ -665,7 +669,11 @@ impl Minion {
});
}
let event_kinds = Self::event_kinds(&[EventKind::EncryptedDirectMessage]);
// Allow all feed related event kinds
let mut event_kinds = GLOBALS.settings.read().feed_related_event_kinds();
// But exclude DMs
event_kinds.retain(|f| *f != EventKind::EncryptedDirectMessage);
filters.push(Filter {
e: vec![main],
kinds: event_kinds,
@ -942,32 +950,4 @@ impl Minion {
Ok(String::from_utf8_unchecked(full.to_vec()))
}
}
fn event_kinds(exclude: &[EventKind]) -> Vec<EventKind> {
let (reactions, reposts, show_long_form, direct_messages) = {
let settings = GLOBALS.settings.read();
(
settings.reactions,
settings.reposts,
settings.show_long_form,
settings.direct_messages,
)
};
let mut kinds = vec![EventKind::TextNote, EventKind::EventDeletion];
if reactions && !exclude.contains(&EventKind::Reaction) {
kinds.push(EventKind::Reaction);
}
if reposts && !exclude.contains(&EventKind::Repost) {
kinds.push(EventKind::Repost);
}
if show_long_form && !exclude.contains(&EventKind::LongFormContent) {
kinds.push(EventKind::LongFormContent);
}
if direct_messages && !exclude.contains(&EventKind::EncryptedDirectMessage) {
kinds.push(EventKind::EncryptedDirectMessage);
}
kinds
}
}

View File

@ -140,20 +140,19 @@ impl Overlord {
let feed_chunk = GLOBALS.settings.read().feed_chunk;
let then = now.0 - feed_chunk as i64;
let reactions = if GLOBALS.settings.read().reactions {
" OR kind=7"
} else {
""
};
let reposts = if GLOBALS.settings.read().reactions {
" OR kind=6"
} else {
""
};
let where_kind = GLOBALS
.settings
.read()
.feed_related_event_kinds()
.iter()
.map(|e| <EventKind as Into<u64>>::into(*e))
.map(|e| e.to_string())
.collect::<Vec<String>>()
.join(",");
let cond = format!(
" (kind=1 OR kind=5{}{}) AND created_at > {} ORDER BY created_at ASC",
reactions, reposts, then
" kind in ({}) AND created_at > {} ORDER BY created_at ASC",
where_kind, then
);
let db_events = DbEvent::fetch(Some(&cond)).await?;
@ -1170,15 +1169,6 @@ impl Overlord {
// connected to, as well as any relays we discover might know. This is
// more than strictly necessary, but not too expensive.
let (enable_reposts, enable_reactions, show_long_form) = {
let settings = GLOBALS.settings.read();
(
settings.reposts,
settings.reactions,
settings.show_long_form,
)
};
let mut missing_ancestors: Vec<Id> = Vec::new();
// Include the relays where the referenced_by event was seen
@ -1241,10 +1231,13 @@ impl Overlord {
})
.await?;
let mut kinds = vec![EventKind::EventDeletion];
if enable_reactions {
kinds.push(EventKind::Reaction);
}
let kinds = GLOBALS
.settings
.read()
.feed_related_event_kinds()
.drain(..)
.filter(|k| k.augments_feed_related())
.collect();
let e = GLOBALS
.events
@ -1259,16 +1252,8 @@ impl Overlord {
}
}
let mut kinds = vec![EventKind::TextNote, EventKind::EventDeletion];
if enable_reposts {
kinds.push(EventKind::Repost);
}
if enable_reactions {
kinds.push(EventKind::Reaction);
}
if show_long_form {
kinds.push(EventKind::LongFormContent);
}
let mut kinds = GLOBALS.settings.read().feed_related_event_kinds();
kinds.retain(|f| *f != EventKind::EncryptedDirectMessage);
let e = GLOBALS
.events

View File

@ -19,14 +19,14 @@ pub async fn process_new_event(
subscription: Option<String>,
) -> Result<(), Error> {
if GLOBALS.events.get(&event.id).is_some() {
tracing::debug!(
tracing::trace!(
"{}: Old Event: {} {:?} @{}",
seen_on.as_ref().map(|r| r.as_str()).unwrap_or("_"),
subscription.unwrap_or("_".to_string()),
event.kind,
event.created_at
);
// We arleady had this event.
// We already had this event.
return Ok(());
} else {
tracing::debug!(
@ -52,7 +52,20 @@ pub async fn process_new_event(
};
// Save into event table
DbEvent::insert(db_event).await?;
if event.kind.is_replaceable() {
if !DbEvent::replace(db_event).await? {
return Ok(()); // This did not replace anything.
}
} else if event.kind.is_parameterized_replaceable() {
match event.parameter() {
Some(param) => if ! DbEvent::replace_parameterized(db_event, param).await? {
return Ok(()); // This did not replace anything.
},
None => return Err(Error::General("Parameterized event must have a parameter. This is a code issue, not a data issue".to_owned())),
};
} else {
DbEvent::insert(db_event).await?;
}
}
if from_relay {

View File

@ -1,7 +1,7 @@
use crate::error::Error;
use crate::globals::GLOBALS;
use crate::ui::{Theme, ThemeVariant};
use nostr_types::PublicKey;
use nostr_types::{EventKind, PublicKey};
use rusqlite::params;
use serde::{Deserialize, Serialize};
@ -279,4 +279,22 @@ impl Settings {
Ok(())
}
pub fn enabled_event_kinds(&self) -> Vec<EventKind> {
EventKind::iter()
.filter(|k| {
((*k != EventKind::Reaction) || self.reactions)
&& ((*k != EventKind::Repost) || self.reposts)
&& ((*k != EventKind::LongFormContent) || self.show_long_form)
&& ((*k != EventKind::EncryptedDirectMessage) || self.direct_messages)
})
.collect()
}
pub fn feed_related_event_kinds(&self) -> Vec<EventKind> {
self.enabled_event_kinds()
.drain(..)
.filter(|k| k.is_feed_related())
.collect()
}
}