src/db.rs 2.7 K raw
1
use rand::RngExt;
2
use rusqlite::{Connection, params};
3
use serde::{Deserialize, Serialize};
4
use std::sync::{Arc, Mutex};
5
6
pub type Db = Arc<Mutex<Connection>>;
7
8
#[derive(Serialize, Deserialize)]
9
pub struct Snippet {
10
    pub id: i64,
11
    pub short_id: String,
12
    pub content: String,
13
    pub name: String,
14
}
15
16
const ALPHABET: &[u8] = b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
17
18
fn generate_short_id() -> String {
19
    let mut rng = rand::rng();
20
    (0..10)
21
        .map(|_| ALPHABET[rng.random_range(0..ALPHABET.len())] as char)
22
        .collect()
23
}
24
25
pub fn init_db() -> Db {
26
    let conn = Connection::open("sipp.sqlite").expect("Failed to open database");
27
    conn.execute(
28
        "CREATE TABLE IF NOT EXISTS snippets (
29
            id INTEGER PRIMARY KEY AUTOINCREMENT,
30
            short_id TEXT NOT NULL UNIQUE,
31
            content TEXT NOT NULL,
32
            name TEXT NOT NULL
33
        )",
34
        [],
35
    )
36
    .expect("Failed to create table");
37
    Arc::new(Mutex::new(conn))
38
}
39
40
pub fn create_snippet(db: &Db, name: &str, content: &str) -> Snippet {
41
    let conn = db.lock().unwrap();
42
    let short_id = generate_short_id();
43
    conn.execute(
44
        "INSERT INTO snippets (short_id, content, name) VALUES (?1, ?2, ?3)",
45
        params![short_id, content, name],
46
    )
47
    .expect("Failed to insert snippet");
48
    let id = conn.last_insert_rowid();
49
    Snippet {
50
        id,
51
        short_id,
52
        content: content.to_string(),
53
        name: name.to_string(),
54
    }
55
}
56
57
pub fn get_snippet_by_short_id(db: &Db, short_id: &str) -> Option<Snippet> {
58
    let conn = db.lock().unwrap();
59
    conn.query_row(
60
        "SELECT id, short_id, content, name FROM snippets WHERE short_id = ?1",
61
        params![short_id],
62
        |row| {
63
            Ok(Snippet {
64
                id: row.get(0)?,
65
                short_id: row.get(1)?,
66
                content: row.get(2)?,
67
                name: row.get(3)?,
68
            })
69
        },
70
    )
71
    .ok()
72
}
73
74
pub fn get_all_snippets(db: &Db) -> Vec<Snippet> {
75
    let conn = db.lock().unwrap();
76
    let mut stmt = conn
77
        .prepare("SELECT id, short_id, content, name FROM snippets ORDER BY id DESC")
78
        .expect("Failed to prepare statement");
79
    stmt.query_map([], |row| {
80
        Ok(Snippet {
81
            id: row.get(0)?,
82
            short_id: row.get(1)?,
83
            content: row.get(2)?,
84
            name: row.get(3)?,
85
        })
86
    })
87
    .expect("Failed to query snippets")
88
    .filter_map(|r| r.ok())
89
    .collect()
90
}
91
92
pub fn delete_snippet_by_short_id(db: &Db, short_id: &str) -> bool {
93
    let conn = db.lock().unwrap();
94
    match conn.execute(
95
        "DELETE FROM snippets WHERE short_id = ?1",
96
        params![short_id],
97
    ) {
98
        Ok(rows_affected) => rows_affected > 0,
99
        Err(_) => false,
100
    }
101
}