mirror of
https://github.com/mikedilger/gossip.git
synced 2024-09-30 00:41:42 +00:00
Events::get_local_events_by_filter()
This commit is contained in:
parent
e8ac8d4d5f
commit
80f03a57fe
123
src/events.rs
123
src/events.rs
@ -2,7 +2,8 @@ use crate::error::Error;
|
|||||||
use crate::globals::GLOBALS;
|
use crate::globals::GLOBALS;
|
||||||
use async_recursion::async_recursion;
|
use async_recursion::async_recursion;
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use nostr_types::{Event, Id};
|
use nostr_types::{Event, Filter, Id};
|
||||||
|
use std::fmt::Display;
|
||||||
use tokio::task;
|
use tokio::task;
|
||||||
|
|
||||||
pub struct Events {
|
pub struct Events {
|
||||||
@ -30,7 +31,7 @@ impl Events {
|
|||||||
self.events.get(id).map(|e| e.value().to_owned())
|
self.events.get(id).map(|e| e.value().to_owned())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the event from memory, and also try the database
|
/// Get the event from memory, and also try the database, by Id
|
||||||
pub async fn get_local(&self, id: Id) -> Result<Option<Event>, Error> {
|
pub async fn get_local(&self, id: Id) -> Result<Option<Event>, Error> {
|
||||||
if let Some(e) = self.get(&id) {
|
if let Some(e) = self.get(&id) {
|
||||||
return Ok(Some(e));
|
return Ok(Some(e));
|
||||||
@ -61,6 +62,92 @@ impl Events {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get event from database, by Filter
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub async fn get_local_events_by_filter(&self, filter: Filter) -> Result<Vec<Event>, Error> {
|
||||||
|
let mut conditions: Vec<String> = Vec::new();
|
||||||
|
if !filter.ids.is_empty() {
|
||||||
|
conditions.push(build_prefix_condition("id", &filter.ids));
|
||||||
|
}
|
||||||
|
if !filter.authors.is_empty() {
|
||||||
|
conditions.push(build_prefix_condition("pubkey", &filter.authors));
|
||||||
|
}
|
||||||
|
if !filter.kinds.is_empty() {
|
||||||
|
let mut c = "kind in (".to_owned();
|
||||||
|
let mut virgin = true;
|
||||||
|
for kind in filter.kinds.iter() {
|
||||||
|
if !virgin {
|
||||||
|
c.push(',');
|
||||||
|
}
|
||||||
|
virgin = false;
|
||||||
|
let k: u64 = (*kind).into();
|
||||||
|
c.push_str(&format!("{}", k));
|
||||||
|
}
|
||||||
|
c.push(')');
|
||||||
|
conditions.push(c);
|
||||||
|
}
|
||||||
|
if !filter.a.is_empty() {
|
||||||
|
conditions.push(build_tag_condition("a", &filter.a));
|
||||||
|
}
|
||||||
|
if !filter.d.is_empty() {
|
||||||
|
conditions.push(build_tag_condition("d", &filter.d));
|
||||||
|
}
|
||||||
|
if !filter.e.is_empty() {
|
||||||
|
conditions.push(build_tag_condition("e", &filter.e));
|
||||||
|
}
|
||||||
|
if !filter.g.is_empty() {
|
||||||
|
conditions.push(build_tag_condition("g", &filter.g));
|
||||||
|
}
|
||||||
|
if !filter.p.is_empty() {
|
||||||
|
conditions.push(build_tag_condition("p", &filter.p));
|
||||||
|
}
|
||||||
|
if !filter.r.is_empty() {
|
||||||
|
conditions.push(build_tag_condition("r", &filter.r));
|
||||||
|
}
|
||||||
|
if !filter.t.is_empty() {
|
||||||
|
conditions.push(build_tag_condition("t", &filter.t));
|
||||||
|
}
|
||||||
|
if let Some(since) = filter.since {
|
||||||
|
conditions.push(format!("created_at >= {}", since.0));
|
||||||
|
}
|
||||||
|
if let Some(until) = filter.until {
|
||||||
|
conditions.push(format!("created_at <= {}", until.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut sql = format!("SELECT raw FROM event WHERE {}", conditions.join(" AND "));
|
||||||
|
|
||||||
|
if let Some(limit) = filter.limit {
|
||||||
|
sql.push_str(&(format!(" LIMIT {}", limit)));
|
||||||
|
}
|
||||||
|
|
||||||
|
tracing::trace!("get_local_events_by_filter SQL={}", &sql);
|
||||||
|
|
||||||
|
let events_result = task::spawn_blocking(move || -> Result<Vec<Event>, Error> {
|
||||||
|
let maybe_db = GLOBALS.db.blocking_lock();
|
||||||
|
let db = maybe_db.as_ref().unwrap();
|
||||||
|
let mut stmt = db.prepare(&sql)?;
|
||||||
|
let mut rows = stmt.raw_query();
|
||||||
|
let mut events: Vec<Event> = Vec::new();
|
||||||
|
while let Some(row) = rows.next()? {
|
||||||
|
let s: String = row.get(0)?;
|
||||||
|
events.push(serde_json::from_str(&s)?);
|
||||||
|
}
|
||||||
|
Ok(events)
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
let events = events_result?;
|
||||||
|
|
||||||
|
for event in events.iter() {
|
||||||
|
// Process that event
|
||||||
|
crate::process::process_new_event(event, false, None, None).await?;
|
||||||
|
|
||||||
|
// Add to memory
|
||||||
|
self.insert(event.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(events)
|
||||||
|
}
|
||||||
|
|
||||||
#[async_recursion]
|
#[async_recursion]
|
||||||
pub async fn get_highest_local_parent(&self, id: &Id) -> Result<Option<Id>, Error> {
|
pub async fn get_highest_local_parent(&self, id: &Id) -> Result<Option<Id>, Error> {
|
||||||
if let Some(event) = self.get_local(*id).await? {
|
if let Some(event) = self.get_local(*id).await? {
|
||||||
@ -81,3 +168,35 @@ impl Events {
|
|||||||
self.events.iter()
|
self.events.iter()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn build_prefix_condition<T: Display>(field: &str, values: &[T]) -> String {
|
||||||
|
let mut c = "(".to_owned();
|
||||||
|
let mut virgin = true;
|
||||||
|
for val in values.iter() {
|
||||||
|
if !virgin {
|
||||||
|
c.push_str(" OR ");
|
||||||
|
}
|
||||||
|
virgin = false;
|
||||||
|
c.push_str(&format!("{} LIKE '{}%'", field, val));
|
||||||
|
}
|
||||||
|
c.push(')');
|
||||||
|
c
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_tag_condition<T: Display>(tag: &str, values: &[T]) -> String {
|
||||||
|
// "id in (SELECT event FROM event_tag WHERE label='e' AND field0={})";
|
||||||
|
let mut c = format!(
|
||||||
|
"id in (SELECT event FROM event_tag WHERE label='{}' AND field0 IN (",
|
||||||
|
tag
|
||||||
|
);
|
||||||
|
let mut virgin = true;
|
||||||
|
for val in values.iter() {
|
||||||
|
if !virgin {
|
||||||
|
c.push(',');
|
||||||
|
}
|
||||||
|
virgin = false;
|
||||||
|
c.push_str(&format!("'{}'", val));
|
||||||
|
}
|
||||||
|
c.push_str("))");
|
||||||
|
c
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user