Merge branch 'disgo'

This commit is contained in:
2024-04-10 17:03:04 +02:00
15 changed files with 815 additions and 969 deletions

View File

@@ -1,32 +1,29 @@
package main package main
import ( import (
"github.com/bwmarrin/discordgo" "github.com/disgoorg/disgo/discord"
"github.com/disgoorg/disgo/events"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
var cmd_ask Command = Command{ var cmd_ask = Command{
Definition: discordgo.ApplicationCommand{ Definition: discord.SlashCommandCreate{
Name: "ask", Name: "ask",
Description: "Ask anything and get a gif as response!", Description: "Ask anything and get a gif as response!",
Options: []*discordgo.ApplicationCommandOption{ Options: []discord.ApplicationCommandOption{
{ &discord.ApplicationCommandOptionString{
Type: discordgo.ApplicationCommandOptionString,
Name: "question", Name: "question",
Description: "The question you want to ask", Description: "The question you want to ask",
Required: true, Required: true,
}, },
}, },
}, },
Interact: func(s *discordgo.Session, i *discordgo.InteractionCreate) { Interact: func(e *events.ApplicationCommandInteractionCreate) {
err := respondEmbed(i.Interaction, discordgo.MessageEmbed{ err := e.CreateMessage(discord.NewMessageCreateBuilder().
Type: discordgo.EmbedTypeImage, AddEmbeds(discord.NewEmbedBuilder().SetImage(simpleGetFromAPI("image", "https://yesno.wtf/api").(string)).SetColor(hexToDecimal(color["primary"])).Build()).
Color: hexToDecimal(color["primary"]), Build())
Image: &discordgo.MessageEmbedImage{
URL: simpleGetFromAPI("image", "https://yesno.wtf/api").(string),
}}, false)
if err != nil { if err != nil {
logrus.Error("Failed to respond with embed: ", err) logrus.Error(err)
} }
}, },
AllowDM: true, AllowDM: true,

View File

@@ -1,68 +1,67 @@
package main package main
import ( import (
"github.com/bwmarrin/discordgo" "github.com/disgoorg/disgo/discord"
"github.com/disgoorg/disgo/events"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
var cmd_autojoinroles Command = Command{ var cmd_autojoinroles Command = Command{
Definition: discordgo.ApplicationCommand{ Definition: discord.SlashCommandCreate{
Name: "autojoinroles", Name: "autojoinroles",
Description: "Give users a role when they join", Description: "Give users a role when they join",
Options: []*discordgo.ApplicationCommandOption{ Options: []discord.ApplicationCommandOption{
{ &discord.ApplicationCommandOptionSubCommand{
Type: discordgo.ApplicationCommandOptionSubCommand,
Name: "bot", Name: "bot",
Description: "Give bots a role when they join (Leave empty to remove current)", Description: "Give bots a role when they join (Leave empty to remove current)",
Options: []*discordgo.ApplicationCommandOption{ Options: []discord.ApplicationCommandOption{
{ &discord.ApplicationCommandOptionRole{
Type: discordgo.ApplicationCommandOptionRole,
Name: "role", Name: "role",
Description: "The role bots should get when they join the server", Description: "The role bots should get when they join the server",
}, },
}, },
}, },
{ &discord.ApplicationCommandOptionSubCommand{
Type: discordgo.ApplicationCommandOptionSubCommand,
Name: "user", Name: "user",
Description: "Give users a role when they join (Leave empty to remove current)", Description: "Give users a role when they join (Leave empty to remove current)",
Options: []*discordgo.ApplicationCommandOption{ Options: []discord.ApplicationCommandOption{
{ &discord.ApplicationCommandOptionRole{
Type: discordgo.ApplicationCommandOptionRole,
Name: "role", Name: "role",
Description: "The role users should get when they join the server", Description: "The role users should get when they join the server",
}}, }},
}, },
}, },
}, },
Interact: func(s *discordgo.Session, i *discordgo.InteractionCreate) { Interact: func(e *events.ApplicationCommandInteractionCreate) {
var role string var role string
option := i.ApplicationCommandData().Options[0].Name option := *e.SlashCommandInteractionData().SubCommandName
var content string var content string
if len(i.ApplicationCommandData().Options[0].Options) == 1 { if len(e.SlashCommandInteractionData().Options) == 1 {
var givenRole *discordgo.Role = i.ApplicationCommandData().Options[0].Options[0].RoleValue(s, i.GuildID) var givenRole discord.Role = e.SlashCommandInteractionData().Role("role")
role = givenRole.ID role = givenRole.ID.String()
botrole, err := getHighestRole(i.GuildID) botrole, err := getHighestRole(e.GuildID().String(), e.Client())
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
if givenRole.Position >= botrole.Position { if givenRole.Position >= botrole.Position {
content = "<@&" + role + "> is not below the Bot's current highest role(<@&" + botrole.ID + ">). That makes it unable to manage it." content = "<@&" + role + "> is not below the Bot's current highest role(<@&" + botrole.ID.String() + ">). That makes it unable to manage it."
} else { } else {
if setAutoJoinRole(i.GuildID, option, role) { if setAutoJoinRole(e.GuildID().String(), option, role) {
content = "Updated auto join role for " + option + "s as <@&" + role + ">" content = "Updated auto join role for " + option + "s as <@&" + role + ">"
} else { } else {
content = "Setup auto join role for " + option + "s as <@&" + role + ">" content = "Setup auto join role for " + option + "s as <@&" + role + ">"
} }
} }
} else if setAutoJoinRole(i.GuildID, option, role) { } else if setAutoJoinRole(e.GuildID().String(), option, role) {
content = "Deleted auto join role for " + option + "s" content = "Deleted auto join role for " + option + "s"
} }
err := respond(i.Interaction, content, true) if content == "" {
content = "No auto join role set for " + option + "s to delete."
}
err := e.CreateMessage(discord.NewMessageCreateBuilder().SetContent(content).SetEphemeral(true).Build())
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
purgeUnusedAutoJoinRoles(i.GuildID) purgeUnusedAutoJoinRoles(e.GuildID().String())
}, },
} }

View File

@@ -1,31 +1,38 @@
package main package main
import ( import (
"github.com/bwmarrin/discordgo" "github.com/disgoorg/disgo/discord"
"github.com/disgoorg/disgo/events"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
var cmd_autopublish Command = Command{ var cmd_autopublish Command = Command{
Definition: discordgo.ApplicationCommand{ Definition: discord.SlashCommandCreate{
Name: "autopublish", Name: "autopublish",
Description: "Toggle automatically publishing every post in a announcement channel", Description: "Toggle automatically publishing every post in a announcement channel",
}, },
Interact: func(s *discordgo.Session, i *discordgo.InteractionCreate) { Interact: func(e *events.ApplicationCommandInteractionCreate) {
channel, _ := s.State.Channel(i.ChannelID) channel := e.Channel()
if channel.Type == discordgo.ChannelTypeGuildNews { if channel.Type() == discord.ChannelTypeGuildNews {
if toggleAutoPublish(i.GuildID, i.ChannelID) { if toggleAutoPublish(e.GuildID().String(), e.Channel().ID().String()) {
err := respond(i.Interaction, "Autopublishing is now disabled on <#"+i.ChannelID+">", true) err := e.CreateMessage(discord.NewMessageCreateBuilder().
SetContent("Autopublishing is now disabled on " + discord.ChannelMention(e.Channel().ID())).SetEphemeral(true).
Build())
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
} else { } else {
err := respond(i.Interaction, "Autopublishing is now enabled on <#"+i.ChannelID+">", true) err := e.CreateMessage(discord.NewMessageCreateBuilder().
SetContent("Autopublishing is now enabled on " + discord.ChannelMention(e.Channel().ID())).SetEphemeral(true).
Build())
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
} }
} else { } else {
err := respond(i.Interaction, "This is not an announcement channel!", true) err := e.CreateMessage(discord.NewMessageCreateBuilder().
SetContent("This is not an announcement channel!").SetEphemeral(true).
Build())
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }

View File

@@ -5,29 +5,25 @@ import (
"io" "io"
"net/http" "net/http"
"github.com/bwmarrin/discordgo" "github.com/disgoorg/disgo/discord"
"github.com/disgoorg/disgo/events"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
var cmd_cat Command = Command{ var cmd_cat = Command{
Definition: discordgo.ApplicationCommand{ Definition: discord.SlashCommandCreate{
Name: "cat", Name: "cat",
Description: "Random cat pictures", Description: "Random cat pictures",
}, },
Interact: func(s *discordgo.Session, i *discordgo.InteractionCreate) { Interact: func(e *events.ApplicationCommandInteractionCreate) {
cat, err := GetCatImageURL() cat, err := GetCatImageURL()
if err == nil { if err == nil {
err := respondEmbed(i.Interaction, discordgo.MessageEmbed{ err = e.CreateMessage(discord.NewMessageCreateBuilder().
Type: discordgo.EmbedTypeImage, AddEmbeds(discord.NewEmbedBuilder().SetImage(cat).SetColor(hexToDecimal(color["primary"])).Build()).
Color: hexToDecimal(color["primary"]), Build())
Image: &discordgo.MessageEmbedImage{
URL: cat,
}}, false)
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
} else {
logrus.Error(err)
} }
}, },
AllowDM: true, AllowDM: true,

View File

@@ -1,17 +1,21 @@
package main package main
import ( import (
"github.com/bwmarrin/discordgo" "github.com/disgoorg/disgo/discord"
"github.com/disgoorg/disgo/events"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
var cmd_dadjoke Command = Command{ var cmd_dadjoke = Command{
Definition: discordgo.ApplicationCommand{ Definition: discord.SlashCommandCreate{
Name: "dadjoke", Name: "dadjoke",
Description: "Gives you a random joke that is as bad as your dad would tell them", Description: "Gives you a random joke that is as bad as your dad would tell them",
}, },
Interact: func(s *discordgo.Session, i *discordgo.InteractionCreate) { Interact: func(e *events.ApplicationCommandInteractionCreate) {
err := respond(i.Interaction, simpleGetFromAPI("joke", "https://icanhazdadjoke.com/").(string), false) joke := simpleGetFromAPI("joke", "https://icanhazdadjoke.com/").(string)
err := e.CreateMessage(discord.NewMessageCreateBuilder().
SetContent(joke).
Build())
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }

View File

@@ -5,70 +5,64 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/bwmarrin/discordgo" "github.com/disgoorg/disgo/bot"
"github.com/disgoorg/disgo/discord"
"github.com/disgoorg/disgo/events"
"github.com/disgoorg/json"
"github.com/disgoorg/snowflake/v2"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
var cmd_form Command = Command{ var cmd_form Command = Command{
Definition: discordgo.ApplicationCommand{ Definition: discord.SlashCommandCreate{
Name: "form", Name: "form",
DefaultMemberPermissions: int64Ptr(discordgo.PermissionManageChannels), DefaultMemberPermissions: json.NewNullablePtr(discord.PermissionManageChannels),
Description: "Create custom forms right inside Discord", Description: "Create custom forms right inside Discord",
Options: []*discordgo.ApplicationCommandOption{ Options: []discord.ApplicationCommandOption{
{ &discord.ApplicationCommandOptionSubCommand{
Type: discordgo.ApplicationCommandOptionSubCommand,
Name: "help", Name: "help",
Description: "Gives you a example file and demo for creating custom forms", Description: "Gives you an example file and demo for creating custom forms",
}, },
{ &discord.ApplicationCommandOptionSubCommand{
Type: discordgo.ApplicationCommandOptionSubCommand,
Name: "custom", Name: "custom",
Description: "Create a new custom form right inside Discord", Description: "Create a new custom form right inside Discord",
Options: []*discordgo.ApplicationCommandOption{ Options: []discord.ApplicationCommandOption{
{ &discord.ApplicationCommandOptionAttachment{
Type: discordgo.ApplicationCommandOptionAttachment,
Name: "json", Name: "json",
Description: "Your edited form file", Description: "Your edited form file",
Required: true, Required: true,
}, },
}, },
}, },
{ &discord.ApplicationCommandOptionSubCommand{
Type: discordgo.ApplicationCommandOptionSubCommand,
Name: "add", Name: "add",
Description: "Adds existing forms to this channel", Description: "Adds existing forms to this channel",
Options: []*discordgo.ApplicationCommandOption{ Options: []discord.ApplicationCommandOption{
{ &discord.ApplicationCommandOptionChannel{
Type: discordgo.ApplicationCommandOptionChannel,
Name: "result_channel", Name: "result_channel",
Description: "Where the form results should appear", Description: "Where the form results should appear",
ChannelTypes: []discordgo.ChannelType{discordgo.ChannelTypeGuildText}, ChannelTypes: []discord.ChannelType{discord.ChannelTypeGuildText},
}, },
{ &discord.ApplicationCommandOptionMentionable{
Type: discordgo.ApplicationCommandOptionMentionable,
Name: "moderator", Name: "moderator",
Description: "Who can interact with moderating buttons.", Description: "Who can interact with moderating buttons.",
}, },
{ &discord.ApplicationCommandOptionString{
Type: discordgo.ApplicationCommandOptionString,
Name: "type", Name: "type",
Description: "Which type of form you want to add", Description: "Which type of form you want to add",
Autocomplete: true, Autocomplete: true,
}, },
{ &discord.ApplicationCommandOptionString{
Type: discordgo.ApplicationCommandOptionString,
Name: "title", Name: "title",
Description: "The title the form should have", Description: "The title the form should have",
}, },
{ &discord.ApplicationCommandOptionChannel{
Type: discordgo.ApplicationCommandOptionChannel,
Name: "approve_channel", Name: "approve_channel",
Description: "Channel for results that need to be accepted by a moderator before sending it to the result channel", Description: "Channel for results that need to be accepted by a moderator before sending it to the result channel",
ChannelTypes: []discordgo.ChannelType{discordgo.ChannelTypeGuildText}, ChannelTypes: []discord.ChannelType{discord.ChannelTypeGuildText},
}, },
{ &discord.ApplicationCommandOptionBool{
Type: discordgo.ApplicationCommandOptionBoolean,
Name: "mods_can_answer", Name: "mods_can_answer",
Description: "Moderators can open a new channel on the form result, which then pings the user who submitted it", Description: "Moderators can open a new channel on the form result, which then pings the user who submitted it",
}, },
@@ -76,8 +70,8 @@ var cmd_form Command = Command{
}, },
}, },
}, },
Interact: func(s *discordgo.Session, i *discordgo.InteractionCreate) { Interact: func(e *events.ApplicationCommandInteractionCreate) {
switch i.ApplicationCommandData().Options[0].Name { switch *e.SlashCommandInteractionData().SubCommandName {
case "help": case "help":
fileData, err := formTemplates.ReadFile("form_templates/form_demo.json") fileData, err := formTemplates.ReadFile("form_templates/form_demo.json")
if err != nil { if err != nil {
@@ -85,39 +79,18 @@ var cmd_form Command = Command{
return return
} }
fileReader := bytes.NewReader(fileData) fileReader := bytes.NewReader(fileData)
err = s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ err = e.CreateMessage(discord.NewMessageCreateBuilder().
Type: discordgo.InteractionResponseChannelMessageWithSource, SetContent("NOT SUPPORTED YET!(use `/form add` instead)\n\nGet the example file edit it (make sure to have a unique \"form_type\") and submit it via `/form create`.\nOr use the demo button to get an idea of how the example would look like.").
Data: &discordgo.InteractionResponseData{ SetFiles(discord.NewFile("example.json", "json", fileReader)).
Content: "NOT SUPPORTED YET!(use `/form add` instead)\n\nGet the example file edit it (make sure to have a unique \"form_type\") and submit it via `/form create`.\nOr use the demo button to get an idea of how the example would look like.", SetContainerComponents(discord.ActionRowComponent{discord.NewPrimaryButton("Demo", "form_demo").WithEmoji(discord.ComponentEmoji{Name: "📑"})}).SetEphemeral(true).
Flags: discordgo.MessageFlagsEphemeral, Build())
Files: []*discordgo.File{
{
Name: "example.json",
ContentType: "json",
Reader: fileReader,
},
},
Components: []discordgo.MessageComponent{
discordgo.ActionsRow{
Components: []discordgo.MessageComponent{
discordgo.Button{
Emoji: discordgo.ComponentEmoji{
Name: "📑",
},
CustomID: "form_demo",
Label: "Demo",
Style: discordgo.PrimaryButton,
},
},
},
},
},
})
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
case "custom": case "custom":
err := respond(i.Interaction, "Feature not available yet use `/form add` instead", true) err := e.CreateMessage(discord.NewMessageCreateBuilder().
SetContent("Feature not available yet use `/form add` instead").SetEphemeral(true).
Build())
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
@@ -125,30 +98,24 @@ var cmd_form Command = Command{
var title, formID, overwriteTitle, acceptChannelID string var title, formID, overwriteTitle, acceptChannelID string
var modsCanAnswer bool var modsCanAnswer bool
var resultChannelID string var resultChannelID string
moderator := i.Member.User.ID data := e.SlashCommandInteractionData()
if i.ApplicationCommandData().Options != nil { if data.Channel("result_channel").ID.String() != "0" {
options := i.ApplicationCommandData().Options[0] resultChannelID = data.Channel("result_channel").ID.String()
for _, opt := range options.Options { }
switch opt.Name { moderator := data.Role("moderator").ID.String()
case "result_channel": if moderator == "0" {
resultChannelID = opt.ChannelValue(s).ID moderator = e.User().ID.String()
case "type": }
formID = opt.StringValue() formID = data.String("type")
case "title": overwriteTitle = data.String("title")
overwriteTitle = opt.StringValue() if overwriteTitle != "" {
title = overwriteTitle title = overwriteTitle
case "approve_channel":
acceptChannelID = opt.ChannelValue(s).ID
case "mods_can_answer":
modsCanAnswer = opt.BoolValue()
case "moderator":
moderator = opt.RoleValue(s, i.GuildID).ID
if moderator == "" {
moderator = opt.UserValue(s).ID
}
}
} }
if data.Channel("approve_channel").ID.String() != "0" {
acceptChannelID = data.Channel("approve_channel").ID.String()
} }
modsCanAnswer = data.Bool("mods_can_answer")
if formID == "" { if formID == "" {
formID = "template_general" formID = "template_general"
} }
@@ -168,44 +135,30 @@ var cmd_form Command = Command{
formManageID = uuid.New() formManageID = uuid.New()
exists = getFormManageIdExists(formManageID) exists = getFormManageIdExists(formManageID)
} }
messagebuild := discord.NewMessageCreateBuilder().SetEmbeds(discord.NewEmbedBuilder().
message, err := s.ChannelMessageSendComplex(i.ChannelID, &discordgo.MessageSend{ SetTitle(title).SetDescription("Press the bottom button to open a form popup.").SetColor(hexToDecimal(color["primary"])).
Embed: &discordgo.MessageEmbed{ Build()).SetContainerComponents(discord.ActionRowComponent{
Color: hexToDecimal(color["primary"]), discord.NewSuccessButton("Submit", "form:"+formManageID.String()).WithEmoji(discord.ComponentEmoji{
Title: title,
Description: "Press the bottom button to open a form popup.",
},
Components: []discordgo.MessageComponent{
discordgo.ActionsRow{
Components: []discordgo.MessageComponent{
discordgo.Button{
CustomID: "form:" + formManageID.String(),
Style: discordgo.SuccessButton,
Label: "Submit",
Emoji: discordgo.ComponentEmoji{
Name: "anim_rocket", Name: "anim_rocket",
ID: "1215740398706757743", ID: snowflake.MustParse("1215740398706757743"),
Animated: true, Animated: true,
}, })}).
}, Build()
}, message, err := e.Client().Rest().CreateMessage(e.Channel().ID(), messagebuild)
},
},
})
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
return
} }
var category string var category string
if modsCanAnswer { if modsCanAnswer {
c, err := s.GuildChannelCreate(i.GuildID, title+" mod answers", discordgo.ChannelTypeGuildCategory) c, err := e.Client().Rest().CreateGuildChannel(*e.GuildID(), discord.GuildCategoryChannelCreate{Name: title + " mod answers"})
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
category = c.ID category = c.ID().String()
} }
addFormButton(i.GuildID, i.ChannelID, message.ID, formManageID.String(), formID, resultChannelID, overwriteTitle, acceptChannelID, category, moderator)
err = respond(i.Interaction, "Successfully added form button!", true) addFormButton(e.GuildID().String(), e.Channel().ID().String(), message.ID.String(), formManageID.String(), formID, resultChannelID, overwriteTitle, acceptChannelID, category, moderator)
err = e.CreateMessage(discord.NewMessageCreateBuilder().SetContent("Successfully added form button!").SetEphemeral(true).Build())
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
@@ -213,176 +166,135 @@ var cmd_form Command = Command{
}, },
DynamicComponentIDs: func() []string { return getFormButtonIDs() }, DynamicComponentIDs: func() []string { return getFormButtonIDs() },
DynamicModalIDs: func() []string { return getFormButtonIDs() }, DynamicModalIDs: func() []string { return getFormButtonIDs() },
ComponentInteract: func(s *discordgo.Session, i *discordgo.InteractionCreate) { ComponentInteract: func(e *events.ComponentInteractionCreate) {
if strings.ContainsAny(i.MessageComponentData().CustomID, ";") { if e.Data.Type() == discord.ComponentTypeButton {
var form_manage_id string = strings.TrimPrefix(strings.Split(i.MessageComponentData().CustomID, ";")[0], "form:") if strings.ContainsAny(e.ButtonInteractionData().CustomID(), ";") {
switch strings.Split(i.MessageComponentData().CustomID, ";")[1] { var form_manage_id string = strings.TrimPrefix(strings.Split(e.ButtonInteractionData().CustomID(), ";")[0], "form:")
switch strings.Split(e.ButtonInteractionData().CustomID(), ";")[1] {
case "decline": case "decline":
err := s.ChannelMessageDelete(i.ChannelID, i.Message.ID) err := e.Client().Rest().DeleteMessage(e.Channel().ID(), e.Message.ID)
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
respond(i.Interaction, "Submission declined!", true) e.CreateMessage(discord.NewMessageCreateBuilder().SetContent("Submission declined!").SetEphemeral(true).Build())
case "approve": case "approve":
embed := i.Message.Embeds[0] embed := e.Message.Embeds[0]
embed.Description = fmt.Sprintf("This submission was approved by <@%s>.", i.Member.User.ID) embed.Description = fmt.Sprintf("This submission was approved by <@%s>.", e.User().ID)
_, err := s.ChannelMessageSendComplex(getFormResultValues(form_manage_id).ResultChannelID, &discordgo.MessageSend{ _, err := e.Client().Rest().CreateMessage(snowflake.MustParse(getFormResultValues(form_manage_id).ResultChannelID), discord.NewMessageCreateBuilder().
Embed: embed, SetEmbeds(embed).
}) Build())
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
respond(i.Interaction, "Submission accepted!", true) e.CreateMessage(discord.NewMessageCreateBuilder().SetContent("Submission accepted!").SetEphemeral(true).Build())
err = s.ChannelMessageDelete(i.ChannelID, i.Message.ID) err = e.Client().Rest().DeleteMessage(e.Channel().ID(), e.Message.ID)
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
case "comment": case "comment":
author := strings.TrimSuffix(strings.Split(i.Message.Embeds[0].Fields[len(i.Message.Embeds[0].Fields)-1].Value, "<@")[1], ">") author := strings.TrimSuffix(strings.Split(e.Message.Embeds[0].Fields[len(e.Message.Embeds[0].Fields)-1].Value, "<@")[1], ">")
embed := i.Message.Embeds[0] embed := e.Message.Embeds[0]
moderator := i.Member.User.ID moderator := e.User().ID
createFormComment(form_manage_id, author, moderator, "answer", embed, i) channel := createFormComment(form_manage_id, snowflake.MustParse(author), moderator, "answer", embed, *e.GuildID(), e.Client())
e.CreateMessage(discord.NewMessageCreateBuilder().SetContent("Created channel " + discord.ChannelMention(channel.ID())).SetEphemeral(true).Build())
} }
} else { } else {
if strings.HasPrefix(i.Interaction.MessageComponentData().CustomID, "form:") { if strings.HasPrefix(e.ButtonInteractionData().CustomID(), "form:") {
var formManageID string = strings.TrimPrefix(i.Interaction.MessageComponentData().CustomID, "form:") var formManageID string = strings.TrimPrefix(e.ButtonInteractionData().CustomID(), "form:")
jsonStringShowModal(i.Interaction, i.Interaction.MessageComponentData().CustomID, getFormType(formManageID), getFormOverwriteTitle(formManageID)) e.Modal(jsonStringBuildModal(e.User().ID.String(), formManageID, getFormType(formManageID), getFormOverwriteTitle(formManageID)))
} else if i.Interaction.MessageComponentData().CustomID == "form_demo" { } else if e.ButtonInteractionData().CustomID() == "form_demo" {
jsonStringShowModal(i.Interaction, "form_demo", "form_demo") e.Modal(jsonStringBuildModal(e.User().ID.String(), "form_demo", "form_demo"))
}
} }
} }
}, },
ModalSubmit: func(s *discordgo.Session, i *discordgo.InteractionCreate) { ModalSubmit: func(e *events.ModalSubmitInteractionCreate) {
if !strings.HasPrefix(i.ModalSubmitData().CustomID, "form_demo") { if !strings.HasPrefix(e.Data.CustomID, "form_demo") {
var form_manage_id string = strings.Split(i.ModalSubmitData().CustomID, ":")[1] var form_manage_id string = strings.Split(e.Data.CustomID, ":")[1]
var result FormResult = getFormResultValues(form_manage_id) var result FormResult = getFormResultValues(form_manage_id)
var fields []*discordgo.MessageEmbedField var fields []discord.EmbedField
var modal ModalJson = getModalByFormID(getFormType(form_manage_id)) var modal ModalJson = getModalByFormID(getFormType(form_manage_id))
var overwrite_title string = getFormOverwriteTitle(form_manage_id) var overwrite_title string = getFormOverwriteTitle(form_manage_id)
if overwrite_title != "" { if overwrite_title != "" {
modal.Title = overwrite_title modal.Title = overwrite_title
} }
for index, component := range i.ModalSubmitData().Components { var inline bool
var input *discordgo.TextInput = component.(*discordgo.ActionsRow).Components[0].(*discordgo.TextInput) var index int = 0
fields = append(fields, &discordgo.MessageEmbedField{ for _, component := range e.Data.Components {
var input discord.TextInputComponent = component.(discord.TextInputComponent)
inline = input.Style == discord.TextInputStyleShort
fields = append(fields, discord.EmbedField{
Name: modal.Form[index].Label, Name: modal.Form[index].Label,
Value: input.Value, Value: input.Value,
Inline: input.Style == discordgo.TextInputShort, Inline: &inline,
}) })
index++
} }
channel, _ := s.Channel(i.ChannelID) fields = append(fields, discord.EmbedField{
fields = append(fields, &discordgo.MessageEmbedField{ Value: "From <#" + e.Channel().ID().String() + "> by " + e.User().Mention(),
Value: "From <#" + channel.ID + "> by <@" + i.Member.User.ID + ">",
}) })
if result.ResultChannelID == "" { if result.ResultChannelID == "" {
if result.CommentCategoryID != "" { if result.CommentCategoryID != "" {
createFormComment(form_manage_id, i.Member.User.ID, result.ModeratorID, "answer", &discordgo.MessageEmbed{ channel := createFormComment(form_manage_id, e.User().ID, snowflake.MustParse(result.ModeratorID), "answer", discord.NewEmbedBuilder().
Author: &discordgo.MessageEmbedAuthor{ SetAuthorName(*e.User().GlobalName).SetAuthorIcon(*e.User().AvatarURL()).SetTitle("\""+modal.Title+"\"").SetDescription("This is the submitted result").
Name: i.Member.User.Username, SetColor(hexToDecimal(color["primary"])).SetFields(fields...).
IconURL: i.Member.AvatarURL("256"), Build(), *e.GuildID(), e.Client())
}, err := e.CreateMessage(discord.NewMessageCreateBuilder().SetContent("Created channel " + discord.ChannelMention(channel.ID())).SetEphemeral(true).Build())
Title: "\"" + modal.Title + "\"", if err != nil {
Color: hexToDecimal(color["primary"]), logrus.Error(err)
Description: "This is the submitted result",
Fields: fields,
}, i)
} else {
respond(i.Interaction, "You need to provide either a `result_channel` or enable `mods_can_answer` to create a valid form.", true)
} }
} else { } else {
e.CreateMessage(discord.NewMessageCreateBuilder().
SetContent("You need to provide either a `result_channel` or enable `mods_can_answer` to create a valid form.").SetEphemeral(true).
Build())
}
} else {
logrus.Debug(result.AcceptChannelID)
if result.AcceptChannelID == "" { if result.AcceptChannelID == "" {
var buttons []discordgo.MessageComponent _, err := e.Client().Rest().CreateMessage(snowflake.MustParse(result.ResultChannelID), discord.NewMessageCreateBuilder().
SetEmbeds(discord.NewEmbedBuilder().
SetAuthorName(*e.User().GlobalName).SetAuthorIcon(*e.User().AvatarURL()).SetTitle("\""+modal.Title+"\"").SetDescription("This is the submitted result").
SetColor(hexToDecimal(color["primary"])).SetFields(fields...).
Build()).
SetContainerComponents(discord.NewActionRow(discord.
NewButton(discord.ButtonStylePrimary, "Comment", "form:"+form_manage_id+";comment", "").
WithEmoji(discord.ComponentEmoji{Name: "👥"}))).
Build())
if err != nil {
logrus.Error(err)
} else {
err = e.CreateMessage(discord.NewMessageCreateBuilder().SetContent("Submitted!").SetEphemeral(true).Build())
if err != nil {
logrus.Error(err)
}
}
} else {
logrus.Debug("HEERE")
var buttons []discord.InteractiveComponent
if result.CommentCategoryID != "" { if result.CommentCategoryID != "" {
buttons = []discordgo.MessageComponent{ buttons = []discord.InteractiveComponent{discord.
discordgo.ActionsRow{ NewButton(discord.ButtonStylePrimary, "Comment", "form:"+form_manage_id+";comment", "").
Components: []discordgo.MessageComponent{ WithEmoji(discord.ComponentEmoji{Name: "👥"})}
discordgo.Button{
Style: discordgo.PrimaryButton,
Emoji: discordgo.ComponentEmoji{
Name: "👥",
},
Label: "Comment",
CustomID: "form:" + form_manage_id + ";comment",
},
},
},
} }
} buttons = append(buttons, discord.
_, err := s.ChannelMessageSendComplex(result.ResultChannelID, &discordgo.MessageSend{ NewButton(discord.ButtonStyleDanger, "Decline", "form:"+form_manage_id+";decline", "").
Embed: &discordgo.MessageEmbed{ WithEmoji(discord.ComponentEmoji{Name: "🛑"}),
Author: &discordgo.MessageEmbedAuthor{ discord.
Name: i.Member.User.Username, NewButton(discord.ButtonStyleSuccess, "Approve", "form:"+form_manage_id+";approve", "").
IconURL: i.Member.AvatarURL("256"), WithEmoji(discord.ComponentEmoji{Name: "🎉"}))
}, _, err := e.Client().Rest().CreateMessage(snowflake.MustParse(result.AcceptChannelID), discord.NewMessageCreateBuilder().
Title: "\"" + modal.Title + "\"", SetEmbeds(discord.NewEmbedBuilder().
Color: hexToDecimal(color["primary"]), SetAuthorName(*e.User().GlobalName).SetAuthorIcon(*e.User().AvatarURL()).SetTitle("\""+modal.Title+"\"").SetDescription("**This submission needs approval.**").
Description: "This is the submitted result", SetColor(hexToDecimal(color["primary"])).SetFields(fields...).
Fields: fields, Build()).
}, SetContainerComponents(discord.NewActionRow(buttons...)).
Components: buttons, Build())
})
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} else { } else {
err = respond(i.Interaction, "Submited!", true) err = e.CreateMessage(discord.NewMessageCreateBuilder().SetContent("Submitted!").SetEphemeral(true).Build())
if err != nil {
logrus.Error(err)
}
}
} else {
var buttons []discordgo.MessageComponent
if result.CommentCategoryID != "" {
buttons = []discordgo.MessageComponent{
discordgo.Button{
Style: discordgo.PrimaryButton,
Emoji: discordgo.ComponentEmoji{
Name: "👥",
},
Label: "Comment",
CustomID: "form:" + form_manage_id + ";comment",
},
}
}
buttons = append(buttons,
discordgo.Button{
Style: discordgo.DangerButton,
Emoji: discordgo.ComponentEmoji{
Name: "🛑",
},
Label: "Decline",
CustomID: "form:" + form_manage_id + ";decline",
},
discordgo.Button{
Style: discordgo.SuccessButton,
Emoji: discordgo.ComponentEmoji{
Name: "🎉",
},
Label: "Approve",
CustomID: "form:" + form_manage_id + ";approve",
})
_, err := s.ChannelMessageSendComplex(result.AcceptChannelID, &discordgo.MessageSend{
Embed: &discordgo.MessageEmbed{
Author: &discordgo.MessageEmbedAuthor{
Name: i.Member.User.Username,
IconURL: i.Member.AvatarURL("256"),
},
Title: "\"" + modal.Title + "\"",
Color: hexToDecimal(color["primary"]),
Description: "**This submission needs approval.**",
Fields: fields,
},
Components: []discordgo.MessageComponent{
discordgo.ActionsRow{
Components: buttons,
},
}},
)
if err != nil {
logrus.Error(err)
} else {
err = respond(i.Interaction, "Submited!", true)
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
@@ -390,33 +302,27 @@ var cmd_form Command = Command{
} }
} }
} else { } else {
err := respond(i.Interaction, "The results would be submited...", true) err := e.CreateMessage(discord.NewMessageCreateBuilder().SetContent("The results would be submited...").SetEphemeral(true).Build())
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
} }
}, },
Autocomplete: func(s *discordgo.Session, i *discordgo.InteractionCreate) { Autocomplete: func(e *events.AutocompleteInteractionCreate) {
choices := []*discordgo.ApplicationCommandOptionChoice{ err := e.AutocompleteResult([]discord.AutocompleteChoice{
{ &discord.AutocompleteChoiceString{
Name: "Support Ticket", Name: "Support Ticket",
Value: "template_ticket", Value: "template_ticket",
}, },
{ &discord.AutocompleteChoiceString{
Name: "Submit URL", Name: "Submit URL",
Value: "template_url", Value: "template_url",
}, },
{ &discord.AutocompleteChoiceString{
Name: "General", Name: "General",
Value: "template_general", Value: "template_general",
}, },
}
err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionApplicationCommandAutocompleteResult,
Data: &discordgo.InteractionResponseData{
Choices: choices,
},
}) })
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
@@ -425,41 +331,31 @@ var cmd_form Command = Command{
} }
var cmd_ticket_form Command = Command{ var cmd_ticket_form Command = Command{
Definition: discordgo.ApplicationCommand{ Definition: discord.SlashCommandCreate{
Name: "ticket", Name: "ticket",
DefaultMemberPermissions: int64Ptr(discordgo.PermissionManageChannels), DefaultMemberPermissions: json.NewNullablePtr(discord.PermissionManageChannels),
Description: "A quick command to create Ticketpanels. (/form for more)", Description: "A quick command to create Ticketpanels. (/form for more)",
Options: []*discordgo.ApplicationCommandOption{ Options: []discord.ApplicationCommandOption{
{ &discord.ApplicationCommandOptionString{
Type: discordgo.ApplicationCommandOptionString,
Name: "title", Name: "title",
Description: "The title the ticket should have", Description: "The title the ticket should have",
}, },
{ &discord.ApplicationCommandOptionMentionable{
Type: discordgo.ApplicationCommandOptionMentionable,
Name: "moderator", Name: "moderator",
Description: "Who can interact with moderating buttons.", Description: "Who can interact with moderating buttons.",
}, },
}, },
}, },
Interact: func(s *discordgo.Session, i *discordgo.InteractionCreate) { Interact: func(e *events.ApplicationCommandInteractionCreate) {
var title string = "Ticket" var title string = "Ticket"
var moderator string var moderator string
if i.ApplicationCommandData().Options != nil { data := e.SlashCommandInteractionData()
for _, opt := range i.ApplicationCommandData().Options { if data.String("title") != "" {
switch opt.Name { title = data.String("title")
case "title": }
title = opt.StringValue() moderator = data.Role("moderator").ID.String()
case "moderator":
moderator = opt.RoleValue(s, i.GuildID).ID
if moderator == "" { if moderator == "" {
moderator = opt.UserValue(s).ID moderator = data.User("moderator").ID.String()
}
}
}
}
if moderator == "" {
moderator = i.Member.User.ID
} }
var exists bool = true var exists bool = true
var formManageID uuid.UUID = uuid.New() var formManageID uuid.UUID = uuid.New()
@@ -467,29 +363,16 @@ var cmd_ticket_form Command = Command{
formManageID = uuid.New() formManageID = uuid.New()
exists = getFormManageIdExists(formManageID) exists = getFormManageIdExists(formManageID)
} }
message, err := s.ChannelMessageSendComplex(i.ChannelID, &discordgo.MessageSend{ messagebuild := discord.NewMessageCreateBuilder().SetEmbeds(discord.NewEmbedBuilder().
Embed: &discordgo.MessageEmbed{ SetTitle(title).SetDescription("Press the bottom button to open a form popup.").SetColor(hexToDecimal(color["primary"])).
Color: hexToDecimal(color["primary"]), Build()).SetContainerComponents(discord.ActionRowComponent{
Title: title, discord.NewSuccessButton("Submit", "form:"+formManageID.String()).WithEmoji(discord.ComponentEmoji{
Description: "Press the bottom button to open a form popup.",
},
Components: []discordgo.MessageComponent{
discordgo.ActionsRow{
Components: []discordgo.MessageComponent{
discordgo.Button{
CustomID: "form:" + formManageID.String(),
Style: discordgo.SuccessButton,
Label: "Submit",
Emoji: discordgo.ComponentEmoji{
Name: "anim_rocket", Name: "anim_rocket",
ID: "1215740398706757743", ID: snowflake.MustParse("1215740398706757743"),
Animated: true, Animated: true,
}, })}).
}, Build()
}, message, err := e.Client().Rest().CreateMessage(e.Channel().ID(), messagebuild)
},
},
})
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
return return
@@ -498,17 +381,17 @@ var cmd_ticket_form Command = Command{
title = "Ticket" title = "Ticket"
} }
var category string var category string
c, err := s.GuildChannelCreate(i.GuildID, title+" mod answers", discordgo.ChannelTypeGuildCategory) c, err := e.Client().Rest().CreateGuildChannel(*e.GuildID(), discord.GuildCategoryChannelCreate{Name: title + " mod answers"})
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
category = c.ID category = c.ID().String()
if title == "Ticket" { if title == "Ticket" {
title = "" title = ""
} }
addFormButton(i.GuildID, i.ChannelID, message.ID, formManageID.String(), "template_ticket", "", title, "", category, moderator) addFormButton(e.GuildID().String(), e.Channel().ID().String(), message.ID.String(), formManageID.String(), "template_ticket", "", title, "", category, moderator)
err = respond(i.Interaction, "Successfully added ticket panel!\n(`/form` for more options or custom ticket forms.)", true) err = e.CreateMessage(discord.NewMessageCreateBuilder().SetContent("Successfully added ticket panel!\n(`/form` for more options or custom ticket forms.)").SetEphemeral(true).Build())
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
@@ -516,52 +399,61 @@ var cmd_ticket_form Command = Command{
} }
// moderator can be userID as well as roleID // moderator can be userID as well as roleID
func createFormComment(form_manage_id string, author string, moderator string, commentName string, embed *discordgo.MessageEmbed, i *discordgo.InteractionCreate) { func createFormComment(form_manage_id string, author snowflake.ID, moderator snowflake.ID, commentName string, embed discord.Embed, guildID snowflake.ID, client bot.Client) discord.Channel {
category := getFormResultValues(form_manage_id).CommentCategoryID var category snowflake.ID = snowflake.MustParse(getFormResultValues(form_manage_id).CommentCategoryID)
_, err := bot.Channel(category) _, err := client.Rest().GetChannel(category)
if err != nil { if err != nil {
c, err := bot.GuildChannelCreate(i.GuildID, strings.Trim(embed.Title, "\"")+" mod "+commentName+"s", discordgo.ChannelTypeGuildCategory) c, err := client.Rest().CreateGuildChannel(guildID, discord.GuildCategoryChannelCreate{Name: strings.Trim(embed.Title, "\"") + " mod " + commentName + "s"})
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
category = c.ID category = c.ID()
updateFormCommentCategory(form_manage_id, c.ID) updateFormCommentCategory(form_manage_id, category.String())
} }
ch, err := bot.GuildChannelCreateComplex(i.GuildID, discordgo.GuildChannelCreateData{ ch, err := client.Rest().CreateGuildChannel(guildID, discord.GuildTextChannelCreate{
ParentID: category, ParentID: category,
Name: strings.ToLower(embed.Author.Name) + "-" + commentName, Name: strings.ToLower(embed.Author.Name) + "-" + commentName,
}) })
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
err = bot.ChannelPermissionSet(ch.ID, i.GuildID, discordgo.PermissionOverwriteTypeRole, 0, discordgo.PermissionViewChannel) var permissionOverwrites []discord.PermissionOverwrite = []discord.PermissionOverwrite{
if err != nil { discord.RolePermissionOverwrite{
logrus.Error(err) RoleID: guildID,
} Deny: discord.PermissionViewChannel,
modType := discordgo.PermissionOverwriteTypeMember }}
if isIDRole(i.GuildID, moderator) {
modType = discordgo.PermissionOverwriteTypeRole if isIDRole(client, guildID, moderator) {
} permissionOverwrites = append(permissionOverwrites, discord.RolePermissionOverwrite{
err = bot.ChannelPermissionSet(ch.ID, moderator, modType, discordgo.PermissionViewChannel, 0) RoleID: moderator,
if err != nil { Allow: discord.PermissionViewChannel,
logrus.Error(err)
}
err = bot.ChannelPermissionSet(ch.ID, author, discordgo.PermissionOverwriteTypeMember, discordgo.PermissionViewChannel, 0)
if err != nil {
logrus.Error(err)
}
modTypeChar := "&"
if modType == discordgo.PermissionOverwriteTypeMember {
modTypeChar = ""
}
_, err = bot.ChannelMessageSendComplex(ch.ID, &discordgo.MessageSend{
Content: "<@" + modTypeChar + moderator + "> <@" + author + ">",
Embed: embed,
}) })
} else {
permissionOverwrites = append(permissionOverwrites, discord.MemberPermissionOverwrite{
UserID: moderator,
Allow: discord.PermissionViewChannel,
})
}
permissionOverwrites = append(permissionOverwrites, discord.RolePermissionOverwrite{
RoleID: author,
Allow: discord.PermissionViewChannel,
})
_, err = client.Rest().UpdateChannel(ch.ID(), discord.GuildTextChannelUpdate{PermissionOverwrites: &permissionOverwrites})
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
respond(i.Interaction, "Created channel <#"+ch.ID+">", true) modTypeChar := ""
if isIDRole(client, guildID, moderator) {
modTypeChar = "&"
}
embed.Description = "This was submitted"
_, err = client.Rest().CreateMessage(ch.ID(), discord.NewMessageCreateBuilder().
SetContent("<@"+modTypeChar+moderator.String()+"> <@"+author.String()+">").SetEmbeds(embed).
Build())
if err != nil {
logrus.Error(err)
}
return ch
} }
func getFormButtonIDs() []string { func getFormButtonIDs() []string {

View File

@@ -1,16 +1,12 @@
package main package main
import ( import (
"encoding/json"
"fmt" "fmt"
"io"
"net/http"
"os"
"strconv" "strconv"
"strings" "strings"
"time"
"github.com/bwmarrin/discordgo" "github.com/disgoorg/disgo/discord"
"github.com/disgoorg/disgo/events"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@@ -24,128 +20,100 @@ type AvatarDecoration struct {
URL string URL string
} }
var userFlagsString map[discordgo.UserFlags]string = map[discordgo.UserFlags]string{ var userFlagsString map[discord.UserFlags]string = map[discord.UserFlags]string{
discordgo.UserFlagDiscordEmployee: "<:Discord_Employee:1224708831419043942>[`Discord Employee`](https://discord.com/company)", discord.UserFlagDiscordEmployee: "<:Discord_Employee:1224708831419043942>[`Discord Employee`](https://discord.com/company)",
discordgo.UserFlagDiscordPartner: "<:Discord_Partner:1224708689190060092>[`Discord Partner`](https://discord.com/partners)", discord.UserFlagPartneredServerOwner: "<:Discord_Partner:1224708689190060092>[`Discord Partner`](https://discord.com/partners)",
discordgo.UserFlagHypeSquadEvents: "<:Hypesquad_Events:1224708685494747237>[`HypeSquad Events`](https://discord.com/hypesquad)", discord.UserFlagHypeSquadEvents: "<:Hypesquad_Events:1224708685494747237>[`HypeSquad Events`](https://discord.com/hypesquad)",
discordgo.UserFlagBugHunterLevel1: "<:Bug_Hunter_Level_1:1224708828415918231>[`Bug Hunter Level 1`](https://support.discord.com/hc/en-us/articles/360046057772-Discord-Bugs)", discord.UserFlagBugHunterLevel1: "<:Bug_Hunter_Level_1:1224708828415918231>[`Bug Hunter Level 1`](https://support.discord.com/hc/en-us/articles/360046057772-Discord-Bugs)",
discordgo.UserFlagHouseBravery: "<:Hypesquad_Bravery:1224708678905630801>[`HypeSquad Bravery`](https://discord.com/settings/hypesquad-online)", discord.UserFlagHouseBravery: "<:Hypesquad_Bravery:1224708678905630801>[`HypeSquad Bravery`](https://discord.com/settings/hypesquad-online)",
discordgo.UserFlagHouseBrilliance: "<:Hypesquad_Brilliance:1224708677584424961>[`HypeSquad Brilliance`](https://discord.com/settings/hypesquad-online)", discord.UserFlagHouseBrilliance: "<:Hypesquad_Brilliance:1224708677584424961>[`HypeSquad Brilliance`](https://discord.com/settings/hypesquad-online)",
discordgo.UserFlagHouseBalance: "<:Hypequad_Balance:1224708826901516309>[`HypeSquad Balance`](https://discord.com/settings/hypesquad-online)", discord.UserFlagHouseBalance: "<:Hypequad_Balance:1224708826901516309>[`HypeSquad Balance`](https://discord.com/settings/hypesquad-online)",
discordgo.UserFlagEarlySupporter: "<:Early_Supporter:1224708674065272873>[`Early Supporter`](https://discord.com/settings/premium)", discord.UserFlagEarlySupporter: "<:Early_Supporter:1224708674065272873>[`Early Supporter`](https://discord.com/settings/premium)",
discordgo.UserFlagTeamUser: "`TeamUser`", discord.UserFlagTeamUser: "`TeamUser`",
discordgo.UserFlagSystem: "", discord.UserFlagBugHunterLevel2: "<:Bug_Hunter_Level_2:1224708682378383461>[`Bug Hunter Level 2`](https://support.discord.com/hc/en-us/articles/360046057772-Discord-Bugs)",
discordgo.UserFlagBugHunterLevel2: "<:Bug_Hunter_Level_2:1224708682378383461>[`Bug Hunter Level 2`](https://support.discord.com/hc/en-us/articles/360046057772-Discord-Bugs)", discord.UserFlagVerifiedBot: "",
discordgo.UserFlagVerifiedBot: "", discord.UserFlagEarlyVerifiedBotDeveloper: "<:Early_Verified_Bot_Developer:1224708675294203934>`Early Verified Bot Developer`",
discordgo.UserFlagVerifiedBotDeveloper: "<:Early_Verified_Bot_Developer:1224708675294203934>`Early Verified Bot Developer`", discord.UserFlagDiscordCertifiedModerator: "<:Discord_Certified_Moderator:1224708830223532124>[`Discord Certified Moderator`](https://discord.com/safety)",
discordgo.UserFlagDiscordCertifiedModerator: "<:Discord_Certified_Moderator:1224708830223532124>[`Discord Certified Moderator`](https://discord.com/safety)", discord.UserFlagBotHTTPInteractions: "`BotHTTPInteractions`",
1 << 19: "`BotHTTPInteractions`", discord.UserFlagActiveDeveloper: "<:Active_Developer:1224708676611215380>[`Active Developer`](https://support-dev.discord.com/hc/en-us/articles/10113997751447?ref=badge)",
1 << 22: "<:Active_Developer:1224708676611215380>[`Active Developer`](https://support-dev.discord.com/hc/en-us/articles/10113997751447?ref=badge)",
} }
var cmd_userinfo Command = Command{ var cmd_userinfo Command = Command{
Definition: discordgo.ApplicationCommand{ Definition: discord.SlashCommandCreate{
Name: "info", Name: "info",
Description: "Gives you information about a user or this bot.", Description: "Gives you information about a user or this bot.",
Options: []*discordgo.ApplicationCommandOption{ Options: []discord.ApplicationCommandOption{
{ &discord.ApplicationCommandOptionSubCommand{
Type: discordgo.ApplicationCommandOptionSubCommand,
Name: "user", Name: "user",
Description: "Gives you information about a user and its profile images.", Description: "Gives you information about a user and its profile images.",
Options: []*discordgo.ApplicationCommandOption{ Options: []discord.ApplicationCommandOption{
{ &discord.ApplicationCommandOptionUser{
Type: discordgo.ApplicationCommandOptionUser,
Name: "user", Name: "user",
Description: "The user you need information about.", Description: "The user you need information about.",
Required: true, Required: true,
}, },
}, },
}, },
{ &discord.ApplicationCommandOptionSubCommand{
Type: discordgo.ApplicationCommandOptionSubCommand,
Name: "bot-service", Name: "bot-service",
Description: "Gives you information about this bot's server service.", Description: "Gives you information about this bot's server service.",
}, },
}, },
}, },
Interact: func(s *discordgo.Session, i *discordgo.InteractionCreate) { Interact: func(e *events.ApplicationCommandInteractionCreate) {
switch i.ApplicationCommandData().Options[0].Name { switch *e.SlashCommandInteractionData().SubCommandName {
case "user": case "user":
var user *discordgo.User = i.ApplicationCommandData().Options[0].Options[0].UserValue(s) user, err := e.Client().Rest().GetUser(e.SlashCommandInteractionData().User("user").ID)
var extendedUser UserExtend = extendedUserFromAPI(user.ID) if err != nil {
var userHasFlags string = fetchFlagStrings(user, extendedUser.AvatarDecorationData.Asset) logrus.Error(err)
}
var userHasFlags string = fetchFlagStrings(*user)
var userType string = "User" var userType string = "User"
if user.Bot { if user.Bot {
userType = "Unverified Bot" userType = "Unverified Bot"
if user.PublicFlags&discordgo.UserFlagVerifiedBot != 0 { if user.PublicFlags&discord.UserFlagVerifiedBot != 0 {
userType = "Verified Bot" userType = "Verified Bot"
} }
} else if user.System { } else if user.System {
userType = "System" userType = "System"
} }
createdate, err := discordgo.SnowflakeTimestamp(user.ID) embedBuilder := discord.NewEmbedBuilder()
if err != nil { embedBuilder.SetThumbnail(checkDefaultPb(*user) + "?size=4096")
logrus.Error(err) embedBuilder.AddField("ID", user.ID.String(), false)
} embedBuilder.AddField("Type", userType, true)
err = respondEmbed(i.Interaction, discordgo.MessageEmbed{ if user.GlobalName != nil {
Title: extendedUser.GlobalName + " user info", embedBuilder.AddField("Global name", *user.GlobalName, true)
Thumbnail: &discordgo.MessageEmbedThumbnail{URL: user.AvatarURL("512")}, }
Description: user.Mention(), embedBuilder.AddField("Username", user.Username, true)
Type: discordgo.EmbedTypeArticle, if userHasFlags != "" {
Fields: []*discordgo.MessageEmbedField{ embedBuilder.AddField("Badges", userHasFlags, false)
{ }
Name: "test", if user.Discriminator != "0" {
Value: fmt.Sprint(s.State.Application.BotPublic), embedBuilder.AddField("Discriminator", user.Discriminator, false)
}, }
{ if user.AccentColor != nil {
Name: "ID", embedBuilder.AddField("Accent color", strconv.Itoa(*user.AccentColor), true)
Value: user.ID, }
}, if user.AvatarDecorationURL() != nil {
{ value := fmt.Sprintf("[PNG (animated)](%s)\n[PNG](%s)", *user.AvatarDecorationURL(), *user.AvatarDecorationURL()+"?passthrough=false")
Name: "Type", embedBuilder.AddField("Avatar decoration", value, true)
Value: userType, }
Inline: true, creation := "<:discord_member:1224717530078253166> " + discord.TimestampStyleLongDateTime.FormatTime(user.CreatedAt()) + "-" + discord.TimestampStyleRelative.FormatTime(user.CreatedAt())
}, embedBuilder.AddField("Created at", creation, false)
{
Name: "Global name", if user.BannerURL() != nil {
Value: extendedUser.GlobalName, embedBuilder.SetImage(*user.BannerURL() + "?size=4096")
Inline: true, }
}, embedBuilder.SetTitle("User info")
{ embedBuilder.SetDescription(user.Mention())
Name: "Username", embedBuilder.SetColor(hexToDecimal(color["primary"]))
Value: user.Username, err = e.CreateMessage(discord.NewMessageCreateBuilder().
Inline: true, SetEmbeds(embedBuilder.Build()).
}, Build())
{
Name: "Badges",
Value: userHasFlags,
},
{
Name: "Discriminator",
Value: user.Discriminator,
Inline: true,
},
{
Name: "Accent color",
Value: "#" + decimalToHex(user.AccentColor),
Inline: true,
},
{
Name: "Avatar Decoration",
Value: "[PNG (animated)](" + extendedUser.AvatarDecorationData.URL + ")\n[PNG](" + extendedUser.AvatarDecorationData.URL + "?size=4096&passthrough=false)\nSKU ID: `" + extendedUser.AvatarDecorationData.SkuID + "`",
Inline: true,
},
{
Name: "Created at",
Value: "<:discord_member:1224717530078253166> <t:" + fmt.Sprint(createdate.Unix()) + ":f> - <t:" + fmt.Sprint(createdate.Unix()) + ":R>",
},
},
Color: hexToDecimal(color["primary"]),
Image: &discordgo.MessageEmbedImage{URL: user.BannerURL("512")},
}, false)
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
case "bot-service": case "bot-service":
} }
@@ -154,19 +122,27 @@ var cmd_userinfo Command = Command{
AllowDM: true, AllowDM: true,
} }
func fetchFlagStrings(user *discordgo.User, decorationAsset string) string { func checkDefaultPb(user discord.User) string {
if user.AvatarURL() == nil {
return "https://discord.com/assets/ac6f8cf36394c66e7651.png"
}
return *user.AvatarURL()
}
func fetchFlagStrings(user discord.User) string {
var userHasFlagsString string var userHasFlagsString string
for flag, flagName := range userFlagsString { for flag, flagName := range userFlagsString {
if user.PublicFlags&flag != 0 { if flag&user.PublicFlags != 0 {
userHasFlagsString += flagName + ", " userHasFlagsString += flagName + ", "
} }
} }
if user.AvatarDecorationData != nil && user.AvatarDecorationData.Asset == "a_5e1210779d99ece1c0b4f438a5bc6e72" {
userHasFlagsString += "<:Limited_Lootbox_Clown:1224714172705804300>[`Lootbox Clown`](https://discord.com/settings/Lootboxes)"
}
/*
if user.PremiumType > 0 { if user.PremiumType > 0 {
userHasFlagsString += "<:Nitro:1224708672492666943>[`Nitro`](https://discord.com/settings/premium), " userHasFlagsString += "<:Nitro:1224708672492666943>[`Nitro`](https://discord.com/settings/premium), "
} }
if decorationAsset == "a_5e1210779d99ece1c0b4f438a5bc6e72" {
userHasFlagsString += "<:Limited_Lootbox_Clown:1224714172705804300>[`Lootbox Clown`](https://discord.com/settings/Lootboxes)"
}
if user.Bot { if user.Bot {
appuser := bot.State.Application appuser := bot.State.Application
if appuser.Flags&1<<23 != 0 { if appuser.Flags&1<<23 != 0 {
@@ -176,59 +152,7 @@ func fetchFlagStrings(user *discordgo.User, decorationAsset string) string {
userHasFlagsString += "<:Uses_Automod:1224862880982106202>`Uses Automod`" userHasFlagsString += "<:Uses_Automod:1224862880982106202>`Uses Automod`"
} }
} }
*/
returnString := strings.TrimSuffix(userHasFlagsString, ", ") returnString := strings.TrimSuffix(userHasFlagsString, ", ")
return returnString return returnString
} }
func extendedUserFromAPI(userID string) UserExtend {
client := &http.Client{}
var userExtend UserExtend
req, err := http.NewRequest("GET", "https://discord.com/api/v10/users/"+userID, nil)
if err != nil {
logrus.Error(err)
return userExtend
}
req.Header.Add("Authorization", "Bot "+os.Getenv("BOT_TOKEN"))
req.Header.Add("Content-Type", "application/json")
res, err := client.Do(req)
if err != nil {
logrus.Error(err)
return userExtend
}
defer res.Body.Close()
if res.StatusCode == http.StatusTooManyRequests {
retryAfter := parseRetryAfterHeader(res.Header)
if retryAfter > 0 {
time.Sleep(retryAfter)
}
}
body, err := io.ReadAll(res.Body)
if err != nil {
logrus.Error(err)
return userExtend
}
json.Unmarshal(body, &userExtend)
if userExtend.AvatarDecorationData.Asset != "" {
userExtend.AvatarDecorationData.URL = "https://cdn.discordapp.com/avatar-decoration-presets/" + userExtend.AvatarDecorationData.Asset + ".png"
}
return userExtend
}
func parseRetryAfterHeader(headers http.Header) time.Duration {
retryAfterStr := headers.Get("Retry-After")
if retryAfterStr == "" {
return 0
}
retryAfter, err := strconv.Atoi(retryAfterStr)
if err != nil {
return 0
}
return time.Duration(retryAfter) * time.Millisecond
}

View File

@@ -5,23 +5,24 @@ import (
"net/http" "net/http"
"time" "time"
"github.com/bwmarrin/discordgo" "github.com/disgoorg/disgo/discord"
"github.com/disgoorg/disgo/events"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
var cmd_ping Command = Command{ var cmd_ping Command = Command{
Definition: discordgo.ApplicationCommand{ Definition: discord.SlashCommandCreate{
Name: "ping", Name: "ping",
Description: "Returns the ping of the bot", Description: "Returns the ping of the bot",
}, },
Interact: func(s *discordgo.Session, i *discordgo.InteractionCreate) { Interact: func(e *events.ApplicationCommandInteractionCreate) {
start := time.Now() start := time.Now()
client := http.Client{ client := http.Client{
Timeout: 5 * time.Second, Timeout: 5 * time.Second,
} }
resp, err := client.Get("https://discord.com/api/" + discordgo.APIVersion + "/gateway/bot") resp, err := client.Get("https://discord.com/api/v9/gateway/bot")
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
return return
@@ -29,19 +30,23 @@ var cmd_ping Command = Command{
defer resp.Body.Close() defer resp.Body.Close()
ping := time.Since(start) ping := time.Since(start)
var ping_color string var pingColor string
if ping.Milliseconds() < 200 { if ping.Milliseconds() < 200 {
ping_color = "green" pingColor = "green"
} else if ping.Milliseconds() < 400 { } else if ping.Milliseconds() < 400 {
ping_color = "yellow" pingColor = "yellow"
} else { } else {
ping_color = "red" pingColor = "red"
} }
err = respondEmbed(i.Interaction, discordgo.MessageEmbed{ app, err := e.Client().Rest().GetCurrentApplication()
Title: s.State.User.Username + " ping", if err != nil {
Description: fmt.Sprintf("# %.2fms", ping.Seconds()*1000), logrus.Error(err)
Type: discordgo.EmbedTypeArticle, }
Color: hexToDecimal(color[ping_color])}, true) err = e.CreateMessage(discord.NewMessageCreateBuilder().
SetEmbeds(discord.NewEmbedBuilder().
SetTitle(app.Bot.Username + " ping").
SetDescription(fmt.Sprintf("# %.2fms", ping.Seconds()*1000)).
SetColor(hexToDecimal(color[pingColor])).Build()).SetEphemeral(true).Build())
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }

View File

@@ -1,98 +1,103 @@
package main package main
import ( import (
"github.com/bwmarrin/discordgo" "github.com/disgoorg/disgo/discord"
"github.com/disgoorg/disgo/events"
"github.com/disgoorg/json"
"github.com/disgoorg/snowflake/v2"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
var cmd_sticky Command = Command{ var cmd_sticky Command = Command{
Definition: discordgo.ApplicationCommand{ Definition: discord.SlashCommandCreate{
Name: "sticky", Name: "sticky",
Description: "Stick or unstick messages to the bottom of the current channel", Description: "Stick or unstick messages to the bottom of the current channel",
DefaultMemberPermissions: int64Ptr(discordgo.PermissionManageMessages), DefaultMemberPermissions: json.NewNullablePtr(discord.PermissionManageMessages),
Options: []*discordgo.ApplicationCommandOption{ Options: []discord.ApplicationCommandOption{
{ &discord.ApplicationCommandOptionString{
Type: discordgo.ApplicationCommandOptionString,
Name: "message", Name: "message",
Description: "The message you want to stick to the bottom of this channel", Description: "The message you want to stick to the bottom of this channel",
Required: false, Required: false,
}, },
}, },
}, },
Interact: func(s *discordgo.Session, i *discordgo.InteractionCreate) { Interact: func(e *events.ApplicationCommandInteractionCreate) {
if len(i.ApplicationCommandData().Options) == 0 { if len(e.SlashCommandInteractionData().Options) == 0 {
if hasSticky(i.GuildID, i.ChannelID) { if hasSticky(e.GuildID().String(), e.Channel().ID().String()) {
err := s.ChannelMessageDelete(i.ChannelID, getStickyMessageID(i.GuildID, i.ChannelID)) err := e.Client().Rest().DeleteMessage(e.Channel().ID(), snowflake.MustParse(getStickyMessageID(e.GuildID().String(), e.Channel().ID().String())))
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
removeSticky(i.GuildID, i.ChannelID) removeSticky(e.GuildID().String(), e.Channel().ID().String())
err = respond(i.Interaction, "The sticky message was removed from this channel!", true) err = e.CreateMessage(discord.NewMessageCreateBuilder().
SetContent("The sticky message was removed from this channel!").SetEphemeral(true).
Build())
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
} else { } else {
err := respond(i.Interaction, "This channel has no sticky message!", true) err := e.CreateMessage(discord.NewMessageCreateBuilder().
SetContent("This channel has no sticky message!").SetEphemeral(true).
Build())
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
} }
} else { } else {
inputStickyMessage(i) inputStickyMessage(e)
} }
}, },
} }
var context_sticky Command = Command{ var context_sticky Command = Command{
Definition: discordgo.ApplicationCommand{ Definition: discord.MessageCommandCreate{
Name: "Stick to channel", Name: "Stick to channel",
Type: discordgo.MessageApplicationCommand, DefaultMemberPermissions: json.NewNullablePtr(discord.PermissionManageMessages),
DefaultMemberPermissions: int64Ptr(discordgo.PermissionManageMessages),
}, },
Interact: func(s *discordgo.Session, i *discordgo.InteractionCreate) { Interact: func(e *events.ApplicationCommandInteractionCreate) {
inputStickyMessage(i) inputStickyMessage(e)
}, },
} }
func inputStickyMessage(i *discordgo.InteractionCreate) { func inputStickyMessage(e *events.ApplicationCommandInteractionCreate) {
var messageText string var messageText string
if len(i.ApplicationCommandData().Options) == 0 { if e.ApplicationCommandInteraction.Data.Type() == discord.ApplicationCommandTypeMessage {
messageText = i.ApplicationCommandData().Resolved.Messages[i.ApplicationCommandData().TargetID].Content //TODO add more data then just content messageText = e.MessageCommandInteractionData().TargetMessage().Content //TODO add more data then just content
} else { } else {
messageText = i.ApplicationCommandData().Options[0].StringValue() messageText = e.SlashCommandInteractionData().String("message")
} }
if messageText == "" { if messageText == "" {
err := respond(i.Interaction, "Can't add empty sticky messages!", true) err := e.CreateMessage(discord.NewMessageCreateBuilder().
SetContent("Can't add empty sticky messages!").SetEphemeral(true).
Build())
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
} else { } else {
message, err := bot.ChannelMessageSendEmbed(i.ChannelID, &discordgo.MessageEmbed{ message, err := e.Client().Rest().CreateMessage(e.Channel().ID(), discord.MessageCreate{Embeds: []discord.Embed{
Type: discordgo.EmbedTypeArticle, {Description: messageText, Footer: &discord.EmbedFooter{Text: "📌 Sticky message"}, Color: hexToDecimal(color["primary"])}}})
Footer: &discordgo.MessageEmbedFooter{
Text: "📌 Sticky message",
},
Color: hexToDecimal(color["primary"]),
Description: messageText,
})
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
if hasSticky(i.GuildID, i.ChannelID) { if hasSticky(e.GuildID().String(), e.Channel().ID().String()) {
err = bot.ChannelMessageDelete(i.ChannelID, getStickyMessageID(i.GuildID, i.ChannelID)) err = e.Client().Rest().DeleteMessage(e.Channel().ID(), snowflake.MustParse(getStickyMessageID(e.GuildID().String(), e.Channel().ID().String())))
if err != nil { if err != nil {
logrus.Error(err, getStickyMessageID(i.GuildID, i.ChannelID)) logrus.Error(err, getStickyMessageID(e.GuildID().String(), e.Channel().ID().String()))
} }
removeSticky(i.GuildID, i.ChannelID) removeSticky(e.GuildID().String(), e.Channel().ID().String())
addSticky(i.GuildID, i.ChannelID, messageText, message.ID) addSticky(e.GuildID().String(), e.Channel().ID().String(), messageText, message.ID.String())
err = respond(i.Interaction, "Sticky message in this channel was updated!", true) err = e.CreateMessage(discord.NewMessageCreateBuilder().
SetContent("Sticky message in this channel was updated!").SetEphemeral(true).
Build())
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
} else { } else {
addSticky(i.GuildID, i.ChannelID, messageText, message.ID) addSticky(e.GuildID().String(), e.Channel().ID().String(), messageText, message.ID.String())
err := respond(i.Interaction, "Message sticked to the channel!", true) err := e.CreateMessage(discord.NewMessageCreateBuilder().
SetContent("Message sticked to the channel!").SetEphemeral(true).
Build())
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }

View File

@@ -1,23 +1,23 @@
package main package main
import ( import (
"github.com/bwmarrin/discordgo" "github.com/disgoorg/disgo/discord"
"github.com/disgoorg/disgo/events"
"github.com/disgoorg/json"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
var cmd_tag Command = Command{ var cmd_tag Command = Command{
Definition: discordgo.ApplicationCommand{ Definition: discord.SlashCommandCreate{
Name: "tag", Name: "tag",
DefaultMemberPermissions: int64Ptr(discordgo.PermissionManageServer), DefaultMemberPermissions: json.NewNullablePtr(discord.PermissionManageGuild),
Description: "A command to show and edit saved presaved messages.", Description: "A command to show and edit saved presaved messages.",
Options: []*discordgo.ApplicationCommandOption{ Options: []discord.ApplicationCommandOption{
{ discord.ApplicationCommandOptionSubCommand{
Name: "get", Name: "get",
Description: "A command to get messages saved to the bot.", Description: "A command to get messages saved to the bot.",
Type: discordgo.ApplicationCommandOptionSubCommand, Options: []discord.ApplicationCommandOption{
Options: []*discordgo.ApplicationCommandOption{ discord.ApplicationCommandOptionString{
{
Type: discordgo.ApplicationCommandOptionString,
Name: "tag", Name: "tag",
Description: "Your predefined tag for the saved message", Description: "Your predefined tag for the saved message",
Required: true, Required: true,
@@ -25,18 +25,15 @@ var cmd_tag Command = Command{
}, },
}, },
}, },
{ discord.ApplicationCommandOptionSubCommand{
Name: "add", Name: "add",
Description: "A command to add messages saved to the bot.", Description: "A command to add messages saved to the bot.",
Type: discordgo.ApplicationCommandOptionSubCommand,
}, },
{ discord.ApplicationCommandOptionSubCommand{
Name: "remove", Name: "remove",
Description: "A command to remove messages saved to the bot.", Description: "A command to remove messages saved to the bot.",
Type: discordgo.ApplicationCommandOptionSubCommand, Options: []discord.ApplicationCommandOption{
Options: []*discordgo.ApplicationCommandOption{ discord.ApplicationCommandOptionString{
{
Type: discordgo.ApplicationCommandOptionString,
Name: "tag", Name: "tag",
Description: "The tag you want to remove", Description: "The tag you want to remove",
Required: true, Required: true,
@@ -46,42 +43,45 @@ var cmd_tag Command = Command{
}, },
}, },
}, },
Interact: func(s *discordgo.Session, i *discordgo.InteractionCreate) { Interact: func(e *events.ApplicationCommandInteractionCreate) {
switch i.ApplicationCommandData().Options[0].Name { switch *e.SlashCommandInteractionData().SubCommandName {
case "get": case "get":
GetTagCommand(i, i.ApplicationCommandData().Options[0].Options[0]) GetTagCommand(e)
case "add": case "add":
AddTagCommand(i, "") AddTagCommand(e)
case "remove": case "remove":
removeTag(i.GuildID, i.ApplicationCommandData().Options[0].Options[0].StringValue()) removeTag(e.GuildID().String(), e.SlashCommandInteractionData().String("tag"))
err := respond(i.Interaction, "Tag removed!", true) err := e.CreateMessage(discord.NewMessageCreateBuilder().
SetContent("Tag removed!").SetEphemeral(true).
Build())
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
} }
}, },
ModalIDs: []string{"tag_add_modal"}, ModalIDs: []string{"tag_add_modal"},
ModalSubmit: func(s *discordgo.Session, i *discordgo.InteractionCreate) { ModalSubmit: func(e *events.ModalSubmitInteractionCreate) {
tagName := i.ModalSubmitData().Components[0].(*discordgo.ActionsRow).Components[0].(*discordgo.TextInput).Value tagName := e.Data.Text("tag_add_modal_name")
tagContent := i.ModalSubmitData().Components[1].(*discordgo.ActionsRow).Components[0].(*discordgo.TextInput).Value tagContent := e.Data.Text("tag_add_modal_content")
addTag(i.GuildID, tagName, tagContent) addTag(e.GuildID().String(), tagName, tagContent)
err := respond(i.Interaction, "Tag \""+tagName+"\" added!", true) err := e.CreateMessage(discord.NewMessageCreateBuilder().
SetContent("Tag \"" + tagName + "\" added!").SetEphemeral(true).
Build())
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
}, },
Autocomplete: func(s *discordgo.Session, i *discordgo.InteractionCreate) { Autocomplete: func(e *events.AutocompleteInteractionCreate) {
AutocompleteTag(i) AutocompleteTag(e)
}, },
} }
var cmd_tag_short Command = Command{ var cmd_tag_short Command = Command{
Definition: discordgo.ApplicationCommand{ Definition: discord.SlashCommandCreate{
Name: "g", Name: "g",
Description: "A short command to get presaved messages.", Description: "A short command to get presaved messages.",
Options: []*discordgo.ApplicationCommandOption{ Options: []discord.ApplicationCommandOption{
{ discord.ApplicationCommandOptionString{
Type: discordgo.ApplicationCommandOptionString,
Name: "tag", Name: "tag",
Description: "Your predefined tag for the saved message", Description: "Your predefined tag for the saved message",
Required: true, Required: true,
@@ -89,86 +89,78 @@ var cmd_tag_short Command = Command{
}, },
}, },
}, },
Interact: func(s *discordgo.Session, i *discordgo.InteractionCreate) { Interact: func(e *events.ApplicationCommandInteractionCreate) {
GetTagCommand(i, i.ApplicationCommandData().Options[0]) GetTagCommand(e)
}, },
Autocomplete: func(s *discordgo.Session, i *discordgo.InteractionCreate) { Autocomplete: func(e *events.AutocompleteInteractionCreate) {
AutocompleteTag(i) AutocompleteTag(e)
}, },
} }
var context_tag Command = Command{ var context_tag Command = Command{
Definition: discordgo.ApplicationCommand{ Definition: discord.MessageCommandCreate{
Type: discordgo.MessageApplicationCommand,
Name: "Save as tag", Name: "Save as tag",
DefaultMemberPermissions: int64Ptr(discordgo.PermissionManageServer), DefaultMemberPermissions: json.NewNullablePtr(discord.PermissionManageGuild),
}, },
Interact: func(s *discordgo.Session, i *discordgo.InteractionCreate) { Interact: func(e *events.ApplicationCommandInteractionCreate) {
AddTagCommand(i, i.ApplicationCommandData().Resolved.Messages[i.ApplicationCommandData().TargetID].Content) AddTagCommand(e)
}, },
} }
func GetTagCommand(i *discordgo.InteractionCreate, option *discordgo.ApplicationCommandInteractionDataOption) { func GetTagCommand(e *events.ApplicationCommandInteractionCreate) {
err := respond(i.Interaction, getTagContent(i.GuildID, option.Value.(string)), false) err := e.CreateMessage(discord.NewMessageCreateBuilder().
SetContent(getTagContent(e.GuildID().String(), e.SlashCommandInteractionData().String("tag"))).
Build())
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
} }
func AddTagCommand(i *discordgo.InteractionCreate, prevalue string) { func AddTagCommand(e *events.ApplicationCommandInteractionCreate) {
err := bot.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ var prevalue string
Type: discordgo.InteractionResponseModal, if e.ApplicationCommandInteraction.Data.Type() == discord.ApplicationCommandTypeMessage {
Data: &discordgo.InteractionResponseData{ prevalue = e.MessageCommandInteractionData().TargetMessage().Content
CustomID: "tag_add_modal" + i.Interaction.Member.User.ID, }
err := e.Modal(discord.ModalCreate{
CustomID: "tag_add_modal" + e.User().ID.String(),
Title: "Add a custom tag command", Title: "Add a custom tag command",
Components: []discordgo.MessageComponent{ Components: []discord.ContainerComponent{
discordgo.ActionsRow{ discord.ActionRowComponent{
Components: []discordgo.MessageComponent{ discord.TextInputComponent{
discordgo.TextInput{
CustomID: "tag_add_modal_name", CustomID: "tag_add_modal_name",
Label: "Name", Label: "Name",
Style: discordgo.TextInputShort, Style: discord.TextInputStyleShort,
Required: true, Required: true,
MaxLength: 20, MaxLength: 20,
Value: "", Value: "",
}, },
}, },
}, discord.ActionRowComponent{
discordgo.ActionsRow{ discord.TextInputComponent{
Components: []discordgo.MessageComponent{
discordgo.TextInput{
CustomID: "tag_add_modal_content", CustomID: "tag_add_modal_content",
Label: "Content", Label: "Content",
Placeholder: "Content that gets returned when the tag will be run", Style: discord.TextInputStyleParagraph,
Style: discordgo.TextInputParagraph,
Required: true, Required: true,
MaxLength: 2000, MaxLength: 2000,
Value: prevalue, Value: prevalue,
}, },
}, },
}, },
},
},
}) })
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
} }
func AutocompleteTag(i *discordgo.InteractionCreate) { func AutocompleteTag(e *events.AutocompleteInteractionCreate) {
err := bot.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ err := e.AutocompleteResult(generateTagChoices(e.GuildID().String()))
Type: discordgo.InteractionApplicationCommandAutocompleteResult,
Data: &discordgo.InteractionResponseData{
Choices: generateTagChoices(i.GuildID),
},
})
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
} }
func generateTagChoices(guildID string) []*discordgo.ApplicationCommandOptionChoice { func generateTagChoices(guildID string) []discord.AutocompleteChoice {
choices := []*discordgo.ApplicationCommandOptionChoice{} choices := []discord.AutocompleteChoice{}
IDs, err := getTagIDs(guildID) IDs, err := getTagIDs(guildID)
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
@@ -176,7 +168,7 @@ func generateTagChoices(guildID string) []*discordgo.ApplicationCommandOptionCho
} }
for _, id := range IDs { for _, id := range IDs {
id_name := getTagName(guildID, id) id_name := getTagName(guildID, id)
choices = append(choices, &discordgo.ApplicationCommandOptionChoice{ choices = append(choices, &discord.AutocompleteChoiceString{
Name: id_name, Name: id_name,
Value: id, Value: id,
}) })

12
go.mod
View File

@@ -3,7 +3,9 @@ module github.com/vaporvee/acecore
go 1.21.6 go 1.21.6
require ( require (
github.com/bwmarrin/discordgo v0.27.1 github.com/disgoorg/disgo v0.18.1-0.20240408224120-2676e29d6e86
github.com/disgoorg/json v1.1.0
github.com/disgoorg/snowflake/v2 v2.0.1
github.com/google/uuid v1.6.0 github.com/google/uuid v1.6.0
github.com/joho/godotenv v1.5.1 github.com/joho/godotenv v1.5.1
github.com/lib/pq v1.10.9 github.com/lib/pq v1.10.9
@@ -11,9 +13,11 @@ require (
) )
require ( require (
github.com/gorilla/websocket v1.4.2 // indirect github.com/gorilla/websocket v1.5.1 // indirect
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b // indirect github.com/sasha-s/go-csync v0.0.0-20240107134140-fcbab37b09ad // indirect
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect golang.org/x/crypto v0.19.0 // indirect
golang.org/x/net v0.21.0 // indirect
golang.org/x/sys v0.17.0 // indirect
) )
replace github.com/vaporvee/acecore/custom => ./custom replace github.com/vaporvee/acecore/custom => ./custom

44
go.sum
View File

@@ -1,32 +1,48 @@
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/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/disgoorg/disgo v0.17.2 h1:RxiLq8guMtk+9tArFwve02iya2APQ9yZVtV30ySKNtw=
github.com/disgoorg/disgo v0.17.2/go.mod h1:8r3h9fXSz7BbACxLPsPbtB6LX8gaQFUETgPKV/0gAKQ=
github.com/disgoorg/disgo v0.18.0 h1:EviKy/OiGofYW2X4kLjgxAUYrqjmBEMpVp/MMXHP1pY=
github.com/disgoorg/disgo v0.18.0/go.mod h1:gkl6DBdbKUvmOOJayWPSvS52KPN/8uJGJ2f13gCEB1o=
github.com/disgoorg/disgo v0.18.1-0.20240408224120-2676e29d6e86 h1:hSRIjnKWL07TYxvZRxdSBpS78gJNf+JkAuzXY3O1Kos=
github.com/disgoorg/disgo v0.18.1-0.20240408224120-2676e29d6e86/go.mod h1:gkl6DBdbKUvmOOJayWPSvS52KPN/8uJGJ2f13gCEB1o=
github.com/disgoorg/json v1.1.0 h1:7xigHvomlVA9PQw9bMGO02PHGJJPqvX5AnwlYg/Tnys=
github.com/disgoorg/json v1.1.0/go.mod h1:BHDwdde0rpQFDVsRLKhma6Y7fTbQKub/zdGO5O9NqqA=
github.com/disgoorg/snowflake/v2 v2.0.1 h1:CuUxGLwggUxEswZOmZ+mZ5i0xSumQdXW9tXW7uGqe+0=
github.com/disgoorg/snowflake/v2 v2.0.1/go.mod h1:SPU9c2CNn5DSyb86QcKtdZgix9osEtKrHLW4rMhfLCs=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sasha-s/go-csync v0.0.0-20240107134140-fcbab37b09ad h1:qIQkSlF5vAUHxEmTbaqt1hkJ/t6skqEGYiMag343ucI=
github.com/sasha-s/go-csync v0.0.0-20240107134140-fcbab37b09ad/go.mod h1:/pA7k3zsXKdjjAiUhB5CjuKib9KJGCaLvZwtxGC8U0s=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b h1:7mWr3k41Qtv8XlltBkDkl8LoP3mpSgBW8BUoxtEdbXg= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@@ -1,98 +1,129 @@
package main package main
import ( import (
"fmt"
"os" "os"
"slices" "slices"
"strings" "strings"
"github.com/bwmarrin/discordgo" "github.com/disgoorg/disgo/bot"
"github.com/disgoorg/disgo/discord"
"github.com/disgoorg/disgo/events"
"github.com/disgoorg/snowflake/v2"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
type Command struct { type Command struct {
Definition discordgo.ApplicationCommand Definition discord.ApplicationCommandCreate
Interact func(s *discordgo.Session, i *discordgo.InteractionCreate) Interact func(e *events.ApplicationCommandInteractionCreate)
ComponentInteract func(s *discordgo.Session, i *discordgo.InteractionCreate) Autocomplete func(e *events.AutocompleteInteractionCreate)
Autocomplete func(s *discordgo.Session, i *discordgo.InteractionCreate) ComponentInteract func(e *events.ComponentInteractionCreate)
ModalSubmit func(s *discordgo.Session, i *discordgo.InteractionCreate) ModalSubmit func(e *events.ModalSubmitInteractionCreate)
ComponentIDs []string ComponentIDs []string
ModalIDs []string ModalIDs []string
DynamicComponentIDs func() []string
DynamicModalIDs func() []string DynamicModalIDs func() []string
DynamicComponentIDs func() []string
AllowDM bool AllowDM bool
} }
var commands []Command = []Command{cmd_form, cmd_ticket_form, cmd_tag, cmd_tag_short, cmd_dadjoke, cmd_ping, cmd_ask, cmd_sticky, cmd_cat, cmd_autojoinroles, cmd_autopublish, context_sticky, context_tag, cmd_userinfo} var commands []Command = []Command{cmd_tag, cmd_tag_short, context_tag, cmd_sticky, context_sticky, cmd_ping, cmd_userinfo, cmd_form, cmd_ask, cmd_cat, cmd_dadjoke, cmd_ticket_form, cmd_autopublish, cmd_autojoinroles}
func ready(s *discordgo.Session, event *discordgo.Ready) { func ready(e *events.Ready) {
logrus.Info("Starting up...") logrus.Info("Starting up...")
findAndDeleteUnusedMessages() findAndDeleteUnusedMessages(e.Client())
removeOldCommandFromAllGuilds(s) removeOldCommandFromAllGuilds(e.Client())
var existingCommandNames []string var existingCommandNames []string
existingCommands, err := s.ApplicationCommands(s.State.User.ID, "") existingCommands, err := e.Client().Rest().GetGlobalCommands(e.Client().ApplicationID(), false)
if err != nil { if err != nil {
logrus.Errorf("error fetching existing global commands: %v", err) logrus.Errorf("error fetching existing global commands: %v", err)
} else { } else {
for _, existingCommand := range existingCommands { for _, existingCommand := range existingCommands {
existingCommandNames = append(existingCommandNames, existingCommand.Name) existingCommandNames = append(existingCommandNames, existingCommand.Name())
}
}
if slices.Contains(os.Args, "--clean") {
guilds := s.State.Guilds
if err != nil {
logrus.Errorf("error retrieving guilds: %v", err)
}
for _, guild := range guilds {
_, err := s.ApplicationCommandBulkOverwrite(s.State.User.ID, guild.ID, []*discordgo.ApplicationCommand{})
if err != nil {
logrus.Errorf("error deleting guild commands: %v", err)
}
} }
} }
globalCommands := []discord.ApplicationCommandCreate{}
for _, command := range commands { for _, command := range commands {
if !slices.Contains(existingCommandNames, command.Definition.Name) || slices.Contains(os.Args, "--update="+command.Definition.Name) || slices.Contains(os.Args, "--update=all") || slices.Contains(os.Args, "--clean") { if !slices.Contains(existingCommandNames, command.Definition.CommandName()) || slices.Contains(os.Args, "--update-all") || slices.Contains(os.Args, "--clean") {
cmd, err := s.ApplicationCommandCreate(s.State.User.ID, "", &command.Definition) globalCommands = append(globalCommands, command.Definition)
if err != nil { logrus.Infof("Appending command \"%s\"", command.Definition.CommandName())
logrus.Errorf("error creating global command '%s': %v", cmd.Name, err)
} else {
logrus.Infof("Added global command '%s'", cmd.Name)
} }
} }
if len(globalCommands) > 0 {
logrus.Infof("Attempting to add global commands %s", fmt.Sprint(globalCommands))
_, err = e.Client().Rest().SetGlobalCommands(e.Client().ApplicationID(), globalCommands)
if err != nil {
logrus.Errorf("error creating global commands '%s'", err)
} else {
logrus.Infof("Added global commands sucessfully!")
}
} }
logrus.Info("Successfully started the Bot!") logrus.Info("Successfully started the Bot!")
} }
func interactionCreate(s *discordgo.Session, i *discordgo.InteractionCreate) { func applicationCommandInteractionCreate(e *events.ApplicationCommandInteractionCreate) {
for _, command := range commands { for _, command := range commands {
switch i.Type { if command.Interact != nil && e.Data.CommandName() == command.Definition.CommandName() {
case discordgo.InteractionApplicationCommand: if !command.AllowDM && e.ApplicationCommandInteraction.GuildID().String() == "" {
if command.Interact != nil && i.ApplicationCommandData().Name == command.Definition.Name { err := e.CreateMessage(discord.NewMessageCreateBuilder().
if !command.AllowDM && i.Interaction.GuildID == "" { SetContent("This command is not available in DMs.").SetEphemeral(true).
respond(i.Interaction, "This command is not available in DMs.", true) Build())
} else {
command.Interact(s, i)
}
}
case discordgo.InteractionApplicationCommandAutocomplete:
if command.Autocomplete != nil && i.ApplicationCommandData().Name == command.Definition.Name {
if !command.AllowDM && i.Interaction.GuildID == "" {
err := bot.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionApplicationCommandAutocompleteResult,
Data: &discordgo.InteractionResponseData{
Choices: nil,
},
})
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
} else { } else {
command.Autocomplete(s, i) command.Interact(e)
}
}
} }
} }
case discordgo.InteractionModalSubmit:
if !command.AllowDM && i.Interaction.GuildID == "" { func autocompleteInteractionCreate(e *events.AutocompleteInteractionCreate) {
respond(i.Interaction, "This modal is not available in DMs.", true) for _, command := range commands {
if command.Autocomplete != nil && e.Data.CommandName == command.Definition.CommandName() {
if !command.AllowDM && e.AutocompleteInteraction.GuildID().String() == "" {
err := e.AutocompleteResult(nil)
if err != nil {
logrus.Error(err)
}
} else {
command.Autocomplete(e)
}
}
}
}
func componentInteractionCreate(e *events.ComponentInteractionCreate) {
for _, command := range commands {
if !command.AllowDM && e.ComponentInteraction.GuildID().String() == "" {
e.CreateMessage(discord.NewMessageCreateBuilder().
SetContent("This component is not available in DMs.").SetEphemeral(true).
Build())
} else {
if command.ComponentInteract != nil {
if slices.Contains(command.ComponentIDs, e.Data.CustomID()) || slices.ContainsFunc(command.DynamicComponentIDs(), func(id string) bool {
var customID string
if strings.ContainsAny(e.Data.CustomID(), ";") {
customID = strings.TrimSuffix(e.Data.CustomID(), ";"+strings.Split(e.Data.CustomID(), ";")[1])
} else {
customID = e.Data.CustomID()
}
return id == customID
}) {
command.ComponentInteract(e)
}
}
}
}
}
func modalSubmitInteractionCreate(e *events.ModalSubmitInteractionCreate) {
for _, command := range commands {
if !command.AllowDM && e.ModalSubmitInteraction.GuildID().String() == "" {
e.CreateMessage(discord.NewMessageCreateBuilder().
SetContent("This modal is not available in DMs.").SetEphemeral(true).
Build())
} else { } else {
if command.ModalSubmit != nil { if command.ModalSubmit != nil {
var hasID bool = false var hasID bool = false
@@ -104,82 +135,75 @@ func interactionCreate(s *discordgo.Session, i *discordgo.InteractionCreate) {
modalIDs = append(command.ModalIDs, command.DynamicModalIDs()...) modalIDs = append(command.ModalIDs, command.DynamicModalIDs()...)
} }
for _, modalID := range modalIDs { for _, modalID := range modalIDs {
if strings.HasPrefix(i.ModalSubmitData().CustomID, modalID) { if strings.HasPrefix(e.Data.CustomID, modalID) {
hasID = true hasID = true
break break
} }
} }
if hasID { if hasID {
command.ModalSubmit(s, i) command.ModalSubmit(e)
return // I have no idea why it crashes without that return return // I have no idea why it crashes without that return
} }
} }
} }
case discordgo.InteractionMessageComponent:
if !command.AllowDM && i.Interaction.GuildID == "" {
respond(i.Interaction, "This component is not available in DMs.", true)
} else {
if command.ComponentInteract != nil {
if slices.Contains(command.ComponentIDs, i.MessageComponentData().CustomID) || slices.ContainsFunc(command.DynamicComponentIDs(), func(id string) bool {
var customID string
if strings.ContainsAny(i.MessageComponentData().CustomID, ";") {
customID = strings.TrimSuffix(i.MessageComponentData().CustomID, ";"+strings.Split(i.MessageComponentData().CustomID, ";")[1])
} else {
customID = i.MessageComponentData().CustomID
}
return id == customID
}) {
command.ComponentInteract(s, i)
}
}
}
}
} }
} }
func removeOldCommandFromAllGuilds(s *discordgo.Session) { func removeOldCommandFromAllGuilds(c bot.Client) {
existingCommands, err := s.ApplicationCommands(s.State.User.ID, "") app, err := c.Rest().GetCurrentApplication()
if err != nil { if err != nil {
logrus.Errorf("error fetching existing commands: %v\n", err) logrus.Error(err)
var commandIDs []string }
globalCommands, err := c.Rest().GetGlobalCommands(app.Bot.ID, false)
if err != nil {
logrus.Errorf("error fetching existing global commands: %v", err)
return
}
var commandNames []string
for _, command := range commands { for _, command := range commands {
commandIDs = append(commandIDs, command.Definition.Name) commandNames = append(commandNames, command.Definition.CommandName())
} }
for _, existingCommand := range existingCommands { for _, existingCommand := range globalCommands {
if !slices.Contains(commandIDs, existingCommand.Name) { if !slices.Contains(commandNames, existingCommand.Name()) {
logrus.Infof("Deleting command '%s'", existingCommand.Name) logrus.Infof("Deleting command '%s'", existingCommand.Name())
err := s.ApplicationCommandDelete(s.State.User.ID, "", existingCommand.ID) err := c.Rest().DeleteGlobalCommand(c.ApplicationID(), existingCommand.ID())
if err != nil { if err != nil {
logrus.Errorf("error deleting command %s: %v", existingCommand.Name, err) logrus.Errorf("error deleting command %s: %v", existingCommand.Name(), err)
}
} }
} }
} }
} }
func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) { func messageCreate(e *events.MessageCreate) {
if len(m.Embeds) == 0 || m.Embeds[0].Footer == nil || m.Embeds[0].Footer.Text != "📌 Sticky message" { if len(e.Message.Embeds) == 0 || e.Message.Embeds[0].Footer == nil || e.Message.Embeds[0].Footer.Text != "📌 Sticky message" {
if hasSticky(m.GuildID, m.ChannelID) { if hasSticky(e.Message.GuildID.String(), e.Message.ChannelID.String()) {
stickymessageID := getStickyMessageID(m.GuildID, m.ChannelID) stickymessageID := getStickyMessageID(e.Message.GuildID.String(), e.Message.ChannelID.String())
err := s.ChannelMessageDelete(m.ChannelID, stickymessageID) err := e.Client().Rest().DeleteMessage(e.ChannelID, snowflake.MustParse(stickymessageID))
stickyMessage, _ := s.ChannelMessageSendEmbed(m.ChannelID, &discordgo.MessageEmbed{ stickyMessage, _ := e.Client().Rest().CreateMessage(e.ChannelID, discord.MessageCreate{
Type: discordgo.EmbedTypeArticle, Embeds: []discord.Embed{
Footer: &discordgo.MessageEmbedFooter{ {
Footer: &discord.EmbedFooter{
Text: "📌 Sticky message", Text: "📌 Sticky message",
}, },
Color: hexToDecimal(color["primary"]), Color: hexToDecimal(color["primary"]),
Description: getStickyMessageContent(m.GuildID, m.ChannelID), Description: getStickyMessageContent(e.Message.GuildID.String(), e.Message.ChannelID.String()),
},
},
}) })
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
updateStickyMessageID(m.GuildID, m.ChannelID, stickyMessage.ID) updateStickyMessageID(e.Message.GuildID.String(), e.Message.ChannelID.String(), stickyMessage.ID.String())
} }
} }
channel, _ := s.Channel(m.ChannelID) channel, err := e.Client().Rest().GetChannel(e.Message.ChannelID)
if channel.Type == discordgo.ChannelTypeGuildNews { if err != nil {
if isAutopublishEnabled(m.GuildID, m.ChannelID) { logrus.Error(err)
_, err := s.ChannelMessageCrosspost(m.ChannelID, m.ID) }
if channel != nil && channel.Type() == discord.ChannelTypeGuildNews {
logrus.Debug("HERE")
if isAutopublishEnabled(e.GuildID.String(), e.ChannelID.String()) {
_, err := e.Client().Rest().CrosspostMessage(e.ChannelID, e.MessageID)
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
return return
@@ -188,14 +212,15 @@ func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
} }
} }
func messageDelete(s *discordgo.Session, m *discordgo.MessageDelete) { //TODO: also clear on bot start when message doesn't exist func messageDelete(e *events.MessageDelete) { //TODO: also clear on bot start when message doesn't exist
tryDeleteUnusedMessage(m.ID) tryDeleteUnusedMessage(e.MessageID.String())
} }
func guildMemberJoin(s *discordgo.Session, m *discordgo.GuildMemberAdd) { func guildMemberJoin(e *events.GuildMemberJoin) {
role := getAutoJoinRole(m.GuildID, m.User.Bot) logrus.Debug("TESSST")
role := getAutoJoinRole(e.GuildID.String(), e.Member.User.Bot)
if role != "" { if role != "" {
err := s.GuildMemberRoleAdd(m.GuildID, m.User.ID, role) err := e.Client().Rest().AddMemberRole(e.GuildID, e.Member.User.ID, snowflake.MustParse(role))
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }

57
main.go
View File

@@ -1,27 +1,29 @@
package main package main
import ( import (
"context"
"database/sql"
"io" "io"
"net/url"
"os" "os"
"os/signal" "os/signal"
"strconv" "strconv"
"syscall" "syscall"
"time" "time"
"database/sql"
"net/url"
"github.com/bwmarrin/discordgo"
"github.com/joho/godotenv"
_ "github.com/lib/pq" _ "github.com/lib/pq"
"github.com/disgoorg/disgo"
"github.com/disgoorg/disgo/bot"
"github.com/disgoorg/disgo/gateway"
"github.com/joho/godotenv"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/vaporvee/acecore/log2webhook" "github.com/vaporvee/acecore/log2webhook"
) )
//TODO: add more error handlings var (
db *sql.DB
var db *sql.DB )
var bot *discordgo.Session
func main() { func main() {
logrusInitFile() logrusInitFile()
@@ -33,30 +35,45 @@ func main() {
logrus.Fatal(err) logrus.Fatal(err)
} }
initTables() initTables()
bot, err = discordgo.New("Bot " + os.Getenv("BOT_TOKEN")) client, err := disgo.New(os.Getenv("BOT_TOKEN"),
bot.WithGatewayConfigOpts(
gateway.WithIntents(
gateway.IntentGuilds,
gateway.IntentGuildMessages,
gateway.IntentGuildMembers,
gateway.IntentDirectMessages,
),
),
bot.WithEventListenerFunc(ready),
bot.WithEventListenerFunc(applicationCommandInteractionCreate),
bot.WithEventListenerFunc(autocompleteInteractionCreate),
bot.WithEventListenerFunc(componentInteractionCreate),
bot.WithEventListenerFunc(modalSubmitInteractionCreate),
bot.WithEventListenerFunc(messageCreate),
bot.WithEventListenerFunc(messageDelete),
bot.WithEventListenerFunc(guildMemberJoin),
)
if err != nil { if err != nil {
logrus.Fatal("error creating Discord session,", err) logrus.Fatal("error creating Discord session,", err)
return return
} else { } else {
logrus.Info("Discord session created") logrus.Info("Discord session created")
} }
bot.Identify.Intents = discordgo.IntentsGuildMessages | discordgo.IntentsGuilds | discordgo.IntentMessageContent | discordgo.IntentGuildMembers
bot.AddHandler(ready) if err = client.OpenGateway(context.TODO()); err != nil {
bot.AddHandler(interactionCreate)
bot.AddHandler(messageCreate)
bot.AddHandler(messageDelete)
bot.AddHandler(guildMemberJoin)
err = bot.Open()
if err != nil {
logrus.Error("error opening connection,", err) logrus.Error("error opening connection,", err)
return return
} }
logrus.Infof("Bot is now running as '%s'!", bot.State.User.Username) app, err := client.Rest().GetCurrentApplication()
if err != nil {
logrus.Error(err)
}
logrus.Infof("Bot is now running as '%s'!", app.Bot.Username)
sc := make(chan os.Signal, 1) sc := make(chan os.Signal, 1)
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt) signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt)
<-sc <-sc
logrus.Info("Shutting down...") logrus.Info("Shutting down...")
bot.Close()
} }
func logrusInitFile() { func logrusInitFile() {

129
tool.go
View File

@@ -9,7 +9,9 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/bwmarrin/discordgo" "github.com/disgoorg/disgo/bot"
"github.com/disgoorg/disgo/discord"
"github.com/disgoorg/snowflake/v2"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@@ -34,46 +36,52 @@ type MessageIDs struct {
ChannelID string ChannelID string
} }
func jsonStringShowModal(interaction *discordgo.Interaction, manageID string, formID string, overwrite ...string) { func noNullString(in interface{}) string {
var modal ModalJson = getModalByFormID(formID) var s string = ""
var components []discordgo.MessageComponent var is_str bool
for index, component := range modal.Form { switch in.(type) {
var style discordgo.TextInputStyle = discordgo.TextInputShort case string:
if component.IsParagraph { is_str = true
style = discordgo.TextInputParagraph case *string:
is_str = true
} }
components = append(components, discordgo.ActionsRow{ if in != nil && is_str {
Components: []discordgo.MessageComponent{ s = fmt.Sprint(in)
discordgo.TextInput{ }
return s
}
func jsonStringBuildModal(userID string, manageID string, formID string, overwrite ...string) discord.ModalCreate {
var modal ModalJson = getModalByFormID(formID)
var components []discord.ContainerComponent
for index, component := range modal.Form {
var style discord.TextInputStyle = discord.TextInputStyleShort
if component.IsParagraph {
style = discord.TextInputStyleParagraph
}
components = append(components, discord.ActionRowComponent{
discord.TextInputComponent{
CustomID: fmt.Sprint(index), CustomID: fmt.Sprint(index),
Label: component.Label, Label: component.Label,
Style: style, Style: style,
Placeholder: component.Placeholder, Placeholder: component.Placeholder,
Required: component.Required, Required: component.Required,
MaxLength: component.MaxLength, MaxLength: component.MaxLength,
MinLength: component.MinLength, MinLength: &component.MinLength,
Value: component.Value, Value: component.Value,
}, },
},
}) })
} }
if overwrite != nil && overwrite[0] != "" { if overwrite != nil && overwrite[0] != "" {
modal.Title = overwrite[0] modal.Title = overwrite[0]
} }
var err error
if modal.Title != "" && components != nil { return discord.ModalCreate{
err = bot.InteractionRespond(interaction, &discordgo.InteractionResponse{ CustomID: "form:" + manageID + ":" + userID,
Type: discordgo.InteractionResponseModal,
Data: &discordgo.InteractionResponseData{
CustomID: manageID + ":" + interaction.Member.User.ID,
Title: modal.Title, Title: modal.Title,
Components: components, Components: components,
},
})
}
if err != nil {
logrus.Error(err)
} }
} }
// Why does the golang compiler care about commands?? // Why does the golang compiler care about commands??
@@ -83,6 +91,9 @@ var formTemplates embed.FS
func getModalByFormID(formID string) ModalJson { func getModalByFormID(formID string) ModalJson {
var modal ModalJson var modal ModalJson
if formID == "" {
return modal
}
entries, err := formTemplates.ReadDir("form_templates") entries, err := formTemplates.ReadDir("form_templates")
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
@@ -106,22 +117,21 @@ func getModalByFormID(formID string) ModalJson {
return modal return modal
} }
func getHighestRole(guildID string) (*discordgo.Role, error) { func getHighestRole(guildID string, c bot.Client) (*discord.Role, error) {
botMember, err := bot.GuildMember(guildID, bot.State.User.ID) botmember, err := c.Rest().GetMember(snowflake.MustParse(guildID), c.ApplicationID())
if err != nil { if err != nil {
return nil, err return nil, err
} }
roles, err := bot.GuildRoles(guildID) roles, err := c.Rest().GetRoles(snowflake.MustParse(guildID))
if err != nil { if err != nil {
return nil, err return nil, err
} }
var highestRole *discord.Role
var highestRole *discordgo.Role for _, roleID := range botmember.RoleIDs {
for _, roleID := range botMember.Roles {
for _, role := range roles { for _, role := range roles {
if role.ID == roleID { if role.ID == roleID {
if highestRole == nil || role.Position > highestRole.Position { if highestRole == nil || role.Position > highestRole.Position {
highestRole = role highestRole = &role
} }
break break
} }
@@ -130,10 +140,6 @@ func getHighestRole(guildID string) (*discordgo.Role, error) {
return highestRole, nil return highestRole, nil
} }
func int64Ptr(i int64) *int64 {
return &i
}
func hexToDecimal(hexColor string) int { func hexToDecimal(hexColor string) int {
hexColor = strings.TrimPrefix(hexColor, "#") hexColor = strings.TrimPrefix(hexColor, "#")
decimal, err := strconv.ParseInt(hexColor, 16, 64) decimal, err := strconv.ParseInt(hexColor, 16, 64)
@@ -143,11 +149,6 @@ func hexToDecimal(hexColor string) int {
return int(decimal) return int(decimal)
} }
func decimalToHex(decimal int) string {
hexString := strconv.FormatInt(int64(decimal), 16)
return hexString
}
func simpleGetFromAPI(key string, url string) interface{} { func simpleGetFromAPI(key string, url string) interface{} {
client := &http.Client{} client := &http.Client{}
req, err := http.NewRequest("GET", url, nil) req, err := http.NewRequest("GET", url, nil)
@@ -173,59 +174,21 @@ func simpleGetFromAPI(key string, url string) interface{} {
return result[key] return result[key]
} }
func respond(interaction *discordgo.Interaction, content string, ephemeral bool) error { func findAndDeleteUnusedMessages(c bot.Client) {
var flag discordgo.MessageFlags
if ephemeral {
flag = discordgo.MessageFlagsEphemeral
}
err := bot.InteractionRespond(interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseChannelMessageWithSource,
Data: &discordgo.InteractionResponseData{
Content: content,
Flags: flag,
},
})
if err != nil {
return err
}
return nil
}
func respondEmbed(interaction *discordgo.Interaction, embed discordgo.MessageEmbed, ephemeral bool) error {
var flag discordgo.MessageFlags
if ephemeral {
flag = discordgo.MessageFlagsEphemeral
}
err := bot.InteractionRespond(interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseChannelMessageWithSource,
Data: &discordgo.InteractionResponseData{
Flags: flag,
Embeds: []*discordgo.MessageEmbed{
&embed,
},
},
})
if err != nil {
return err
}
return nil
}
func findAndDeleteUnusedMessages() {
for _, message := range getAllSavedMessages() { for _, message := range getAllSavedMessages() {
_, err := bot.ChannelMessage(message.ChannelID, message.ID) _, err := c.Rest().GetMessage(snowflake.MustParse(message.ChannelID), snowflake.MustParse(message.ID))
if err != nil { if err != nil {
tryDeleteUnusedMessage(message.ID) tryDeleteUnusedMessage(message.ID)
} }
} }
} }
func isIDRole(guildID, id string) bool { func isIDRole(c bot.Client, guildID snowflake.ID, id snowflake.ID) bool {
_, err1 := bot.GuildMember(guildID, id) _, err1 := c.Rest().GetMember(guildID, id)
if err1 == nil { if err1 == nil {
return false return false
} }
roles, err2 := bot.GuildRoles(guildID) roles, err2 := c.Rest().GetRoles(guildID)
if err2 == nil { if err2 == nil {
for _, role := range roles { for _, role := range roles {
if role.ID == id { if role.ID == id {