From 1406767a0a25374281a7d853d6cb32c37d01e4b7 Mon Sep 17 00:00:00 2001 From: Jose Rojo <6jarv91@gmail.com> Date: Thu, 18 Apr 2024 19:31:19 +0100 Subject: [PATCH 01/20] sendAsUserWebhook fix (+1 squashed commits) Squashed commits: [e6afd4d] Change in sendAsUser and other small changes --- cmd/jarvbot/commands.go | 2 +- cmd/jarvbot/config.go | 2 ++ cmd/jarvbot/main.go | 29 +++++++++++++++++------------ cmd/jarvbot/time.go | 2 -- 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/cmd/jarvbot/commands.go b/cmd/jarvbot/commands.go index 856d748..747fbfd 100644 --- a/cmd/jarvbot/commands.go +++ b/cmd/jarvbot/commands.go @@ -57,7 +57,7 @@ func onMessageCreated(ctx context.Context) func(ds *discordgo.Session, mc *disco // the command key must be lowercased var commands = map[string]command{ // public - "!version": simpleTextResponse("v3.6.2"), + "!version": simpleTextResponse("v3.6.3"), "!source": simpleTextResponse("Source code: https://github.com/j4rv/discord-bot"), "!genshindailycheckin": answerGenshinDailyCheckIn, "!genshindailycheckinstop": answerGenshinDailyCheckInStop, diff --git a/cmd/jarvbot/config.go b/cmd/jarvbot/config.go index bb3f360..35eb2a7 100644 --- a/cmd/jarvbot/config.go +++ b/cmd/jarvbot/config.go @@ -17,6 +17,7 @@ const avatarTargetSize = "1024" const cleanStateMessagesCRON = "0 * * * *" const stateMessageMaxLifetime = 12 * time.Hour const maxMessageCount = 100 +const expensiveOperationCooldown = 15 * time.Second // https://discord.com/branding const colorBlue = 0x5865F2 @@ -57,3 +58,4 @@ const commandReceivedMessage = "Gotcha!" const commandSuccessMessage = "Successfully donette!" const commandWithTwoArgumentsError = "Something went wrong, please make sure to use the command with the following format: '!command (...) (...)'" const commandWithMentionError = "Something went wrong, please make sure that the command has an user mention" +const expensiveOperationErrorMsg = "You just executed an expensive operation, please wait." diff --git a/cmd/jarvbot/main.go b/cmd/jarvbot/main.go index c61c3bd..e338c89 100644 --- a/cmd/jarvbot/main.go +++ b/cmd/jarvbot/main.go @@ -3,11 +3,11 @@ package main import ( "context" "flag" + "fmt" "log" "os" "os/signal" "strings" - "syscall" "time" "github.com/bwmarrin/discordgo" @@ -28,17 +28,20 @@ func main() { ds := initDiscordSession() initCRONs(ds) + var removeSlashCommands func() if !noSlashCommands { - removeSlashCommands := initSlashCommands(ds) - defer removeSlashCommands() + removeSlashCommands = initSlashCommands(ds) } // Wait here until CTRL-C or other term signal is received. - log.Println("Bot is now running. Press CTRL-C to exit.") - signalChan := make(chan os.Signal, 1) - signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM, os.Interrupt) - <-signalChan + stop := make(chan os.Signal, 1) + signal.Notify(stop, os.Interrupt) + log.Println("Press Ctrl+C to exit") + <-stop + if !noSlashCommands { + removeSlashCommands() + } ds.Close() } @@ -87,6 +90,7 @@ func initDiscordSession() *discordgo.Session { ds.Identify.Intents |= discordgo.IntentGuildMessages ds.Identify.Intents |= discordgo.IntentGuildMessageReactions ds.Identify.Intents |= discordgo.IntentDirectMessages + ds.Identify.Intents |= discordgo.IntentGuildWebhooks ds.State.MaxMessageCount = maxMessageCount // Open a websocket connection to Discord and begin listening. @@ -175,10 +179,7 @@ func cleanStateMessagesInChannel(ds *discordgo.Session, channel *discordgo.Chann } func sendAsUserWebhook(ds *discordgo.Session, channelID string) (*discordgo.Webhook, error) { - hooks, err := ds.ChannelWebhooks(channelID) - if err != nil { - return nil, err - } + hooks, _ := ds.ChannelWebhooks(channelID) if len(hooks) == 0 { return ds.WebhookCreate(channelID, "SendAsUser", ds.State.User.AvatarURL("")) @@ -194,7 +195,11 @@ func sendAsUser(ds *discordgo.Session, user *discordgo.User, channelID string, c webhook, err := sendAsUserWebhook(ds, channelID) if err != nil { - return nil, err + // webhook didn't work, let's try sending a normal silent message with a mention + return ds.ChannelMessageSendComplex(channelID, &discordgo.MessageSend{ + Content: fmt.Sprintf("%s:\n%s", user.Mention(), content), + AllowedMentions: &discordgo.MessageAllowedMentions{}, + }) } return ds.WebhookExecute(webhook.ID, webhook.Token, false, &discordgo.WebhookParams{ diff --git a/cmd/jarvbot/time.go b/cmd/jarvbot/time.go index 4e32436..8ce508a 100644 --- a/cmd/jarvbot/time.go +++ b/cmd/jarvbot/time.go @@ -14,8 +14,6 @@ var stringMinsRegex = regexp.MustCompile(`^(\d{1,2})m`) var stringSecsRegex = regexp.MustCompile(`^(\d{1,2})s`) const secondsInADay = 60 * 60 * 24 -const expensiveOperationCooldown = 5 * 60 * time.Second -const expensiveOperationErrorMsg = "You just executed an expensive operation, please wait." func removeRoleAfterDuration(ds *discordgo.Session, guildID string, memberID string, roleID string, duration time.Duration) { go func() { From dc66632806efae929a4ea95ae80a659e4682ada1 Mon Sep 17 00:00:00 2001 From: Jose Rojo <6jarv91@gmail.com> Date: Thu, 18 Apr 2024 18:04:16 +0200 Subject: [PATCH 02/20] fix? --- cmd/jarvbot/commands.go | 2 +- cmd/jarvbot/main.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/jarvbot/commands.go b/cmd/jarvbot/commands.go index 747fbfd..369fcb5 100644 --- a/cmd/jarvbot/commands.go +++ b/cmd/jarvbot/commands.go @@ -57,7 +57,7 @@ func onMessageCreated(ctx context.Context) func(ds *discordgo.Session, mc *disco // the command key must be lowercased var commands = map[string]command{ // public - "!version": simpleTextResponse("v3.6.3"), + "!version": simpleTextResponse("v3.6.4"), "!source": simpleTextResponse("Source code: https://github.com/j4rv/discord-bot"), "!genshindailycheckin": answerGenshinDailyCheckIn, "!genshindailycheckinstop": answerGenshinDailyCheckInStop, diff --git a/cmd/jarvbot/main.go b/cmd/jarvbot/main.go index e338c89..41edda8 100644 --- a/cmd/jarvbot/main.go +++ b/cmd/jarvbot/main.go @@ -179,13 +179,13 @@ func cleanStateMessagesInChannel(ds *discordgo.Session, channel *discordgo.Chann } func sendAsUserWebhook(ds *discordgo.Session, channelID string) (*discordgo.Webhook, error) { - hooks, _ := ds.ChannelWebhooks(channelID) + hooks, err := ds.ChannelWebhooks(channelID) if len(hooks) == 0 { return ds.WebhookCreate(channelID, "SendAsUser", ds.State.User.AvatarURL("")) } - return hooks[0], nil + return hooks[0], err } func sendAsUser(ds *discordgo.Session, user *discordgo.User, channelID string, content string) (*discordgo.Message, error) { From 7c7686e4b5c09f5d871e366b7f497531c7df88db Mon Sep 17 00:00:00 2001 From: Jose Rojo <6jarv91@gmail.com> Date: Thu, 18 Apr 2024 18:10:08 +0200 Subject: [PATCH 03/20] Fixed? --- cmd/jarvbot/config.go | 7 ++++++- cmd/jarvbot/main.go | 12 +++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/cmd/jarvbot/config.go b/cmd/jarvbot/config.go index 35eb2a7..01d3077 100644 --- a/cmd/jarvbot/config.go +++ b/cmd/jarvbot/config.go @@ -1,11 +1,16 @@ package main -import "time" +import ( + "errors" + "time" +) // TODO make this a config file var dbFilename = "db.sqlite" +var errNotFound = errors.New("not found") + var zero = 0.0 var strongboxMinAmount = 1.0 var strongboxMaxAmount = 1000.0 diff --git a/cmd/jarvbot/main.go b/cmd/jarvbot/main.go index 41edda8..71bcad4 100644 --- a/cmd/jarvbot/main.go +++ b/cmd/jarvbot/main.go @@ -179,18 +179,20 @@ func cleanStateMessagesInChannel(ds *discordgo.Session, channel *discordgo.Chann } func sendAsUserWebhook(ds *discordgo.Session, channelID string) (*discordgo.Webhook, error) { - hooks, err := ds.ChannelWebhooks(channelID) + hooks, _ := ds.ChannelWebhooks(channelID) - if len(hooks) == 0 { - return ds.WebhookCreate(channelID, "SendAsUser", ds.State.User.AvatarURL("")) + for _, hook := range hooks { + if hook.Name == "SendAsUser" { + return hook, nil + } } - return hooks[0], err + return ds.WebhookCreate(channelID, "SendAsUser", ds.State.User.AvatarURL("")) } func sendAsUser(ds *discordgo.Session, user *discordgo.User, channelID string, content string) (*discordgo.Message, error) { if user == nil || ds == nil || channelID == "" || content == "" { - return nil, nil + return nil, fmt.Errorf("user, ds, channelID, or content is nil") } webhook, err := sendAsUserWebhook(ds, channelID) From 228adf04e841c77a7b0f9d1a33222f729d9d7ef5 Mon Sep 17 00:00:00 2001 From: Jose Rojo <6jarv91@gmail.com> Date: Fri, 19 Apr 2024 16:19:19 +0200 Subject: [PATCH 04/20] Twitter link fix improvements --- README.md | 2 +- cmd/jarvbot/commands.go | 54 ++++++++++++++++++++++++++++++++++- cmd/jarvbot/main.go | 31 ++++++++++++++++++-- cmd/jarvbot/slash_commands.go | 25 +++++++++------- 4 files changed, 97 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 8034bcc..ff29495 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # J4RV's Discord bot -[Add it to your server!](https://discord.com/api/oauth2/authorize?client_id=901475699699875880&permissions=412384290880&scope=bot) +[Add it to your server!](https://discord.com/oauth2/authorize?client_id=901475699699875880&permissions=8&scope=bot) ## How to run: diff --git a/cmd/jarvbot/commands.go b/cmd/jarvbot/commands.go index 369fcb5..164bb81 100644 --- a/cmd/jarvbot/commands.go +++ b/cmd/jarvbot/commands.go @@ -256,6 +256,8 @@ func answerFixTwitterLinks(ds *discordgo.Session, mc *discordgo.MessageCreate, c return err == nil } +var messageLinkFixToOgAuthorId = map[*discordgo.Message]string{} + func processMessageWithTwitterLinks(ds *discordgo.Session, mc *discordgo.MessageCreate, ctx context.Context) { currSetting, _ := serverDS.getServerProperty(mc.GuildID, serverPropFixTwitterLinks) if currSetting != serverPropYes { @@ -263,11 +265,12 @@ func processMessageWithTwitterLinks(ds *discordgo.Session, mc *discordgo.Message } messageContent := ogTwitterLinkRegex.ReplaceAllString(mc.Content, "https://fxtwitter.com") - _, err := sendAsUser(ds, mc.Author, mc.ChannelID, messageContent) + fixedMsg, err := sendAsUser(ds, mc.Author, mc.ChannelID, messageContent, mc.ReferencedMessage) if err != nil { notifyIfErr("processMessageWithTwitterLinks::sendAsUser", err, ds) return } + messageLinkFixToOgAuthorId[fixedMsg] = mc.Author.ID ds.State.MessageRemove(mc.Message) err = ds.ChannelMessageDelete(mc.ChannelID, mc.ID) @@ -277,6 +280,55 @@ func processMessageWithTwitterLinks(ds *discordgo.Session, mc *discordgo.Message } } +func answerDeleteLinkFixMessage(ds *discordgo.Session, ic *discordgo.InteractionCreate) { + interactionUserId := interactionUser(ic).ID + ogAuthorId, ok := messageLinkFixToOgAuthorId[ic.Message] + if !ok && !isAdmin(interactionUserId) { + ds.InteractionRespond(ic.Interaction, &discordgo.InteractionResponse{ + Type: discordgo.InteractionResponseChannelMessageWithSource, + Data: &discordgo.InteractionResponseData{ + Content: "Could not find original author, only a mod can delete that message", + Flags: discordgo.MessageFlagsEphemeral, + }, + }) + return + } + + // Check if the user can delete the message + if interactionUserId != ogAuthorId || !isAdmin(interactionUserId) { + ds.InteractionRespond(ic.Interaction, &discordgo.InteractionResponse{ + Type: discordgo.InteractionResponseChannelMessageWithSource, + Data: &discordgo.InteractionResponseData{ + Content: "You did not send that message", + Flags: discordgo.MessageFlagsEphemeral, + }, + }) + return + } + + // Try to delete and respond if it was successful + fixedMsgID := ic.ApplicationCommandData().TargetID + err := ds.ChannelMessageDelete(ic.ChannelID, fixedMsgID) + notifyIfErr("answerDeleteLinkFixMessage::ChannelMessageDelete", err, ds) + if err != nil { + ds.InteractionRespond(ic.Interaction, &discordgo.InteractionResponse{ + Type: discordgo.InteractionResponseChannelMessageWithSource, + Data: &discordgo.InteractionResponseData{ + Content: "Sorry, I could not delete the message u_u", + Flags: discordgo.MessageFlagsEphemeral, + }, + }) + return + } + ds.InteractionRespond(ic.Interaction, &discordgo.InteractionResponse{ + Type: discordgo.InteractionResponseChannelMessageWithSource, + Data: &discordgo.InteractionResponseData{ + Content: "Message deleted ^w^", + Flags: discordgo.MessageFlagsEphemeral, + }, + }) +} + func answerMessageLogs(ds *discordgo.Session, mc *discordgo.MessageCreate, ctx context.Context) bool { err := serverDS.setServerProperty(mc.GuildID, serverPropMessageLogs, mc.ChannelID) notifyIfErr("answerMessageLogs", err, ds) diff --git a/cmd/jarvbot/main.go b/cmd/jarvbot/main.go index 71bcad4..a806735 100644 --- a/cmd/jarvbot/main.go +++ b/cmd/jarvbot/main.go @@ -129,7 +129,7 @@ func initSlashCommands(ds *discordgo.Session) func() { if h, ok := slashHandlers[ic.ApplicationCommandData().Name]; ok { h(ds, ic) } else { - log.Println("ERROR couldnt add handler for slash command:", ic.ApplicationCommandData().Name) + notifyIfErr("Slash command not found:"+ic.ApplicationCommandData().Name, nil, ds) } }) @@ -140,9 +140,11 @@ func initSlashCommands(ds *discordgo.Session) func() { if err != nil { notifyIfErr("Creating command: "+slashCommand.Name, err, ds) log.Printf("Cannot create '%v' command: %v", slashCommand.Name, err) + continue } registeredCommands[i] = cmd } + log.Println("Finished registering slash commands") return func() { log.Println("Removing registered slash commands...") @@ -167,17 +169,29 @@ func cleanStateMessagesCRONFunc(ds *discordgo.Session) func() { cleanStateMessagesInChannel(ds, gc) } } + for m := range messageLinkFixToOgAuthorId { + if messagePastLifetime(m) { + delete(messageLinkFixToOgAuthorId, m) + } + } } } func cleanStateMessagesInChannel(ds *discordgo.Session, channel *discordgo.Channel) { for _, msg := range channel.Messages { - if msg.Timestamp.Before(time.Now().Add(-stateMessageMaxLifetime)) { + if messagePastLifetime(msg) { ds.State.MessageRemove(msg) } } } +func messagePastLifetime(msg *discordgo.Message) bool { + if msg == nil { + return true + } + return msg.Timestamp.Before(time.Now().Add(-stateMessageMaxLifetime)) +} + func sendAsUserWebhook(ds *discordgo.Session, channelID string) (*discordgo.Webhook, error) { hooks, _ := ds.ChannelWebhooks(channelID) @@ -190,11 +204,22 @@ func sendAsUserWebhook(ds *discordgo.Session, channelID string) (*discordgo.Webh return ds.WebhookCreate(channelID, "SendAsUser", ds.State.User.AvatarURL("")) } -func sendAsUser(ds *discordgo.Session, user *discordgo.User, channelID string, content string) (*discordgo.Message, error) { +// sendAsUser sends a message as the given user +// It will either use a Webhook when possible (to keep the sender's username and avatar) +// Or it will send a normal message with a mention of the original user +func sendAsUser(ds *discordgo.Session, user *discordgo.User, channelID string, content string, referencedMessage *discordgo.Message) (*discordgo.Message, error) { if user == nil || ds == nil || channelID == "" || content == "" { return nil, fmt.Errorf("user, ds, channelID, or content is nil") } + // Webhook doesn't allow "replies" :( + if referencedMessage != nil { + return ds.ChannelMessageSendComplex(channelID, &discordgo.MessageSend{ + Content: content, + Reference: referencedMessage.Reference(), + }) + } + webhook, err := sendAsUserWebhook(ds, channelID) if err != nil { // webhook didn't work, let's try sending a normal silent message with a mention diff --git a/cmd/jarvbot/slash_commands.go b/cmd/jarvbot/slash_commands.go index 7dc8852..a60fd91 100644 --- a/cmd/jarvbot/slash_commands.go +++ b/cmd/jarvbot/slash_commands.go @@ -288,19 +288,24 @@ var slashCommands = []*discordgo.ApplicationCommand{ }, }, }, + { + Name: "Delete LinkFix Message", + Type: discordgo.MessageApplicationCommand, + }, } var slashHandlers = map[string]func(s *discordgo.Session, i *discordgo.InteractionCreate){ - "help": answerHelp, - "8ball": answer8ball, - "avatar": answerAvatar, - "genshin_chances": expensiveSlashCommand(answerGenshinChance), - "star_rail_chances": expensiveSlashCommand(answerStarRailChance), - "strongbox": expensiveSlashCommand(answerStrongbox), - "character": answerCharacter, - "abyss_challenge": answerAbyssChallenge, - "warn": answerWarn, - "warnings": answerWarnings, + "help": answerHelp, + "8ball": answer8ball, + "avatar": answerAvatar, + "genshin_chances": expensiveSlashCommand(answerGenshinChance), + "star_rail_chances": expensiveSlashCommand(answerStarRailChance), + "strongbox": expensiveSlashCommand(answerStrongbox), + "character": answerCharacter, + "abyss_challenge": answerAbyssChallenge, + "warn": answerWarn, + "warnings": answerWarnings, + "Delete LinkFix Message": answerDeleteLinkFixMessage, } func expensiveSlashCommand(expensiveOp func(ds *discordgo.Session, ic *discordgo.InteractionCreate)) func(ds *discordgo.Session, ic *discordgo.InteractionCreate) { From 892825bc57edc97bb6d2d04fda4ef77051d97245 Mon Sep 17 00:00:00 2001 From: Jarv <6jarv91@gmail.com> Date: Fri, 19 Apr 2024 18:11:02 +0200 Subject: [PATCH 05/20] Pixiv link fixing --- cmd/jarvbot/commands.go | 41 +++++++++++++++++++++++++---------------- cmd/jarvbot/config.go | 2 +- cmd/jarvbot/main.go | 5 ++++- 3 files changed, 30 insertions(+), 18 deletions(-) diff --git a/cmd/jarvbot/commands.go b/cmd/jarvbot/commands.go index 164bb81..41b46a3 100644 --- a/cmd/jarvbot/commands.go +++ b/cmd/jarvbot/commands.go @@ -21,11 +21,18 @@ const roleEveryone = "@everyone" const globalGuildID = "" var ogNonRootTwitterLinkRegex = regexp.MustCompile(`\b(?:https?://)?(?:www\.)?(?:twitter|x)\.com/\S+\b`) -var ogTwitterLinkRegex = regexp.MustCompile(`\b(?:https?://)?(?:www\.)?(?:twitter|x)\.com\b`) +var ogNonRootPixivLinkRegex = regexp.MustCompile(`\b(?:https?://)?(?:www\.)?pixiv\.net/\S+\b`) var commandPrefixRegex = regexp.MustCompile(`^!\w+\s*`) var commandWithTwoArguments = regexp.MustCompile(`^!\w+\s*(\(.{1,36}\))\s*(\(.{1,36}\))`) var commandWithMention = regexp.MustCompile(`^!\w+\s*<@!?(\d+)>`) +var badEmbedLinkReplacements = map[*regexp.Regexp]string{ + regexp.MustCompile(`\b(?:https?://)?(?:www\.)?(?:twitter|x)\.com\b`): "https://fxtwitter.com", + regexp.MustCompile(`\b(?:https?://)?(?:www\.)?pixiv\.net\b`): "https://phixiv.net", +} + +var messageLinkFixToOgAuthorId = map[*discordgo.Message]string{} + type command func(*discordgo.Session, *discordgo.MessageCreate, context.Context) bool func onMessageCreated(ctx context.Context) func(ds *discordgo.Session, mc *discordgo.MessageCreate) { @@ -47,8 +54,9 @@ func onMessageCreated(ctx context.Context) func(ds *discordgo.Session, mc *disco } // Twitter links replacement - if ogNonRootTwitterLinkRegex.MatchString(mc.Content) { - processMessageWithTwitterLinks(ds, mc, ctx) + if ogNonRootTwitterLinkRegex.MatchString(mc.Content) || + ogNonRootPixivLinkRegex.MatchString(mc.Content) { + processMessageWithBadEmbedLinks(ds, mc, ctx) return } } @@ -88,7 +96,7 @@ var commands = map[string]command{ "!preventspamming": guildOnly(modOnly(answerPreventSpamming)), "!setcustomtimeoutrole": guildOnly(modOnly(answerSetCustomTimeoutRole)), "!announcehere": guildOnly(modOnly(answerAnnounceHere)), - "!fixtwitterlinks": guildOnly(modOnly(answerFixTwitterLinks)), + "!fixbadembedlinks": guildOnly(modOnly(answerFixBadEmbedLinks)), "!messagelogs": guildOnly(modOnly(answerMessageLogs)), "!commandstats": guildOnly(modOnly(answerCommandStats)), // only available for the bot owner @@ -241,33 +249,34 @@ func answerAnnounceHere(ds *discordgo.Session, mc *discordgo.MessageCreate, ctx return err == nil } -func answerFixTwitterLinks(ds *discordgo.Session, mc *discordgo.MessageCreate, ctx context.Context) bool { - currSetting, _ := serverDS.getServerProperty(mc.GuildID, serverPropFixTwitterLinks) +func answerFixBadEmbedLinks(ds *discordgo.Session, mc *discordgo.MessageCreate, ctx context.Context) bool { + currSetting, _ := serverDS.getServerProperty(mc.GuildID, serverPropFixBadEmbedLinks) newSetting := serverPropYes if currSetting == serverPropYes { newSetting = serverPropNo } - err := serverDS.setServerProperty(mc.GuildID, serverPropFixTwitterLinks, newSetting) + err := serverDS.setServerProperty(mc.GuildID, serverPropFixBadEmbedLinks, newSetting) if err == nil && newSetting == serverPropYes { - ds.ChannelMessageSend(mc.ChannelID, "Okay! Will fix twitter links") + ds.ChannelMessageSend(mc.ChannelID, "Okay! Will fix bad embed links") } else if err == nil && newSetting == serverPropNo { - ds.ChannelMessageSend(mc.ChannelID, "Okay! Will not fix twitter links") + ds.ChannelMessageSend(mc.ChannelID, "Okay! Will not fix bad embed links") } return err == nil } -var messageLinkFixToOgAuthorId = map[*discordgo.Message]string{} - -func processMessageWithTwitterLinks(ds *discordgo.Session, mc *discordgo.MessageCreate, ctx context.Context) { - currSetting, _ := serverDS.getServerProperty(mc.GuildID, serverPropFixTwitterLinks) +func processMessageWithBadEmbedLinks(ds *discordgo.Session, mc *discordgo.MessageCreate, ctx context.Context) { + currSetting, _ := serverDS.getServerProperty(mc.GuildID, serverPropFixBadEmbedLinks) if currSetting != serverPropYes { return } - messageContent := ogTwitterLinkRegex.ReplaceAllString(mc.Content, "https://fxtwitter.com") + messageContent := mc.Content + for rgx, rpl := range badEmbedLinkReplacements { + messageContent = rgx.ReplaceAllString(messageContent, rpl) + } fixedMsg, err := sendAsUser(ds, mc.Author, mc.ChannelID, messageContent, mc.ReferencedMessage) if err != nil { - notifyIfErr("processMessageWithTwitterLinks::sendAsUser", err, ds) + notifyIfErr("processMessageWithBadEmbedLinks::sendAsUser", err, ds) return } messageLinkFixToOgAuthorId[fixedMsg] = mc.Author.ID @@ -275,7 +284,7 @@ func processMessageWithTwitterLinks(ds *discordgo.Session, mc *discordgo.Message ds.State.MessageRemove(mc.Message) err = ds.ChannelMessageDelete(mc.ChannelID, mc.ID) if err != nil { - notifyIfErr("processMessageWithTwitterLinks::ds.ChannelMessageDelete", err, ds) + notifyIfErr("processMessageWithBadEmbedLinks::ds.ChannelMessageDelete", err, ds) return } } diff --git a/cmd/jarvbot/config.go b/cmd/jarvbot/config.go index 01d3077..fd7828c 100644 --- a/cmd/jarvbot/config.go +++ b/cmd/jarvbot/config.go @@ -32,7 +32,7 @@ const colorRed = 0xED4245 const serverPropCustomTimeoutRoleName = "custom_timeout_role_name" const serverPropAnnounceHere = "announce_here" const serverPropMessageLogs = "message_logs" -const serverPropFixTwitterLinks = "fix_twitter_links" +const serverPropFixBadEmbedLinks = "fix_twitter_links" const serverPropYes = "Y" const serverPropNo = "N" diff --git a/cmd/jarvbot/main.go b/cmd/jarvbot/main.go index a806735..74ffac4 100644 --- a/cmd/jarvbot/main.go +++ b/cmd/jarvbot/main.go @@ -215,8 +215,11 @@ func sendAsUser(ds *discordgo.Session, user *discordgo.User, channelID string, c // Webhook doesn't allow "replies" :( if referencedMessage != nil { return ds.ChannelMessageSendComplex(channelID, &discordgo.MessageSend{ - Content: content, + Content: fmt.Sprintf("%s:\n%s", user.Mention(), content), Reference: referencedMessage.Reference(), + AllowedMentions: &discordgo.MessageAllowedMentions{ + RepliedUser: true, + }, }) } From 02af6938017cbdcc70b351bfea3d81817624fd69 Mon Sep 17 00:00:00 2001 From: Jarv <6jarv91@gmail.com> Date: Fri, 19 Apr 2024 18:11:25 +0200 Subject: [PATCH 06/20] Version change --- cmd/jarvbot/commands.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/jarvbot/commands.go b/cmd/jarvbot/commands.go index 41b46a3..cf73d38 100644 --- a/cmd/jarvbot/commands.go +++ b/cmd/jarvbot/commands.go @@ -65,7 +65,7 @@ func onMessageCreated(ctx context.Context) func(ds *discordgo.Session, mc *disco // the command key must be lowercased var commands = map[string]command{ // public - "!version": simpleTextResponse("v3.6.4"), + "!version": simpleTextResponse("v3.6.5"), "!source": simpleTextResponse("Source code: https://github.com/j4rv/discord-bot"), "!genshindailycheckin": answerGenshinDailyCheckIn, "!genshindailycheckinstop": answerGenshinDailyCheckInStop, From 01b3f6493a6bb8b869534bbd582c50f93fc56430 Mon Sep 17 00:00:00 2001 From: Jose Rojo <6jarv91@gmail.com> Date: Wed, 15 May 2024 19:21:19 +0100 Subject: [PATCH 07/20] Explosion change and message edited log change --- README.md | 2 +- cmd/jarvbot/bunker.go | 10 ++++++++-- cmd/jarvbot/commands.go | 4 ++-- cmd/jarvbot/main.go | 12 ++++++++---- cmd/jarvbot/modding.go | 4 ++-- go.mod | 1 + go.sum | 6 ++---- 7 files changed, 24 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index ff29495..acfb579 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # J4RV's Discord bot -[Add it to your server!](https://discord.com/oauth2/authorize?client_id=901475699699875880&permissions=8&scope=bot) +[Add it to your server!](https://discord.com/oauth2/authorize?client_id=901475699699875880) ## How to run: diff --git a/cmd/jarvbot/bunker.go b/cmd/jarvbot/bunker.go index da80482..91a95ea 100644 --- a/cmd/jarvbot/bunker.go +++ b/cmd/jarvbot/bunker.go @@ -140,8 +140,14 @@ func shoot(ds *discordgo.Session, channelID string, guildID string, shooter *dis if member.User.ID == ds.State.User.ID { continue } - ds.GuildMemberRoleAdd(guildID, member.User.ID, timeoutRoleID) - removeRoleAfterDuration(ds, guildID, member.User.ID, timeoutRoleID, timeoutDurationWhenNuclearCatastrophe) + if rand.Float32() <= 0.02 { + ds.ChannelMessageSendComplex(channelID, &discordgo.MessageSend{ + Content: fmt.Sprintf("%s died in the explosion!", member.User.Mention()), + AllowedMentions: &discordgo.MessageAllowedMentions{}, + }) + ds.GuildMemberRoleAdd(guildID, member.User.ID, timeoutRoleID) + removeRoleAfterDuration(ds, guildID, member.User.ID, timeoutRoleID, timeoutDurationWhenNuclearCatastrophe) + } } return nil } diff --git a/cmd/jarvbot/commands.go b/cmd/jarvbot/commands.go index cf73d38..c791f54 100644 --- a/cmd/jarvbot/commands.go +++ b/cmd/jarvbot/commands.go @@ -370,7 +370,7 @@ func answerAddCommand(ds *discordgo.Session, mc *discordgo.MessageCreate, ctx co commandBody := commandPrefixRegex.ReplaceAllString(mc.Content, "") key := strings.TrimSpace(commandPrefixRegex.FindString(commandBody)) if key == "" { - ds.ChannelMessageSend(mc.ChannelID, diff("Could not get the key from the command body", "- ")) + ds.ChannelMessageSend(mc.ChannelID, markdownDiffBlock("Could not get the key from the command body", "- ")) return false } response := commandPrefixRegex.ReplaceAllString(commandBody, "") @@ -386,7 +386,7 @@ func answerAddGlobalCommand(ds *discordgo.Session, mc *discordgo.MessageCreate, commandBody := commandPrefixRegex.ReplaceAllString(mc.Content, "") key := strings.TrimSpace(commandPrefixRegex.FindString(commandBody)) if key == "" { - ds.ChannelMessageSend(mc.ChannelID, diff("Could not get the key from the command body", "- ")) + ds.ChannelMessageSend(mc.ChannelID, markdownDiffBlock("Could not get the key from the command body", "- ")) return false } response := commandPrefixRegex.ReplaceAllString(commandBody, "") diff --git a/cmd/jarvbot/main.go b/cmd/jarvbot/main.go index 74ffac4..536ca9d 100644 --- a/cmd/jarvbot/main.go +++ b/cmd/jarvbot/main.go @@ -239,11 +239,15 @@ func sendAsUser(ds *discordgo.Session, user *discordgo.User, channelID string, c }) } -func diff(body, prefix string) string { +func markdownDiffBlock(body, prefix string) string { lines := strings.Split(body, "\n") var formattedBody string - for _, line := range lines { - formattedBody += prefix + line + "\n" + if prefix == "" { + formattedBody = body + } else { + for _, line := range lines { + formattedBody += prefix + line + "\n" + } } return "```diff\n" + formattedBody + "```" } @@ -252,6 +256,6 @@ func notifyIfErr(context string, err error, ds *discordgo.Session) { if err != nil { msg := "ERROR [" + context + "]: " + err.Error() log.Println(msg) - sendDirectMessage(adminID, diff(msg, "- "), ds) + sendDirectMessage(adminID, markdownDiffBlock(msg, "- "), ds) } } diff --git a/cmd/jarvbot/modding.go b/cmd/jarvbot/modding.go index 977ccb8..2ae677b 100644 --- a/cmd/jarvbot/modding.go +++ b/cmd/jarvbot/modding.go @@ -6,6 +6,7 @@ import ( "time" "github.com/bwmarrin/discordgo" + "github.com/kylelemons/godebug/diff" ) func onMessageDeleted(ctx context.Context) func(ds *discordgo.Session, mc *discordgo.MessageDelete) { @@ -166,8 +167,7 @@ func messageUpdatedToString(from, to *discordgo.Message) string { if from.Author != nil { str += "\nAuthor: " + from.Author.Mention() } - str += diff(from.Content, "- ") - str += diff(to.Content, "+ ") + str += markdownDiffBlock(diff.Diff(from.Content, to.Content), "") str += fmt.Sprintf("\n[Link to message](https://discord.com/channels/%s/%s/%s)", from.GuildID, from.ChannelID, from.ID) return str diff --git a/go.mod b/go.mod index ad0b1f6..8b6abb2 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/j4rv/genshinartis v0.0.0-20230911183910-b19c3dc323f3 github.com/j4rv/rollssim v0.0.0-20240404184348-3de18bb2de33 github.com/jmoiron/sqlx v1.3.5 + github.com/kylelemons/godebug v1.1.0 github.com/mattn/go-sqlite3 v1.14.22 github.com/robfig/cron/v3 v3.0.1 ) diff --git a/go.sum b/go.sum index d22e124..8d18d4f 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,3 @@ -github.com/bwmarrin/discordgo v0.27.1 h1:ib9AIc/dom1E/fSIulrBwnez0CToJE113ZGt4HoliGY= -github.com/bwmarrin/discordgo v0.27.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY= github.com/bwmarrin/discordgo v0.28.1 h1:gXsuo2GBO7NbR6uqmrrBDplPUx2T3nzu775q/Rd1aG4= github.com/bwmarrin/discordgo v0.28.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY= github.com/enescakir/emoji v1.0.0 h1:W+HsNql8swfCQFtioDGDHCHri8nudlK1n5p2rHCJoog= @@ -11,12 +9,12 @@ github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/ github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/j4rv/genshinartis v0.0.0-20230911183910-b19c3dc323f3 h1:bdBq6XxKRQvZWRyunxC/Svo5cTEfJ49S75qBvOUSH9w= github.com/j4rv/genshinartis v0.0.0-20230911183910-b19c3dc323f3/go.mod h1:NXUI4xa2rw8D2BjTBqgT6934wIJXJgn1vG9x/FGXW4E= -github.com/j4rv/rollssim v0.0.0-20240329011720-1ac34fe7b422 h1:hB8eYD6EUsqv8KagIC/vVrm1/k9exSi/o+Za2fcvTrM= -github.com/j4rv/rollssim v0.0.0-20240329011720-1ac34fe7b422/go.mod h1:giZ+GfPdq1sGjpWZHM5YSQ7Pfz2/doB9I2uSUXl/ZxU= github.com/j4rv/rollssim v0.0.0-20240404184348-3de18bb2de33 h1:cGdwtbBohkaKAc/b4RDz/Yv0J3J7RRJktf+1RVkk9Hg= github.com/j4rv/rollssim v0.0.0-20240404184348-3de18bb2de33/go.mod h1:giZ+GfPdq1sGjpWZHM5YSQ7Pfz2/doB9I2uSUXl/ZxU= github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= From 1e26c24c09756d5bf2e08842dbc02379d5306273 Mon Sep 17 00:00:00 2001 From: Jose Rojo <6jarv91@gmail.com> Date: Wed, 15 May 2024 19:36:19 +0100 Subject: [PATCH 08/20] Fix for message link deletion --- cmd/jarvbot/config.go | 2 +- cmd/jarvbot/main.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/jarvbot/config.go b/cmd/jarvbot/config.go index fd7828c..5d4d51c 100644 --- a/cmd/jarvbot/config.go +++ b/cmd/jarvbot/config.go @@ -20,7 +20,7 @@ var warnMessageMaxLength = 320 const avatarTargetSize = "1024" const cleanStateMessagesCRON = "0 * * * *" -const stateMessageMaxLifetime = 12 * time.Hour +const stateMessageMaxLifetime = 24 * time.Hour const maxMessageCount = 100 const expensiveOperationCooldown = 15 * time.Second diff --git a/cmd/jarvbot/main.go b/cmd/jarvbot/main.go index 536ca9d..e1d83a1 100644 --- a/cmd/jarvbot/main.go +++ b/cmd/jarvbot/main.go @@ -232,7 +232,7 @@ func sendAsUser(ds *discordgo.Session, user *discordgo.User, channelID string, c }) } - return ds.WebhookExecute(webhook.ID, webhook.Token, false, &discordgo.WebhookParams{ + return ds.WebhookExecute(webhook.ID, webhook.Token, true, &discordgo.WebhookParams{ Content: content, Username: user.GlobalName, AvatarURL: user.AvatarURL(""), From a6a588675944d7d11bc16066f75afb08545e0e7a Mon Sep 17 00:00:00 2001 From: Jose Rojo <6jarv91@gmail.com> Date: Tue, 21 May 2024 14:56:13 +0200 Subject: [PATCH 09/20] Message updated change --- cmd/jarvbot/commands.go | 2 +- cmd/jarvbot/modding.go | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/cmd/jarvbot/commands.go b/cmd/jarvbot/commands.go index c791f54..0c35fb2 100644 --- a/cmd/jarvbot/commands.go +++ b/cmd/jarvbot/commands.go @@ -65,7 +65,7 @@ func onMessageCreated(ctx context.Context) func(ds *discordgo.Session, mc *disco // the command key must be lowercased var commands = map[string]command{ // public - "!version": simpleTextResponse("v3.6.5"), + "!version": simpleTextResponse("v3.6.6"), "!source": simpleTextResponse("Source code: https://github.com/j4rv/discord-bot"), "!genshindailycheckin": answerGenshinDailyCheckIn, "!genshindailycheckinstop": answerGenshinDailyCheckInStop, diff --git a/cmd/jarvbot/modding.go b/cmd/jarvbot/modding.go index 2ae677b..b19fc72 100644 --- a/cmd/jarvbot/modding.go +++ b/cmd/jarvbot/modding.go @@ -12,8 +12,8 @@ import ( func onMessageDeleted(ctx context.Context) func(ds *discordgo.Session, mc *discordgo.MessageDelete) { return func(ds *discordgo.Session, mc *discordgo.MessageDelete) { if mc.BeforeDelete != nil && mc.BeforeDelete.Author != nil { - // dont mind if the bot messages get deleted - if mc.BeforeDelete.Author.ID == ds.State.User.ID { + // dont mind if bot messages get deleted + if mc.Author.Bot { return } @@ -40,13 +40,19 @@ func onMessageDeleted(ctx context.Context) func(ds *discordgo.Session, mc *disco func onMessageUpdated(ctx context.Context) func(ds *discordgo.Session, mc *discordgo.MessageUpdate) { return func(ds *discordgo.Session, mc *discordgo.MessageUpdate) { if mc.BeforeUpdate != nil && mc.Author != nil { + if mc.Author.Bot { + return + } + logsChannelID, err := serverDS.getServerProperty(mc.GuildID, serverPropMessageLogs) if err != nil { return } + if mc.BeforeUpdate.Content == mc.Message.Content { return } + ds.ChannelMessageSendEmbed( logsChannelID, &discordgo.MessageEmbed{ From 1e3672d33ddf7385aaff205b9dbb46359d71d66e Mon Sep 17 00:00:00 2001 From: Jose Rojo <6jarv91@gmail.com> Date: Wed, 12 Jun 2024 13:49:26 +0200 Subject: [PATCH 10/20] Added adjectives to genshinchargen --- cmd/jarvbot/commands.go | 2 +- pkg/genshinchargen/main.go | 50 ++++++++++++++++++++++++++++---------- 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/cmd/jarvbot/commands.go b/cmd/jarvbot/commands.go index 0c35fb2..7cebc51 100644 --- a/cmd/jarvbot/commands.go +++ b/cmd/jarvbot/commands.go @@ -65,7 +65,7 @@ func onMessageCreated(ctx context.Context) func(ds *discordgo.Session, mc *disco // the command key must be lowercased var commands = map[string]command{ // public - "!version": simpleTextResponse("v3.6.6"), + "!version": simpleTextResponse("v3.6.7"), "!source": simpleTextResponse("Source code: https://github.com/j4rv/discord-bot"), "!genshindailycheckin": answerGenshinDailyCheckIn, "!genshindailycheckinstop": answerGenshinDailyCheckInStop, diff --git a/pkg/genshinchargen/main.go b/pkg/genshinchargen/main.go index fa8395c..003b585 100644 --- a/pkg/genshinchargen/main.go +++ b/pkg/genshinchargen/main.go @@ -58,17 +58,39 @@ var models = NewWeightedSlice(map[string]int{ "Short female": 40, }) +var visualAdjectives = NewWeightedSlice(map[string]int{ + "Boring": 10, + "Elegant": 10, + "Ferocious": 10, + "Graceful": 10, + "Mysterious": 10, + "Sickly": 10, + "Intimidating": 10, + "Muscular": 10, + "Fit": 10, + "Skinny": 10, + "Cute": 10, + "Soft": 10, + "Furry": 5, + "Bulky": 5, + "Brawny": 5, + "Barefoot": 5, + "Gloomy": 5, + "Gothic": 5, + "Slutty": 2, +}) + var scaling = NewWeightedSlice(map[string]int{ "ATK": 500, "HP": 200, "DEF": 100, "EM": 100, - "Energy Recharge": 30, + "Energy Recharge": 20, "EM and ATK": 20, "HP and ATK": 20, "DEF and ATK": 20, "Healing Bonus": 20, - "Shield Strength": 1, + "Shield Strength": 5, }) var roles = NewWeightedSlice(map[string]int{ @@ -126,20 +148,21 @@ var weaknesses = NewWeightedSlice(map[string]int{ }) type GeneratedCharacter struct { - name string - rarity string - element string - weapon string - model string - scaling string - role string - strength string - weakness string + name string + rarity string + element string + weapon string + model string + adjective string + scaling string + role string + strength string + weakness string } func (c GeneratedCharacter) PrettyString() string { - return fmt.Sprintf("%s is a %s %s character.\nWeapon: %s.\nModel: %s.\nKit: %s, scales with %s, %s but %s.", - c.name, c.rarity, c.element, c.weapon, c.model, c.role, c.scaling, c.strength, c.weakness) + return fmt.Sprintf("%s is a %s %s character.\nWeapon: %s.\nModel: %s %s.\nKit: %s, scales with %s, %s but %s.", + c.name, c.rarity, c.element, c.weapon, c.adjective, c.model, c.role, c.scaling, c.strength, c.weakness) } func NewChar(name string, seedSalt int64) GeneratedCharacter { @@ -155,6 +178,7 @@ func NewChar(name string, seedSalt int64) GeneratedCharacter { result.role = roles.Random(rng) result.strength = strengths.Random(rng) result.weakness = weaknesses.Random(rng) + result.adjective = visualAdjectives.Random(rng) return result } From d311eadaa01c18c5eb5731f0553c68a2442c0319 Mon Sep 17 00:00:00 2001 From: Jose Rojo <6jarv91@gmail.com> Date: Thu, 13 Jun 2024 11:47:01 +0200 Subject: [PATCH 11/20] Fixes --- cmd/jarvbot/commands.go | 2 +- cmd/jarvbot/modding.go | 4 +++- cmd/jarvbot/time.go | 7 ++++++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/cmd/jarvbot/commands.go b/cmd/jarvbot/commands.go index 7cebc51..1e6fef8 100644 --- a/cmd/jarvbot/commands.go +++ b/cmd/jarvbot/commands.go @@ -65,7 +65,7 @@ func onMessageCreated(ctx context.Context) func(ds *discordgo.Session, mc *disco // the command key must be lowercased var commands = map[string]command{ // public - "!version": simpleTextResponse("v3.6.7"), + "!version": simpleTextResponse("v3.6.8"), "!source": simpleTextResponse("Source code: https://github.com/j4rv/discord-bot"), "!genshindailycheckin": answerGenshinDailyCheckIn, "!genshindailycheckinstop": answerGenshinDailyCheckInStop, diff --git a/cmd/jarvbot/modding.go b/cmd/jarvbot/modding.go index b19fc72..97fb86e 100644 --- a/cmd/jarvbot/modding.go +++ b/cmd/jarvbot/modding.go @@ -13,7 +13,7 @@ func onMessageDeleted(ctx context.Context) func(ds *discordgo.Session, mc *disco return func(ds *discordgo.Session, mc *discordgo.MessageDelete) { if mc.BeforeDelete != nil && mc.BeforeDelete.Author != nil { // dont mind if bot messages get deleted - if mc.Author.Bot { + if mc.BeforeDelete.Author.Bot { return } @@ -21,6 +21,7 @@ func onMessageDeleted(ctx context.Context) func(ds *discordgo.Session, mc *disco if err != nil { return } + ds.ChannelMessageSendEmbed( logsChannelID, &discordgo.MessageEmbed{ @@ -40,6 +41,7 @@ func onMessageDeleted(ctx context.Context) func(ds *discordgo.Session, mc *disco func onMessageUpdated(ctx context.Context) func(ds *discordgo.Session, mc *discordgo.MessageUpdate) { return func(ds *discordgo.Session, mc *discordgo.MessageUpdate) { if mc.BeforeUpdate != nil && mc.Author != nil { + // dont mind if bot messages get updated if mc.Author.Bot { return } diff --git a/cmd/jarvbot/time.go b/cmd/jarvbot/time.go index 8ce508a..95b1b6a 100644 --- a/cmd/jarvbot/time.go +++ b/cmd/jarvbot/time.go @@ -18,7 +18,12 @@ const secondsInADay = 60 * 60 * 24 func removeRoleAfterDuration(ds *discordgo.Session, guildID string, memberID string, roleID string, duration time.Duration) { go func() { time.Sleep(duration) - ds.GuildMemberRoleRemove(guildID, memberID, roleID) + err := ds.GuildMemberRoleRemove(guildID, memberID, roleID) + if err != nil { + notifyIfErr("removeRoleAfterDuration", err, ds) + // try again in a minute + removeRoleAfterDuration(ds, guildID, memberID, roleID, time.Minute) + } }() } From 05ecc0b63a346774fa0a70207078b44780882012 Mon Sep 17 00:00:00 2001 From: Jose Rojo <6jarv91@gmail.com> Date: Thu, 20 Jun 2024 10:19:56 +0200 Subject: [PATCH 12/20] Small changes --- cmd/jarvbot/commands.go | 2 +- pkg/genshinchargen/main.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/jarvbot/commands.go b/cmd/jarvbot/commands.go index 1e6fef8..20fbfa6 100644 --- a/cmd/jarvbot/commands.go +++ b/cmd/jarvbot/commands.go @@ -65,7 +65,7 @@ func onMessageCreated(ctx context.Context) func(ds *discordgo.Session, mc *disco // the command key must be lowercased var commands = map[string]command{ // public - "!version": simpleTextResponse("v3.6.8"), + "!version": simpleTextResponse("v3.6.9"), "!source": simpleTextResponse("Source code: https://github.com/j4rv/discord-bot"), "!genshindailycheckin": answerGenshinDailyCheckIn, "!genshindailycheckinstop": answerGenshinDailyCheckInStop, diff --git a/pkg/genshinchargen/main.go b/pkg/genshinchargen/main.go index 003b585..e8e1ef7 100644 --- a/pkg/genshinchargen/main.go +++ b/pkg/genshinchargen/main.go @@ -77,7 +77,7 @@ var visualAdjectives = NewWeightedSlice(map[string]int{ "Barefoot": 5, "Gloomy": 5, "Gothic": 5, - "Slutty": 2, + "Vtuber": 2, }) var scaling = NewWeightedSlice(map[string]int{ From 332e10721227227c52b5ca32873aaacdd847cdcd Mon Sep 17 00:00:00 2001 From: Jarv <6jarv91@gmail.com> Date: Sat, 6 Jul 2024 18:21:52 +0200 Subject: [PATCH 13/20] Added ZZZ to daily web links --- cmd/jarvbot/commands.go | 2 +- cmd/jarvbot/config.go | 5 +++-- go.mod | 3 ++- go.sum | 4 ++++ 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/cmd/jarvbot/commands.go b/cmd/jarvbot/commands.go index 20fbfa6..9112cf8 100644 --- a/cmd/jarvbot/commands.go +++ b/cmd/jarvbot/commands.go @@ -65,7 +65,7 @@ func onMessageCreated(ctx context.Context) func(ds *discordgo.Session, mc *disco // the command key must be lowercased var commands = map[string]command{ // public - "!version": simpleTextResponse("v3.6.9"), + "!version": simpleTextResponse("v3.6.10"), "!source": simpleTextResponse("Source code: https://github.com/j4rv/discord-bot"), "!genshindailycheckin": answerGenshinDailyCheckIn, "!genshindailycheckinstop": answerGenshinDailyCheckInStop, diff --git a/cmd/jarvbot/config.go b/cmd/jarvbot/config.go index 5d4d51c..5c54a4b 100644 --- a/cmd/jarvbot/config.go +++ b/cmd/jarvbot/config.go @@ -46,8 +46,9 @@ const timeoutDurationWhenNuclearCatastrophe = 2 * time.Minute const backupCRON = "0 0 * * 1" const dailyCheckInReminderCRON = "CRON_TZ=Asia/Shanghai 0 0 * * *" const dailyCheckInReminderMessage = `Remember to do the Daily Check-In! -- Genshin: https://webstatic-sea.mihoyo.com/ys/event/signin-sea/index.html?act_id=e202102251931481 -- Star Rail: https://act.hoyolab.com/bbs/event/signin/hkrpg/index.html?act_id=e202303301540311 +- Genshin Impact: https://webstatic-sea.mihoyo.com/ys/event/signin-sea/index.html?act_id=e202102251931481 +- Honkai: Star Rail: https://act.hoyolab.com/bbs/event/signin/hkrpg/index.html?act_id=e202303301540311 +- Zenless Zone Zero: https://act.hoyolab.com/bbs/event/signin/zzz/e202406031448091.html?act_id=e202406031448091 Use !genshindailycheckinstop if you want to stop these reminders.` const parametricReminderCRON = "0 * * * *" const parametricReminderMessage = "Remember to use the Parametric Transformer!\nI will remind you again in 7 days.\nUse !parametrictransformerstop if you want to stop these reminders." diff --git a/go.mod b/go.mod index 8b6abb2..17e7854 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/bwmarrin/discordgo v0.28.1 github.com/enescakir/emoji v1.0.0 - github.com/j4rv/genshinartis v0.0.0-20230911183910-b19c3dc323f3 + github.com/j4rv/genshinartis v0.0.0-20240510155157-e4a2078f376f github.com/j4rv/rollssim v0.0.0-20240404184348-3de18bb2de33 github.com/jmoiron/sqlx v1.3.5 github.com/kylelemons/godebug v1.1.0 @@ -15,6 +15,7 @@ require ( require ( github.com/gorilla/websocket v1.5.1 // indirect + github.com/mroth/weightedrand/v2 v2.1.0 // indirect golang.org/x/crypto v0.21.0 // indirect golang.org/x/net v0.22.0 // indirect golang.org/x/sys v0.18.0 // indirect diff --git a/go.sum b/go.sum index 8d18d4f..4e6f57b 100644 --- a/go.sum +++ b/go.sum @@ -9,6 +9,8 @@ github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/ github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/j4rv/genshinartis v0.0.0-20230911183910-b19c3dc323f3 h1:bdBq6XxKRQvZWRyunxC/Svo5cTEfJ49S75qBvOUSH9w= github.com/j4rv/genshinartis v0.0.0-20230911183910-b19c3dc323f3/go.mod h1:NXUI4xa2rw8D2BjTBqgT6934wIJXJgn1vG9x/FGXW4E= +github.com/j4rv/genshinartis v0.0.0-20240510155157-e4a2078f376f h1:Qkb60dXQpQFebxNxWsebOsyZ39JJzq/1B0vWO8IvPwI= +github.com/j4rv/genshinartis v0.0.0-20240510155157-e4a2078f376f/go.mod h1:6XYkTXc4nhiZmc3caNnjmE8TaWLAwKtRXiK/VdTAuUI= github.com/j4rv/rollssim v0.0.0-20240404184348-3de18bb2de33 h1:cGdwtbBohkaKAc/b4RDz/Yv0J3J7RRJktf+1RVkk9Hg= github.com/j4rv/rollssim v0.0.0-20240404184348-3de18bb2de33/go.mod h1:giZ+GfPdq1sGjpWZHM5YSQ7Pfz2/doB9I2uSUXl/ZxU= github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= @@ -20,6 +22,8 @@ github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/mroth/weightedrand/v2 v2.1.0 h1:o1ascnB1CIVzsqlfArQQjeMy1U0NcIbBO5rfd5E/OeU= +github.com/mroth/weightedrand/v2 v2.1.0/go.mod h1:f2faGsfOGOwc1p94wzHKKZyTpcJUW7OJ/9U4yfiNAOU= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= From 9ed5481e77cd4479a947cc4b7bd3c5d5ce84ade4 Mon Sep 17 00:00:00 2001 From: Jose Rojo <6jarv91@gmail.com> Date: Tue, 3 Sep 2024 11:22:36 +0200 Subject: [PATCH 14/20] Small fixes --- cmd/jarvbot/commands.go | 16 +++++++++++++++- cmd/jarvbot/config.go | 6 +++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/cmd/jarvbot/commands.go b/cmd/jarvbot/commands.go index 9112cf8..7148a3b 100644 --- a/cmd/jarvbot/commands.go +++ b/cmd/jarvbot/commands.go @@ -65,7 +65,7 @@ func onMessageCreated(ctx context.Context) func(ds *discordgo.Session, mc *disco // the command key must be lowercased var commands = map[string]command{ // public - "!version": simpleTextResponse("v3.6.10"), + "!version": simpleTextResponse("v3.6.11"), "!source": simpleTextResponse("Source code: https://github.com/j4rv/discord-bot"), "!genshindailycheckin": answerGenshinDailyCheckIn, "!genshindailycheckinstop": answerGenshinDailyCheckInStop, @@ -374,6 +374,10 @@ func answerAddCommand(ds *discordgo.Session, mc *discordgo.MessageCreate, ctx co return false } response := commandPrefixRegex.ReplaceAllString(commandBody, "") + if response == "" { + ds.ChannelMessageSend(mc.ChannelID, markdownDiffBlock("Could not get the response from the command body", "- ")) + return false + } err := commandDS.addSimpleCommand(key, response, mc.GuildID) notifyIfErr("addSimpleCommand", err, ds) if err == nil { @@ -390,6 +394,10 @@ func answerAddGlobalCommand(ds *discordgo.Session, mc *discordgo.MessageCreate, return false } response := commandPrefixRegex.ReplaceAllString(commandBody, "") + if response == "" { + ds.ChannelMessageSend(mc.ChannelID, markdownDiffBlock("Could not get the response from the command body", "- ")) + return false + } err := commandDS.addSimpleCommand(key, response, globalGuildID) notifyIfErr("addGlobalCommand", err, ds) if err == nil { @@ -401,6 +409,9 @@ func answerAddGlobalCommand(ds *discordgo.Session, mc *discordgo.MessageCreate, func answerRemoveCommand(ds *discordgo.Session, mc *discordgo.MessageCreate, ctx context.Context) bool { commandBody := strings.TrimSpace(commandPrefixRegex.ReplaceAllString(mc.Content, "")) err := commandDS.removeSimpleCommand(commandBody, mc.GuildID) + if err == errZeroRowsAffected { + ds.ChannelMessageSend(mc.ChannelID, "I could not find that command! sowwy u_u") + } notifyIfErr("removeSimpleCommand", err, ds) if err == nil { ds.ChannelMessageSend(mc.ChannelID, commandSuccessMessage) @@ -411,6 +422,9 @@ func answerRemoveCommand(ds *discordgo.Session, mc *discordgo.MessageCreate, ctx func answerRemoveGlobalCommand(ds *discordgo.Session, mc *discordgo.MessageCreate, ctx context.Context) bool { commandBody := strings.TrimSpace(commandPrefixRegex.ReplaceAllString(mc.Content, "")) err := commandDS.removeSimpleCommand(commandBody, globalGuildID) + if err == errZeroRowsAffected { + ds.ChannelMessageSend(mc.ChannelID, "I could not find that command! sowwy u_u") + } notifyIfErr("removeGlobalCommand", err, ds) if err == nil { ds.ChannelMessageSend(mc.ChannelID, commandSuccessMessage) diff --git a/cmd/jarvbot/config.go b/cmd/jarvbot/config.go index 5c54a4b..afec5bb 100644 --- a/cmd/jarvbot/config.go +++ b/cmd/jarvbot/config.go @@ -46,9 +46,9 @@ const timeoutDurationWhenNuclearCatastrophe = 2 * time.Minute const backupCRON = "0 0 * * 1" const dailyCheckInReminderCRON = "CRON_TZ=Asia/Shanghai 0 0 * * *" const dailyCheckInReminderMessage = `Remember to do the Daily Check-In! -- Genshin Impact: https://webstatic-sea.mihoyo.com/ys/event/signin-sea/index.html?act_id=e202102251931481 -- Honkai: Star Rail: https://act.hoyolab.com/bbs/event/signin/hkrpg/index.html?act_id=e202303301540311 -- Zenless Zone Zero: https://act.hoyolab.com/bbs/event/signin/zzz/e202406031448091.html?act_id=e202406031448091 +- [Genshin Impact](https://webstatic-sea.mihoyo.com/ys/event/signin-sea/index.html?act_id=e202102251931481) +- [Honkai: Star Rail](https://act.hoyolab.com/bbs/event/signin/hkrpg/index.html?act_id=e202303301540311) +- [Zenless Zone Zero](https://act.hoyolab.com/bbs/event/signin/zzz/e202406031448091.html?act_id=e202406031448091) Use !genshindailycheckinstop if you want to stop these reminders.` const parametricReminderCRON = "0 * * * *" const parametricReminderMessage = "Remember to use the Parametric Transformer!\nI will remind you again in 7 days.\nUse !parametrictransformerstop if you want to stop these reminders." From 969c60e3c1a605a17cbdc005c33f686ffddbaecf Mon Sep 17 00:00:00 2001 From: Jarv <6jarv91@gmail.com> Date: Sun, 15 Sep 2024 02:50:41 +0200 Subject: [PATCH 15/20] Genshin char gen changes --- pkg/genshinchargen/main.go | 81 +++++++++++++++++++++++++++++++-- pkg/genshinchargen/main_test.go | 20 +++++--- 2 files changed, 91 insertions(+), 10 deletions(-) diff --git a/pkg/genshinchargen/main.go b/pkg/genshinchargen/main.go index e8e1ef7..fdac96c 100644 --- a/pkg/genshinchargen/main.go +++ b/pkg/genshinchargen/main.go @@ -49,6 +49,57 @@ var rarity = NewWeightedSlice(map[string]int{ "2*": 1, }) +var region = NewWeightedSlice(map[string]int{ + "Mondstadt": 100, + "Liyue": 100, + "Inazuma": 100, + "Sumeru": 100, + "Fontaine": 100, + "Natlan": 100, + "Snezhnaya": 100, + "Khaenri'ah": 10, + "Celestia": 10, + "Enkanomiya": 5, + "The Chasm": 5, + "Dragonspine": 5, +}) + +var title = NewWeightedSlice(map[string]int{ + "None": 200, + "1st Fatui Harbinger": 10, + "2nd Fatui Harbinger": 10, + "3rd Fatui Harbinger": 10, + "4th Fatui Harbinger": 10, + "5th Fatui Harbinger": 10, + "6th Fatui Harbinger": 10, + "7th Fatui Harbinger": 10, + "8th Fatui Harbinger": 10, + "9th Fatui Harbinger": 10, + "10th Fatui Harbinger": 10, + "11th Fatui Harbinger": 10, + "Adeptus": 70, + "Archon": 70, + "Sovereign": 50, + "Hexenzirkel": 50, + "Descender": 30, + "The First Who Came": 5, + "The Second Who Came": 5, + "The Primordial One": 5, + "Emanator": 1, + "Herrscher": 1, + "Aeon": 1, +}) + +var outsideTeyvatTitles = map[string]struct{}{ + "Descender": {}, + "The First Who Came": {}, + "The Second Who Came": {}, + "The Primordial One": {}, + "Emanator": {}, + "Herrscher": {}, + "Aeon": {}, +} + var models = NewWeightedSlice(map[string]int{ "Tall male": 50, "Tall female": 50, @@ -68,15 +119,18 @@ var visualAdjectives = NewWeightedSlice(map[string]int{ "Intimidating": 10, "Muscular": 10, "Fit": 10, - "Skinny": 10, "Cute": 10, "Soft": 10, + "Skinny": 5, "Furry": 5, "Bulky": 5, "Brawny": 5, "Barefoot": 5, "Gloomy": 5, "Gothic": 5, + "Stinky": 5, + "Zombi": 3, + "Chubby": 3, "Vtuber": 2, }) @@ -143,7 +197,7 @@ var weaknesses = NewWeightedSlice(map[string]int{ "consumes a lot of stamina to play optimally": 5, "needs resistance to interruption to be good": 5, "doesn't create particles": 5, - "has limited range": 5, + "has very limited range": 5, "can't crit": 2, }) @@ -151,6 +205,7 @@ type GeneratedCharacter struct { name string rarity string element string + region string weapon string model string adjective string @@ -158,11 +213,16 @@ type GeneratedCharacter struct { role string strength string weakness string + title string } func (c GeneratedCharacter) PrettyString() string { - return fmt.Sprintf("%s is a %s %s character.\nWeapon: %s.\nModel: %s %s.\nKit: %s, scales with %s, %s but %s.", - c.name, c.rarity, c.element, c.weapon, c.adjective, c.model, c.role, c.scaling, c.strength, c.weakness) + return fmt.Sprintf(`%s is a %s %s character from %s. + Weapon: %s. + Model: %s %s. + Kit: %s, scales with %s, %s but %s. + Title: %s.`, + c.name, c.rarity, c.element, c.region, c.weapon, c.adjective, c.model, c.role, c.scaling, c.strength, c.weakness, c.title) } func NewChar(name string, seedSalt int64) GeneratedCharacter { @@ -180,6 +240,19 @@ func NewChar(name string, seedSalt int64) GeneratedCharacter { result.weakness = weaknesses.Random(rng) result.adjective = visualAdjectives.Random(rng) + if result.rarity == "5*" || result.rarity == "6*" || result.rarity == "7*" { + result.title = title.Random(rng) + } else { + result.title = "None" + } + + _, outsideTeyvat := outsideTeyvatTitles[result.title] + if outsideTeyvat { + result.region = "outside Teyvat" + } else { + result.region = region.Random(rng) + } + return result } diff --git a/pkg/genshinchargen/main_test.go b/pkg/genshinchargen/main_test.go index e483136..5b33cd8 100644 --- a/pkg/genshinchargen/main_test.go +++ b/pkg/genshinchargen/main_test.go @@ -4,15 +4,23 @@ import "testing" func TestNewChar(t *testing.T) { char := NewChar("Gold", 0) - t.Log(char) + t.Log(char.PrettyString()) char = NewChar("Gold", 1) - t.Log(char) + t.Log(char.PrettyString()) char = NewChar("Gold", 2) - t.Log(char) + t.Log(char.PrettyString()) char = NewChar("Silver", 0) - t.Log(char) + t.Log(char.PrettyString()) char = NewChar("Alice", 0) - t.Log(char) + t.Log(char.PrettyString()) char = NewChar("Timmie", 0) - t.Log(char) + t.Log(char.PrettyString()) + char = NewChar("Timmie", 1) + t.Log(char.PrettyString()) + char = NewChar("Timmie", 2) + t.Log(char.PrettyString()) + char = NewChar("Timmie", 3) + t.Log(char.PrettyString()) + char = NewChar("Timmie", 4) + t.Log(char.PrettyString()) } From 5e1242df0fc74f3f6c9f2179dbb263230971e04d Mon Sep 17 00:00:00 2001 From: Jarv <6jarv91@gmail.com> Date: Sun, 15 Sep 2024 02:52:02 +0200 Subject: [PATCH 16/20] version change --- cmd/jarvbot/commands.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/jarvbot/commands.go b/cmd/jarvbot/commands.go index 7148a3b..79bf678 100644 --- a/cmd/jarvbot/commands.go +++ b/cmd/jarvbot/commands.go @@ -65,7 +65,7 @@ func onMessageCreated(ctx context.Context) func(ds *discordgo.Session, mc *disco // the command key must be lowercased var commands = map[string]command{ // public - "!version": simpleTextResponse("v3.6.11"), + "!version": simpleTextResponse("v3.6.12"), "!source": simpleTextResponse("Source code: https://github.com/j4rv/discord-bot"), "!genshindailycheckin": answerGenshinDailyCheckIn, "!genshindailycheckinstop": answerGenshinDailyCheckInStop, From 48304049a032e1de2cf1a8deb5b2724043c672dd Mon Sep 17 00:00:00 2001 From: Jose Rojo <6jarv91@gmail.com> Date: Wed, 18 Sep 2024 14:23:19 +0200 Subject: [PATCH 17/20] Small refactor --- cmd/jarvbot/bunker.go | 2 +- cmd/jarvbot/commands.go | 2 -- cmd/jarvbot/config.go | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/jarvbot/bunker.go b/cmd/jarvbot/bunker.go index 91a95ea..fcec531 100644 --- a/cmd/jarvbot/bunker.go +++ b/cmd/jarvbot/bunker.go @@ -140,7 +140,7 @@ func shoot(ds *discordgo.Session, channelID string, guildID string, shooter *dis if member.User.ID == ds.State.User.ID { continue } - if rand.Float32() <= 0.02 { + if rand.Float32() <= nuclearCatastropheDeathRatio { ds.ChannelMessageSendComplex(channelID, &discordgo.MessageSend{ Content: fmt.Sprintf("%s died in the explosion!", member.User.Mention()), AllowedMentions: &discordgo.MessageAllowedMentions{}, diff --git a/cmd/jarvbot/commands.go b/cmd/jarvbot/commands.go index 79bf678..c6078d8 100644 --- a/cmd/jarvbot/commands.go +++ b/cmd/jarvbot/commands.go @@ -570,8 +570,6 @@ func notSpammable(wrapped command) command { var lastUserCommandTime = map[string]time.Time{} -const commandCooldown = time.Minute * 15 - func resetUserCooldown(userID string) { lastUserCommandTime[userID] = time.Now() } diff --git a/cmd/jarvbot/config.go b/cmd/jarvbot/config.go index afec5bb..f89e33f 100644 --- a/cmd/jarvbot/config.go +++ b/cmd/jarvbot/config.go @@ -23,6 +23,7 @@ const cleanStateMessagesCRON = "0 * * * *" const stateMessageMaxLifetime = 24 * time.Hour const maxMessageCount = 100 const expensiveOperationCooldown = 15 * time.Second +const commandCooldown = time.Minute * 15 // https://discord.com/branding const colorBlue = 0x5865F2 @@ -39,6 +40,7 @@ const serverPropNo = "N" const defaultTimeoutRoleName = "Shadow Realm" const shootMisfireChance = 0.2 const nuclearCatastropheChance = 0.006 +const nuclearCatastropheDeathRatio = 0.015 const timeoutDurationWhenShot = 4 * time.Minute const timeoutDurationWhenMisfire = 8 * time.Minute const timeoutDurationWhenNuclearCatastrophe = 2 * time.Minute From 0b7b66492121d9cd1e8964993a9c1a84bccfe7fd Mon Sep 17 00:00:00 2001 From: Jose Rojo <6jarv91@gmail.com> Date: Thu, 19 Sep 2024 11:41:48 +0200 Subject: [PATCH 18/20] removeRoleAfterDuration - better error message --- cmd/jarvbot/commands.go | 2 +- cmd/jarvbot/time.go | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/cmd/jarvbot/commands.go b/cmd/jarvbot/commands.go index c6078d8..69a1b6c 100644 --- a/cmd/jarvbot/commands.go +++ b/cmd/jarvbot/commands.go @@ -65,7 +65,7 @@ func onMessageCreated(ctx context.Context) func(ds *discordgo.Session, mc *disco // the command key must be lowercased var commands = map[string]command{ // public - "!version": simpleTextResponse("v3.6.12"), + "!version": simpleTextResponse("v3.6.13"), "!source": simpleTextResponse("Source code: https://github.com/j4rv/discord-bot"), "!genshindailycheckin": answerGenshinDailyCheckIn, "!genshindailycheckinstop": answerGenshinDailyCheckInStop, diff --git a/cmd/jarvbot/time.go b/cmd/jarvbot/time.go index 95b1b6a..d9d7d11 100644 --- a/cmd/jarvbot/time.go +++ b/cmd/jarvbot/time.go @@ -20,9 +20,14 @@ func removeRoleAfterDuration(ds *discordgo.Session, guildID string, memberID str time.Sleep(duration) err := ds.GuildMemberRoleRemove(guildID, memberID, roleID) if err != nil { - notifyIfErr("removeRoleAfterDuration", err, ds) - // try again in a minute - removeRoleAfterDuration(ds, guildID, memberID, roleID, time.Minute) + guild, err := ds.Guild(guildID) + if err == nil { + notifyIfErr("removeRoleAfterDuration in guild: "+guild.Name, err, ds) + } else { + notifyIfErr("removeRoleAfterDuration in guild with ID: "+guildID, err, ds) + } + // try again later + removeRoleAfterDuration(ds, guildID, memberID, roleID, 2*time.Minute) } }() } From c07e87fcf971c11314318aa82e5f76b2853fbe7b Mon Sep 17 00:00:00 2001 From: Jarv <6jarv91@gmail.com> Date: Mon, 11 Nov 2024 14:14:33 +0100 Subject: [PATCH 19/20] Better error handling for !shoot Added !deletecommand alias for !removecommand Added support to track simple command creators Added !guildlist --- cmd/jarvbot/bunker.go | 3 +++ cmd/jarvbot/commands.go | 49 ++++++++++++++++++++++++++++++++++++----- cmd/jarvbot/db.go | 16 ++++++++++---- cmd/jarvbot/main.go | 1 + cmd/jarvbot/modding.go | 6 +++++ 5 files changed, 66 insertions(+), 9 deletions(-) diff --git a/cmd/jarvbot/bunker.go b/cmd/jarvbot/bunker.go index fcec531..d03977e 100644 --- a/cmd/jarvbot/bunker.go +++ b/cmd/jarvbot/bunker.go @@ -52,18 +52,21 @@ func answerShoot(ds *discordgo.Session, mc *discordgo.MessageCreate, ctx context timeoutRole, err := getTimeoutRole(ds, mc.GuildID) notifyIfErr("answerShoot: get timeout role", err, ds) if err != nil { + ds.ChannelMessageSend(mc.ChannelID, "Could not find the Timeout Role, maybe I'm missing permissions or it does not exist :(") return false } shooter, err := ds.GuildMember(mc.GuildID, mc.Author.ID) notifyIfErr("answerShoot: get shooter member", err, ds) if err != nil { + ds.ChannelMessageSend(mc.ChannelID, "Could not find you in this server, maybe I'm missing permissions u_u") return false } target, err := ds.GuildMember(mc.GuildID, match[1]) notifyIfErr("answerShoot: get target member", err, ds) if err != nil { + ds.ChannelMessageSend(mc.ChannelID, "Couldn't find member with user ID: "+match[1]+", maybe I'm missing permissions u_u") return false } diff --git a/cmd/jarvbot/commands.go b/cmd/jarvbot/commands.go index 69a1b6c..f2552d0 100644 --- a/cmd/jarvbot/commands.go +++ b/cmd/jarvbot/commands.go @@ -79,18 +79,20 @@ var commands = map[string]command{ "!randomdomainrun": notSpammable(answerRandomDomainRun), "!remindme": notSpammable(answerRemindme), "!roll": notSpammable(answerRoll), + "!shoot": notSpammable(answerShoot), + "!pp": notSpammable(answerPP), // hidden or easter eggs "!hello": notSpammable(answerHello), "!liquid": notSpammable(answerLiquid), "!don": notSpammable(answerDon), - "!shoot": notSpammable(answerShoot), "!sniper_shoot": notSpammable(answerSniperShoot), - "!pp": notSpammable(answerPP), // only available for discord mods "!roleids": guildOnly((answerRoleIDs)), "!react4roles": guildOnly((answerMakeReact4RolesMsg)), "!addcommand": guildOnly((answerAddCommand)), "!removecommand": guildOnly((answerRemoveCommand)), + "!deletecommand": guildOnly((answerRemoveCommand)), + "!commandcreator": guildOnly((answerCommandCreator)), "!listcommands": modOnly(answerListCommands), "!allowspamming": guildOnly(modOnly(answerAllowSpamming)), "!preventspamming": guildOnly(modOnly(answerPreventSpamming)), @@ -100,8 +102,10 @@ var commands = map[string]command{ "!messagelogs": guildOnly(modOnly(answerMessageLogs)), "!commandstats": guildOnly(modOnly(answerCommandStats)), // only available for the bot owner + "!guildlist": adminOnly(answerGuildList), "!addglobalcommand": adminOnly(answerAddGlobalCommand), "!removeglobalcommand": adminOnly(answerRemoveGlobalCommand), + "!deleteglobalcommand": adminOnly(answerRemoveGlobalCommand), "!announce": adminOnly(answerAnnounce), "!dbbackup": adminOnly(answerDbBackup), "!runtimestats": adminOnly(answerRuntimeStats), @@ -168,11 +172,11 @@ func answerHello(ds *discordgo.Session, mc *discordgo.MessageCreate, ctx context func answerPP(ds *discordgo.Session, mc *discordgo.MessageCreate, ctx context.Context) bool { seed, err := strconv.ParseInt(mc.Author.ID, 10, 64) - seed *= unixDay() notifyIfErr("answerPP: parsing user id: "+mc.Author.ID, err, ds) if err != nil { return false } + seed *= unixDay() pp := ppgen.NewPenisWithSeed(seed) _, err = ds.ChannelMessageSend(mc.ChannelID, fmt.Sprintf("%s's penis: %s", mc.Author.Mention(), pp)) return err == nil @@ -364,6 +368,20 @@ func answerCommandStats(ds *discordgo.Session, mc *discordgo.MessageCreate, ctx return err == nil } +func answerGuildList(ds *discordgo.Session, mc *discordgo.MessageCreate, ctx context.Context) bool { + guilds, err := ds.UserGuilds(100, "", "", true) + if err != nil { + notifyIfErr("answerGuildList", err, ds) + return false + } + guildsMsg := "" + for _, g := range guilds { + guildsMsg += fmt.Sprintf("%s [%s] - Member count %d - Presence count %d\n", g.Name, g.ID, g.ApproximateMemberCount, g.ApproximatePresenceCount) + } + _, err = ds.ChannelMessageSend(mc.ChannelID, guildsMsg) + return err == nil +} + // ---------- Simple command stuff ---------- func answerAddCommand(ds *discordgo.Session, mc *discordgo.MessageCreate, ctx context.Context) bool { @@ -378,7 +396,7 @@ func answerAddCommand(ds *discordgo.Session, mc *discordgo.MessageCreate, ctx co ds.ChannelMessageSend(mc.ChannelID, markdownDiffBlock("Could not get the response from the command body", "- ")) return false } - err := commandDS.addSimpleCommand(key, response, mc.GuildID) + err := commandDS.addSimpleCommand(key, response, mc.GuildID, mc.Author.ID) notifyIfErr("addSimpleCommand", err, ds) if err == nil { ds.ChannelMessageSend(mc.ChannelID, commandSuccessMessage) @@ -398,7 +416,7 @@ func answerAddGlobalCommand(ds *discordgo.Session, mc *discordgo.MessageCreate, ds.ChannelMessageSend(mc.ChannelID, markdownDiffBlock("Could not get the response from the command body", "- ")) return false } - err := commandDS.addSimpleCommand(key, response, globalGuildID) + err := commandDS.addSimpleCommand(key, response, globalGuildID, mc.Author.ID) notifyIfErr("addGlobalCommand", err, ds) if err == nil { ds.ChannelMessageSend(mc.ChannelID, commandSuccessMessage) @@ -419,6 +437,27 @@ func answerRemoveCommand(ds *discordgo.Session, mc *discordgo.MessageCreate, ctx return err == nil } +func answerCommandCreator(ds *discordgo.Session, mc *discordgo.MessageCreate, ctx context.Context) bool { + commandBody := strings.TrimSpace(commandPrefixRegex.ReplaceAllString(mc.Content, "")) + if commandBody == "" { + return false + } + if commandBody[0] != '!' { + commandBody = "!" + commandBody + } + + creator, err := commandDS.getCommandCreator(commandBody, mc.GuildID) + if err != nil { + ds.ChannelMessageSend(mc.ChannelID, "Could not find command creator. I'm sowwy u_u") + return false + } + ds.ChannelMessageSendComplex(mc.ChannelID, &discordgo.MessageSend{ + Content: fmt.Sprintf("Command creator: <@%s>", creator), + AllowedMentions: &discordgo.MessageAllowedMentions{}, + }) + return true +} + func answerRemoveGlobalCommand(ds *discordgo.Session, mc *discordgo.MessageCreate, ctx context.Context) bool { commandBody := strings.TrimSpace(commandPrefixRegex.ReplaceAllString(mc.Content, "")) err := commandDS.removeSimpleCommand(commandBody, globalGuildID) diff --git a/cmd/jarvbot/db.go b/cmd/jarvbot/db.go index 2c74b5d..3832d5e 100644 --- a/cmd/jarvbot/db.go +++ b/cmd/jarvbot/db.go @@ -65,6 +65,7 @@ func createTableSimpleCommand(db *sqlx.DB) { "Response TEXT NOT NULL", "GuildID VARCHAR(20) NOT NULL DEFAULT ''", "CreatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP", + "CreatedBy VARCHAR(20)", "UNIQUE(Key, GuildID)", }, db) createIndex("SimpleCommand", "Key", db) @@ -135,9 +136,9 @@ type CommandStat struct { Count int `db:"Count"` } -func (c commandDataStore) addSimpleCommand(key, response, guildID string) error { - _, err := c.db.Exec(`INSERT INTO SimpleCommand (Key, Response, GuildID) VALUES (?, ?, ?)`, - key, response, guildID) +func (c commandDataStore) addSimpleCommand(key, response, guildID, creatorUserID string) error { + _, err := c.db.Exec(`INSERT INTO SimpleCommand (Key, Response, GuildID, CreatedBy) VALUES (?, ?, ?, ?)`, + key, response, guildID, creatorUserID) return err } @@ -154,9 +155,16 @@ func (c commandDataStore) removeSimpleCommand(key, guildID string) error { return nil } +func (c commandDataStore) getCommandCreator(key, guildID string) (string, error) { + var creator string + err := c.db.Get(&creator, `SELECT CreatedBy FROM SimpleCommand WHERE Key = ? AND (GuildID = ?) COLLATE NOCASE`, + key, guildID) + return creator, err +} + func (c commandDataStore) simpleCommandResponse(key, guildID string) (string, error) { var response []string - err := c.db.Select(&response, `SELECT Response FROM SimpleCommand WHERE Key = ? AND (GuildID = ? OR GuildID = '') COLLATE NOCASE`, + err := c.db.Select(&response, `SELECT Response FROM SimpleCommand WHERE Key = ? AND (GuildID = ?) COLLATE NOCASE`, key, guildID) if len(response) == 0 { return "", err diff --git a/cmd/jarvbot/main.go b/cmd/jarvbot/main.go index e1d83a1..76522a1 100644 --- a/cmd/jarvbot/main.go +++ b/cmd/jarvbot/main.go @@ -79,6 +79,7 @@ func initDiscordSession() *discordgo.Session { backgroundCtx := context.Background() + //ds.AddHandler(onGuildJoin(backgroundCtx)) ds.AddHandler(onMessageCreated(backgroundCtx)) ds.AddHandler(onMessageUpdated(backgroundCtx)) ds.AddHandler(onMessageDeleted(backgroundCtx)) diff --git a/cmd/jarvbot/modding.go b/cmd/jarvbot/modding.go index 97fb86e..1792f2d 100644 --- a/cmd/jarvbot/modding.go +++ b/cmd/jarvbot/modding.go @@ -9,6 +9,12 @@ import ( "github.com/kylelemons/godebug/diff" ) +func onGuildJoin(ctx context.Context) func(ds *discordgo.Session, gc *discordgo.GuildCreate) { + return func(ds *discordgo.Session, gc *discordgo.GuildCreate) { + sendDirectMessage(adminID, fmt.Sprintf("Joined guild: %s with id: %s", gc.Name, gc.ID), ds) + } +} + func onMessageDeleted(ctx context.Context) func(ds *discordgo.Session, mc *discordgo.MessageDelete) { return func(ds *discordgo.Session, mc *discordgo.MessageDelete) { if mc.BeforeDelete != nil && mc.BeforeDelete.Author != nil { From eba9593e57de5c26053b4e7071ed612ae64d8b7c Mon Sep 17 00:00:00 2001 From: Jarv <6jarv91@gmail.com> Date: Mon, 11 Nov 2024 14:15:29 +0100 Subject: [PATCH 20/20] Version change --- cmd/jarvbot/commands.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/jarvbot/commands.go b/cmd/jarvbot/commands.go index f2552d0..f96347b 100644 --- a/cmd/jarvbot/commands.go +++ b/cmd/jarvbot/commands.go @@ -65,7 +65,7 @@ func onMessageCreated(ctx context.Context) func(ds *discordgo.Session, mc *disco // the command key must be lowercased var commands = map[string]command{ // public - "!version": simpleTextResponse("v3.6.13"), + "!version": simpleTextResponse("v3.7.0"), "!source": simpleTextResponse("Source code: https://github.com/j4rv/discord-bot"), "!genshindailycheckin": answerGenshinDailyCheckIn, "!genshindailycheckinstop": answerGenshinDailyCheckInStop,