128 lines
3.1 KiB
Go

// internal/db/db.go
package db
import (
"fmt"
"path/filepath"
"github.com/jmoiron/sqlx"
_ "github.com/mattn/go-sqlite3"
)
// DB holds the database connection
type DB struct {
*sqlx.DB
}
// New creates a new DB instance
func New(dbPath string) (*DB, error) {
// Ensure the directory exists
dir := filepath.Dir(dbPath)
if err := ensureDir(dir); err != nil {
return nil, fmt.Errorf("failed to create database directory: %w", err)
}
// Connect to the database
db, err := sqlx.Connect("sqlite3", dbPath)
if err != nil {
return nil, fmt.Errorf("failed to connect to database: %w", err)
}
// Set pragmas for better performance
db.MustExec("PRAGMA journal_mode=WAL;")
db.MustExec("PRAGMA foreign_keys=ON;")
return &DB{db}, nil
}
// Initialize creates the database schema if it doesn't exist
func (db *DB) Initialize() error {
// Create bots table
_, err := db.Exec(`
CREATE TABLE IF NOT EXISTS bots (
id INTEGER PRIMARY KEY AUTOINCREMENT,
pubkey TEXT NOT NULL UNIQUE,
encrypted_privkey TEXT NOT NULL,
name TEXT NOT NULL,
display_name TEXT,
bio TEXT,
nip05 TEXT,
zap_address TEXT,
profile_picture TEXT,
banner TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
owner_pubkey TEXT NOT NULL
)`)
if err != nil {
return fmt.Errorf("failed to create bots table: %w", err)
}
// Create post_config table
_, err = db.Exec(`
CREATE TABLE IF NOT EXISTS post_config (
id INTEGER PRIMARY KEY AUTOINCREMENT,
bot_id INTEGER NOT NULL,
hashtags TEXT,
interval_minutes INTEGER NOT NULL DEFAULT 60,
post_template TEXT,
enabled BOOLEAN NOT NULL DEFAULT 0,
FOREIGN KEY (bot_id) REFERENCES bots(id) ON DELETE CASCADE
)`)
if err != nil {
return fmt.Errorf("failed to create post_config table: %w", err)
}
// Create media_config table
_, err = db.Exec(`
CREATE TABLE IF NOT EXISTS media_config (
id INTEGER PRIMARY KEY AUTOINCREMENT,
bot_id INTEGER NOT NULL,
primary_service TEXT NOT NULL,
fallback_service TEXT,
nip94_server_url TEXT,
blossom_server_url TEXT,
FOREIGN KEY (bot_id) REFERENCES bots(id) ON DELETE CASCADE
)`)
if err != nil {
return fmt.Errorf("failed to create media_config table: %w", err)
}
// Create relays table
_, err = db.Exec(`
CREATE TABLE IF NOT EXISTS relays (
id INTEGER PRIMARY KEY AUTOINCREMENT,
bot_id INTEGER NOT NULL,
url TEXT NOT NULL,
read BOOLEAN NOT NULL DEFAULT 1,
write BOOLEAN NOT NULL DEFAULT 1,
FOREIGN KEY (bot_id) REFERENCES bots(id) ON DELETE CASCADE,
UNIQUE (bot_id, url)
)`)
if err != nil {
return fmt.Errorf("failed to create relays table: %w", err)
}
// Create posts table
_, err = db.Exec(`
CREATE TABLE IF NOT EXISTS posts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
bot_id INTEGER NOT NULL,
content_filename TEXT,
media_url TEXT,
event_id TEXT,
status TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
error TEXT,
FOREIGN KEY (bot_id) REFERENCES bots(id) ON DELETE CASCADE
)`)
if err != nil {
return fmt.Errorf("failed to create posts table: %w", err)
}
return nil
}
// ensureDir makes sure the directory exists
func ensureDir(dir string) error {
return nil // This will be implemented in a file utility package
}