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
+106
View File
@@ -121,6 +121,30 @@ var Config = &discordgo.ApplicationCommand{
},
},
},
{
Type: discordgo.ApplicationCommandOptionSubCommand,
Name: "setlogchannel",
Description: "Set the moderation log channel",
Options: []*discordgo.ApplicationCommandOption{
{
Type: discordgo.ApplicationCommandOptionChannel,
Name: "channel",
Description: "Text channel for logs",
Required: true,
ChannelTypes: []discordgo.ChannelType{discordgo.ChannelTypeGuildText, discordgo.ChannelTypeGuildNews},
},
},
},
{
Type: discordgo.ApplicationCommandOptionSubCommand,
Name: "enablelogging",
Description: "Enable server logging events",
},
{
Type: discordgo.ApplicationCommandOptionSubCommand,
Name: "disablelogging",
Description: "Disable server logging events",
},
},
}
@@ -169,6 +193,15 @@ func ConfigHandler(s *discordgo.Session, i *discordgo.InteractionCreate) {
case "setdefaultrole":
log.Printf("defaultrole: /config setdefaultrole invoked by %s in guild %s", i.Member.User.ID, i.GuildID)
handleSetDefaultRole(s, i)
case "setlogchannel":
log.Printf("log: /config setlogchannel invoked by %s in guild %s", i.Member.User.ID, i.GuildID)
handleSetLogChannel(s, i)
case "enablelogging":
log.Printf("log: /config enablelogging invoked by %s in guild %s", i.Member.User.ID, i.GuildID)
handleSetLoggingEnabled(s, i, true)
case "disablelogging":
log.Printf("log: /config disablelogging invoked by %s in guild %s", i.Member.User.ID, i.GuildID)
handleSetLoggingEnabled(s, i, false)
default:
respondEphemeral(s, i, "Unknown subcommand.")
}
@@ -460,6 +493,79 @@ func handleSetDefaultRole(s *discordgo.Session, i *discordgo.InteractionCreate)
respondEphemeral(s, i, "Default role set to "+role.Mention()+".")
}
func handleSetLogChannel(s *discordgo.Session, i *discordgo.InteractionCreate) {
if services.Global.LogSettings == nil {
respondEphemeral(s, i, "Log settings service is not available.")
return
}
guildID, err := strconv.ParseInt(i.GuildID, 10, 64)
if err != nil {
respondEphemeral(s, i, "Invalid guild ID.")
return
}
opt := i.ApplicationCommandData().Options[0]
var chOpt *discordgo.ApplicationCommandInteractionDataOption
for _, o := range opt.Options {
if o.Name == "channel" {
chOpt = o
break
}
}
if chOpt == nil {
respondEphemeral(s, i, "Missing channel option.")
return
}
ch := chOpt.ChannelValue(s)
if ch == nil {
respondEphemeral(s, i, "Invalid channel.")
return
}
channelID, err := strconv.ParseInt(ch.ID, 10, 64)
if err != nil {
respondEphemeral(s, i, "Invalid channel ID.")
return
}
if err := services.Global.LogSettings.SetChannel(context.Background(), guildID, channelID); err != nil {
respondEphemeral(s, i, "Failed to set log channel.")
return
}
if err := services.Global.LogSettings.SetEnabled(context.Background(), guildID, true); err != nil {
respondEphemeral(s, i, "Log channel set, but failed to enable logging.")
return
}
respondEphemeral(s, i, "Logging enabled in "+ch.Mention()+".")
}
func handleSetLoggingEnabled(s *discordgo.Session, i *discordgo.InteractionCreate, enabled bool) {
if services.Global.LogSettings == nil {
respondEphemeral(s, i, "Log settings service is not available.")
return
}
guildID, err := strconv.ParseInt(i.GuildID, 10, 64)
if err != nil {
respondEphemeral(s, i, "Invalid guild ID.")
return
}
if err := services.Global.LogSettings.SetEnabled(context.Background(), guildID, enabled); err != nil {
respondEphemeral(s, i, "Failed to update logging state.")
return
}
if enabled {
respondEphemeral(s, i, "Logging is now enabled.")
return
}
respondEphemeral(s, i, "Logging is now disabled.")
}
func respondEphemeral(s *discordgo.Session, i *discordgo.InteractionCreate, msg string) {
_ = s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseChannelMessageWithSource,