Add jukebox_maker web app v1.0
Go web application for filling USB drives with media files. Runs in Docker on Unraid with /media, /mnt/usb, /config volumes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
92
internal/db/db.go
Normal file
92
internal/db/db.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"time"
|
||||
|
||||
_ "modernc.org/sqlite"
|
||||
)
|
||||
|
||||
type DB struct {
|
||||
sql *sql.DB
|
||||
}
|
||||
|
||||
type CopyRecord struct {
|
||||
DiskID string
|
||||
SourcePath string
|
||||
FileSize int64
|
||||
CopiedAt time.Time
|
||||
}
|
||||
|
||||
func Open(path string) (*DB, error) {
|
||||
conn, err := sql.Open("sqlite", path+"?_journal=WAL&_timeout=5000")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conn.SetMaxOpenConns(1)
|
||||
d := &DB{sql: conn}
|
||||
if err := d.migrate(); err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
return d, nil
|
||||
}
|
||||
|
||||
func (d *DB) Close() error {
|
||||
return d.sql.Close()
|
||||
}
|
||||
|
||||
func (d *DB) migrate() error {
|
||||
_, err := d.sql.Exec(`
|
||||
CREATE TABLE IF NOT EXISTS copy_history (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
disk_id TEXT NOT NULL,
|
||||
source_path TEXT NOT NULL,
|
||||
file_size INTEGER NOT NULL DEFAULT 0,
|
||||
copied_at DATETIME NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ','now'))
|
||||
);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_copy_history_disk_path
|
||||
ON copy_history (disk_id, source_path);
|
||||
`)
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *DB) WasCopied(diskID, sourcePath string) (bool, error) {
|
||||
var n int
|
||||
err := d.sql.QueryRow(
|
||||
`SELECT COUNT(*) FROM copy_history WHERE disk_id=? AND source_path=?`,
|
||||
diskID, sourcePath,
|
||||
).Scan(&n)
|
||||
return n > 0, err
|
||||
}
|
||||
|
||||
func (d *DB) RecordCopy(rec CopyRecord) error {
|
||||
t := rec.CopiedAt
|
||||
if t.IsZero() {
|
||||
t = time.Now().UTC()
|
||||
}
|
||||
_, err := d.sql.Exec(
|
||||
`INSERT OR IGNORE INTO copy_history (disk_id, source_path, file_size, copied_at) VALUES (?,?,?,?)`,
|
||||
rec.DiskID, rec.SourcePath, rec.FileSize, t.Format(time.RFC3339),
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *DB) CopiedPaths(diskID string) (map[string]struct{}, error) {
|
||||
rows, err := d.sql.Query(
|
||||
`SELECT source_path FROM copy_history WHERE disk_id=?`, diskID,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
m := make(map[string]struct{})
|
||||
for rows.Next() {
|
||||
var p string
|
||||
if err := rows.Scan(&p); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m[p] = struct{}{}
|
||||
}
|
||||
return m, rows.Err()
|
||||
}
|
||||
Reference in New Issue
Block a user