feat(bot,events,commands): guild configuration and logging

This commit is contained in:
Gustavo "Guz" L. de Mello
2024-08-26 11:16:26 -03:00
parent 220e14c020
commit b37934ded1
14 changed files with 429 additions and 182 deletions

1
.gitignore vendored
View File

@@ -9,3 +9,4 @@ dist
tmp
bin
static/uno.css
guild.db

View File

@@ -4,33 +4,33 @@
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
templ.url = "github:a-h/templ?ref=v0.2.707";
};
outputs = { nixpkgs, ... } @ inputs:
let
systems = [
"x86_64-linux"
"aarch64-linux"
"x86_64-darwin"
"aarch64-darwin"
];
forAllSystems = f: nixpkgs.lib.genAttrs systems (system:
let
pkgs = import nixpkgs { inherit system; };
in
outputs = {nixpkgs, ...} @ inputs: let
systems = [
"x86_64-linux"
"aarch64-linux"
"x86_64-darwin"
"aarch64-darwin"
];
forAllSystems = f:
nixpkgs.lib.genAttrs systems (system: let
pkgs = import nixpkgs {inherit system;};
in
f system pkgs);
templ = system: inputs.templ.packages.${system}.templ;
in
{
devShells = forAllSystems (system: pkgs: {
default = pkgs.mkShell {
buildInputs = with pkgs; [
sqlite
sqlitebrowser
go
golangci-lint
docker-compose
(templ system)
];
};
});
};
templ = system: inputs.templ.packages.${system}.templ;
in {
devShells = forAllSystems (system: pkgs: {
default = pkgs.mkShell {
hardeningDisable = ["fortify"];
buildInputs = with pkgs; [
sqlite
sqlitebrowser
go
golangci-lint
delve
docker-compose
(templ system)
];
};
});
};
}

View File

@@ -1,22 +1,23 @@
package bot
import (
"dislate/internals/guilddb"
"dislate/internals/translator"
"log/slog"
"dislate/internals/discord/bot/gconf"
"dislate/internals/translator"
dgo "github.com/bwmarrin/discordgo"
)
type Bot struct {
token string
db guilddb.GuildDB
db gconf.DB
translator translator.Translator
session *dgo.Session
logger *slog.Logger
}
func NewBot(token string, db guilddb.GuildDB, translator translator.Translator, logger *slog.Logger) (*Bot, error) {
func NewBot(token string, db gconf.DB, translator translator.Translator, logger *slog.Logger) (*Bot, error) {
discord, err := dgo.New("Bot " + token)
if err != nil {
return &Bot{}, err

View File

@@ -13,6 +13,7 @@ import (
func (b *Bot) registerCommands() error {
cs := []commands.Command{
commands.NewMagageConfig(b.db),
commands.NewManageChannel(b.db),
}

View File

@@ -5,6 +5,7 @@ import (
"fmt"
"strings"
"dislate/internals/discord/bot/gconf"
"dislate/internals/guilddb"
gdb "dislate/internals/guilddb"
"dislate/internals/translator/lang"
@@ -13,10 +14,10 @@ import (
)
type ManageChannel struct {
db gdb.GuildDB
db gconf.DB
}
func NewManageChannel(db gdb.GuildDB) ManageChannel {
func NewManageChannel(db gconf.DB) ManageChannel {
return ManageChannel{db}
}
func (c ManageChannel) Info() *dgo.ApplicationCommand {
@@ -43,7 +44,7 @@ func (c ManageChannel) Components() []Component {
}
type ChannelsInfo struct {
db gdb.GuildDB
db gconf.DB
}
func (c ChannelsInfo) Info() *dgo.ApplicationCommand {
@@ -110,7 +111,7 @@ func (c ChannelsInfo) Subcommands() []Command {
}
type ChannelsLink struct {
db guilddb.GuildDB
db gconf.DB
}
func (c ChannelsLink) Info() *dgo.ApplicationCommand {
@@ -223,7 +224,7 @@ func (c ChannelsLink) Subcommands() []Command {
}
type ChannelsSetLang struct {
db guilddb.GuildDB
db gconf.DB
}
func (c ChannelsSetLang) Info() *dgo.ApplicationCommand {
@@ -315,7 +316,7 @@ func (c ChannelsSetLang) Subcommands() []Command {
return []Command{}
}
func getChannel(db guilddb.GuildDB, guildID, channelID string) (gdb.Channel, error) {
func getChannel(db gconf.DB, guildID, channelID string) (gdb.Channel, error) {
ch, err := db.Channel(guildID, channelID)
if errors.Is(err, gdb.ErrNotFound) {
if err := db.ChannelInsert(gdb.NewChannel(guildID, channelID, lang.EN)); err != nil {
@@ -332,7 +333,7 @@ func getChannel(db guilddb.GuildDB, guildID, channelID string) (gdb.Channel, err
return ch, nil
}
func getChannelInfo(db guilddb.GuildDB, ch gdb.Channel) (*dgo.MessageEmbed, error) {
func getChannelInfo(db gconf.DB, ch gdb.Channel) (*dgo.MessageEmbed, error) {
group, err := db.ChannelGroup(ch.GuildID, ch.ID)
if !errors.Is(err, gdb.ErrNotFound) {
return nil, err

View File

@@ -0,0 +1,102 @@
package commands
import (
"dislate/internals/discord/bot/gconf"
"fmt"
dgo "github.com/bwmarrin/discordgo"
)
type ManageConfig struct {
db gconf.DB
}
func NewMagageConfig(db gconf.DB) ManageConfig {
return ManageConfig{db}
}
func (c ManageConfig) Info() *dgo.ApplicationCommand {
var permissions int64 = dgo.PermissionAdministrator
return &dgo.ApplicationCommand{
Name: "config",
Description: "Manages the guild's configuration",
DefaultMemberPermissions: &permissions,
}
}
func (c ManageConfig) Handle(s *dgo.Session, ic *dgo.InteractionCreate) error {
return nil
}
func (c ManageConfig) Components() []Component {
return []Component{}
}
func (c ManageConfig) Subcommands() []Command {
return []Command{
loggerConfigChannel(c),
}
}
type loggerConfigChannel struct {
db gconf.DB
}
func (c loggerConfigChannel) Info() *dgo.ApplicationCommand {
var permissions int64 = dgo.PermissionAdministrator
return &dgo.ApplicationCommand{
Name: "log-channel",
Description: "Change logging channel",
DefaultMemberPermissions: &permissions,
Options: []*dgo.ApplicationCommandOption{{
Type: dgo.ApplicationCommandOptionChannel,
Required: true,
Name: "log-channel",
Description: "The channel to send log messages and errors to",
ChannelTypes: []dgo.ChannelType{
dgo.ChannelTypeGuildText,
},
}},
}
}
func (c loggerConfigChannel) Handle(s *dgo.Session, ic *dgo.InteractionCreate) error {
opts := getOptions(ic.ApplicationCommandData().Options)
var err error
var dch *dgo.Channel
if c, ok := opts["log-channel"]; ok {
dch = c.ChannelValue(s)
} else {
dch, err = s.Channel(ic.ChannelID)
if err != nil {
return err
}
}
guild, err := c.db.Guild(ic.GuildID)
if err != nil {
return err
}
conf := guild.Config
conf.LoggingChannel = &dch.ID
guild.Config = conf
err = c.db.GuildUpdate(guild)
if err != nil {
return err
}
// FIXME: response message continuously on "thinking..."
err = s.InteractionRespond(ic.Interaction, &dgo.InteractionResponse{
Type: dgo.InteractionResponseDeferredChannelMessageWithSource,
Data: &dgo.InteractionResponseData{
Content: fmt.Sprintf("Logging channel changed to %s", *guild.Config.LoggingChannel),
Flags: dgo.MessageFlagsEphemeral,
},
})
return err
}
func (c loggerConfigChannel) Components() []Component {
return []Component{}
}
func (c loggerConfigChannel) Subcommands() []Command {
return []Command{}
}

View File

@@ -0,0 +1,86 @@
package errors
import (
"fmt"
"log/slog"
"strings"
dgo "github.com/bwmarrin/discordgo"
)
type Error interface {
Log(*slog.Logger)
Reply(*dgo.Session, *dgo.Message)
LogReply(*slog.Logger, *dgo.Session, *dgo.Message)
Error() string
}
type defaultError struct {
err string
args []slog.Attr
}
func NewError(err string, args ...slog.Attr) defaultError {
return defaultError{err, args}
}
func New(err string, args ...slog.Attr) defaultError {
return NewError(err, args...)
}
func (err defaultError) Log(l *slog.Logger) {
args := make([]any, len(err.args))
for i, a := range err.args {
args[i] = any(a)
}
l.Error(err.err, args...)
}
func (err defaultError) Reply(s *dgo.Session, m *dgo.Message) {
_, erro := s.ChannelMessageSendReply(
m.ChannelID,
fmt.Sprintf("Error: %s\nSee logs for more details", err.err),
m.Reference(),
)
if erro != nil {
_, _ = s.ChannelMessageSendReply(
m.ChannelID,
fmt.Sprintf("Failed to send error message (somehow), due to:\n%s", erro.Error()),
m.Reference(),
)
}
}
func (err defaultError) LogReply(l *slog.Logger, s *dgo.Session, m *dgo.Message) {
err.Reply(s,m)
err.Log(l)
}
func (err defaultError) Error() string {
s := make([]string, len(err.args))
for i, a := range err.args {
s[i] = fmt.Sprintf("%s=%s", a.Key, a.Value)
}
return fmt.Sprintf("%s\n%s", err.err, strings.Join(s, " "))
}
type ErrDatabase struct {
defaultError
}
func NewErrDatabase(args ...slog.Attr) ErrDatabase {
return ErrDatabase{defaultError{
"Error while trying to talk to the database.",
args,
}}
}
type ErrUserWebhook struct {
defaultError
}
func NewErrUserWebhook(args ...slog.Attr) ErrUserWebhook {
return ErrUserWebhook{defaultError{
"Error while trying to access/execute the user webhook",
args,
}}
}

View File

@@ -5,7 +5,7 @@ import "dislate/internals/discord/bot/events"
func (b *Bot) registerEventHandlers() {
ehs := []any{
events.NewGuildCreate(b.logger, b.db).Serve,
events.NewMessageCreate(b.logger, b.db, b.translator).Serve,
events.NewMessageCreate(b.db, b.translator).Serve,
events.NewReady(b.logger, b.db).Serve,
}
for _, h := range ehs {

View File

@@ -0,0 +1,9 @@
package events
import (
dgo "github.com/bwmarrin/discordgo"
)
type EventHandler[E any] interface {
Serve(*dgo.Session, E)
}

View File

@@ -4,23 +4,24 @@ import (
"errors"
"log/slog"
"dislate/internals/guilddb"
"dislate/internals/discord/bot/gconf"
gdb "dislate/internals/guilddb"
dgo "github.com/bwmarrin/discordgo"
)
type GuildCreate struct {
log *slog.Logger
db guilddb.GuildDB
db gconf.DB
}
func NewGuildCreate(log *slog.Logger, db guilddb.GuildDB) GuildCreate {
func NewGuildCreate(log *slog.Logger, db gconf.DB) GuildCreate {
return GuildCreate{log, db}
}
func (h GuildCreate) Serve(s *dgo.Session, e *dgo.GuildCreate) {
err := h.db.GuildInsert(guilddb.Guild{ID: e.Guild.ID})
err := h.db.GuildInsert(gdb.Guild[gconf.ConfigString]{ID: e.Guild.ID})
if err != nil && !errors.Is(err, guilddb.ErrNoAffect) {
if err != nil && !errors.Is(err, gdb.ErrNoAffect) {
h.log.Error("Failed to add guild to database",
slog.String("id", e.Guild.ID),
slog.String("err", err.Error()),
@@ -34,17 +35,17 @@ func (h GuildCreate) Serve(s *dgo.Session, e *dgo.GuildCreate) {
type Ready struct {
log *slog.Logger
db guilddb.GuildDB
db gconf.DB
}
func NewReady(log *slog.Logger, db guilddb.GuildDB) EventHandler[*dgo.Ready] {
func NewReady(log *slog.Logger, db gconf.DB) EventHandler[*dgo.Ready] {
return Ready{log, db}
}
func (h Ready) Serve(s *dgo.Session, e *dgo.Ready) {
for _, g := range e.Guilds {
err := h.db.GuildInsert(guilddb.Guild{ID: g.ID})
err := h.db.GuildInsert(gdb.Guild[gconf.ConfigString]{ID: g.ID})
if err != nil && !errors.Is(err, guilddb.ErrNoAffect) {
if err != nil && !errors.Is(err, gdb.ErrNoAffect) {
h.log.Error("Failed to add guild to database",
slog.String("id", g.ID),
slog.String("err", err.Error()),

View File

@@ -1,11 +1,12 @@
package events
import (
"errors"
"fmt"
e "errors"
"log/slog"
"slices"
"dislate/internals/discord/bot/errors"
"dislate/internals/discord/bot/gconf"
"dislate/internals/guilddb"
"dislate/internals/translator"
"dislate/internals/translator/lang"
@@ -13,71 +14,60 @@ import (
dgo "github.com/bwmarrin/discordgo"
)
type EventHandler[E any] interface {
Serve(*dgo.Session, E)
}
type MessageCreate struct {
log *slog.Logger
db guilddb.GuildDB
db gconf.DB
translator translator.Translator
}
func NewMessageCreate(log *slog.Logger, db guilddb.GuildDB, t translator.Translator) MessageCreate {
return MessageCreate{log, db, t}
func NewMessageCreate(db gconf.DB, t translator.Translator) MessageCreate {
return MessageCreate{db, t}
}
func (h MessageCreate) Serve(s *dgo.Session, e *dgo.MessageCreate) {
if e.Message.Author.Bot {
func (h MessageCreate) Serve(s *dgo.Session, ev *dgo.MessageCreate) {
log := gconf.GetLogger(ev.GuildID, s, h.db)
if ev.Message.Author.Bot {
return
}
ch, err := h.db.Channel(e.GuildID, e.ChannelID)
if errors.Is(err, guilddb.ErrNotFound) {
h.log.Debug("Channel is not in database, ignoring.", slog.String("guild", e.GuildID), slog.String("channel", e.ChannelID))
ch, err := h.db.Channel(ev.GuildID, ev.ChannelID)
if e.Is(err, guilddb.ErrNotFound) {
log.Debug("Channel is not in database, ignoring.",
slog.String("guild", ev.GuildID),
slog.String("channel", ev.ChannelID),
)
return
} else if err != nil {
h.log.Error("Error while trying to get channel from database",
slog.String("guild", e.GuildID),
slog.String("channel", e.ChannelID),
errors.NewErrDatabase(
slog.String("guild", ev.GuildID),
slog.String("channel", ev.ChannelID),
slog.String("err", err.Error()),
)
).LogReply(log, s, ev.Message)
return
}
gc, err := h.db.ChannelGroup(ch.GuildID, ch.ID)
if errors.Is(err, guilddb.ErrNotFound) {
h.log.Debug("Channel is not in a group, ignoring.", slog.String("guild", e.GuildID), slog.String("channel", e.ChannelID))
if e.Is(err, guilddb.ErrNotFound) {
log.Debug("Channel is not in a group, ignoring.",
slog.String("guild", ev.GuildID),
slog.String("channel", ev.ChannelID),
)
return
} else if err != nil {
h.log.Error("Error while trying to get channel group from database",
slog.String("guild", e.GuildID),
slog.String("channel", e.ChannelID),
errors.NewErrDatabase(
slog.String("guild", ev.GuildID),
slog.String("channel", ev.ChannelID),
slog.String("err", err.Error()),
)
).LogReply(log, s, ev.Message)
return
}
_, err = h.getMessage(e.Message, ch.Language)
_, err = h.getMessage(ev.Message, ch.Language)
if err != nil {
h.log.Error("Error while trying to get/set message to database",
slog.String("guild", e.Message.GuildID),
slog.String("channel", e.Message.ChannelID),
slog.String("message", e.Message.ID),
errors.NewErrDatabase(
slog.String("guild", ev.Message.GuildID),
slog.String("channel", ev.Message.ChannelID),
slog.String("message", ev.Message.ID),
slog.String("err", err.Error()),
)
_, err := s.ChannelMessageSendReply(
e.Message.ChannelID,
fmt.Sprintf("Error while trying to send message to database. %s", err.Error()),
e.Message.Reference(),
)
if err != nil {
h.log.Error("Error while trying to send error message",
slog.String("guild", e.Message.GuildID),
slog.String("channel", e.Message.ChannelID),
slog.String("message", e.Message.ID),
slog.String("err", err.Error()),
)
}
).LogReply(log, s, ev.Message)
return
}
@@ -86,106 +76,53 @@ func (h MessageCreate) Serve(s *dgo.Session, e *dgo.MessageCreate) {
continue
}
go func(c guilddb.Channel) {
uw, err := h.getUserWebhook(s, c.ID, e.Message.Author)
uw, err := h.getUserWebhook(s, c.ID, ev.Message.Author)
if err != nil {
h.log.Error("Error while trying to create user webhook",
slog.String("guild", e.Message.GuildID),
slog.String("channel", e.Message.ChannelID),
slog.Any("user", e.Message.Author),
)
_, err := s.ChannelMessageSendReply(
e.Message.ChannelID,
fmt.Sprintf("Error while trying to create user webhook %s", err.Error()),
e.Message.Reference(),
)
if err != nil {
h.log.Error("Error while trying to send error message",
slog.String("guild", e.Message.GuildID),
slog.String("channel", e.Message.ChannelID),
slog.String("message", e.Message.ID),
slog.String("err", err.Error()),
)
}
errors.NewErrUserWebhook(
slog.String("guild", ev.Message.GuildID),
slog.String("channel", ev.Message.ChannelID),
slog.Any("user", ev.Message.Author),
).LogReply(log, s, ev.Message)
}
t, err := h.translator.Translate(ch.Language, c.Language, e.Message.Content)
t, err := h.translator.Translate(ch.Language, c.Language, ev.Message.Content)
if err != nil {
h.log.Error("Error while trying to translate message",
slog.String("guild", e.Message.GuildID),
slog.String("channel", e.Message.ChannelID),
slog.String("message", e.Message.ID),
slog.String("content", e.Message.Content),
errors.New("Error while trying to translate message",
slog.String("guild", ev.Message.GuildID),
slog.String("channel", ev.Message.ChannelID),
slog.String("message", ev.Message.ID),
slog.String("content", ev.Message.Content),
slog.String("err", err.Error()),
)
_, err := s.ChannelMessageSendReply(
e.Message.ChannelID,
fmt.Sprintf("Error while trying to translate message. %s", err.Error()),
e.Message.Reference(),
)
if err != nil {
h.log.Error("Error while trying to send error message",
slog.String("guild", e.Message.GuildID),
slog.String("channel", e.Message.ChannelID),
slog.String("message", e.Message.ID),
slog.String("err", err.Error()),
)
}
).LogReply(log, s, ev.Message)
}
tdm, err := s.WebhookExecute(uw.ID, uw.Token, true, &dgo.WebhookParams{
AvatarURL: e.Message.Author.AvatarURL(""),
Username: e.Message.Author.GlobalName,
AvatarURL: ev.Message.Author.AvatarURL(""),
Username: ev.Message.Author.GlobalName,
Content: t,
})
// tdm, err := s.ChannelMessageSend(c.ID, t)
if err != nil {
h.log.Error("Error while trying to send translated message",
slog.String("guild", e.Message.GuildID),
slog.String("channel", e.Message.ChannelID),
slog.String("message", e.Message.ID),
slog.String("content", e.Message.Content),
errors.NewErrUserWebhook(
slog.String("guild", ev.Message.GuildID),
slog.String("channel", ev.Message.ChannelID),
slog.String("message", ev.Message.ID),
slog.String("content", ev.Message.Content),
slog.String("err", err.Error()),
)
_, err := s.ChannelMessageSendReply(
e.Message.ChannelID,
fmt.Sprintf("Error while trying to send translated message. %s", err.Error()),
e.Message.Reference(),
)
if err != nil {
h.log.Error("Error while trying to send error message",
slog.String("guild", e.Message.GuildID),
slog.String("channel", e.Message.ChannelID),
slog.String("message", e.Message.ID),
slog.String("err", err.Error()),
)
}
).LogReply(log, s, ev.Message)
}
if tdm.GuildID == "" {
tdm.GuildID = e.Message.GuildID
tdm.GuildID = ev.Message.GuildID
}
_, err = h.getTranslatedMessage(tdm, e.Message, c.Language)
_, err = h.getTranslatedMessage(tdm, ev.Message, c.Language)
if err != nil {
h.log.Error("Error while trying to get/set translated message to database",
slog.String("guild", e.Message.GuildID),
slog.String("channel", e.Message.ChannelID),
slog.String("message", e.Message.ID),
errors.NewErrDatabase(
slog.String("guild", ev.Message.GuildID),
slog.String("channel", ev.Message.ChannelID),
slog.String("message", ev.Message.ID),
slog.String("err", err.Error()),
)
_, err := s.ChannelMessageSendReply(
e.Message.ChannelID,
fmt.Sprintf("Error while trying to send translated message to database. %s", err.Error()),
e.Message.Reference(),
)
if err != nil {
h.log.Error("Error while trying to send error message",
slog.String("guild", e.Message.GuildID),
slog.String("channel", e.Message.ChannelID),
slog.String("message", e.Message.ID),
slog.String("err", err.Error()),
)
}
).LogReply(log, s, ev.Message)
}
}(c)
@@ -219,7 +156,7 @@ func (h MessageCreate) getUserWebhook(s *dgo.Session, channelID string, user *dg
func (h MessageCreate) getMessage(m *dgo.Message, lang lang.Language) (guilddb.Message, error) {
msg, err := h.db.Message(m.GuildID, m.ChannelID, m.ID)
if errors.Is(err, guilddb.ErrNotFound) {
if e.Is(err, guilddb.ErrNotFound) {
if err := h.db.MessageInsert(guilddb.NewMessage(m.GuildID, m.ChannelID, m.ID, lang)); err != nil {
return guilddb.Message{}, err
}
@@ -236,7 +173,7 @@ func (h MessageCreate) getMessage(m *dgo.Message, lang lang.Language) (guilddb.M
func (h MessageCreate) getTranslatedMessage(m, original *dgo.Message, lang lang.Language) (guilddb.Message, error) {
msg, err := h.db.Message(m.GuildID, m.ChannelID, m.ID)
if errors.Is(err, guilddb.ErrNotFound) {
if e.Is(err, guilddb.ErrNotFound) {
if err := h.db.MessageInsert(guilddb.NewTranslatedMessage(
m.GuildID,
m.ChannelID,

View File

@@ -0,0 +1,61 @@
package gconf
import (
"log/slog"
gdb "dislate/internals/guilddb"
dgo "github.com/bwmarrin/discordgo"
)
type Config struct {
Logger *slog.Logger
}
type ConfigString struct {
LoggingChannel *string `json:"logging_channel"`
LoggingLevel *slog.Level `json:"logging_level"`
}
type Guild gdb.Guild[ConfigString]
type DB gdb.GuildDB[ConfigString]
func (g Guild) GetConfig(s *dgo.Session) (*Config, error) {
var l *slog.Logger
var err error
if g.Config.LoggingChannel != nil {
c, err := s.Channel(*g.Config.LoggingChannel)
if err != nil {
return nil, err
}
var lv slog.Level
if g.Config.LoggingLevel != nil {
lv = *g.Config.LoggingLevel
} else {
lv = slog.LevelInfo
}
l = slog.New(NewGuildHandler(s,c, &slog.HandlerOptions{
Level: lv,
}))
} else {
l = slog.New(disabledHandler{})
}
return &Config{l}, err
}
func GetLogger(guildID string, s *dgo.Session, db DB) *slog.Logger {
g, err := db.Guild(guildID)
if err != nil {
return slog.New(disabledHandler{})
}
c, err := Guild(g).GetConfig(s)
if err != nil {
return slog.New(disabledHandler{})
}
return c.Logger
}

View File

@@ -0,0 +1,45 @@
package gconf
import (
"context"
"log/slog"
dgo "github.com/bwmarrin/discordgo"
)
type guildHandler struct {
*slog.TextHandler
}
func NewGuildHandler(s *dgo.Session, c *dgo.Channel, opts *slog.HandlerOptions) guildHandler {
w := NewChannelWriter(s, c)
h := slog.NewTextHandler(w, opts)
return guildHandler{h}
}
type disabledHandler struct {
*slog.TextHandler
}
func (_ disabledHandler) Enabled(_ context.Context,_ slog.Level) bool {
return false
}
type channelWriter struct {
session *dgo.Session
channel *dgo.Channel
}
func NewChannelWriter(s *dgo.Session, c *dgo.Channel) channelWriter {
w := channelWriter{s, c}
return w
}
func (w channelWriter) Write(p []byte) (int, error) {
m, err := w.session.ChannelMessageSend(w.channel.ID, string(p))
if err != nil {
return 0, err
}
return len(m.Content), nil
}

14
main.go
View File

@@ -1,9 +1,6 @@
package main
import (
"dislate/internals/discord/bot"
"dislate/internals/guilddb"
"dislate/internals/translator"
"flag"
"log/slog"
"os"
@@ -11,6 +8,11 @@ import (
"syscall"
"time"
"dislate/internals/discord/bot"
"dislate/internals/discord/bot/gconf"
"dislate/internals/guilddb"
"dislate/internals/translator"
"github.com/charmbracelet/log"
)
@@ -30,12 +32,12 @@ func init() {
func main() {
logger := slog.New(log.NewWithOptions(os.Stderr, log.Options{
TimeFormat: time.DateTime,
TimeFormat: time.DateTime,
ReportTimestamp: true,
ReportCaller: true,
ReportCaller: true,
}))
db, err := guilddb.NewSQLiteDB(*database_file)
db, err := guilddb.NewSQLiteDB[gconf.ConfigString](*database_file)
if err != nil {
logger.Error("Failed to open database connection", slog.String("err", err.Error()))
return