Implement checking for deleted coordinate
This commit is contained in:
parent
1cd2a49e35
commit
255905021c
14
flake.lock
14
flake.lock
|
@ -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": {
|
||||
|
|
|
@ -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,6 +546,7 @@ impl NostrSqlite {
|
|||
// Insert into Tags table
|
||||
log::debug!("inserting new event into tags");
|
||||
for tag in event.tags.clone() {
|
||||
if Self::tag_is_indexable(&tag) {
|
||||
let tag = tag.to_vec();
|
||||
if tag.len() >= 2 {
|
||||
let tag_name = &tag[0];
|
||||
|
@ -551,7 +554,11 @@ impl NostrSqlite {
|
|||
if tag_name.len() == 1 {
|
||||
let (sql, values) = Query::insert()
|
||||
.into_table(TagsTable::Table)
|
||||
.columns([TagsTable::Tag, TagsTable::Value, TagsTable::EventId])
|
||||
.columns([
|
||||
TagsTable::Tag,
|
||||
TagsTable::Value,
|
||||
TagsTable::EventId,
|
||||
])
|
||||
.values_panic([
|
||||
tag_name.into(),
|
||||
tag_value.into(),
|
||||
|
@ -559,8 +566,12 @@ impl NostrSqlite {
|
|||
])
|
||||
.build_rusqlite(SqliteQueryBuilder);
|
||||
|
||||
if let Err(err) = tx.execute(sql.as_str(), &*values.as_params()) {
|
||||
log::error!("Error inserting event into 'tags' table: {}", err);
|
||||
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);
|
||||
|
@ -569,6 +580,7 @@ impl NostrSqlite {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match tx.commit() {
|
||||
Ok(_) => Ok(true),
|
||||
|
@ -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> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue