feat(guilddb): guild configuration
This commit is contained in:
@@ -5,12 +5,13 @@ import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
type Guild struct {
|
||||
ID string
|
||||
type Guild[C any] struct {
|
||||
ID string
|
||||
Config C
|
||||
}
|
||||
|
||||
func NewGuild(ID string) Guild {
|
||||
return Guild{ID}
|
||||
func NewGuild[C any](ID string, config C) Guild[C] {
|
||||
return Guild[C]{ID, config}
|
||||
}
|
||||
|
||||
type Channel struct {
|
||||
@@ -45,7 +46,7 @@ func NewTranslatedMessage(
|
||||
return Message{GuildID, ChannelID, ID, lang, &OriginChannelID, &OriginID}
|
||||
}
|
||||
|
||||
type GuildDB interface {
|
||||
type GuildDB[C any] interface {
|
||||
// Selects and returns a Message from the database, based on the
|
||||
// key pair of Channel's ID and Message's ID.
|
||||
//
|
||||
@@ -126,16 +127,20 @@ type GuildDB interface {
|
||||
// Selects and returns a Guild from the database.
|
||||
//
|
||||
// Will return ErrNotFound if no Guild is found or ErrInternal.
|
||||
Guild(ID string) (Guild, error)
|
||||
Guild(ID string) (Guild[C], error)
|
||||
// Inserts a new Guild object in the database. Guild.ID must be unique and
|
||||
// not already in the database.
|
||||
//
|
||||
// Will return ErrNoAffect if the object already exists or ErrInternal.
|
||||
GuildInsert(g Guild) error
|
||||
GuildInsert(g Guild[C]) error
|
||||
// Delete a Guild from the database. Guild.ID is used to find the object.
|
||||
//
|
||||
// Will return ErrNoAffect if no object was deleted or ErrInternal.
|
||||
GuildDelete(g Guild) error
|
||||
GuildDelete(g Guild[C]) error
|
||||
// Updates the Guild object in the database.
|
||||
//
|
||||
// Will return ErrNoAffect if no object was updated or ErrInternal.
|
||||
GuildUpdate(g Guild[C]) error
|
||||
}
|
||||
|
||||
var ErrNoAffect = errors.New("Not able to affect anything in the database")
|
||||
@@ -143,3 +148,4 @@ var ErrNotFound = errors.New("Object not found in the database")
|
||||
var ErrPreconditionFailed = errors.New("Precondition failed")
|
||||
var ErrInvalidObject = errors.New("Invalid object")
|
||||
var ErrInternal = errors.New("Internal error while trying to use database")
|
||||
var ErrConfigParsing = errors.New("Error while parsing Guild's config")
|
||||
|
||||
@@ -13,26 +13,27 @@ import (
|
||||
_ "github.com/tursodatabase/go-libsql"
|
||||
)
|
||||
|
||||
type SQLiteDB struct {
|
||||
type SQLiteDB[C any] struct {
|
||||
sql *sql.DB
|
||||
}
|
||||
|
||||
func NewSQLiteDB(file string) (*SQLiteDB, error) {
|
||||
func NewSQLiteDB[C any](file string) (*SQLiteDB[C], error) {
|
||||
db, err := sql.Open("libsql", file)
|
||||
if err != nil {
|
||||
return &SQLiteDB{}, err
|
||||
return &SQLiteDB[C]{}, err
|
||||
}
|
||||
return &SQLiteDB{db}, nil
|
||||
return &SQLiteDB[C]{db}, nil
|
||||
}
|
||||
|
||||
func (db *SQLiteDB) Close() error {
|
||||
func (db *SQLiteDB[C]) Close() error {
|
||||
return db.sql.Close()
|
||||
}
|
||||
|
||||
func (db *SQLiteDB) Prepare() error {
|
||||
func (db *SQLiteDB[C]) Prepare() error {
|
||||
if _, err := db.sql.Exec(`
|
||||
CREATE TABLE IF NOT EXISTS guilds (
|
||||
ID text NOT NULL,
|
||||
Config text NOT NULL,
|
||||
PRIMARY KEY(ID)
|
||||
);
|
||||
`); err != nil {
|
||||
@@ -81,19 +82,19 @@ func (db *SQLiteDB) Prepare() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *SQLiteDB) Message(guildID, channelID, messageID string) (Message, error) {
|
||||
func (db *SQLiteDB[C]) Message(guildID, channelID, messageID string) (Message, error) {
|
||||
return db.selectMessage(`
|
||||
WHERE "GuildID" = $1 AND "ChannelID" = $2 AND "ID" = $3
|
||||
`, guildID, channelID, messageID)
|
||||
}
|
||||
|
||||
func (db *SQLiteDB) MessagesWithOrigin(guildID, originChannelID, originID string) ([]Message, error) {
|
||||
func (db *SQLiteDB[C]) MessagesWithOrigin(guildID, originChannelID, originID string) ([]Message, error) {
|
||||
return db.selectMessages(`
|
||||
WHERE "GuildID" = $1 AND "OriginChannelID" = $2 AND "OriginID" = $3
|
||||
`, guildID, originChannelID, originID)
|
||||
}
|
||||
|
||||
func (db *SQLiteDB) MessageWithOriginByLang(
|
||||
func (db *SQLiteDB[C]) MessageWithOriginByLang(
|
||||
guildID, originChannelID, originID string,
|
||||
language lang.Language,
|
||||
) (Message, error) {
|
||||
@@ -102,7 +103,7 @@ func (db *SQLiteDB) MessageWithOriginByLang(
|
||||
`, guildID, originChannelID, originID, language)
|
||||
}
|
||||
|
||||
func (db *SQLiteDB) MessageInsert(m Message) error {
|
||||
func (db *SQLiteDB[C]) MessageInsert(m Message) error {
|
||||
_, err := db.Channel(m.GuildID, m.ChannelID)
|
||||
if errors.Is(err, ErrNotFound) {
|
||||
return errors.Join(
|
||||
@@ -131,7 +132,7 @@ func (db *SQLiteDB) MessageInsert(m Message) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *SQLiteDB) MessageUpdate(m Message) error {
|
||||
func (db *SQLiteDB[C]) MessageUpdate(m Message) error {
|
||||
r, err := db.sql.Exec(`
|
||||
UPDATE messages
|
||||
SET Language = $1, OriginChannelID = $2, OriginID = $3
|
||||
@@ -153,7 +154,7 @@ func (db *SQLiteDB) MessageUpdate(m Message) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *SQLiteDB) MessageDelete(m Message) error {
|
||||
func (db *SQLiteDB[C]) MessageDelete(m Message) error {
|
||||
_, err := db.sql.Exec(`
|
||||
DELETE channels
|
||||
WHERE "GuildID" = $1 AND "OriginChannelID" = $2 AND "OriginID" = $3
|
||||
@@ -177,7 +178,7 @@ func (db *SQLiteDB) MessageDelete(m Message) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *SQLiteDB) selectMessage(query string, args ...any) (Message, error) {
|
||||
func (db *SQLiteDB[C]) selectMessage(query string, args ...any) (Message, error) {
|
||||
var m Message
|
||||
err := db.sql.QueryRow(fmt.Sprintf(`
|
||||
SELECT GuildID, ChannelID, ID, Language, OriginChannelID, OriginID FROM messages
|
||||
@@ -194,7 +195,7 @@ func (db *SQLiteDB) selectMessage(query string, args ...any) (Message, error) {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (db *SQLiteDB) selectMessages(query string, args ...any) ([]Message, error) {
|
||||
func (db *SQLiteDB[C]) selectMessages(query string, args ...any) ([]Message, error) {
|
||||
r, err := db.sql.Query(fmt.Sprintf(`
|
||||
SELECT GuildID, ChannelID, ID, Language, OriginChannelID, OriginID FROM messages
|
||||
%s
|
||||
@@ -229,13 +230,13 @@ func (db *SQLiteDB) selectMessages(query string, args ...any) ([]Message, error)
|
||||
return ms, err
|
||||
}
|
||||
|
||||
func (db *SQLiteDB) Channel(guildID, ID string) (Channel, error) {
|
||||
func (db *SQLiteDB[C]) Channel(guildID, ID string) (Channel, error) {
|
||||
return db.selectChannel(`
|
||||
WHERE "GuildID" = $1 AND "ID" = $2
|
||||
`, guildID, ID)
|
||||
}
|
||||
|
||||
func (db *SQLiteDB) ChannelInsert(c Channel) error {
|
||||
func (db *SQLiteDB[C]) ChannelInsert(c Channel) error {
|
||||
r, err := db.sql.Exec(`
|
||||
INSERT OR IGNORE INTO channels (GuildID, ID, Language)
|
||||
VALUES ($1, $2, $3)
|
||||
@@ -250,7 +251,7 @@ func (db *SQLiteDB) ChannelInsert(c Channel) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *SQLiteDB) ChannelUpdate(c Channel) error {
|
||||
func (db *SQLiteDB[C]) ChannelUpdate(c Channel) error {
|
||||
r, err := db.sql.Exec(`
|
||||
UPDATE channels
|
||||
SET Language = $1
|
||||
@@ -266,7 +267,7 @@ func (db *SQLiteDB) ChannelUpdate(c Channel) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *SQLiteDB) ChannelDelete(c Channel) error {
|
||||
func (db *SQLiteDB[C]) ChannelDelete(c Channel) error {
|
||||
r, err := db.sql.Exec(`
|
||||
DELETE channels
|
||||
WHERE "GuildID" = $1 AND "ID" = $2
|
||||
@@ -281,7 +282,7 @@ func (db *SQLiteDB) ChannelDelete(c Channel) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *SQLiteDB) ChannelGroup(guildID, channelID string) (ChannelGroup, error) {
|
||||
func (db *SQLiteDB[C]) ChannelGroup(guildID, channelID string) (ChannelGroup, error) {
|
||||
|
||||
var j string
|
||||
err := db.sql.QueryRow(fmt.Sprintf(`
|
||||
@@ -321,7 +322,7 @@ func (db *SQLiteDB) ChannelGroup(guildID, channelID string) (ChannelGroup, error
|
||||
return cs, nil
|
||||
}
|
||||
|
||||
func (db *SQLiteDB) ChannelGroupInsert(g ChannelGroup) error {
|
||||
func (db *SQLiteDB[C]) ChannelGroupInsert(g ChannelGroup) error {
|
||||
if len(g) == 0 {
|
||||
return ErrNoAffect
|
||||
}
|
||||
@@ -351,7 +352,7 @@ func (db *SQLiteDB) ChannelGroupInsert(g ChannelGroup) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *SQLiteDB) ChannelGroupUpdate(g ChannelGroup) error {
|
||||
func (db *SQLiteDB[C]) ChannelGroupUpdate(g ChannelGroup) error {
|
||||
if len(g) != 0 {
|
||||
return nil
|
||||
}
|
||||
@@ -382,7 +383,7 @@ func (db *SQLiteDB) ChannelGroupUpdate(g ChannelGroup) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *SQLiteDB) ChannelGroupDelete(g ChannelGroup) error {
|
||||
func (db *SQLiteDB[C]) ChannelGroupDelete(g ChannelGroup) error {
|
||||
if len(g) != 0 {
|
||||
return nil
|
||||
}
|
||||
@@ -411,7 +412,7 @@ func (db *SQLiteDB) ChannelGroupDelete(g ChannelGroup) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *SQLiteDB) selectChannel(query string, args ...any) (Channel, error) {
|
||||
func (db *SQLiteDB[C]) selectChannel(query string, args ...any) (Channel, error) {
|
||||
var c Channel
|
||||
err := db.sql.QueryRow(fmt.Sprintf(`
|
||||
SELECT GuildID, ID, Language FROM channels
|
||||
@@ -427,7 +428,7 @@ func (db *SQLiteDB) selectChannel(query string, args ...any) (Channel, error) {
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (db *SQLiteDB) selectChannels(query string, args ...any) ([]Channel, error) {
|
||||
func (db *SQLiteDB[C]) selectChannels(query string, args ...any) ([]Channel, error) {
|
||||
r, err := db.sql.Query(fmt.Sprintf(`
|
||||
SELECT GuildID, ID, Language FROM channels
|
||||
%s
|
||||
@@ -462,26 +463,40 @@ func (db *SQLiteDB) selectChannels(query string, args ...any) ([]Channel, error)
|
||||
return cs, err
|
||||
}
|
||||
|
||||
func (db *SQLiteDB) Guild(ID string) (Guild, error) {
|
||||
var g Guild
|
||||
|
||||
if err := db.sql.QueryRow(`
|
||||
SELECT "ID" FROM guilds
|
||||
WHERE "ID" = $1
|
||||
`, ID).Scan(g.ID); errors.Is(err, sql.ErrNoRows) {
|
||||
return Guild{}, errors.Join(ErrNotFound, err)
|
||||
} else if err != nil {
|
||||
return Guild{}, errors.Join(ErrInternal, err)
|
||||
func (db *SQLiteDB[C]) Guild(ID string) (Guild[C], error) {
|
||||
var g struct {
|
||||
ID string
|
||||
Config string
|
||||
}
|
||||
|
||||
return g, nil
|
||||
if err := db.sql.QueryRow(`
|
||||
SELECT "ID", "Config" FROM guilds
|
||||
WHERE "ID" = $1
|
||||
`, ID).Scan(&g.ID, &g.Config); errors.Is(err, sql.ErrNoRows) {
|
||||
return Guild[C]{}, errors.Join(ErrNotFound, err)
|
||||
} else if err != nil {
|
||||
return Guild[C]{}, errors.Join(ErrInternal, err)
|
||||
}
|
||||
|
||||
var c C
|
||||
err := json.Unmarshal([]byte(g.Config), &c)
|
||||
if err != nil {
|
||||
return Guild[C]{}, errors.Join(ErrConfigParsing, err)
|
||||
}
|
||||
|
||||
return Guild[C]{g.ID, c}, nil
|
||||
}
|
||||
|
||||
func (db *SQLiteDB) GuildInsert(g Guild) error {
|
||||
func (db *SQLiteDB[C]) GuildInsert(g Guild[C]) error {
|
||||
j, err := json.Marshal(g.Config)
|
||||
if err != nil {
|
||||
return errors.Join(ErrConfigParsing, err)
|
||||
}
|
||||
|
||||
r, err := db.sql.Exec(`
|
||||
INSERT OR IGNORE INTO guilds (ID)
|
||||
VALUES ($1)
|
||||
`, g.ID)
|
||||
INSERT OR IGNORE INTO guilds (ID, Config)
|
||||
VALUES ($1, $2)
|
||||
`, g.ID, string(j))
|
||||
|
||||
if err != nil {
|
||||
return errors.Join(ErrInternal, err)
|
||||
@@ -492,7 +507,28 @@ func (db *SQLiteDB) GuildInsert(g Guild) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *SQLiteDB) GuildDelete(g Guild) error {
|
||||
func (db *SQLiteDB[C]) GuildUpdate(g Guild[C]) error {
|
||||
j, err := json.Marshal(g.Config)
|
||||
if err != nil {
|
||||
return errors.Join(ErrConfigParsing, err)
|
||||
}
|
||||
|
||||
r, err := db.sql.Exec(fmt.Sprintf(`
|
||||
UPDATE guilds
|
||||
SET "Config" = '%s'
|
||||
WHERE "ID" = '%s'
|
||||
`, string(j), g.ID))
|
||||
|
||||
if err != nil {
|
||||
return errors.Join(ErrInternal, err)
|
||||
} else if rows, _ := r.RowsAffected(); rows == 0 {
|
||||
return ErrNoAffect
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *SQLiteDB[C]) GuildDelete(g Guild[C]) error {
|
||||
r, err := db.sql.Exec(`
|
||||
DELETE FROM guilds
|
||||
WHERE "ID" = $1
|
||||
|
||||
Reference in New Issue
Block a user