playback-device-server/data/remote_database.go

256 lines
7.3 KiB
Go

package data
import (
"database/sql"
"fmt"
"path/filepath"
gonanoid "github.com/matoous/go-nanoid"
)
type RemoteDatabase struct {
Connection *sql.DB
databaseDirectory string
}
func (db *RemoteDatabase) Initialize() error {
connection, error := sql.Open("sqlite3", filepath.Join(db.databaseDirectory, "remotes.db"))
if error != nil {
return error
}
db.Connection = connection
_, error = db.Connection.Exec(`PRAGMA foreign_keys = ON;`)
if error != nil {
return fmt.Errorf("error enabling foreign keys: %s", error)
}
_, error = db.Connection.Exec(`
CREATE TABLE IF NOT EXISTS Remotes (
id TEXT PRIMARY KEY,
title TEXT NOT NULL
);`)
if error != nil {
return fmt.Errorf("error creating remotes table: %s", error)
}
_, error = db.Connection.Exec(`
CREATE TABLE IF NOT EXISTS Commands (
id TEXT PRIMARY KEY,
protocol TEXT,
commandNumber INTEGER,
device INTEGER,
commandType TEXT,
title TEXT
);`)
if error != nil {
return fmt.Errorf("error creating commands table: %s", error)
}
_, error = db.Connection.Exec(`
CREATE TABLE IF NOT EXISTS RemoteCommands (
remote_id TEXT NOT NULL,
command_id TEXT NOT NULL,
PRIMARY KEY (remote_id, command_id),
FOREIGN KEY (remote_id) REFERENCES Remotes(id) ON DELETE CASCADE,
FOREIGN KEY (command_id) REFERENCES Commands(id) ON DELETE CASCADE
);`)
if error != nil {
return fmt.Errorf("error creating remote-commands table: %s", error)
}
return nil
}
func (db *RemoteDatabase) Close() error {
return db.Connection.Close()
}
func (db *RemoteDatabase) CreateRemote(remote Remote) (string, error) {
remoteId, err := gonanoid.Nanoid(8)
if err != nil {
return "", err
}
queryString := "INSERT INTO Remotes (id, title) VALUES (?, ?)"
_, err = db.Connection.Exec(queryString, remoteId, remote.Title)
if err != nil {
return "", err
}
commandIds := []string{}
for _, command := range remote.Commands {
commandIds = append(commandIds, command.Id)
}
err = db.CreateRemoteCommands(remoteId, commandIds)
if err != nil {
return "", err
}
return remoteId, nil
}
func (db *RemoteDatabase) CreateRemoteCommands(remoteId string, commandIds []string) error {
for _, commandId := range commandIds {
queryString := "INSERT INTO RemoteCommands (remote_id, command_id) VALUES (?, ?)"
_, err := db.Connection.Exec(queryString, remoteId, commandId)
if err != nil {
return err
}
}
return nil
}
func (db *RemoteDatabase) UpdateRemoteCommands(remoteId string, commandIds []string) error {
queryString := "DELETE FROM RemoteCommands WHERE remote_id = ?"
_, err := db.Connection.Exec(queryString, remoteId)
if err != nil {
return err
}
err = db.CreateRemoteCommands(remoteId, commandIds)
if err != nil {
return err
}
return nil
}
func (db *RemoteDatabase) GetRemote(remoteId string) (Remote, error) {
var remote Remote
queryString := "SELECT id, title FROM Remotes WHERE id = ?"
row := db.Connection.QueryRow(queryString, remoteId)
error := row.Scan(&remote.Id, &remote.Title)
if error != nil {
return Remote{}, fmt.Errorf("error scanning remote: %s", error)
}
commands, error := db.GetCommandsByRemoteId(remoteId)
if error != nil {
return Remote{}, error
}
remote.Commands = commands
return remote, nil
}
func (db *RemoteDatabase) GetRemotes() ([]Remote, error) {
rows, error := db.Connection.Query("SELECT id, title FROM Remotes")
if error != nil {
return nil, fmt.Errorf("error querying remotes: %s", error)
}
defer rows.Close()
remotes := []Remote{}
for rows.Next() {
var remote Remote
error = rows.Scan(&remote.Id, &remote.Title)
if error != nil {
return nil, fmt.Errorf("error scanning remote: %s", error)
}
remotes = append(remotes, remote)
}
return remotes, nil
}
func (db *RemoteDatabase) UpdateRemote(remote Remote) error {
queryString := "UPDATE Remotes SET title = ? WHERE id = ?"
_, error := db.Connection.Exec(queryString, remote.Title, remote.Id)
if error != nil {
return fmt.Errorf("error updating remote %s: %s", remote.Id, error)
}
commandIds := []string{}
for _, command := range remote.Commands {
commandIds = append(commandIds, command.Id)
}
err := db.UpdateRemoteCommands(remote.Id, commandIds)
if err != nil {
return err
}
return nil
}
func (db *RemoteDatabase) DeleteRemote(remoteId string) error {
queryString := "DELETE FROM Remotes WHERE id = ?"
_, error := db.Connection.Exec(queryString, remoteId)
if error != nil {
return fmt.Errorf("error deleting remote %s: %s", remoteId, error)
}
return nil
}
func (db *RemoteDatabase) GetCommandsByRemoteId(remoteId string) ([]Command, error) {
rows, error := db.Connection.Query("SELECT id, protocol, commandNumber, device, commandType, title FROM Commands WHERE id IN (SELECT command_id FROM RemoteCommands WHERE remote_id = ?)", remoteId)
if error != nil {
return nil, fmt.Errorf("error querying commands for remote %s: %s", remoteId, error)
}
defer rows.Close()
commands := []Command{}
for rows.Next() {
var command Command
error = rows.Scan(&command.Id, &command.Protocol, &command.CommandNumber, &command.Device, &command.CommandType, &command.Title)
if error != nil {
return nil, fmt.Errorf("error scanning command: %s", error)
}
commands = append(commands, command)
}
return commands, nil
}
func (db *RemoteDatabase) CreateCommand(command Command) (string, error) {
commandId, err := gonanoid.Nanoid(8)
if err != nil {
return "", err
}
queryString := "INSERT INTO Commands (id, protocol, commandNumber, device, commandType, title) VALUES (?, ?, ?, ?, ?, ?)"
_, err = db.Connection.Exec(queryString, commandId, command.Protocol, command.CommandNumber, command.Device, command.CommandType, command.Title)
if err != nil {
return "", err
}
return commandId, nil
}
func (db *RemoteDatabase) CreateCommands(commands []Command) error {
for _, command := range commands {
_, err := db.CreateCommand(command)
if err != nil {
return err
}
}
return nil
}
func (db *RemoteDatabase) GetCommands() ([]Command, error) {
rows, error := db.Connection.Query("SELECT id, protocol, commandNumber, device, commandType, title FROM Commands")
if error != nil {
return nil, fmt.Errorf("error querying commands: %s", error)
}
defer rows.Close()
commands := []Command{}
for rows.Next() {
var command Command
error = rows.Scan(&command.Id, &command.Protocol, &command.CommandNumber, &command.Device, &command.CommandType, &command.Title)
if error != nil {
return nil, fmt.Errorf("error scanning command: %s", error)
}
commands = append(commands, command)
}
return commands, nil
}
func (db *RemoteDatabase) UpdateCommand(command Command) error {
queryString := "UPDATE Commands SET protocol = ?, commandNumber = ?, device = ?, commandType = ?, title = ? WHERE id = ?"
_, error := db.Connection.Exec(queryString, command.Protocol, command.CommandNumber, command.Device, command.CommandType, command.Title, command.Id)
if error != nil {
return fmt.Errorf("error updating command %s: %s", command.Id, error)
}
return nil
}
func (db *RemoteDatabase) DeleteCommand(commandId string) error {
queryString := "DELETE FROM Commands WHERE id = ?"
_, error := db.Connection.Exec(queryString, commandId)
if error != nil {
return fmt.Errorf("error deleting command %s: %s", commandId, error)
}
return nil
}
func (db *RemoteDatabase) SetDirectory(directory string) {
db.databaseDirectory = directory
}