feat: implement server logging functionality

- Added a logging service to manage server event logs including message edits, deletions, member joins/leaves, and moderation actions.
- Introduced commands to configure logging settings, including setting the log channel and enabling/disabling logging.
- Updated the README to document the new logging features and commands.
- Enhanced moderation commands to log actions taken on members.
This commit is contained in:
2026-03-18 13:18:12 +00:00
parent 2b14079e50
commit 035e383db2
13 changed files with 883 additions and 3 deletions
+80
View File
@@ -15,6 +15,12 @@ type LevelReward struct {
RoleID int64
}
type LogSettings struct {
GuildID int64
ChannelID int64
IsEnabled bool
}
func NewRepo(db *sql.DB) *Repo {
return &Repo{db: db}
}
@@ -240,6 +246,80 @@ func (r *Repo) SetLevelUpMessage(ctx context.Context, guildID int64, message str
return err
}
func (r *Repo) SetLogChannel(ctx context.Context, guildID int64, channelID int64) error {
const q = `
INSERT INTO logsettings (guild_id, log_channel_id, is_enabled)
VALUES ($1, $2, TRUE)
ON CONFLICT (guild_id)
DO UPDATE SET log_channel_id = EXCLUDED.log_channel_id
`
_, err := r.db.ExecContext(ctx, q, guildID, channelID)
return err
}
func (r *Repo) SetLogEnabled(ctx context.Context, guildID int64, enabled bool) error {
const q = `
INSERT INTO logsettings (guild_id, is_enabled)
VALUES ($1, $2)
ON CONFLICT (guild_id)
DO UPDATE SET is_enabled = EXCLUDED.is_enabled
`
_, err := r.db.ExecContext(ctx, q, guildID, enabled)
return err
}
func (r *Repo) GetLogSettings(ctx context.Context, guildID int64) (*LogSettings, error) {
const q = `
SELECT log_channel_id, is_enabled
FROM logsettings
WHERE guild_id = $1
`
row := r.db.QueryRowContext(ctx, q, guildID)
var channelID sql.NullInt64
var enabled sql.NullBool
switch err := row.Scan(&channelID, &enabled); err {
case nil:
out := &LogSettings{
GuildID: guildID,
ChannelID: 0,
IsEnabled: false,
}
if channelID.Valid {
out.ChannelID = channelID.Int64
}
if enabled.Valid {
out.IsEnabled = enabled.Bool
}
return out, nil
case sql.ErrNoRows:
return &LogSettings{
GuildID: guildID,
ChannelID: 0,
IsEnabled: false,
}, nil
default:
return nil, err
}
}
func (r *Repo) HasLogSettings(ctx context.Context, guildID int64) (bool, error) {
const q = `
SELECT 1
FROM logsettings
WHERE guild_id = $1
`
row := r.db.QueryRowContext(ctx, q, guildID)
var one int
switch err := row.Scan(&one); err {
case nil:
return true, nil
case sql.ErrNoRows:
return false, nil
default:
return false, err
}
}
func (r *Repo) GetLevelUpMessage(ctx context.Context, guildID int64) (string, error) {
const q = `
SELECT message
@@ -0,0 +1,32 @@
package logsettings
import (
"context"
"velox-bot/internal/db/repos/settingsrepo"
)
type Service struct {
settings *settingsrepo.Repo
}
func New(settings *settingsrepo.Repo) *Service {
return &Service{settings: settings}
}
func (s *Service) SetChannel(ctx context.Context, guildID, channelID int64) error {
return s.settings.SetLogChannel(ctx, guildID, channelID)
}
func (s *Service) SetEnabled(ctx context.Context, guildID int64, enabled bool) error {
return s.settings.SetLogEnabled(ctx, guildID, enabled)
}
func (s *Service) GetSettings(ctx context.Context, guildID int64) (*settingsrepo.LogSettings, error) {
return s.settings.GetLogSettings(ctx, guildID)
}
func (s *Service) HasSettings(ctx context.Context, guildID int64) (bool, error) {
return s.settings.HasLogSettings(ctx, guildID)
}
+5 -2
View File
@@ -1,8 +1,10 @@
package services
import (
"velox-bot/internal/db/services/defaultrole"
"velox-bot/internal/db/services/level"
"velox-bot/internal/db/services/levelsettings"
"velox-bot/internal/db/services/logsettings"
"velox-bot/internal/db/services/meeting"
"velox-bot/internal/db/services/projects"
"velox-bot/internal/db/services/rps"
@@ -10,7 +12,6 @@ import (
"velox-bot/internal/db/services/twitch"
"velox-bot/internal/db/services/usersettings"
"velox-bot/internal/db/services/welcome"
"velox-bot/internal/db/services/defaultrole"
)
type Services struct {
@@ -24,11 +25,12 @@ type Services struct {
Twitch *twitch.Service
Welcome *welcome.Service
DefaultRole *defaultrole.Service
LogSettings *logsettings.Service
}
var Global *Services
func NewServices(level *level.Service, levelSettings *levelsettings.Service, meeting *meeting.Service, schedule *schedule.Service, userSettings *usersettings.Service, projects *projects.Service, rps *rps.Service, twitchSvc *twitch.Service, welcomeSvc *welcome.Service, defaultRoleSvc *defaultrole.Service) *Services {
func NewServices(level *level.Service, levelSettings *levelsettings.Service, meeting *meeting.Service, schedule *schedule.Service, userSettings *usersettings.Service, projects *projects.Service, rps *rps.Service, twitchSvc *twitch.Service, welcomeSvc *welcome.Service, defaultRoleSvc *defaultrole.Service, logSettingsSvc *logsettings.Service) *Services {
s := &Services{
Level: level,
LevelSettings: levelSettings,
@@ -40,6 +42,7 @@ func NewServices(level *level.Service, levelSettings *levelsettings.Service, mee
Twitch: twitchSvc,
Welcome: welcomeSvc,
DefaultRole: defaultRoleSvc,
LogSettings: logSettingsSvc,
}
Global = s
return s