Initial workspace scaffold
Cargo workspace with 5 crates: buh-entity (pure data structs), buh-data (Turso/libsql data access), buh-util (scraper, rules, processor, sync modules), buh-cli (binary "buh" with client/daemon subcommands), and buh-ws (axum WebSocket server). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
11
crates/buh-data/Cargo.toml
Normal file
11
crates/buh-data/Cargo.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "buh-data"
|
||||
edition.workspace = true
|
||||
version.workspace = true
|
||||
|
||||
[dependencies]
|
||||
buh-entity = { workspace = true }
|
||||
libsql = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
77
crates/buh-data/src/lib.rs
Normal file
77
crates/buh-data/src/lib.rs
Normal file
@@ -0,0 +1,77 @@
|
||||
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<Self, DataError> {
|
||||
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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user