mirror of
https://github.com/mikedilger/gossip.git
synced 2024-09-29 16:31:18 +00:00
Merge commit 'c14dbac8b26249fd56319259c195c1bf41a75d30'
This commit is contained in:
commit
26f5dc3140
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -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",
|
||||
|
109
src/db/event.rs
109
src/db/event.rs
@ -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, ¶m))?;
|
||||
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, ¶m)?;
|
||||
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> {
|
||||
|
37
src/feed.rs
37
src/feed.rs
@ -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))
|
||||
|
@ -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) => {
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user