Implement checking for deleted coordinate

This commit is contained in:
Tony Klink 2024-01-28 20:44:30 -06:00
parent 1cd2a49e35
commit 255905021c
Signed by: klink
GPG key ID: 85175567C4D19231
2 changed files with 148 additions and 29 deletions

View file

@ -38,10 +38,10 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1705496572,
"narHash": "sha256-rPIe9G5EBLXdBdn9ilGc0nq082lzQd0xGGe092R/5QE=",
"path": "/nix/store/wcidiyklj0nrljlz5m3qlkvhv8f2ddv8-source",
"rev": "842d9d80cfd4560648c785f8a4e6f3b096790e19",
"lastModified": 1706191920,
"narHash": "sha256-eLihrZAPZX0R6RyM5fYAWeKVNuQPYjAkCUBr+JNvtdE=",
"path": "/nix/store/9s5qs4hni9fj88x79iw6im7amv7ghb76-source",
"rev": "ae5c332cbb5827f6b1f02572496b141021de335f",
"type": "path"
},
"original": {
@ -51,11 +51,11 @@
},
"nixpkgs_2": {
"locked": {
"lastModified": 1705566941,
"narHash": "sha256-CLNtVRDA8eUPk+bxsCCZtRO0Cp+SpHdn1nNOLoFypLs=",
"lastModified": 1706173671,
"narHash": "sha256-lciR7kQUK2FCAYuszyd7zyRRmTaXVeoZsCyK6QFpGdk=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b06ff4bf8f4ad900fe0c2a61fc2946edc3a84be7",
"rev": "4fddc9be4eaf195d631333908f2a454b03628ee5",
"type": "github"
},
"original": {

View file

@ -5,7 +5,9 @@ use crate::{
};
use async_trait::async_trait;
use deadpool_sqlite::{Config, Object, Pool, Runtime};
use nostr::{nips::nip01::Coordinate, Event, EventId, Filter, RelayMessage, Timestamp, Url};
use nostr::{
nips::nip01::Coordinate, Event, EventId, Filter, RelayMessage, TagKind, Timestamp, Url,
};
use nostr_database::{Backend, DatabaseOptions, NostrDatabase, Order};
use rusqlite::Row;
use sea_query::{extension::sqlite::SqliteExpr, Order as SqOrder, Query, SqliteQueryBuilder};
@ -544,26 +546,36 @@ impl NostrSqlite {
// Insert into Tags table
log::debug!("inserting new event into tags");
for tag in event.tags.clone() {
let tag = tag.to_vec();
if tag.len() >= 2 {
let tag_name = &tag[0];
let tag_value = &tag[1];
if tag_name.len() == 1 {
let (sql, values) = Query::insert()
.into_table(TagsTable::Table)
.columns([TagsTable::Tag, TagsTable::Value, TagsTable::EventId])
.values_panic([
tag_name.into(),
tag_value.into(),
id.clone().into(),
])
.build_rusqlite(SqliteQueryBuilder);
if Self::tag_is_indexable(&tag) {
let tag = tag.to_vec();
if tag.len() >= 2 {
let tag_name = &tag[0];
let tag_value = &tag[1];
if tag_name.len() == 1 {
let (sql, values) = Query::insert()
.into_table(TagsTable::Table)
.columns([
TagsTable::Tag,
TagsTable::Value,
TagsTable::EventId,
])
.values_panic([
tag_name.into(),
tag_value.into(),
id.clone().into(),
])
.build_rusqlite(SqliteQueryBuilder);
if let Err(err) = tx.execute(sql.as_str(), &*values.as_params()) {
log::error!("Error inserting event into 'tags' table: {}", err);
tx.rollback().unwrap();
if let Err(err) = tx.execute(sql.as_str(), &*values.as_params())
{
log::error!(
"Error inserting event into 'tags' table: {}",
err
);
tx.rollback().unwrap();
return Ok(false);
return Ok(false);
}
}
}
}
@ -586,6 +598,22 @@ impl NostrSqlite {
event_saved
}
fn tag_is_indexable(tag: &nostr::Tag) -> bool {
matches!(
tag.kind(),
TagKind::E
| TagKind::P
| TagKind::UpperP
| TagKind::A
| TagKind::D
| TagKind::G
| TagKind::I
| TagKind::M
| TagKind::R
| TagKind::T
)
}
async fn has_event_already_been_saved(&self, event_id: &EventId) -> Result<bool, Error> {
match self.get_event_by_id(*event_id).await {
Ok(_) => Ok(true),
@ -1136,7 +1164,55 @@ impl NostrSqlite {
coordinate: &Coordinate,
timestamp: Timestamp,
) -> Result<bool, Error> {
Ok(true)
let Ok(connection) = self.get_connection().await else {
return Err(Error::internal_with_message("Unable to get DB connection"));
};
let ident = if coordinate.identifier.is_empty() {
format!("{}:{}", coordinate.kind, coordinate.pubkey)
} else {
format!(
"{}:{}:{}",
coordinate.kind, coordinate.pubkey, coordinate.identifier
)
};
let Ok(query_result) = connection
.interact(move |conn: &mut rusqlite::Connection| -> Result<bool, Error> {
let (sql, value) = Query::select()
.from(EventsTable::Table)
.columns([EventsTable::EventId, EventsTable::CreatedAt])
.left_join(
TagsTable::Table,
sea_query::Expr::col((TagsTable::Table, TagsTable::EventId))
.equals((EventsTable::Table, EventsTable::EventId)),
)
.and_where(sea_query::Expr::col((TagsTable::Table, TagsTable::Tag)).eq("a"))
.and_where(sea_query::Expr::col((TagsTable::Table, TagsTable::Value)).eq(ident))
.and_where(
sea_query::Expr::col((EventsTable::Table, EventsTable::CreatedAt))
.gte(timestamp.as_i64()),
)
.limit(1)
.build_rusqlite(SqliteQueryBuilder);
let mut stmt = conn.prepare(sql.as_str()).unwrap();
let mut rows = stmt.query(&*value.as_params()).unwrap();
if let Ok(Some(record)) = rows.next() {
return Ok(false)
}
Ok(true)
})
.await
else {
return Err(Error::internal_with_message(
"Failed to execute query 'get_event_by_id'",
));
};
query_result
}
}
@ -1196,7 +1272,7 @@ impl NostrDatabase for NostrSqlite {
coordinate: &Coordinate,
timestamp: Timestamp,
) -> Result<bool, Self::Err> {
todo!()
self.has_coordinate_been_deleted(coordinate, timestamp).await
}
/// Set [`EventId`] as seen by relay
@ -1245,7 +1321,9 @@ impl NostrDatabase for NostrSqlite {
&self,
filter: Filter,
) -> Result<Vec<(EventId, Timestamp)>, Self::Err> {
todo!()
Err(Error::internal_with_message(
"negentropy is not currently supported",
))
}
/// Wipe all data
@ -1577,4 +1655,45 @@ mod tests {
assert_eq!(result.len(), 1)
}
#[tokio::test]
async fn save_event_with_a_tag() {
let config = Arc::new(ServiceConfig::new());
let db = NostrSqlite::new(config).await;
let keys = nostr::Keys::generate();
let d_tag = nostr::Tag::Identifier("test".to_string());
let coordinate_event =
nostr::EventBuilder::new(nostr::Kind::TextNote, "hello", vec![d_tag.clone()])
.to_event(&keys)
.unwrap();
db.save_event(&coordinate_event).await.unwrap();
let coordinate = nostr::nips::nip01::Coordinate::new(
nostr::Kind::CategorizedBookmarkList,
coordinate_event.pubkey,
)
.identifier("test");
let a_tag = nostr::Tag::A {
kind: nostr::Kind::CategorizedBookmarkList,
public_key: keys.public_key(),
identifier: "test".to_string(),
relay_url: None,
};
let event =
nostr::EventBuilder::new(nostr::Kind::CategorizedBookmarkList, "", vec![d_tag, a_tag])
.to_event(&keys)
.unwrap();
let result = db.save_event(&event).await.unwrap();
let ts = nostr::Timestamp::now();
let res = db
.has_coordinate_been_deleted(&coordinate, ts)
.await
.unwrap();
dbg!(res);
}
}