package data import ( "database/sql" "fmt" "path/filepath" "time" gonanoid "github.com/matoous/go-nanoid" _ "github.com/mattn/go-sqlite3" ) type DeviceDatabase struct { Connection *sql.DB databaseDirectory string } func (db *DeviceDatabase) Initialize() error { connection, error := sql.Open("sqlite3", filepath.Join(db.databaseDirectory, "devices.db")) if error != nil { return error } db.Connection = connection _, error = db.Connection.Exec(`CREATE TABLE IF NOT EXISTS devices ( id TEXT PRIMARY KEY, device_name TEXT UNIQUE, description TEXT )`) if error != nil { return fmt.Errorf("error creating devices table: %s", error) } _, error = db.Connection.Exec(`CREATE TABLE IF NOT EXISTS sessions ( token TEXT PRIMARY KEY, device_id INTEGER, expiry_date TIMESTAMP, FOREIGN KEY (device_id) REFERENCES devices(id) )`) if error != nil { return fmt.Errorf("error creating device sessions table: %s", error) } return nil } func (db *DeviceDatabase) Close() error { return db.Connection.Close() } func (db *DeviceDatabase) CreateDevice(device_name string, description string) (string, error) { deviceID, err := gonanoid.Nanoid(8) if err != nil { return "", err } _, err = db.Connection.Exec("INSERT INTO devices (id, device_name, description) VALUES (?, ?, ?)", deviceID, device_name, description) return deviceID, err } func (db *DeviceDatabase) CreateSession(deviceID string, expiryDate time.Time) (string, error) { sessionToken, err := gonanoid.Nanoid(16) if err != nil { return "", err } _, err = db.Connection.Exec("INSERT INTO sessions (device_id, token, expiry_date) VALUES (?, ?, ?)", deviceID, sessionToken, expiryDate) if err != nil { return "", err } return sessionToken, nil } func (db *DeviceDatabase) GetDeviceById(id string) (*PlaybackDevice, error) { var device PlaybackDevice err := db.Connection.QueryRow("SELECT id, device_name, description FROM devices WHERE id = ?", id).Scan(&device.ID, &device.Name, &device.Description) if err != nil { return nil, err } return &device, nil } func (db *DeviceDatabase) DeviceIdExists(id string) (bool, error) { var exists bool err := db.Connection.QueryRow("SELECT EXISTS(SELECT 1 FROM devices WHERE id = ?)", id).Scan(&exists) if err != nil { return false, err } return exists, nil } func (db *DeviceDatabase) UpdateDevice(device *PlaybackDevice) error { _, err := db.Connection.Exec("UPDATE devices SET name = ?, description = ? WHERE id = ?", device.Name, device.Description, device.ID) return err } func (db *DeviceDatabase) GetSession(sessionToken string) (*DeviceSession, error) { var session DeviceSession row := db.Connection.QueryRow("SELECT token, device_id, expiry_date FROM sessions WHERE token = ?", sessionToken) err := row.Scan(&session.Token, &session.DeviceID, &session.ExpiryDate) if err != nil { if err == sql.ErrNoRows { return nil, nil } return nil, err } return &session, nil } func (db *DeviceDatabase) DeleteSessionByToken(token string) error { _, err := db.Connection.Exec("DELETE FROM sessions WHERE token = ?", token) return err } func (db *DeviceDatabase) GetDevices() (*[]PlaybackDevice, error) { var devices []PlaybackDevice rows, err := db.Connection.Query("SELECT id, device_name, description FROM devices") if err != nil { return nil, err } defer rows.Close() for rows.Next() { var device PlaybackDevice err := rows.Scan(&device.ID, &device.Name, &device.Description) if err != nil { if err == sql.ErrNoRows { return nil, nil } return nil, err } devices = append(devices, device) } return &devices, nil } func (db *DeviceDatabase) DeleteDevice(ID string) error { _, err := db.Connection.Exec("DELETE FROM devices WHERE id = ?", ID) return err } func (db *DeviceDatabase) SetDirectory(directory string) { db.databaseDirectory = directory }