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": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1705496572,
|
"lastModified": 1706191920,
|
||||||
"narHash": "sha256-rPIe9G5EBLXdBdn9ilGc0nq082lzQd0xGGe092R/5QE=",
|
"narHash": "sha256-eLihrZAPZX0R6RyM5fYAWeKVNuQPYjAkCUBr+JNvtdE=",
|
||||||
"path": "/nix/store/wcidiyklj0nrljlz5m3qlkvhv8f2ddv8-source",
|
"path": "/nix/store/9s5qs4hni9fj88x79iw6im7amv7ghb76-source",
|
||||||
"rev": "842d9d80cfd4560648c785f8a4e6f3b096790e19",
|
"rev": "ae5c332cbb5827f6b1f02572496b141021de335f",
|
||||||
"type": "path"
|
"type": "path"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -51,11 +51,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
"nixpkgs_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1705566941,
|
"lastModified": 1706173671,
|
||||||
"narHash": "sha256-CLNtVRDA8eUPk+bxsCCZtRO0Cp+SpHdn1nNOLoFypLs=",
|
"narHash": "sha256-lciR7kQUK2FCAYuszyd7zyRRmTaXVeoZsCyK6QFpGdk=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "b06ff4bf8f4ad900fe0c2a61fc2946edc3a84be7",
|
"rev": "4fddc9be4eaf195d631333908f2a454b03628ee5",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
|
@ -5,7 +5,9 @@ use crate::{
|
||||||
};
|
};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use deadpool_sqlite::{Config, Object, Pool, Runtime};
|
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 nostr_database::{Backend, DatabaseOptions, NostrDatabase, Order};
|
||||||
use rusqlite::Row;
|
use rusqlite::Row;
|
||||||
use sea_query::{extension::sqlite::SqliteExpr, Order as SqOrder, Query, SqliteQueryBuilder};
|
use sea_query::{extension::sqlite::SqliteExpr, Order as SqOrder, Query, SqliteQueryBuilder};
|
||||||
|
@ -544,26 +546,36 @@ impl NostrSqlite {
|
||||||
// Insert into Tags table
|
// Insert into Tags table
|
||||||
log::debug!("inserting new event into tags");
|
log::debug!("inserting new event into tags");
|
||||||
for tag in event.tags.clone() {
|
for tag in event.tags.clone() {
|
||||||
let tag = tag.to_vec();
|
if Self::tag_is_indexable(&tag) {
|
||||||
if tag.len() >= 2 {
|
let tag = tag.to_vec();
|
||||||
let tag_name = &tag[0];
|
if tag.len() >= 2 {
|
||||||
let tag_value = &tag[1];
|
let tag_name = &tag[0];
|
||||||
if tag_name.len() == 1 {
|
let tag_value = &tag[1];
|
||||||
let (sql, values) = Query::insert()
|
if tag_name.len() == 1 {
|
||||||
.into_table(TagsTable::Table)
|
let (sql, values) = Query::insert()
|
||||||
.columns([TagsTable::Tag, TagsTable::Value, TagsTable::EventId])
|
.into_table(TagsTable::Table)
|
||||||
.values_panic([
|
.columns([
|
||||||
tag_name.into(),
|
TagsTable::Tag,
|
||||||
tag_value.into(),
|
TagsTable::Value,
|
||||||
id.clone().into(),
|
TagsTable::EventId,
|
||||||
])
|
])
|
||||||
.build_rusqlite(SqliteQueryBuilder);
|
.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()) {
|
if let Err(err) = tx.execute(sql.as_str(), &*values.as_params())
|
||||||
log::error!("Error inserting event into 'tags' table: {}", err);
|
{
|
||||||
tx.rollback().unwrap();
|
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
|
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> {
|
async fn has_event_already_been_saved(&self, event_id: &EventId) -> Result<bool, Error> {
|
||||||
match self.get_event_by_id(*event_id).await {
|
match self.get_event_by_id(*event_id).await {
|
||||||
Ok(_) => Ok(true),
|
Ok(_) => Ok(true),
|
||||||
|
@ -1136,7 +1164,55 @@ impl NostrSqlite {
|
||||||
coordinate: &Coordinate,
|
coordinate: &Coordinate,
|
||||||
timestamp: Timestamp,
|
timestamp: Timestamp,
|
||||||
) -> Result<bool, Error> {
|
) -> 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,
|
coordinate: &Coordinate,
|
||||||
timestamp: Timestamp,
|
timestamp: Timestamp,
|
||||||
) -> Result<bool, Self::Err> {
|
) -> Result<bool, Self::Err> {
|
||||||
todo!()
|
self.has_coordinate_been_deleted(coordinate, timestamp).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set [`EventId`] as seen by relay
|
/// Set [`EventId`] as seen by relay
|
||||||
|
@ -1245,7 +1321,9 @@ impl NostrDatabase for NostrSqlite {
|
||||||
&self,
|
&self,
|
||||||
filter: Filter,
|
filter: Filter,
|
||||||
) -> Result<Vec<(EventId, Timestamp)>, Self::Err> {
|
) -> Result<Vec<(EventId, Timestamp)>, Self::Err> {
|
||||||
todo!()
|
Err(Error::internal_with_message(
|
||||||
|
"negentropy is not currently supported",
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wipe all data
|
/// Wipe all data
|
||||||
|
@ -1577,4 +1655,45 @@ mod tests {
|
||||||
|
|
||||||
assert_eq!(result.len(), 1)
|
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