use libsql::Connection; #[derive(Debug, thiserror::Error)] pub enum DataError { #[error("database error: {0}")] Database(#[from] libsql::Error), #[error("not found: {0}")] NotFound(String), } pub struct Db { conn: Connection, } impl Db { pub async fn connect(url: &str, auth_token: Option<&str>) -> Result { let db = match auth_token { Some(token) => { libsql::Builder::new_remote(url.to_string(), token.to_string()) .build() .await? } None => { libsql::Builder::new_local(url) .build() .await? } }; let conn = db.connect()?; Ok(Self { conn }) } pub async fn migrate(&self) -> Result<(), DataError> { self.conn .execute_batch( " CREATE TABLE IF NOT EXISTS torrents ( id INTEGER PRIMARY KEY AUTOINCREMENT, info_hash TEXT NOT NULL UNIQUE, name TEXT NOT NULL, media_type TEXT, state TEXT NOT NULL DEFAULT 'discovered', source_url TEXT NOT NULL, created_at TEXT NOT NULL DEFAULT (datetime('now')), updated_at TEXT NOT NULL DEFAULT (datetime('now')) ); CREATE TABLE IF NOT EXISTS rules ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, media_type TEXT NOT NULL, action TEXT NOT NULL, pattern TEXT NOT NULL, priority INTEGER NOT NULL DEFAULT 0, created_at TEXT NOT NULL DEFAULT (datetime('now')) ); CREATE TABLE IF NOT EXISTS media_items ( id INTEGER PRIMARY KEY AUTOINCREMENT, media_type TEXT NOT NULL, title TEXT NOT NULL, year INTEGER, torrent_id INTEGER REFERENCES torrents(id), created_at TEXT NOT NULL DEFAULT (datetime('now')) ); ", ) .await?; tracing::info!("database migrations applied"); Ok(()) } pub fn conn(&self) -> &Connection { &self.conn } }