nostr_sdk_sqlite/
store.rs1use std::net::SocketAddr;
7use std::path::Path;
8
9use nostr::{Event, Url};
10use r2d2_sqlite::SqliteConnectionManager;
11use rusqlite::OpenFlags;
12
13use crate::migration::{self, MigrationError, STARTUP_SQL};
14
15pub(crate) type SqlitePool = r2d2::Pool<SqliteConnectionManager>;
16pub(crate) type PooledConnection = r2d2::PooledConnection<SqliteConnectionManager>;
17
18#[derive(Debug, thiserror::Error)]
20pub enum Error {
21 #[error(transparent)]
23 Sqlite(#[from] rusqlite::Error),
24 #[error(transparent)]
26 Pool(#[from] r2d2::Error),
27 #[error(transparent)]
29 Migration(#[from] MigrationError),
30}
31
32#[derive(Debug, Clone)]
34pub struct Store {
35 pool: SqlitePool,
36}
37
38impl Drop for Store {
39 fn drop(&mut self) {}
40}
41
42impl Store {
43 pub fn open<P>(path: P) -> Result<Self, Error>
45 where
46 P: AsRef<Path>,
47 {
48 let manager = SqliteConnectionManager::file(path.as_ref())
49 .with_flags(OpenFlags::SQLITE_OPEN_READ_WRITE | OpenFlags::SQLITE_OPEN_CREATE)
50 .with_init(|c| c.execute_batch(STARTUP_SQL));
51 let pool = r2d2::Pool::new(manager)?;
52 migration::run(&mut pool.get()?)?;
53 Ok(Self { pool })
54 }
55
56 pub fn close(self) {
58 drop(self);
59 }
60
61 pub fn insert_relay(&self, url: Url, proxy: Option<SocketAddr>) -> Result<(), Error> {
63 let conn = self.pool.get()?;
64 conn.execute(
65 "INSERT OR IGNORE INTO relays (url, proxy) VALUES (?, ?);",
66 (url, proxy.map(|a| a.to_string())),
67 )?;
68 Ok(())
69 }
70
71 pub fn get_relays(&self, enabled: bool) -> Result<Vec<(Url, Option<SocketAddr>)>, Error> {
73 let conn = self.pool.get()?;
74 let mut stmt = conn.prepare("SELECT url, proxy FROM relays WHERE enabled = ?")?;
75 let mut rows = stmt.query([enabled])?;
76
77 let mut relays: Vec<(Url, Option<SocketAddr>)> = Vec::new();
78 while let Ok(Some(row)) = rows.next() {
79 let url: Url = row.get(0)?;
80 let proxy: Option<String> = row.get(1)?;
81 relays.push((
82 url,
83 proxy
84 .map(|p| p.parse())
85 .filter(|r| r.is_ok())
86 .map(|r| r.unwrap()),
87 ));
88 }
89 Ok(relays)
90 }
91
92 pub fn delete_relay(&self, url: Url) -> Result<(), Error> {
94 let conn = self.pool.get()?;
95 conn.execute("DELETE FROM relays WHERE url = ?;", [url])?;
96 Ok(())
97 }
98
99 pub fn enable_relay(&self, url: Url) -> Result<(), Error> {
101 let conn = self.pool.get()?;
102 conn.execute("UPDATE relays SET enabled = ? WHERE url = ?;", (1, url))?;
103 Ok(())
104 }
105
106 pub fn disable_relay(&self, url: Url) -> Result<(), Error> {
108 let conn = self.pool.get()?;
109 conn.execute("UPDATE relays SET enabled = ? WHERE url = ?;", (0, url))?;
110 Ok(())
111 }
112
113 pub fn insert_event(&self, event: Event) -> Result<(), Error> {
115 let conn = self.pool.get()?;
116 conn.execute(
118 "INSERT OR IGNORE INTO events (id, pubkey, created_at, kind, content, sig) VALUES (?, ?, ?, ?, ?, ?);",
119 (event.id.to_hex(), &event.pubkey.to_string(), event.created_at.as_u64(), event.kind.as_u64(), event.content, event.sig.to_string()),
120 )?;
121 let mut stmt =
123 conn.prepare("INSERT OR IGNORE INTO tags (event_id, kind, value) VALUES (?, ?, ?)")?;
124 for tag in event.tags.into_iter() {
125 let tag: Vec<String> = tag.as_vec();
126 let kind = &tag[0];
127 let value = tag.get(1..);
128 stmt.execute((event.id.as_bytes(), kind, serde_json::json!(value)))?;
129 }
130 Ok(())
131 }
132}