finished plugin system base
This commit is contained in:
15
build_plugins.py
Normal file
15
build_plugins.py
Normal file
@@ -0,0 +1,15 @@
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
src_dir = './plugin_src'
|
||||
output_dir = './plugins'
|
||||
|
||||
if not os.path.exists(output_dir):
|
||||
os.makedirs(output_dir)
|
||||
|
||||
for folder_name in os.listdir(src_dir):
|
||||
folder_path = os.path.join(src_dir, folder_name)
|
||||
if os.path.isdir(folder_path):
|
||||
command = f'go build -buildmode=plugin -o {output_dir}/{folder_name}.so {folder_path}'
|
||||
subprocess.run(command, shell=True, check=True)
|
||||
print(f'Built plugin: {folder_name}.so')
|
24
cmd/go.sum
24
cmd/go.sum
@@ -1,24 +0,0 @@
|
||||
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/disgoorg/disgo v0.18.2 h1:pZCvaFamfHcnXrj0XA73qtVofP0R8dYEyQfPNgv8dLE=
|
||||
github.com/disgoorg/disgo v0.18.2/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/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
|
||||
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
|
||||
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/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/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
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.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
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/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
@@ -1,95 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/disgoorg/disgo/discord"
|
||||
"github.com/disgoorg/disgo/events"
|
||||
"github.com/disgoorg/json"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vaporvee/acecore/cmd"
|
||||
)
|
||||
|
||||
var cmd_addemoji cmd.Command = cmd.Command{
|
||||
Definition: discord.SlashCommandCreate{
|
||||
Name: "add-emoji",
|
||||
Description: "Add an external emoji directly to the server.",
|
||||
DefaultMemberPermissions: json.NewNullablePtr(discord.PermissionManageGuildExpressions),
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
&discord.ApplicationCommandOptionString{
|
||||
Name: "emoji",
|
||||
Description: "The emoji you want to add",
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Interact: func(e *events.ApplicationCommandInteractionCreate) {
|
||||
emojiRegex := regexp.MustCompile(`<(.+):(\d+)>`)
|
||||
emojistring := emojiRegex.FindString(e.SlashCommandInteractionData().String("emoji"))
|
||||
emojiArray := strings.Split(emojistring, ":")
|
||||
var emojiName string
|
||||
var emojiID string
|
||||
var emojiFileName string
|
||||
if len(emojiArray) > 1 {
|
||||
emojiName = strings.TrimSuffix(emojiArray[1], ">")
|
||||
emojiID = strings.TrimSuffix(emojiArray[2], ">")
|
||||
}
|
||||
imageType, emojiReadBit64 := getEmoji(emojiID)
|
||||
emojiData, err := discord.NewIcon(imageType, emojiReadBit64)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
_, err = e.Client().Rest().CreateEmoji(*e.GuildID(), discord.EmojiCreate{
|
||||
Name: emojiName,
|
||||
Image: *emojiData,
|
||||
})
|
||||
if err != nil {
|
||||
if strings.HasPrefix(err.Error(), "50035") {
|
||||
e.CreateMessage(discord.NewMessageCreateBuilder().SetContent("Failed adding emoji. Did you provide a correct one?").SetEphemeral(true).Build())
|
||||
return
|
||||
}
|
||||
if strings.HasPrefix(err.Error(), "50138") {
|
||||
e.CreateMessage(discord.NewMessageCreateBuilder().SetContent("Failed adding emoji. Unable to resize the emoji image.").SetEphemeral(true).Build())
|
||||
return
|
||||
}
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
if imageType == discord.IconTypeGIF {
|
||||
emojiFileName = emojiName + ".gif"
|
||||
} else {
|
||||
emojiFileName = emojiName + ".png"
|
||||
}
|
||||
_, emojiRead := getEmoji(emojiID) // for some reason any []bit variable thats used with NewIcon gets corrupted even when its redeclared in a new variable
|
||||
err = e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContentf("Emoji %s sucessfully added to this server!", emojiName).SetFiles(discord.NewFile(emojiFileName, "", emojiRead)).SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func getEmoji(emojiID string) (discord.IconType, io.Reader) {
|
||||
resp, err := http.Get("https://cdn.discordapp.com/emojis/" + emojiID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return discord.IconTypePNG, nil
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
imageData, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return discord.IconTypePNG, nil
|
||||
}
|
||||
isAnimated := isGIFImage(imageData)
|
||||
if isAnimated {
|
||||
return discord.IconTypeGIF, bytes.NewReader(imageData)
|
||||
} else {
|
||||
return discord.IconTypePNG, bytes.NewReader(imageData)
|
||||
}
|
||||
}
|
@@ -1,75 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/disgoorg/disgo/discord"
|
||||
"github.com/disgoorg/disgo/events"
|
||||
"github.com/disgoorg/json"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vaporvee/acecore/cmd"
|
||||
)
|
||||
|
||||
var cmd_autojoinroles cmd.Command = cmd.Command{
|
||||
Definition: discord.SlashCommandCreate{
|
||||
Name: "autojoinroles",
|
||||
Description: "Give users a role when they join",
|
||||
DefaultMemberPermissions: json.NewNullablePtr(discord.PermissionManageRoles),
|
||||
Contexts: []discord.InteractionContextType{
|
||||
discord.InteractionContextTypeGuild,
|
||||
discord.InteractionContextTypePrivateChannel},
|
||||
IntegrationTypes: []discord.ApplicationIntegrationType{
|
||||
discord.ApplicationIntegrationTypeGuildInstall},
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
&discord.ApplicationCommandOptionSubCommand{
|
||||
Name: "bot",
|
||||
Description: "Give bots a role when they join (Leave empty to remove current)",
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
&discord.ApplicationCommandOptionRole{
|
||||
Name: "role",
|
||||
Description: "The role bots should get when they join the server",
|
||||
},
|
||||
},
|
||||
},
|
||||
&discord.ApplicationCommandOptionSubCommand{
|
||||
Name: "user",
|
||||
Description: "Give users a role when they join (Leave empty to remove current)",
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
&discord.ApplicationCommandOptionRole{
|
||||
Name: "role",
|
||||
Description: "The role users should get when they join the server",
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
Interact: func(e *events.ApplicationCommandInteractionCreate) {
|
||||
var role string
|
||||
option := *e.SlashCommandInteractionData().SubCommandName
|
||||
var content string
|
||||
if len(e.SlashCommandInteractionData().Options) == 1 {
|
||||
var givenRole discord.Role = e.SlashCommandInteractionData().Role("role")
|
||||
role = givenRole.ID.String()
|
||||
botrole, err := getHighestRole(e.GuildID().String(), e.Client())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
if givenRole.Position >= botrole.Position {
|
||||
content = "<@&" + role + "> is not below the Bot's current highest role(<@&" + botrole.ID.String() + ">). That makes it unable to manage it."
|
||||
} else {
|
||||
if setAutoJoinRole(e.GuildID().String(), option, role) {
|
||||
content = "Updated auto join role for " + option + "s as <@&" + role + ">"
|
||||
} else {
|
||||
content = "Setup auto join role for " + option + "s as <@&" + role + ">"
|
||||
}
|
||||
}
|
||||
} else if setAutoJoinRole(e.GuildID().String(), option, role) {
|
||||
content = "Deleted auto join role for " + option + "s"
|
||||
}
|
||||
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 {
|
||||
logrus.Error(err)
|
||||
}
|
||||
purgeUnusedAutoJoinRoles(e.GuildID().String())
|
||||
},
|
||||
}
|
@@ -1,49 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/disgoorg/disgo/discord"
|
||||
"github.com/disgoorg/disgo/events"
|
||||
"github.com/disgoorg/json"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vaporvee/acecore/cmd"
|
||||
)
|
||||
|
||||
var cmd_autopublish cmd.Command = cmd.Command{
|
||||
Definition: discord.SlashCommandCreate{
|
||||
Name: "autopublish",
|
||||
Description: "Toggle automatically publishing every post in a announcement channel",
|
||||
DefaultMemberPermissions: json.NewNullablePtr(discord.PermissionManageChannels),
|
||||
Contexts: []discord.InteractionContextType{
|
||||
discord.InteractionContextTypeGuild,
|
||||
discord.InteractionContextTypePrivateChannel},
|
||||
IntegrationTypes: []discord.ApplicationIntegrationType{
|
||||
discord.ApplicationIntegrationTypeGuildInstall},
|
||||
},
|
||||
Interact: func(e *events.ApplicationCommandInteractionCreate) {
|
||||
channel := e.Channel()
|
||||
if channel.Type() == discord.ChannelTypeGuildNews {
|
||||
if toggleAutoPublish(e.GuildID().String(), e.Channel().ID().String()) {
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent("Autopublishing is now disabled on " + discord.ChannelMention(e.Channel().ID())).SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
} else {
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent("Autopublishing is now enabled on " + discord.ChannelMention(e.Channel().ID())).SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent("This is not an announcement channel!").SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
@@ -1,88 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/disgoorg/disgo/discord"
|
||||
"github.com/disgoorg/disgo/events"
|
||||
"github.com/disgoorg/json"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vaporvee/acecore/cmd"
|
||||
)
|
||||
|
||||
var cmd_blockpolls cmd.Command = cmd.Command{
|
||||
Definition: discord.SlashCommandCreate{
|
||||
Name: "block-polls",
|
||||
Description: "Block polls from beeing posted in this channel.",
|
||||
DefaultMemberPermissions: json.NewNullablePtr(discord.PermissionManageChannels),
|
||||
Contexts: []discord.InteractionContextType{
|
||||
discord.InteractionContextTypeGuild,
|
||||
discord.InteractionContextTypePrivateChannel},
|
||||
IntegrationTypes: []discord.ApplicationIntegrationType{
|
||||
discord.ApplicationIntegrationTypeGuildInstall},
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
&discord.ApplicationCommandOptionSubCommand{
|
||||
Name: "toggle",
|
||||
Description: "Toggle blocking polls from beeing posted in this channel.",
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
&discord.ApplicationCommandOptionBool{
|
||||
Name: "global",
|
||||
Description: "If polls are blocked server wide or only in the current channel.",
|
||||
},
|
||||
&discord.ApplicationCommandOptionRole{
|
||||
Name: "allowed-role",
|
||||
Description: "The role that bypasses this block role.",
|
||||
},
|
||||
},
|
||||
},
|
||||
/*&discord.ApplicationCommandOptionSubCommand{
|
||||
Name: "list",
|
||||
Description: "List the current block polls rules for this server.",
|
||||
},*/
|
||||
},
|
||||
},
|
||||
Interact: func(e *events.ApplicationCommandInteractionCreate) {
|
||||
switch *e.SlashCommandInteractionData().SubCommandName {
|
||||
case "toggle":
|
||||
isGlobal := isGlobalBlockPolls(e.GuildID().String())
|
||||
if isGlobal && !e.SlashCommandInteractionData().Bool("global") {
|
||||
e.CreateMessage(discord.NewMessageCreateBuilder().SetContent("Polls are currently globally blocked. Disable global blocking to enable channel specific blocking.").SetEphemeral(true).Build())
|
||||
} else {
|
||||
exists, isGlobal := toggleBlockPolls(e.GuildID().String(), e.Channel().ID().String(), e.SlashCommandInteractionData().Bool("global"), e.SlashCommandInteractionData().Role("allowed-role").ID.String())
|
||||
if exists {
|
||||
if e.SlashCommandInteractionData().Bool("global") {
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent("Polls are now globally unblocked.").SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
} else {
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent("Polls are now unblocked in " + discord.ChannelMention(e.Channel().ID())).SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if isGlobal {
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent("Polls are now globally blocked.").SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
} else {
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent("Polls are now blocked in " + discord.ChannelMention(e.Channel().ID())).SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*case "list":
|
||||
list := listBlockPolls(e.GuildID().String())*/
|
||||
}
|
||||
},
|
||||
}
|
474
cmd_form.go
474
cmd_form.go
@@ -1,474 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"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/sirupsen/logrus"
|
||||
"github.com/vaporvee/acecore/cmd"
|
||||
"github.com/vaporvee/acecore/custom"
|
||||
)
|
||||
|
||||
var cmd_form cmd.Command = cmd.Command{
|
||||
Definition: discord.SlashCommandCreate{
|
||||
Name: "form",
|
||||
DefaultMemberPermissions: json.NewNullablePtr(discord.PermissionManageChannels),
|
||||
Description: "Create custom forms right inside Discord",
|
||||
Contexts: []discord.InteractionContextType{
|
||||
discord.InteractionContextTypeGuild,
|
||||
discord.InteractionContextTypePrivateChannel},
|
||||
IntegrationTypes: []discord.ApplicationIntegrationType{
|
||||
discord.ApplicationIntegrationTypeGuildInstall},
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
&discord.ApplicationCommandOptionSubCommand{
|
||||
Name: "help",
|
||||
Description: "Gives you an example file and demo for creating custom forms",
|
||||
},
|
||||
&discord.ApplicationCommandOptionSubCommand{
|
||||
Name: "custom",
|
||||
Description: "Create a new custom form right inside Discord",
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
&discord.ApplicationCommandOptionAttachment{
|
||||
Name: "json",
|
||||
Description: "Your edited form file",
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
&discord.ApplicationCommandOptionSubCommand{
|
||||
Name: "add",
|
||||
Description: "Adds existing forms to this channel",
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
&discord.ApplicationCommandOptionChannel{
|
||||
Name: "result_channel",
|
||||
Description: "Where the form results should appear",
|
||||
ChannelTypes: []discord.ChannelType{discord.ChannelTypeGuildText},
|
||||
},
|
||||
&discord.ApplicationCommandOptionMentionable{
|
||||
Name: "moderator",
|
||||
Description: "Who can interact with moderating buttons.",
|
||||
},
|
||||
&discord.ApplicationCommandOptionString{
|
||||
Name: "type",
|
||||
Description: "Which type of form you want to add",
|
||||
Autocomplete: true,
|
||||
},
|
||||
&discord.ApplicationCommandOptionString{
|
||||
Name: "title",
|
||||
Description: "The title the form should have",
|
||||
},
|
||||
&discord.ApplicationCommandOptionChannel{
|
||||
Name: "approve_channel",
|
||||
Description: "Channel for results that need to be accepted by a moderator before sending it to the result channel",
|
||||
ChannelTypes: []discord.ChannelType{discord.ChannelTypeGuildText},
|
||||
},
|
||||
&discord.ApplicationCommandOptionBool{
|
||||
Name: "mods_can_answer",
|
||||
Description: "Moderators can open a new channel on the form result, which then pings the user who submitted it",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Interact: func(e *events.ApplicationCommandInteractionCreate) {
|
||||
switch *e.SlashCommandInteractionData().SubCommandName {
|
||||
case "help":
|
||||
fileData, err := formTemplates.ReadFile("form_templates/form_demo.json")
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
fileReader := bytes.NewReader(fileData)
|
||||
err = e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
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.").
|
||||
SetFiles(discord.NewFile("example.json", "json", fileReader)).
|
||||
SetContainerComponents(discord.ActionRowComponent{discord.NewPrimaryButton("Demo", "form_demo").WithEmoji(discord.ComponentEmoji{Name: "📑"})}).SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
case "custom":
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent("Feature not available yet use `/form add` instead").SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
case "add":
|
||||
var title, formID, overwriteTitle, acceptChannelID string
|
||||
var modsCanAnswer bool
|
||||
var resultChannelID string
|
||||
data := e.SlashCommandInteractionData()
|
||||
if data.Channel("result_channel").ID.String() != "0" {
|
||||
resultChannelID = data.Channel("result_channel").ID.String()
|
||||
}
|
||||
moderator := data.Role("moderator").ID.String()
|
||||
if moderator == "0" {
|
||||
moderator = e.User().ID.String()
|
||||
}
|
||||
formID = data.String("type")
|
||||
overwriteTitle = data.String("title")
|
||||
if overwriteTitle != "" {
|
||||
title = overwriteTitle
|
||||
}
|
||||
if data.Channel("approve_channel").ID.String() != "0" {
|
||||
acceptChannelID = data.Channel("approve_channel").ID.String()
|
||||
}
|
||||
modsCanAnswer = data.Bool("mods_can_answer")
|
||||
|
||||
if formID == "" {
|
||||
formID = "template_general"
|
||||
}
|
||||
if title == "" {
|
||||
formTitles := map[string]string{
|
||||
"template_ticket": "Make a new ticket",
|
||||
"template_url": "Add your URL",
|
||||
"template_general": "Form",
|
||||
}
|
||||
if val, ok := formTitles[formID]; ok {
|
||||
title = val
|
||||
}
|
||||
}
|
||||
var exists bool = true
|
||||
var formManageID uuid.UUID = uuid.New()
|
||||
for exists {
|
||||
formManageID = uuid.New()
|
||||
exists = getFormManageIdExists(formManageID)
|
||||
}
|
||||
messagebuild := discord.NewMessageCreateBuilder().SetEmbeds(discord.NewEmbedBuilder().
|
||||
SetTitle(title).SetDescription("Press the bottom button to open a form popup.").SetColor(custom.GetColor("primary")).
|
||||
Build()).SetContainerComponents(discord.ActionRowComponent{
|
||||
discord.NewSuccessButton("Submit", "form:"+formManageID.String()).WithEmoji(discord.ComponentEmoji{
|
||||
Name: "anim_rocket",
|
||||
ID: snowflake.MustParse("1215740398706757743"),
|
||||
Animated: true,
|
||||
})}).
|
||||
Build()
|
||||
message, err := e.Client().Rest().CreateMessage(e.Channel().ID(), messagebuild)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
var category string
|
||||
if modsCanAnswer {
|
||||
c, err := e.Client().Rest().CreateGuildChannel(*e.GuildID(), discord.GuildCategoryChannelCreate{Name: title + " mod answers"})
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
category = c.ID().String()
|
||||
}
|
||||
|
||||
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 {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
},
|
||||
DynamicComponentIDs: func() []string { return getFormButtonIDs() },
|
||||
DynamicModalIDs: func() []string { return getFormButtonIDs() },
|
||||
ComponentInteract: func(e *events.ComponentInteractionCreate) {
|
||||
if e.Data.Type() == discord.ComponentTypeButton {
|
||||
if strings.ContainsAny(e.ButtonInteractionData().CustomID(), ";") {
|
||||
var form_manage_id string = strings.TrimPrefix(strings.Split(e.ButtonInteractionData().CustomID(), ";")[0], "form:")
|
||||
switch strings.Split(e.ButtonInteractionData().CustomID(), ";")[1] {
|
||||
case "decline":
|
||||
err := e.Client().Rest().DeleteMessage(e.Channel().ID(), e.Message.ID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
e.CreateMessage(discord.NewMessageCreateBuilder().SetContent("Submission declined!").SetEphemeral(true).Build())
|
||||
case "approve":
|
||||
embed := e.Message.Embeds[0]
|
||||
embed.Description = fmt.Sprintf("This submission was approved by <@%s>.", e.User().ID)
|
||||
_, err := e.Client().Rest().CreateMessage(snowflake.MustParse(getFormResultValues(form_manage_id).ResultChannelID), discord.NewMessageCreateBuilder().
|
||||
SetEmbeds(embed).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
e.CreateMessage(discord.NewMessageCreateBuilder().SetContent("Submission accepted!").SetEphemeral(true).Build())
|
||||
err = e.Client().Rest().DeleteMessage(e.Channel().ID(), e.Message.ID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
case "comment":
|
||||
author := strings.TrimSuffix(strings.Split(e.Message.Embeds[0].Fields[len(e.Message.Embeds[0].Fields)-1].Value, "<@")[1], ">")
|
||||
embed := e.Message.Embeds[0]
|
||||
moderator := e.User().ID
|
||||
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 {
|
||||
if strings.HasPrefix(e.ButtonInteractionData().CustomID(), "form:") {
|
||||
var formManageID string = strings.TrimPrefix(e.ButtonInteractionData().CustomID(), "form:")
|
||||
e.Modal(jsonStringBuildModal(e.User().ID.String(), formManageID, getFormType(formManageID), getFormOverwriteTitle(formManageID)))
|
||||
} else if e.ButtonInteractionData().CustomID() == "form_demo" {
|
||||
e.Modal(jsonStringBuildModal(e.User().ID.String(), "form_demo", "form_demo"))
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
ModalSubmit: func(e *events.ModalSubmitInteractionCreate) {
|
||||
if !strings.HasPrefix(e.Data.CustomID, "form_demo") {
|
||||
var form_manage_id string = strings.Split(e.Data.CustomID, ":")[1]
|
||||
var result FormResult = getFormResultValues(form_manage_id)
|
||||
var fields []discord.EmbedField
|
||||
var modal ModalJson = getModalByFormID(getFormType(form_manage_id))
|
||||
var overwrite_title string = getFormOverwriteTitle(form_manage_id)
|
||||
if overwrite_title != "" {
|
||||
modal.Title = overwrite_title
|
||||
}
|
||||
var inline bool
|
||||
var index int = 0
|
||||
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,
|
||||
Value: input.Value,
|
||||
Inline: &inline,
|
||||
})
|
||||
index++
|
||||
}
|
||||
|
||||
fields = append(fields, discord.EmbedField{
|
||||
Value: "From <#" + e.Channel().ID().String() + "> by " + e.User().Mention(),
|
||||
})
|
||||
if result.ResultChannelID == "" {
|
||||
if result.CommentCategoryID != "" {
|
||||
channel := createFormComment(form_manage_id, e.User().ID, snowflake.MustParse(result.ModeratorID), "answer", discord.NewEmbedBuilder().
|
||||
SetAuthorName(*e.User().GlobalName).SetAuthorIcon(*e.User().AvatarURL()).SetTitle("\""+modal.Title+"\"").SetDescription("This is the submitted result").
|
||||
SetColor(custom.GetColor("primary")).SetFields(fields...).
|
||||
Build(), *e.GuildID(), e.Client())
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().SetContent("Created channel " + discord.ChannelMention(channel.ID())).SetEphemeral(true).Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
} 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 {
|
||||
if result.AcceptChannelID == "" {
|
||||
_, 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(custom.GetColor("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 {
|
||||
var buttons []discord.InteractiveComponent
|
||||
if result.CommentCategoryID != "" {
|
||||
buttons = []discord.InteractiveComponent{discord.
|
||||
NewButton(discord.ButtonStylePrimary, "Comment", "form:"+form_manage_id+";comment", "").
|
||||
WithEmoji(discord.ComponentEmoji{Name: "👥"})}
|
||||
}
|
||||
buttons = append(buttons, discord.
|
||||
NewButton(discord.ButtonStyleDanger, "Decline", "form:"+form_manage_id+";decline", "").
|
||||
WithEmoji(discord.ComponentEmoji{Name: "🛑"}),
|
||||
discord.
|
||||
NewButton(discord.ButtonStyleSuccess, "Approve", "form:"+form_manage_id+";approve", "").
|
||||
WithEmoji(discord.ComponentEmoji{Name: "🎉"}))
|
||||
_, err := e.Client().Rest().CreateMessage(snowflake.MustParse(result.AcceptChannelID), discord.NewMessageCreateBuilder().
|
||||
SetEmbeds(discord.NewEmbedBuilder().
|
||||
SetAuthorName(*e.User().GlobalName).SetAuthorIcon(*e.User().AvatarURL()).SetTitle("\""+modal.Title+"\"").SetDescription("**This submission needs approval.**").
|
||||
SetColor(custom.GetColor("primary")).SetFields(fields...).
|
||||
Build()).
|
||||
SetContainerComponents(discord.NewActionRow(buttons...)).
|
||||
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 {
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().SetContent("The results would be submited...").SetEphemeral(true).Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
Autocomplete: func(e *events.AutocompleteInteractionCreate) {
|
||||
err := e.AutocompleteResult([]discord.AutocompleteChoice{
|
||||
&discord.AutocompleteChoiceString{
|
||||
Name: "Support Ticket",
|
||||
Value: "template_ticket",
|
||||
},
|
||||
&discord.AutocompleteChoiceString{
|
||||
Name: "Submit URL",
|
||||
Value: "template_url",
|
||||
},
|
||||
&discord.AutocompleteChoiceString{
|
||||
Name: "General",
|
||||
Value: "template_general",
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
var cmd_ticket_form cmd.Command = cmd.Command{
|
||||
Definition: discord.SlashCommandCreate{
|
||||
Name: "ticket",
|
||||
DefaultMemberPermissions: json.NewNullablePtr(discord.PermissionManageChannels),
|
||||
Description: "A quick command to create Ticketpanels. (/form for more)",
|
||||
Contexts: []discord.InteractionContextType{
|
||||
discord.InteractionContextTypeGuild,
|
||||
discord.InteractionContextTypePrivateChannel},
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
&discord.ApplicationCommandOptionString{
|
||||
Name: "title",
|
||||
Description: "The title the ticket should have",
|
||||
},
|
||||
&discord.ApplicationCommandOptionMentionable{
|
||||
Name: "moderator",
|
||||
Description: "Who can interact with moderating buttons.",
|
||||
},
|
||||
},
|
||||
},
|
||||
Interact: func(e *events.ApplicationCommandInteractionCreate) {
|
||||
var title string = "Ticket"
|
||||
var moderator string
|
||||
data := e.SlashCommandInteractionData()
|
||||
if data.String("title") != "" {
|
||||
title = data.String("title")
|
||||
}
|
||||
moderator = data.Role("moderator").ID.String()
|
||||
if moderator == "" {
|
||||
moderator = data.User("moderator").ID.String()
|
||||
}
|
||||
var exists bool = true
|
||||
var formManageID uuid.UUID = uuid.New()
|
||||
for exists {
|
||||
formManageID = uuid.New()
|
||||
exists = getFormManageIdExists(formManageID)
|
||||
}
|
||||
messagebuild := discord.NewMessageCreateBuilder().SetEmbeds(discord.NewEmbedBuilder().
|
||||
SetTitle(title).SetDescription("Press the bottom button to open a form popup.").SetColor(custom.GetColor("primary")).
|
||||
Build()).SetContainerComponents(discord.ActionRowComponent{
|
||||
discord.NewSuccessButton("Submit", "form:"+formManageID.String()).WithEmoji(discord.ComponentEmoji{
|
||||
Name: "anim_rocket",
|
||||
ID: snowflake.MustParse("1215740398706757743"),
|
||||
Animated: true,
|
||||
})}).
|
||||
Build()
|
||||
message, err := e.Client().Rest().CreateMessage(e.Channel().ID(), messagebuild)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
if title == "" {
|
||||
title = "Ticket"
|
||||
}
|
||||
var category string
|
||||
c, err := e.Client().Rest().CreateGuildChannel(*e.GuildID(), discord.GuildCategoryChannelCreate{Name: title + " mod answers"})
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
category = c.ID().String()
|
||||
if title == "Ticket" {
|
||||
title = ""
|
||||
}
|
||||
|
||||
addFormButton(e.GuildID().String(), e.Channel().ID().String(), message.ID.String(), formManageID.String(), "template_ticket", "", title, "", category, moderator)
|
||||
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 {
|
||||
logrus.Error(err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// moderator can be userID as well as roleID
|
||||
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 {
|
||||
var category snowflake.ID = snowflake.MustParse(getFormResultValues(form_manage_id).CommentCategoryID)
|
||||
_, err := client.Rest().GetChannel(category)
|
||||
if err != nil {
|
||||
c, err := client.Rest().CreateGuildChannel(guildID, discord.GuildCategoryChannelCreate{Name: strings.Trim(embed.Title, "\"") + " mod " + commentName + "s"})
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
category = c.ID()
|
||||
updateFormCommentCategory(form_manage_id, category.String())
|
||||
}
|
||||
ch, err := client.Rest().CreateGuildChannel(guildID, discord.GuildTextChannelCreate{
|
||||
ParentID: category,
|
||||
Name: strings.ToLower(embed.Author.Name) + "-" + commentName,
|
||||
})
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
var permissionOverwrites []discord.PermissionOverwrite = []discord.PermissionOverwrite{
|
||||
discord.RolePermissionOverwrite{
|
||||
RoleID: guildID,
|
||||
Deny: discord.PermissionViewChannel,
|
||||
}}
|
||||
|
||||
if isIDRole(client, guildID, moderator) {
|
||||
permissionOverwrites = append(permissionOverwrites, discord.RolePermissionOverwrite{
|
||||
RoleID: moderator,
|
||||
Allow: discord.PermissionViewChannel,
|
||||
})
|
||||
} 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 {
|
||||
logrus.Error(err)
|
||||
}
|
||||
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 {
|
||||
var IDs []string = []string{"form_demo"}
|
||||
var formButtonIDs []string = getFormManageIDs()
|
||||
for _, buttonID := range formButtonIDs {
|
||||
IDs = append(IDs, "form:"+buttonID)
|
||||
}
|
||||
return IDs
|
||||
}
|
65
cmd_ping.go
65
cmd_ping.go
@@ -1,65 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/disgoorg/disgo/discord"
|
||||
"github.com/disgoorg/disgo/events"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vaporvee/acecore/cmd"
|
||||
"github.com/vaporvee/acecore/custom"
|
||||
)
|
||||
|
||||
var cmd_ping cmd.Command = cmd.Command{
|
||||
Definition: discord.SlashCommandCreate{
|
||||
Name: "ping",
|
||||
Description: "Returns the ping of the bot",
|
||||
Contexts: []discord.InteractionContextType{
|
||||
discord.InteractionContextTypeGuild,
|
||||
discord.InteractionContextTypePrivateChannel,
|
||||
discord.InteractionContextTypeBotDM,
|
||||
},
|
||||
IntegrationTypes: []discord.ApplicationIntegrationType{
|
||||
discord.ApplicationIntegrationTypeGuildInstall,
|
||||
discord.ApplicationIntegrationTypeUserInstall,
|
||||
},
|
||||
},
|
||||
Interact: func(e *events.ApplicationCommandInteractionCreate) {
|
||||
start := time.Now()
|
||||
|
||||
client := http.Client{
|
||||
Timeout: 5 * time.Second,
|
||||
}
|
||||
|
||||
resp, err := client.Get("https://discord.com/api/v9/gateway/bot")
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
ping := time.Since(start)
|
||||
var pingColor string
|
||||
if ping.Milliseconds() < 200 {
|
||||
pingColor = "green"
|
||||
} else if ping.Milliseconds() < 400 {
|
||||
pingColor = "yellow"
|
||||
} else {
|
||||
pingColor = "red"
|
||||
}
|
||||
app, err := e.Client().Rest().GetCurrentApplication()
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
err = e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetEmbeds(discord.NewEmbedBuilder().
|
||||
SetTitle(app.Bot.Username + " ping").
|
||||
SetDescription(fmt.Sprintf("# %.2fms", ping.Seconds()*1000)).
|
||||
SetColor(custom.GetColor(pingColor)).Build()).SetEphemeral(true).Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
},
|
||||
}
|
118
cmd_sticky.go
118
cmd_sticky.go
@@ -1,118 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"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/vaporvee/acecore/cmd"
|
||||
"github.com/vaporvee/acecore/custom"
|
||||
)
|
||||
|
||||
var cmd_sticky cmd.Command = cmd.Command{
|
||||
Definition: discord.SlashCommandCreate{
|
||||
Name: "sticky",
|
||||
Description: "Stick or unstick messages to the bottom of the current channel",
|
||||
DefaultMemberPermissions: json.NewNullablePtr(discord.PermissionManageMessages),
|
||||
Contexts: []discord.InteractionContextType{
|
||||
discord.InteractionContextTypeGuild,
|
||||
discord.InteractionContextTypePrivateChannel},
|
||||
IntegrationTypes: []discord.ApplicationIntegrationType{
|
||||
discord.ApplicationIntegrationTypeGuildInstall},
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
&discord.ApplicationCommandOptionString{
|
||||
Name: "message",
|
||||
Description: "The message you want to stick to the bottom of this channel",
|
||||
Required: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
Interact: func(e *events.ApplicationCommandInteractionCreate) {
|
||||
if len(e.SlashCommandInteractionData().Options) == 0 {
|
||||
if hasSticky(e.GuildID().String(), e.Channel().ID().String()) {
|
||||
err := e.Client().Rest().DeleteMessage(e.Channel().ID(), snowflake.MustParse(getStickyMessageID(e.GuildID().String(), e.Channel().ID().String())))
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
removeSticky(e.GuildID().String(), e.Channel().ID().String())
|
||||
err = e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent("The sticky message was removed from this channel!").SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
} else {
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent("This channel has no sticky message!").SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
inputStickyMessage(e)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
var context_sticky cmd.Command = cmd.Command{
|
||||
Definition: discord.MessageCommandCreate{
|
||||
Name: "Stick to channel",
|
||||
DefaultMemberPermissions: json.NewNullablePtr(discord.PermissionManageMessages),
|
||||
Contexts: []discord.InteractionContextType{
|
||||
discord.InteractionContextTypeGuild,
|
||||
discord.InteractionContextTypePrivateChannel},
|
||||
IntegrationTypes: []discord.ApplicationIntegrationType{
|
||||
discord.ApplicationIntegrationTypeGuildInstall},
|
||||
},
|
||||
Interact: func(e *events.ApplicationCommandInteractionCreate) {
|
||||
inputStickyMessage(e)
|
||||
},
|
||||
}
|
||||
|
||||
func inputStickyMessage(e *events.ApplicationCommandInteractionCreate) {
|
||||
var messageText string
|
||||
if e.ApplicationCommandInteraction.Data.Type() == discord.ApplicationCommandTypeMessage {
|
||||
messageText = e.MessageCommandInteractionData().TargetMessage().Content //TODO add more data then just content
|
||||
} else {
|
||||
messageText = e.SlashCommandInteractionData().String("message")
|
||||
}
|
||||
if messageText == "" {
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent("Can't add empty sticky messages!").SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
} else {
|
||||
message, err := e.Client().Rest().CreateMessage(e.Channel().ID(), discord.MessageCreate{Embeds: []discord.Embed{
|
||||
{Description: messageText, Footer: &discord.EmbedFooter{Text: "📌 Sticky message"}, Color: custom.GetColor("primary")}}})
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
|
||||
if hasSticky(e.GuildID().String(), e.Channel().ID().String()) {
|
||||
err = e.Client().Rest().DeleteMessage(e.Channel().ID(), snowflake.MustParse(getStickyMessageID(e.GuildID().String(), e.Channel().ID().String())))
|
||||
if err != nil {
|
||||
logrus.Error(err, getStickyMessageID(e.GuildID().String(), e.Channel().ID().String()))
|
||||
}
|
||||
removeSticky(e.GuildID().String(), e.Channel().ID().String())
|
||||
addSticky(e.GuildID().String(), e.Channel().ID().String(), messageText, message.ID.String())
|
||||
err = e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent("Sticky message in this channel was updated!").SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
} else {
|
||||
addSticky(e.GuildID().String(), e.Channel().ID().String(), messageText, message.ID.String())
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent("Message sticked to the channel!").SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
194
cmd_tag.go
194
cmd_tag.go
@@ -1,194 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/disgoorg/disgo/discord"
|
||||
"github.com/disgoorg/disgo/events"
|
||||
"github.com/disgoorg/json"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vaporvee/acecore/cmd"
|
||||
)
|
||||
|
||||
// TODO: make user installable tag command using userIDs instead of guildIDs
|
||||
var cmd_tag cmd.Command = cmd.Command{
|
||||
Definition: discord.SlashCommandCreate{
|
||||
Name: "tag",
|
||||
DefaultMemberPermissions: json.NewNullablePtr(discord.PermissionManageGuild),
|
||||
Description: "A command to show and edit saved presaved messages.",
|
||||
Contexts: []discord.InteractionContextType{
|
||||
discord.InteractionContextTypeGuild,
|
||||
discord.InteractionContextTypePrivateChannel},
|
||||
IntegrationTypes: []discord.ApplicationIntegrationType{
|
||||
discord.ApplicationIntegrationTypeGuildInstall},
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
discord.ApplicationCommandOptionSubCommand{
|
||||
Name: "get",
|
||||
Description: "A command to get messages saved to the bot.",
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
discord.ApplicationCommandOptionString{
|
||||
Name: "tag",
|
||||
Description: "Your predefined tag for the saved message",
|
||||
Required: true,
|
||||
Autocomplete: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
discord.ApplicationCommandOptionSubCommand{
|
||||
Name: "add",
|
||||
Description: "A command to add messages saved to the bot.",
|
||||
},
|
||||
discord.ApplicationCommandOptionSubCommand{
|
||||
Name: "remove",
|
||||
Description: "A command to remove messages saved to the bot.",
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
discord.ApplicationCommandOptionString{
|
||||
Name: "tag",
|
||||
Description: "The tag you want to remove",
|
||||
Required: true,
|
||||
Autocomplete: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Interact: func(e *events.ApplicationCommandInteractionCreate) {
|
||||
switch *e.SlashCommandInteractionData().SubCommandName {
|
||||
case "get":
|
||||
GetTagCommand(e)
|
||||
case "add":
|
||||
AddTagCommand(e)
|
||||
case "remove":
|
||||
removeTag(e.GuildID().String(), e.SlashCommandInteractionData().String("tag"))
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent("Tag removed!").SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
},
|
||||
ModalIDs: []string{"tag_add_modal"},
|
||||
ModalSubmit: func(e *events.ModalSubmitInteractionCreate) {
|
||||
tagName := e.Data.Text("tag_add_modal_name")
|
||||
tagContent := e.Data.Text("tag_add_modal_content")
|
||||
addTag(e.GuildID().String(), tagName, tagContent)
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent("Tag \"" + tagName + "\" added!").SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
},
|
||||
Autocomplete: func(e *events.AutocompleteInteractionCreate) {
|
||||
AutocompleteTag(e)
|
||||
},
|
||||
}
|
||||
|
||||
var cmd_tag_short cmd.Command = cmd.Command{
|
||||
Definition: discord.SlashCommandCreate{
|
||||
Name: "g",
|
||||
Description: "A short command to get presaved messages.",
|
||||
Contexts: []discord.InteractionContextType{
|
||||
discord.InteractionContextTypeGuild,
|
||||
discord.InteractionContextTypePrivateChannel},
|
||||
IntegrationTypes: []discord.ApplicationIntegrationType{
|
||||
discord.ApplicationIntegrationTypeGuildInstall},
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
discord.ApplicationCommandOptionString{
|
||||
Name: "tag",
|
||||
Description: "Your predefined tag for the saved message",
|
||||
Required: true,
|
||||
Autocomplete: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Interact: func(e *events.ApplicationCommandInteractionCreate) {
|
||||
GetTagCommand(e)
|
||||
},
|
||||
Autocomplete: func(e *events.AutocompleteInteractionCreate) {
|
||||
AutocompleteTag(e)
|
||||
},
|
||||
}
|
||||
|
||||
var context_tag cmd.Command = cmd.Command{
|
||||
Definition: discord.MessageCommandCreate{
|
||||
Name: "Save as tag",
|
||||
DefaultMemberPermissions: json.NewNullablePtr(discord.PermissionManageGuild),
|
||||
Contexts: []discord.InteractionContextType{
|
||||
discord.InteractionContextTypeGuild,
|
||||
discord.InteractionContextTypePrivateChannel},
|
||||
IntegrationTypes: []discord.ApplicationIntegrationType{
|
||||
discord.ApplicationIntegrationTypeGuildInstall},
|
||||
},
|
||||
Interact: func(e *events.ApplicationCommandInteractionCreate) {
|
||||
AddTagCommand(e)
|
||||
},
|
||||
}
|
||||
|
||||
func GetTagCommand(e *events.ApplicationCommandInteractionCreate) {
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent(getTagContent(e.GuildID().String(), e.SlashCommandInteractionData().String("tag"))).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func AddTagCommand(e *events.ApplicationCommandInteractionCreate) {
|
||||
var prevalue string
|
||||
if e.ApplicationCommandInteraction.Data.Type() == discord.ApplicationCommandTypeMessage {
|
||||
prevalue = e.MessageCommandInteractionData().TargetMessage().Content
|
||||
}
|
||||
err := e.Modal(discord.ModalCreate{
|
||||
CustomID: "tag_add_modal" + e.User().ID.String(),
|
||||
Title: "Add a custom tag command",
|
||||
Components: []discord.ContainerComponent{
|
||||
discord.ActionRowComponent{
|
||||
discord.TextInputComponent{
|
||||
CustomID: "tag_add_modal_name",
|
||||
Label: "Name",
|
||||
Style: discord.TextInputStyleShort,
|
||||
Required: true,
|
||||
MaxLength: 20,
|
||||
Value: "",
|
||||
},
|
||||
},
|
||||
discord.ActionRowComponent{
|
||||
discord.TextInputComponent{
|
||||
CustomID: "tag_add_modal_content",
|
||||
Label: "Content",
|
||||
Style: discord.TextInputStyleParagraph,
|
||||
Required: true,
|
||||
MaxLength: 2000,
|
||||
Value: prevalue,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func AutocompleteTag(e *events.AutocompleteInteractionCreate) {
|
||||
err := e.AutocompleteResult(generateTagChoices(e.GuildID().String()))
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func generateTagChoices(guildID string) []discord.AutocompleteChoice {
|
||||
choices := []discord.AutocompleteChoice{}
|
||||
IDs, err := getTagIDs(guildID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return choices
|
||||
}
|
||||
for _, id := range IDs {
|
||||
id_name := getTagName(guildID, id)
|
||||
choices = append(choices, &discord.AutocompleteChoiceString{
|
||||
Name: id_name,
|
||||
Value: id,
|
||||
})
|
||||
}
|
||||
return choices
|
||||
}
|
@@ -1,23 +1,22 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"github.com/disgoorg/disgo/discord"
|
||||
"github.com/disgoorg/disgo/events"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vaporvee/acecore/cmd"
|
||||
"github.com/vaporvee/acecore/shared"
|
||||
)
|
||||
|
||||
var Plugin = &cmd.Plugin{
|
||||
var db *sql.DB
|
||||
|
||||
var Plugin = &shared.Plugin{
|
||||
Name: "testplugin",
|
||||
Register: func(e *events.Ready) error {
|
||||
app, err := e.Client().Rest().GetCurrentApplication()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.Infof("%s has a working plugin called \"testplugin\"", app.Bot.Username)
|
||||
Init: func(d *sql.DB) error {
|
||||
db = d
|
||||
return nil
|
||||
},
|
||||
Commands: []cmd.Command{
|
||||
Commands: []shared.Command{
|
||||
{
|
||||
Definition: discord.SlashCommandCreate{
|
||||
Name: "testplugincommand",
|
4
go.mod
4
go.mod
@@ -10,7 +10,7 @@ require (
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/lib/pq v1.10.9
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/vaporvee/acecore/cmd v0.0.0-20240414204205-9ac9f89071f6
|
||||
github.com/vaporvee/acecore/shared v0.0.0-20240414204205-9ac9f89071f6
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -20,3 +20,5 @@ require (
|
||||
golang.org/x/net v0.21.0 // indirect
|
||||
golang.org/x/sys v0.17.0 // indirect
|
||||
)
|
||||
|
||||
replace github.com/vaporvee/acecore/shared => ./shared
|
4
go.sum
4
go.sum
@@ -25,8 +25,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/vaporvee/acecore/cmd v0.0.0-20240414204205-9ac9f89071f6 h1:QyVs7R8dTS5KEnOjUbTV2jFe7VqGyi8q4krdjy8f9j0=
|
||||
github.com/vaporvee/acecore/cmd v0.0.0-20240414204205-9ac9f89071f6/go.mod h1:03W2NrAPbAqa7gsqAM+2K/wT28stj9BmEhC5NzeGe3A=
|
||||
github.com/vaporvee/acecore/shared v0.0.0-20240414204205-9ac9f89071f6 h1:QyVs7R8dTS5KEnOjUbTV2jFe7VqGyi8q4krdjy8f9j0=
|
||||
github.com/vaporvee/acecore/shared v0.0.0-20240414204205-9ac9f89071f6/go.mod h1:03W2NrAPbAqa7gsqAM+2K/wT28stj9BmEhC5NzeGe3A=
|
||||
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.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||
|
139
handlers.go
139
handlers.go
@@ -3,31 +3,22 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"plugin"
|
||||
"runtime"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"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/vaporvee/acecore/cmd"
|
||||
"github.com/vaporvee/acecore/custom"
|
||||
|
||||
"github.com/vaporvee/acecore/shared"
|
||||
)
|
||||
|
||||
var commands []cmd.Command = []cmd.Command{cmd_tag, cmd_tag_short, context_tag, cmd_sticky, context_sticky, cmd_ping, cmd_addemoji, cmd_form, cmd_ticket_form, cmd_blockpolls, cmd_autopublish, cmd_autojoinroles}
|
||||
var commands []shared.Command
|
||||
|
||||
func ready(e *events.Ready) {
|
||||
logrus.Info("Starting up...")
|
||||
findAndDeleteUnusedMessages(e.Client())
|
||||
removeOldCommandFromAllGuilds(e.Client())
|
||||
err := loadPlugins("plugins/", e)
|
||||
if err != nil {
|
||||
logrus.Warn(err)
|
||||
}
|
||||
var existingCommandNames []string
|
||||
existingCommands, err := e.Client().Rest().GetGlobalCommands(e.Client().ApplicationID(), false)
|
||||
if err != nil {
|
||||
@@ -56,68 +47,6 @@ func ready(e *events.Ready) {
|
||||
logrus.Info("Successfully started the Bot!")
|
||||
}
|
||||
|
||||
func loadPlugins(directory string, e *events.Ready) error {
|
||||
files, err := os.ReadDir(directory)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Determine the appropriate file extension for dynamic libraries
|
||||
var ext string
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
ext = ".dll"
|
||||
case "linux":
|
||||
ext = ".so"
|
||||
case "darwin":
|
||||
ext = ".dylib"
|
||||
default:
|
||||
return fmt.Errorf("unsupported operating system: %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
if filepath.Ext(file.Name()) == ext {
|
||||
p, err := plugin.Open(filepath.Join(directory, file.Name()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
symPlugin, err := p.Lookup("Plugin")
|
||||
if err != nil {
|
||||
logrus.Errorf("Error looking up symbol 'Plugin' in %s: %v", file.Name(), err)
|
||||
continue
|
||||
}
|
||||
|
||||
pluginPtr, ok := symPlugin.(**cmd.Plugin)
|
||||
if !ok {
|
||||
logrus.Errorf("Plugin does not match expected type")
|
||||
continue
|
||||
}
|
||||
|
||||
plugin := *pluginPtr
|
||||
if plugin.Name == "" {
|
||||
logrus.Warn("Plugin is unnamed")
|
||||
}
|
||||
if plugin.Commands != nil {
|
||||
commands = append(commands, plugin.Commands...)
|
||||
} else {
|
||||
logrus.Errorf("Plugin %s has no commands set", plugin.Name)
|
||||
continue
|
||||
}
|
||||
if plugin.Register != nil {
|
||||
err = plugin.Register(e, db)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error running plugin register %s function: %v", plugin.Name, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func applicationCommandInteractionCreate(e *events.ApplicationCommandInteractionCreate) {
|
||||
for _, command := range commands {
|
||||
if command.Interact != nil && e.Data.CommandName() == command.Definition.CommandName() {
|
||||
@@ -202,65 +131,3 @@ func removeOldCommandFromAllGuilds(c bot.Client) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func messageCreate(e *events.MessageCreate) {
|
||||
if len(e.Message.Embeds) == 0 || e.Message.Embeds[0].Footer == nil || e.Message.Embeds[0].Footer.Text != "📌 Sticky message" {
|
||||
if hasSticky(e.Message.GuildID.String(), e.Message.ChannelID.String()) {
|
||||
stickymessageID := getStickyMessageID(e.Message.GuildID.String(), e.Message.ChannelID.String())
|
||||
err := e.Client().Rest().DeleteMessage(e.ChannelID, snowflake.MustParse(stickymessageID))
|
||||
stickyMessage, _ := e.Client().Rest().CreateMessage(e.ChannelID, discord.MessageCreate{
|
||||
Embeds: []discord.Embed{
|
||||
{
|
||||
Footer: &discord.EmbedFooter{
|
||||
Text: "📌 Sticky message",
|
||||
},
|
||||
Color: custom.GetColor("primary"),
|
||||
Description: getStickyMessageContent(e.Message.GuildID.String(), e.Message.ChannelID.String()),
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
updateStickyMessageID(e.Message.GuildID.String(), e.Message.ChannelID.String(), stickyMessage.ID.String())
|
||||
}
|
||||
}
|
||||
channel, err := e.Client().Rest().GetChannel(e.Message.ChannelID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
if channel != nil {
|
||||
isBlockPollsEnabledGlobal := isGlobalBlockPolls(e.GuildID.String())
|
||||
isBlockPollsEnabled, allowedRole := getBlockPollsEnabled(e.GuildID.String(), e.Message.ChannelID.String())
|
||||
var hasAllowedRole bool
|
||||
if allowedRole != "" {
|
||||
hasAllowedRole = slices.Contains(e.Message.Member.RoleIDs, snowflake.MustParse(allowedRole))
|
||||
}
|
||||
if (isBlockPollsEnabledGlobal || isBlockPollsEnabled) && !hasAllowedRole && messageIsPoll(e.Message.ChannelID.String(), e.Message.ID.String(), e.Client()) {
|
||||
e.Client().Rest().DeleteMessage(e.Message.ChannelID, e.Message.ID)
|
||||
}
|
||||
if channel.Type() == discord.ChannelTypeGuildNews {
|
||||
if isAutopublishEnabled(e.GuildID.String(), e.ChannelID.String()) {
|
||||
_, err := e.Client().Rest().CrosspostMessage(e.ChannelID, e.MessageID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func messageDelete(e *events.MessageDelete) { //TODO: also clear on bot start when message doesn't exist
|
||||
tryDeleteUnusedMessage(e.MessageID.String())
|
||||
}
|
||||
|
||||
func guildMemberJoin(e *events.GuildMemberJoin) {
|
||||
role := getAutoJoinRole(e.GuildID.String(), e.Member.User.Bot)
|
||||
if role != "" {
|
||||
err := e.Client().Rest().AddMemberRole(e.GuildID, e.Member.User.ID, snowflake.MustParse(role))
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
93
main.go
93
main.go
@@ -3,10 +3,14 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"plugin"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"time"
|
||||
@@ -19,6 +23,7 @@ import (
|
||||
"github.com/joho/godotenv"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vaporvee/acecore/log2webhook"
|
||||
"github.com/vaporvee/acecore/shared"
|
||||
"github.com/vaporvee/acecore/web"
|
||||
)
|
||||
|
||||
@@ -26,6 +31,8 @@ var (
|
||||
db *sql.DB
|
||||
)
|
||||
|
||||
var listeners []func()
|
||||
|
||||
func main() {
|
||||
logrusInitFile()
|
||||
var err error
|
||||
@@ -35,8 +42,16 @@ func main() {
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
initTables()
|
||||
client, err := disgo.New(os.Getenv("BOT_TOKEN"),
|
||||
err = loadPlugins("plugins/")
|
||||
if err != nil {
|
||||
logrus.Warn(err)
|
||||
}
|
||||
shared.BotConfigs = append(shared.BotConfigs,
|
||||
bot.WithEventListenerFunc(ready),
|
||||
bot.WithEventListenerFunc(applicationCommandInteractionCreate),
|
||||
bot.WithEventListenerFunc(autocompleteInteractionCreate),
|
||||
bot.WithEventListenerFunc(componentInteractionCreate),
|
||||
bot.WithEventListenerFunc(modalSubmitInteractionCreate),
|
||||
bot.WithGatewayConfigOpts(
|
||||
gateway.WithIntents(
|
||||
gateway.IntentGuilds,
|
||||
@@ -45,15 +60,9 @@ func main() {
|
||||
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),
|
||||
))
|
||||
client, err := disgo.New(os.Getenv("BOT_TOKEN"),
|
||||
shared.BotConfigs...,
|
||||
)
|
||||
if err != nil {
|
||||
logrus.Fatal("error creating Discord session,", err)
|
||||
@@ -102,3 +111,65 @@ func logrusInitFile() {
|
||||
mw := io.MultiWriter(os.Stdout, log, &log2webhook.WebhookWriter{})
|
||||
logrus.SetOutput(mw)
|
||||
}
|
||||
|
||||
func loadPlugins(directory string) error {
|
||||
files, err := os.ReadDir(directory)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Determine the appropriate file extension for dynamic libraries
|
||||
var ext string
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
ext = ".dll"
|
||||
case "linux":
|
||||
ext = ".so"
|
||||
case "darwin":
|
||||
ext = ".dylib"
|
||||
default:
|
||||
return fmt.Errorf("unsupported operating system: %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
if filepath.Ext(file.Name()) == ext {
|
||||
p, err := plugin.Open(filepath.Join(directory, file.Name()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
symPlugin, err := p.Lookup("Plugin")
|
||||
if err != nil {
|
||||
logrus.Errorf("Error looking up symbol 'Plugin' in %s: %v", file.Name(), err)
|
||||
continue
|
||||
}
|
||||
|
||||
pluginPtr, ok := symPlugin.(**shared.Plugin)
|
||||
if !ok {
|
||||
logrus.Errorf("Plugin does not match expected type")
|
||||
continue
|
||||
}
|
||||
|
||||
plugin := *pluginPtr
|
||||
if plugin.Name == "" {
|
||||
logrus.Warn("Plugin is unnamed")
|
||||
}
|
||||
if plugin.Commands != nil {
|
||||
commands = append(commands, plugin.Commands...)
|
||||
} else {
|
||||
logrus.Errorf("Plugin %s has no commands set", plugin.Name)
|
||||
continue
|
||||
}
|
||||
if plugin.Init != nil {
|
||||
err = plugin.Init(db)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error running plugin register %s function: %v", plugin.Name, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
514
manage_data.go
514
manage_data.go
@@ -1,514 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"slices"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func initTables() {
|
||||
createTableQuery := `CREATE TABLE IF NOT EXISTS tags (
|
||||
tag_id TEXT NOT NULL,
|
||||
tag_name TEXT NOT NULL,
|
||||
tag_content TEXT NOT NULL,
|
||||
guild_id TEXT NOT NULL,
|
||||
PRIMARY KEY (tag_id, guild_id)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS sticky (
|
||||
message_id TEXT NOT NULL,
|
||||
channel_id TEXT NOT NULL,
|
||||
message_content TEXT NOT NULL,
|
||||
guild_id TEXT NOT NULL,
|
||||
PRIMARY KEY (channel_id, guild_id)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS custom_forms (
|
||||
form_type TEXT NOT NULL,
|
||||
title TEXT NOT NULL,
|
||||
json JSON NOT NULL,
|
||||
guild_id TEXT NOT NULL,
|
||||
PRIMARY KEY (form_type, guild_id)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS form_manage (
|
||||
form_manage_id TEXT NOT NULL,
|
||||
form_type TEXT NOT NULL,
|
||||
overwrite_title TEXT,
|
||||
message_id TEXT NOT NULL,
|
||||
channel_id TEXT NOT NULL,
|
||||
guild_id TEXT NOT NULL,
|
||||
result_channel_id TEXT NOT NULL,
|
||||
accept_channel_id TEXT,
|
||||
comment_category TEXT,
|
||||
moderator_id TEXT,
|
||||
PRIMARY KEY (form_manage_id, form_type)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS autojoinroles (
|
||||
guild_id TEXT NOT NULL,
|
||||
bot_role TEXT,
|
||||
user_role TEXT,
|
||||
PRIMARY KEY (guild_id)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS autopublish (
|
||||
guild_id TEXT NOT NULL,
|
||||
news_channel_id TEXT NOT NULL,
|
||||
PRIMARY KEY (guild_id, news_channel_id)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS blockpolls (
|
||||
guild_id TEXT NOT NULL,
|
||||
channel_id TEXT,
|
||||
global BOOLEAN,
|
||||
allowed_role TEXT,
|
||||
PRIMARY KEY (guild_id)
|
||||
)
|
||||
`
|
||||
_, err := db.Exec(createTableQuery)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if slices.Contains(os.Args, "--form-db-update") {
|
||||
_, err = db.Exec("ALTER TABLE blockpolls ADD global BOOLEAN;")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
_, err = db.Exec("ALTER TABLE blockpolls ADD allowed_role TEXT;")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type FormResult struct {
|
||||
OverwriteTitle string
|
||||
ResultChannelID string
|
||||
AcceptChannelID string
|
||||
CommentCategoryID string
|
||||
ModeratorID string
|
||||
}
|
||||
|
||||
type BlockPoll struct {
|
||||
ChannelID string
|
||||
Global bool
|
||||
AllowedRole string
|
||||
}
|
||||
|
||||
func addTag(guildID, tagName, tagContent string) bool {
|
||||
var exists bool = true
|
||||
//TODO: add modify command
|
||||
id := uuid.New()
|
||||
for exists {
|
||||
id = uuid.New()
|
||||
err := db.QueryRow("SELECT EXISTS (SELECT 1 FROM tags WHERE guild_id = $1 AND tag_id = $2)", guildID, id).Scan(&exists)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
_, err := db.Exec("INSERT INTO tags (guild_id, tag_name, tag_content, tag_id) VALUES ($1, $2, $3, $4)", guildID, tagName, tagContent, id)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
|
||||
return exists
|
||||
}
|
||||
func removeTag(guildID string, tagID string) {
|
||||
var exists bool
|
||||
err := db.QueryRow("SELECT EXISTS (SELECT 1 FROM tags WHERE guild_id = $1 AND tag_id = $2)", guildID, tagID).Scan(&exists)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
if exists {
|
||||
_, err = db.Exec("DELETE FROM tags WHERE guild_id = $1 AND tag_id = $2", guildID, tagID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
func getTagIDs(guildID string) ([]string, error) {
|
||||
var IDs []string
|
||||
rows, err := db.Query("SELECT tag_id FROM tags WHERE guild_id = $1", guildID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var id string
|
||||
if err := rows.Scan(&id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
IDs = append(IDs, id)
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return IDs, nil
|
||||
}
|
||||
func getTagName(guildID string, tagID string) string {
|
||||
var tagName string
|
||||
db.QueryRow("SELECT tag_name FROM tags WHERE guild_id = $1 AND tag_id = $2", guildID, tagID).Scan(&tagName)
|
||||
return tagName
|
||||
}
|
||||
func getTagContent(guildID string, tagID string) string {
|
||||
var tagContent string
|
||||
db.QueryRow("SELECT tag_content FROM tags WHERE guild_id = $1 AND tag_id = $2", guildID, tagID).Scan(&tagContent)
|
||||
return tagContent
|
||||
}
|
||||
|
||||
func addSticky(guildID string, channelID string, messageContent string, messageID string) {
|
||||
_, err := db.Exec("INSERT INTO sticky (guild_id, channel_id, message_id, message_content) VALUES ($1, $2, $3, $4)", guildID, channelID, messageID, messageContent)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func hasSticky(guildID string, channelID string) bool {
|
||||
var exists bool
|
||||
err := db.QueryRow("SELECT EXISTS (SELECT 1 FROM sticky WHERE guild_id = $1 AND channel_id = $2)", guildID, channelID).Scan(&exists)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
return exists
|
||||
}
|
||||
|
||||
func getStickyMessageID(guildID string, channelID string) string {
|
||||
var messageID string
|
||||
exists := hasSticky(guildID, channelID)
|
||||
if exists {
|
||||
err := db.QueryRow("SELECT message_id FROM sticky WHERE guild_id = $1 AND channel_id = $2", guildID, channelID).Scan(&messageID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
return messageID
|
||||
}
|
||||
func getStickyMessageContent(guildID string, channelID string) string {
|
||||
var messageID string
|
||||
exists := hasSticky(guildID, channelID)
|
||||
if exists {
|
||||
err := db.QueryRow("SELECT message_content FROM sticky WHERE guild_id = $1 AND channel_id = $2", guildID, channelID).Scan(&messageID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
return messageID
|
||||
}
|
||||
|
||||
func updateStickyMessageID(guildID string, channelID string, messageID string) {
|
||||
exists := hasSticky(guildID, channelID)
|
||||
if exists {
|
||||
_, err := db.Exec("UPDATE sticky SET message_id = $1 WHERE guild_id = $2 AND channel_id = $3", messageID, guildID, channelID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func removeSticky(guildID string, channelID string) {
|
||||
_, err := db.Exec("DELETE FROM sticky WHERE guild_id = $1 AND channel_id = $2", guildID, channelID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func getFormManageIdExists(id uuid.UUID) bool {
|
||||
var exists bool
|
||||
err := db.QueryRow("SELECT EXISTS (SELECT 1 FROM form_manage WHERE form_manage_id = $1)", id).Scan(&exists)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
return exists
|
||||
}
|
||||
|
||||
func addFormButton(guildID string, channelID string, messageID string, formManageID string, formType string, resultChannelID string, overwriteTitle string, acceptChannelID string, commentCategory string, moderator_id string) {
|
||||
_, err := db.Exec(
|
||||
`INSERT INTO form_manage (
|
||||
guild_id,
|
||||
form_manage_id,
|
||||
channel_id,
|
||||
message_id,
|
||||
form_type,
|
||||
result_channel_id,
|
||||
overwrite_title,
|
||||
accept_channel_id,
|
||||
comment_category,
|
||||
moderator_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`,
|
||||
guildID, formManageID, channelID, messageID, formType, resultChannelID, overwriteTitle, acceptChannelID, commentCategory, moderator_id)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func getFormManageIDs() []string {
|
||||
if db == nil {
|
||||
return nil
|
||||
}
|
||||
var IDs []string
|
||||
rows, err := db.Query("SELECT form_manage_id FROM form_manage")
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return nil
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var id string
|
||||
if err := rows.Scan(&id); err != nil {
|
||||
logrus.Error(err)
|
||||
return nil
|
||||
}
|
||||
IDs = append(IDs, id)
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
logrus.Error(err)
|
||||
return nil
|
||||
}
|
||||
return IDs
|
||||
}
|
||||
|
||||
func getFormType(formManageID string) string {
|
||||
var formType string
|
||||
err := db.QueryRow("SELECT form_type FROM form_manage WHERE form_manage_id = $1", formManageID).Scan(&formType)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
return formType
|
||||
}
|
||||
|
||||
func getFormResultValues(formManageID string) FormResult {
|
||||
var result FormResult
|
||||
err := db.QueryRow("SELECT overwrite_title FROM form_manage WHERE form_manage_id = $1", formManageID).Scan(&result.OverwriteTitle)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
err = db.QueryRow("SELECT result_channel_id FROM form_manage WHERE form_manage_id = $1", formManageID).Scan(&result.ResultChannelID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
err = db.QueryRow("SELECT accept_channel_id FROM form_manage WHERE form_manage_id = $1", formManageID).Scan(&result.AcceptChannelID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
err = db.QueryRow("SELECT comment_category FROM form_manage WHERE form_manage_id = $1", formManageID).Scan(&result.CommentCategoryID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
err = db.QueryRow("SELECT moderator_id FROM form_manage WHERE form_manage_id = $1", formManageID).Scan(&result.ModeratorID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func getFormOverwriteTitle(formManageID string) string {
|
||||
var overwriteTitle string
|
||||
err := db.QueryRow("SELECT overwrite_title FROM form_manage WHERE form_manage_id = $1", formManageID).Scan(&overwriteTitle)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
return overwriteTitle
|
||||
}
|
||||
|
||||
func updateFormCommentCategory(formManageID string, comment_category string) {
|
||||
_, err := db.Exec("UPDATE form_manage SET comment_category = $1 WHERE form_manage_id = $2", comment_category, formManageID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func setAutoJoinRole(guildID string, option string, roleID string) bool {
|
||||
var role_exists bool
|
||||
var autojoinroles_exists bool
|
||||
err := db.QueryRow("SELECT EXISTS (SELECT 1 FROM autojoinroles WHERE guild_id = $1)", guildID).Scan(&autojoinroles_exists)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
err = db.QueryRow("SELECT EXISTS (SELECT 1 FROM autojoinroles WHERE guild_id = $1 AND "+option+"_role IS NOT NULL AND "+option+"_role != '')", guildID).Scan(&role_exists)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
if autojoinroles_exists {
|
||||
_, err = db.Exec("UPDATE autojoinroles SET "+option+"_role = $1 WHERE guild_id = $2", roleID, guildID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
} else {
|
||||
_, err = db.Exec("INSERT INTO autojoinroles (guild_id, "+option+"_role) VALUES ($1, $2)", guildID, roleID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
return role_exists
|
||||
}
|
||||
|
||||
func purgeUnusedAutoJoinRoles(guildID string) {
|
||||
_, err := db.Exec("DELETE FROM autojoinroles WHERE guild_id = $1 AND user_role = '' OR user_role IS NULL AND bot_role = '' OR bot_role IS NULL", guildID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func getAutoJoinRole(guildID string, isBot bool) string {
|
||||
var isBotString string
|
||||
var role string
|
||||
if isBot {
|
||||
isBotString = "bot"
|
||||
} else {
|
||||
isBotString = "user"
|
||||
}
|
||||
var exists bool
|
||||
err := db.QueryRow("SELECT EXISTS (SELECT 1 FROM autojoinroles WHERE guild_id = $1)", guildID).Scan(&exists)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return role
|
||||
}
|
||||
if exists {
|
||||
err = db.QueryRow("SELECT "+isBotString+"_role FROM autojoinroles WHERE guild_id = $1", guildID).Scan(&role)
|
||||
if err != nil {
|
||||
logrus.Error(err, guildID)
|
||||
}
|
||||
}
|
||||
return role
|
||||
}
|
||||
|
||||
func toggleAutoPublish(guildID string, newsChannelID string) bool {
|
||||
var exists bool
|
||||
err := db.QueryRow("SELECT EXISTS (SELECT 1 FROM autopublish WHERE guild_id = $1 AND news_channel_id = $2)", guildID, newsChannelID).Scan(&exists)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
if exists {
|
||||
_, err := db.Exec("DELETE FROM autopublish WHERE guild_id = $1 AND news_channel_id = $2", guildID, newsChannelID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
} else {
|
||||
_, err := db.Exec("INSERT INTO autopublish (guild_id, news_channel_id) VALUES ($1, $2)", guildID, newsChannelID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
return exists
|
||||
}
|
||||
|
||||
func isAutopublishEnabled(guildID string, newsChannelID string) bool {
|
||||
var enabled bool
|
||||
err := db.QueryRow("SELECT EXISTS (SELECT 1 FROM autopublish WHERE guild_id = $1 AND news_channel_id = $2)", guildID, newsChannelID).Scan(&enabled)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
return enabled
|
||||
}
|
||||
|
||||
func isGlobalBlockPolls(guildID string) bool {
|
||||
var globalexists bool
|
||||
err := db.QueryRow("SELECT EXISTS (SELECT 1 FROM blockpolls WHERE guild_id = $1 AND global = true)", guildID).Scan(&globalexists)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
return globalexists
|
||||
}
|
||||
|
||||
func toggleBlockPolls(guildID string, channelID string, global bool, allowedRole string) (e bool, isGlobal bool) {
|
||||
globalexists := isGlobalBlockPolls(guildID)
|
||||
var exists bool
|
||||
err := db.QueryRow("SELECT EXISTS (SELECT 1 FROM blockpolls WHERE guild_id = $1 AND channel_id = $2)", guildID, channelID).Scan(&exists)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
if globalexists {
|
||||
_, err := db.Exec("DELETE FROM blockpolls WHERE guild_id = $1 AND global = true", guildID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
return true, true
|
||||
} else if global {
|
||||
_, err = db.Exec("DELETE FROM blockpolls WHERE guild_id = $1", guildID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
_, err := db.Exec("INSERT INTO blockpolls (guild_id, global, channel_id, allowed_role) VALUES ($1, true, $2, $3)", guildID, channelID, allowedRole)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
return false, true
|
||||
} else if exists && !globalexists {
|
||||
_, err := db.Exec("DELETE FROM blockpolls WHERE guild_id = $1 AND channel_id = $2", guildID, channelID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
return true, false
|
||||
} else if !globalexists {
|
||||
_, err := db.Exec("INSERT INTO blockpolls (guild_id, channel_id, allowed_role) VALUES ($1, $2, $3)", guildID, channelID, allowedRole)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
return false, false
|
||||
} else {
|
||||
return false, false
|
||||
}
|
||||
}
|
||||
|
||||
func listBlockPolls(guildID string) []BlockPoll {
|
||||
var list []BlockPoll
|
||||
rows, err := db.Query("SELECT channel_id, global, allowed_role FROM blockpolls WHERE guild_id = $1", guildID)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
for rows.Next() {
|
||||
var bp BlockPoll
|
||||
err := rows.Scan(&bp.ChannelID, &bp.Global, &bp.AllowedRole)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
list = append(list, bp)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
func getBlockPollsEnabled(guildID string, channelID string) (isEnabled bool, allowedRole string) {
|
||||
var enabled bool
|
||||
var v_allowedRole string
|
||||
err := db.QueryRow("SELECT EXISTS (SELECT 1 FROM blockpolls WHERE guild_id = $1 AND channel_id = $2)", guildID, channelID).Scan(&enabled)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
err = db.QueryRow("SELECT allowed_role FROM blockpolls WHERE guild_id = $1 AND channel_id = $2", guildID, channelID).Scan(&v_allowedRole)
|
||||
if err != nil && err.Error() != "sql: no rows in result set" {
|
||||
logrus.Error(err)
|
||||
}
|
||||
return enabled, v_allowedRole
|
||||
}
|
||||
|
||||
func tryDeleteUnusedMessage(messageID string) {
|
||||
_, err := db.Exec("DELETE FROM form_manage WHERE message_id = $1", messageID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func getAllSavedMessages() []MessageIDs {
|
||||
var savedMessages []MessageIDs
|
||||
rows, err := db.Query("SELECT message_id, channel_id FROM form_manage")
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return nil
|
||||
}
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var messageID, channelID string
|
||||
if err := rows.Scan(&messageID, &channelID); err != nil {
|
||||
logrus.Error(err)
|
||||
continue
|
||||
}
|
||||
savedMessages = append(savedMessages, MessageIDs{ID: messageID, ChannelID: channelID})
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
return savedMessages
|
||||
}
|
115
plugin_src/addemoji/main.go
Normal file
115
plugin_src/addemoji/main.go
Normal file
@@ -0,0 +1,115 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/disgoorg/disgo/discord"
|
||||
"github.com/disgoorg/disgo/events"
|
||||
"github.com/disgoorg/json"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vaporvee/acecore/shared"
|
||||
)
|
||||
|
||||
var Plugin = &shared.Plugin{
|
||||
Name: "Add Emoji",
|
||||
Commands: []shared.Command{
|
||||
{
|
||||
Definition: discord.SlashCommandCreate{
|
||||
Name: "add-emoji",
|
||||
Description: "Add an external emoji directly to the server.",
|
||||
DefaultMemberPermissions: json.NewNullablePtr(discord.PermissionManageGuildExpressions),
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
&discord.ApplicationCommandOptionString{
|
||||
Name: "emoji",
|
||||
Description: "The emoji you want to add",
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Interact: func(e *events.ApplicationCommandInteractionCreate) {
|
||||
emojiRegex := regexp.MustCompile(`<(.+):(\d+)>`)
|
||||
emojistring := emojiRegex.FindString(e.SlashCommandInteractionData().String("emoji"))
|
||||
emojiArray := strings.Split(emojistring, ":")
|
||||
var emojiName string
|
||||
var emojiID string
|
||||
var emojiFileName string
|
||||
if len(emojiArray) > 1 {
|
||||
emojiName = strings.TrimSuffix(emojiArray[1], ">")
|
||||
emojiID = strings.TrimSuffix(emojiArray[2], ">")
|
||||
}
|
||||
imageType, emojiReadBit64 := getEmoji(emojiID)
|
||||
emojiData, err := discord.NewIcon(imageType, emojiReadBit64)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
_, err = e.Client().Rest().CreateEmoji(*e.GuildID(), discord.EmojiCreate{
|
||||
Name: emojiName,
|
||||
Image: *emojiData,
|
||||
})
|
||||
if err != nil {
|
||||
if strings.HasPrefix(err.Error(), "50035") {
|
||||
e.CreateMessage(discord.NewMessageCreateBuilder().SetContent("Failed adding emoji. Did you provide a correct one?").SetEphemeral(true).Build())
|
||||
return
|
||||
}
|
||||
if strings.HasPrefix(err.Error(), "50138") {
|
||||
e.CreateMessage(discord.NewMessageCreateBuilder().SetContent("Failed adding emoji. Unable to resize the emoji image.").SetEphemeral(true).Build())
|
||||
return
|
||||
}
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
if imageType == discord.IconTypeGIF {
|
||||
emojiFileName = emojiName + ".gif"
|
||||
} else {
|
||||
emojiFileName = emojiName + ".png"
|
||||
}
|
||||
_, emojiRead := getEmoji(emojiID) // for some reason any []bit variable thats used with NewIcon gets corrupted even when its redeclared in a new variable
|
||||
err = e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContentf("Emoji %s sucessfully added to this server!", emojiName).SetFiles(discord.NewFile(emojiFileName, "", emojiRead)).SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func getEmoji(emojiID string) (discord.IconType, io.Reader) {
|
||||
resp, err := http.Get("https://cdn.discordapp.com/emojis/" + emojiID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return discord.IconTypePNG, nil
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
imageData, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return discord.IconTypePNG, nil
|
||||
}
|
||||
isAnimated := isGIFImage(imageData)
|
||||
if isAnimated {
|
||||
return discord.IconTypeGIF, bytes.NewReader(imageData)
|
||||
} else {
|
||||
return discord.IconTypePNG, bytes.NewReader(imageData)
|
||||
}
|
||||
}
|
||||
|
||||
func isGIFImage(imageData []byte) bool {
|
||||
if len(imageData) < 6 {
|
||||
return false
|
||||
}
|
||||
// Check for the GIF89a header at the beginning of the byte array
|
||||
if string(imageData[0:6]) == "GIF89a" {
|
||||
return true
|
||||
}
|
||||
// Check for the GIF87a header at the beginning of the byte array
|
||||
if string(imageData[0:6]) == "GIF87a" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
60
plugin_src/autojoinroles/data.go
Normal file
60
plugin_src/autojoinroles/data.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func setAutoJoinRole(guildID string, option string, roleID string) bool {
|
||||
var role_exists bool
|
||||
var autojoinroles_exists bool
|
||||
err := db.QueryRow("SELECT EXISTS (SELECT 1 FROM autojoinroles WHERE guild_id = $1)", guildID).Scan(&autojoinroles_exists)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
err = db.QueryRow("SELECT EXISTS (SELECT 1 FROM autojoinroles WHERE guild_id = $1 AND "+option+"_role IS NOT NULL AND "+option+"_role != '')", guildID).Scan(&role_exists)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
if autojoinroles_exists {
|
||||
_, err = db.Exec("UPDATE autojoinroles SET "+option+"_role = $1 WHERE guild_id = $2", roleID, guildID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
} else {
|
||||
_, err = db.Exec("INSERT INTO autojoinroles (guild_id, "+option+"_role) VALUES ($1, $2)", guildID, roleID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
return role_exists
|
||||
}
|
||||
|
||||
func purgeUnusedAutoJoinRoles(guildID string) {
|
||||
_, err := db.Exec("DELETE FROM autojoinroles WHERE guild_id = $1 AND user_role = '' OR user_role IS NULL AND bot_role = '' OR bot_role IS NULL", guildID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func getAutoJoinRole(guildID string, isBot bool) string {
|
||||
var isBotString string
|
||||
var role string
|
||||
if isBot {
|
||||
isBotString = "bot"
|
||||
} else {
|
||||
isBotString = "user"
|
||||
}
|
||||
var exists bool
|
||||
err := db.QueryRow("SELECT EXISTS (SELECT 1 FROM autojoinroles WHERE guild_id = $1)", guildID).Scan(&exists)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return role
|
||||
}
|
||||
if exists {
|
||||
err = db.QueryRow("SELECT "+isBotString+"_role FROM autojoinroles WHERE guild_id = $1", guildID).Scan(&role)
|
||||
if err != nil {
|
||||
logrus.Error(err, guildID)
|
||||
}
|
||||
}
|
||||
return role
|
||||
}
|
17
plugin_src/autojoinroles/listener.go
Normal file
17
plugin_src/autojoinroles/listener.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/disgoorg/disgo/events"
|
||||
"github.com/disgoorg/snowflake/v2"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func guildMemberJoin(e *events.GuildMemberJoin) {
|
||||
role := getAutoJoinRole(e.GuildID.String(), e.Member.User.Bot)
|
||||
if role != "" {
|
||||
err := e.Client().Rest().AddMemberRole(e.GuildID, e.Member.User.ID, snowflake.MustParse(role))
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
127
plugin_src/autojoinroles/main.go
Normal file
127
plugin_src/autojoinroles/main.go
Normal file
@@ -0,0 +1,127 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"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/sirupsen/logrus"
|
||||
"github.com/vaporvee/acecore/shared"
|
||||
)
|
||||
|
||||
var db *sql.DB
|
||||
|
||||
var dbCreateQuery string = `
|
||||
CREATE TABLE IF NOT EXISTS autojoinroles (
|
||||
guild_id TEXT NOT NULL,
|
||||
bot_role TEXT,
|
||||
user_role TEXT,
|
||||
PRIMARY KEY (guild_id)
|
||||
);
|
||||
`
|
||||
|
||||
var Plugin = &shared.Plugin{
|
||||
Name: "Auto Join Roles",
|
||||
Init: func(d *sql.DB) error {
|
||||
db = d
|
||||
_, err := d.Exec(dbCreateQuery)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
shared.BotConfigs = append(shared.BotConfigs, bot.WithEventListenerFunc(guildMemberJoin))
|
||||
return nil
|
||||
},
|
||||
Commands: []shared.Command{
|
||||
{
|
||||
Definition: discord.SlashCommandCreate{
|
||||
Name: "autojoinroles",
|
||||
Description: "Give users a role when they join",
|
||||
DefaultMemberPermissions: json.NewNullablePtr(discord.PermissionManageRoles),
|
||||
Contexts: []discord.InteractionContextType{
|
||||
discord.InteractionContextTypeGuild,
|
||||
discord.InteractionContextTypePrivateChannel},
|
||||
IntegrationTypes: []discord.ApplicationIntegrationType{
|
||||
discord.ApplicationIntegrationTypeGuildInstall},
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
&discord.ApplicationCommandOptionSubCommand{
|
||||
Name: "bot",
|
||||
Description: "Give bots a role when they join (Leave empty to remove current)",
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
&discord.ApplicationCommandOptionRole{
|
||||
Name: "role",
|
||||
Description: "The role bots should get when they join the server",
|
||||
},
|
||||
},
|
||||
},
|
||||
&discord.ApplicationCommandOptionSubCommand{
|
||||
Name: "user",
|
||||
Description: "Give users a role when they join (Leave empty to remove current)",
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
&discord.ApplicationCommandOptionRole{
|
||||
Name: "role",
|
||||
Description: "The role users should get when they join the server",
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
Interact: func(e *events.ApplicationCommandInteractionCreate) {
|
||||
var role string
|
||||
option := *e.SlashCommandInteractionData().SubCommandName
|
||||
var content string
|
||||
if len(e.SlashCommandInteractionData().Options) == 1 {
|
||||
var givenRole discord.Role = e.SlashCommandInteractionData().Role("role")
|
||||
role = givenRole.ID.String()
|
||||
botrole, err := getHighestRole(e.GuildID().String(), e.Client())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
if givenRole.Position >= botrole.Position {
|
||||
content = "<@&" + role + "> is not below the Bot's current highest role(<@&" + botrole.ID.String() + ">). That makes it unable to manage it."
|
||||
} else {
|
||||
if setAutoJoinRole(e.GuildID().String(), option, role) {
|
||||
content = "Updated auto join role for " + option + "s as <@&" + role + ">"
|
||||
} else {
|
||||
content = "Setup auto join role for " + option + "s as <@&" + role + ">"
|
||||
}
|
||||
}
|
||||
} else if setAutoJoinRole(e.GuildID().String(), option, role) {
|
||||
content = "Deleted auto join role for " + option + "s"
|
||||
}
|
||||
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 {
|
||||
logrus.Error(err)
|
||||
}
|
||||
purgeUnusedAutoJoinRoles(e.GuildID().String())
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func getHighestRole(guildID string, c bot.Client) (*discord.Role, error) {
|
||||
botmember, err := c.Rest().GetMember(snowflake.MustParse(guildID), c.ApplicationID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
roles, err := c.Rest().GetRoles(snowflake.MustParse(guildID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var highestRole *discord.Role
|
||||
for _, roleID := range botmember.RoleIDs {
|
||||
for _, role := range roles {
|
||||
if role.ID == roleID {
|
||||
if highestRole == nil || role.Position > highestRole.Position {
|
||||
highestRole = &role
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return highestRole, nil
|
||||
}
|
34
plugin_src/autopublish/data.go
Normal file
34
plugin_src/autopublish/data.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func toggleAutoPublish(guildID string, newsChannelID string) bool {
|
||||
var exists bool
|
||||
err := db.QueryRow("SELECT EXISTS (SELECT 1 FROM autopublish WHERE guild_id = $1 AND news_channel_id = $2)", guildID, newsChannelID).Scan(&exists)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
if exists {
|
||||
_, err := db.Exec("DELETE FROM autopublish WHERE guild_id = $1 AND news_channel_id = $2", guildID, newsChannelID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
} else {
|
||||
_, err := db.Exec("INSERT INTO autopublish (guild_id, news_channel_id) VALUES ($1, $2)", guildID, newsChannelID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
return exists
|
||||
}
|
||||
|
||||
func isAutopublishEnabled(guildID string, newsChannelID string) bool {
|
||||
var enabled bool
|
||||
err := db.QueryRow("SELECT EXISTS (SELECT 1 FROM autopublish WHERE guild_id = $1 AND news_channel_id = $2)", guildID, newsChannelID).Scan(&enabled)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
return enabled
|
||||
}
|
23
plugin_src/autopublish/listener.go
Normal file
23
plugin_src/autopublish/listener.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/disgoorg/disgo/discord"
|
||||
"github.com/disgoorg/disgo/events"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func messageCreate(e *events.MessageCreate) {
|
||||
channel, err := e.Client().Rest().GetChannel(e.Message.ChannelID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
if channel.Type() == discord.ChannelTypeGuildNews {
|
||||
if isAutopublishEnabled(e.GuildID.String(), e.ChannelID.String()) {
|
||||
_, err := e.Client().Rest().CrosspostMessage(e.ChannelID, e.MessageID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
76
plugin_src/autopublish/main.go
Normal file
76
plugin_src/autopublish/main.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"github.com/disgoorg/disgo/bot"
|
||||
"github.com/disgoorg/disgo/discord"
|
||||
"github.com/disgoorg/disgo/events"
|
||||
"github.com/disgoorg/json"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vaporvee/acecore/shared"
|
||||
)
|
||||
|
||||
var db *sql.DB
|
||||
|
||||
var dbCreateQuery string = `
|
||||
CREATE TABLE IF NOT EXISTS autopublish (
|
||||
guild_id TEXT NOT NULL,
|
||||
news_channel_id TEXT NOT NULL,
|
||||
PRIMARY KEY (guild_id, news_channel_id)
|
||||
);
|
||||
`
|
||||
|
||||
var Plugin = &shared.Plugin{
|
||||
Name: "Auto Publish",
|
||||
Init: func(d *sql.DB) error {
|
||||
db = d
|
||||
_, err := d.Exec(dbCreateQuery)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
shared.BotConfigs = append(shared.BotConfigs, bot.WithEventListenerFunc(messageCreate))
|
||||
return nil
|
||||
},
|
||||
Commands: []shared.Command{
|
||||
{
|
||||
Definition: discord.SlashCommandCreate{
|
||||
Name: "autopublish",
|
||||
Description: "Toggle automatically publishing every post in a announcement channel",
|
||||
DefaultMemberPermissions: json.NewNullablePtr(discord.PermissionManageChannels),
|
||||
Contexts: []discord.InteractionContextType{
|
||||
discord.InteractionContextTypeGuild,
|
||||
discord.InteractionContextTypePrivateChannel},
|
||||
IntegrationTypes: []discord.ApplicationIntegrationType{
|
||||
discord.ApplicationIntegrationTypeGuildInstall},
|
||||
},
|
||||
Interact: func(e *events.ApplicationCommandInteractionCreate) {
|
||||
channel := e.Channel()
|
||||
if channel.Type() == discord.ChannelTypeGuildNews {
|
||||
if toggleAutoPublish(e.GuildID().String(), e.Channel().ID().String()) {
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent("Autopublishing is now disabled on " + discord.ChannelMention(e.Channel().ID())).SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
} else {
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent("Autopublishing is now enabled on " + discord.ChannelMention(e.Channel().ID())).SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent("This is not an announcement channel!").SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
93
plugin_src/blockpolls/data.go
Normal file
93
plugin_src/blockpolls/data.go
Normal file
@@ -0,0 +1,93 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type BlockPoll struct {
|
||||
ChannelID string
|
||||
Global bool
|
||||
AllowedRole string
|
||||
}
|
||||
|
||||
func isGlobalBlockPolls(guildID string) bool {
|
||||
var globalexists bool
|
||||
err := db.QueryRow("SELECT EXISTS (SELECT 1 FROM blockpolls WHERE guild_id = $1 AND global = true)", guildID).Scan(&globalexists)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
return globalexists
|
||||
}
|
||||
|
||||
func toggleBlockPolls(guildID string, channelID string, global bool, allowedRole string) (e bool, isGlobal bool) {
|
||||
globalexists := isGlobalBlockPolls(guildID)
|
||||
var exists bool
|
||||
err := db.QueryRow("SELECT EXISTS (SELECT 1 FROM blockpolls WHERE guild_id = $1 AND channel_id = $2)", guildID, channelID).Scan(&exists)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
if globalexists {
|
||||
_, err := db.Exec("DELETE FROM blockpolls WHERE guild_id = $1 AND global = true", guildID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
return true, true
|
||||
} else if global {
|
||||
_, err = db.Exec("DELETE FROM blockpolls WHERE guild_id = $1", guildID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
_, err := db.Exec("INSERT INTO blockpolls (guild_id, global, channel_id, allowed_role) VALUES ($1, true, $2, $3)", guildID, channelID, allowedRole)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
return false, true
|
||||
} else if exists && !globalexists {
|
||||
_, err := db.Exec("DELETE FROM blockpolls WHERE guild_id = $1 AND channel_id = $2", guildID, channelID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
return true, false
|
||||
} else if !globalexists {
|
||||
_, err := db.Exec("INSERT INTO blockpolls (guild_id, channel_id, allowed_role) VALUES ($1, $2, $3)", guildID, channelID, allowedRole)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
return false, false
|
||||
} else {
|
||||
return false, false
|
||||
}
|
||||
}
|
||||
|
||||
func listBlockPolls(guildID string) []BlockPoll {
|
||||
var list []BlockPoll
|
||||
rows, err := db.Query("SELECT channel_id, global, allowed_role FROM blockpolls WHERE guild_id = $1", guildID)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
for rows.Next() {
|
||||
var bp BlockPoll
|
||||
err := rows.Scan(&bp.ChannelID, &bp.Global, &bp.AllowedRole)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
list = append(list, bp)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
func getBlockPollsEnabled(guildID string, channelID string) (isEnabled bool, allowedRole string) {
|
||||
var enabled bool
|
||||
var v_allowedRole string
|
||||
err := db.QueryRow("SELECT EXISTS (SELECT 1 FROM blockpolls WHERE guild_id = $1 AND channel_id = $2)", guildID, channelID).Scan(&enabled)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
err = db.QueryRow("SELECT allowed_role FROM blockpolls WHERE guild_id = $1 AND channel_id = $2", guildID, channelID).Scan(&v_allowedRole)
|
||||
if err != nil && err.Error() != "sql: no rows in result set" {
|
||||
logrus.Error(err)
|
||||
}
|
||||
return enabled, v_allowedRole
|
||||
}
|
27
plugin_src/blockpolls/listener.go
Normal file
27
plugin_src/blockpolls/listener.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"slices"
|
||||
|
||||
"github.com/disgoorg/disgo/events"
|
||||
"github.com/disgoorg/snowflake/v2"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func messageCreate(e *events.MessageCreate) {
|
||||
channel, err := e.Client().Rest().GetChannel(e.Message.ChannelID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
if channel != nil {
|
||||
isBlockPollsEnabledGlobal := isGlobalBlockPolls(e.GuildID.String())
|
||||
isBlockPollsEnabled, allowedRole := getBlockPollsEnabled(e.GuildID.String(), e.Message.ChannelID.String())
|
||||
var hasAllowedRole bool
|
||||
if allowedRole != "" {
|
||||
hasAllowedRole = slices.Contains(e.Message.Member.RoleIDs, snowflake.MustParse(allowedRole))
|
||||
}
|
||||
if (isBlockPollsEnabledGlobal || isBlockPollsEnabled) && !hasAllowedRole && messageIsPoll(e.Message.ChannelID.String(), e.Message.ID.String(), e.Client()) {
|
||||
e.Client().Rest().DeleteMessage(e.Message.ChannelID, e.Message.ID)
|
||||
}
|
||||
}
|
||||
}
|
156
plugin_src/blockpolls/main.go
Normal file
156
plugin_src/blockpolls/main.go
Normal file
@@ -0,0 +1,156 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/disgoorg/disgo/bot"
|
||||
"github.com/disgoorg/disgo/discord"
|
||||
"github.com/disgoorg/disgo/events"
|
||||
"github.com/disgoorg/disgo/rest"
|
||||
"github.com/disgoorg/json"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vaporvee/acecore/shared"
|
||||
)
|
||||
|
||||
var db *sql.DB
|
||||
|
||||
var dbCreateQuery string = `
|
||||
CREATE TABLE IF NOT EXISTS blockpolls (
|
||||
guild_id TEXT NOT NULL,
|
||||
channel_id TEXT,
|
||||
global BOOLEAN,
|
||||
allowed_role TEXT,
|
||||
PRIMARY KEY (guild_id)
|
||||
)
|
||||
`
|
||||
|
||||
var Plugin = &shared.Plugin{
|
||||
Name: "Block Polls",
|
||||
Init: func(d *sql.DB) error {
|
||||
db = d
|
||||
_, err := d.Exec(dbCreateQuery)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
shared.BotConfigs = append(shared.BotConfigs, bot.WithEventListenerFunc(messageCreate))
|
||||
return nil
|
||||
},
|
||||
Commands: []shared.Command{
|
||||
{
|
||||
Definition: discord.SlashCommandCreate{
|
||||
Name: "block-polls",
|
||||
Description: "Block polls from beeing posted in this channel.",
|
||||
DefaultMemberPermissions: json.NewNullablePtr(discord.PermissionManageChannels),
|
||||
Contexts: []discord.InteractionContextType{
|
||||
discord.InteractionContextTypeGuild,
|
||||
discord.InteractionContextTypePrivateChannel},
|
||||
IntegrationTypes: []discord.ApplicationIntegrationType{
|
||||
discord.ApplicationIntegrationTypeGuildInstall},
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
&discord.ApplicationCommandOptionSubCommand{
|
||||
Name: "toggle",
|
||||
Description: "Toggle blocking polls from beeing posted in this channel.",
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
&discord.ApplicationCommandOptionBool{
|
||||
Name: "global",
|
||||
Description: "If polls are blocked server wide or only in the current channel.",
|
||||
},
|
||||
&discord.ApplicationCommandOptionRole{
|
||||
Name: "allowed-role",
|
||||
Description: "The role that bypasses this block role.",
|
||||
},
|
||||
},
|
||||
},
|
||||
/*&discord.ApplicationCommandOptionSubCommand{
|
||||
Name: "list",
|
||||
Description: "List the current block polls rules for this server.",
|
||||
},*/
|
||||
},
|
||||
},
|
||||
Interact: func(e *events.ApplicationCommandInteractionCreate) {
|
||||
switch *e.SlashCommandInteractionData().SubCommandName {
|
||||
case "toggle":
|
||||
isGlobal := isGlobalBlockPolls(e.GuildID().String())
|
||||
if isGlobal && !e.SlashCommandInteractionData().Bool("global") {
|
||||
e.CreateMessage(discord.NewMessageCreateBuilder().SetContent("Polls are currently globally blocked. Disable global blocking to enable channel specific blocking.").SetEphemeral(true).Build())
|
||||
} else {
|
||||
exists, isGlobal := toggleBlockPolls(e.GuildID().String(), e.Channel().ID().String(), e.SlashCommandInteractionData().Bool("global"), e.SlashCommandInteractionData().Role("allowed-role").ID.String())
|
||||
if exists {
|
||||
if e.SlashCommandInteractionData().Bool("global") {
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent("Polls are now globally unblocked.").SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
} else {
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent("Polls are now unblocked in " + discord.ChannelMention(e.Channel().ID())).SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if isGlobal {
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent("Polls are now globally blocked.").SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
} else {
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent("Polls are now blocked in " + discord.ChannelMention(e.Channel().ID())).SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*case "list":
|
||||
list := listBlockPolls(e.GuildID().String())*/
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func messageIsPoll(channelID string, messageID string, client bot.Client) bool {
|
||||
url := rest.DefaultConfig().URL + "/channels/" + channelID + "/messages/" + messageID
|
||||
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return false
|
||||
}
|
||||
|
||||
auth := "Bot " + client.Token()
|
||||
req.Header.Set("Authorization", auth)
|
||||
|
||||
resp, err := client.Rest().HTTPClient().Do(req)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return false
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return false
|
||||
}
|
||||
|
||||
var data map[string]interface{}
|
||||
err = json.Unmarshal(body, &data)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return false
|
||||
}
|
||||
|
||||
_, ok := data["poll"]
|
||||
return ok
|
||||
}
|
154
plugin_src/forms/data.go
Normal file
154
plugin_src/forms/data.go
Normal file
@@ -0,0 +1,154 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/google/uuid"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type FormResult struct {
|
||||
OverwriteTitle string
|
||||
ResultChannelID string
|
||||
AcceptChannelID string
|
||||
CommentCategoryID string
|
||||
ModeratorID string
|
||||
}
|
||||
|
||||
type MessageIDs struct {
|
||||
ID string
|
||||
ChannelID string
|
||||
}
|
||||
|
||||
func getFormManageIdExists(id uuid.UUID) bool {
|
||||
var exists bool
|
||||
err := db.QueryRow("SELECT EXISTS (SELECT 1 FROM form_manage WHERE form_manage_id = $1)", id).Scan(&exists)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
return exists
|
||||
}
|
||||
|
||||
func addFormButton(guildID string, channelID string, messageID string, formManageID string, formType string, resultChannelID string, overwriteTitle string, acceptChannelID string, commentCategory string, moderator_id string) {
|
||||
_, err := db.Exec(
|
||||
`INSERT INTO form_manage (
|
||||
guild_id,
|
||||
form_manage_id,
|
||||
channel_id,
|
||||
message_id,
|
||||
form_type,
|
||||
result_channel_id,
|
||||
overwrite_title,
|
||||
accept_channel_id,
|
||||
comment_category,
|
||||
moderator_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`,
|
||||
guildID, formManageID, channelID, messageID, formType, resultChannelID, overwriteTitle, acceptChannelID, commentCategory, moderator_id)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func getFormManageIDs() []string {
|
||||
if db == nil {
|
||||
return nil
|
||||
}
|
||||
var IDs []string
|
||||
rows, err := db.Query("SELECT form_manage_id FROM form_manage")
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return nil
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var id string
|
||||
if err := rows.Scan(&id); err != nil {
|
||||
logrus.Error(err)
|
||||
return nil
|
||||
}
|
||||
IDs = append(IDs, id)
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
logrus.Error(err)
|
||||
return nil
|
||||
}
|
||||
return IDs
|
||||
}
|
||||
|
||||
func getFormType(formManageID string) string {
|
||||
var formType string
|
||||
err := db.QueryRow("SELECT form_type FROM form_manage WHERE form_manage_id = $1", formManageID).Scan(&formType)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
return formType
|
||||
}
|
||||
|
||||
func getFormResultValues(formManageID string) FormResult {
|
||||
var result FormResult
|
||||
err := db.QueryRow("SELECT overwrite_title FROM form_manage WHERE form_manage_id = $1", formManageID).Scan(&result.OverwriteTitle)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
err = db.QueryRow("SELECT result_channel_id FROM form_manage WHERE form_manage_id = $1", formManageID).Scan(&result.ResultChannelID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
err = db.QueryRow("SELECT accept_channel_id FROM form_manage WHERE form_manage_id = $1", formManageID).Scan(&result.AcceptChannelID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
err = db.QueryRow("SELECT comment_category FROM form_manage WHERE form_manage_id = $1", formManageID).Scan(&result.CommentCategoryID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
err = db.QueryRow("SELECT moderator_id FROM form_manage WHERE form_manage_id = $1", formManageID).Scan(&result.ModeratorID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func getFormOverwriteTitle(formManageID string) string {
|
||||
var overwriteTitle string
|
||||
err := db.QueryRow("SELECT overwrite_title FROM form_manage WHERE form_manage_id = $1", formManageID).Scan(&overwriteTitle)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
return overwriteTitle
|
||||
}
|
||||
|
||||
func updateFormCommentCategory(formManageID string, comment_category string) {
|
||||
_, err := db.Exec("UPDATE form_manage SET comment_category = $1 WHERE form_manage_id = $2", comment_category, formManageID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func tryDeleteUnusedMessage(messageID string) {
|
||||
_, err := db.Exec("DELETE FROM form_manage WHERE message_id = $1", messageID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func getAllSavedMessages() []MessageIDs {
|
||||
var savedMessages []MessageIDs
|
||||
rows, err := db.Query("SELECT message_id, channel_id FROM form_manage")
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return nil
|
||||
}
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var messageID, channelID string
|
||||
if err := rows.Scan(&messageID, &channelID); err != nil {
|
||||
logrus.Error(err)
|
||||
continue
|
||||
}
|
||||
savedMessages = append(savedMessages, MessageIDs{ID: messageID, ChannelID: channelID})
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
return savedMessages
|
||||
}
|
515
plugin_src/forms/main.go
Normal file
515
plugin_src/forms/main.go
Normal file
@@ -0,0 +1,515 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"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/sirupsen/logrus"
|
||||
"github.com/vaporvee/acecore/custom"
|
||||
"github.com/vaporvee/acecore/shared"
|
||||
)
|
||||
|
||||
var db *sql.DB
|
||||
|
||||
var dbCreateQuery string = `
|
||||
CREATE TABLE IF NOT EXISTS custom_forms (
|
||||
form_type TEXT NOT NULL,
|
||||
title TEXT NOT NULL,
|
||||
json JSON NOT NULL,
|
||||
guild_id TEXT NOT NULL,
|
||||
PRIMARY KEY (form_type, guild_id)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS form_manage (
|
||||
form_manage_id TEXT NOT NULL,
|
||||
form_type TEXT NOT NULL,
|
||||
overwrite_title TEXT,
|
||||
message_id TEXT NOT NULL,
|
||||
channel_id TEXT NOT NULL,
|
||||
guild_id TEXT NOT NULL,
|
||||
result_channel_id TEXT NOT NULL,
|
||||
accept_channel_id TEXT,
|
||||
comment_category TEXT,
|
||||
moderator_id TEXT,
|
||||
PRIMARY KEY (form_manage_id, form_type)
|
||||
);
|
||||
`
|
||||
|
||||
var Plugin = &shared.Plugin{
|
||||
Name: "Forms",
|
||||
Init: func(d *sql.DB) error {
|
||||
db = d
|
||||
_, err := d.Exec(dbCreateQuery)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
shared.BotConfigs = append(shared.BotConfigs,
|
||||
bot.WithEventListenerFunc(func(e *events.MessageCreate) { tryDeleteUnusedMessage(e.MessageID.String()) }),
|
||||
bot.WithEventListenerFunc(func(e *events.Ready) { findAndDeleteUnusedMessages(e.Client()) }))
|
||||
return nil
|
||||
},
|
||||
Commands: []shared.Command{
|
||||
{
|
||||
Definition: discord.SlashCommandCreate{
|
||||
Name: "form",
|
||||
DefaultMemberPermissions: json.NewNullablePtr(discord.PermissionManageChannels),
|
||||
Description: "Create custom forms right inside Discord",
|
||||
Contexts: []discord.InteractionContextType{
|
||||
discord.InteractionContextTypeGuild,
|
||||
discord.InteractionContextTypePrivateChannel},
|
||||
IntegrationTypes: []discord.ApplicationIntegrationType{
|
||||
discord.ApplicationIntegrationTypeGuildInstall},
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
&discord.ApplicationCommandOptionSubCommand{
|
||||
Name: "help",
|
||||
Description: "Gives you an example file and demo for creating custom forms",
|
||||
},
|
||||
&discord.ApplicationCommandOptionSubCommand{
|
||||
Name: "custom",
|
||||
Description: "Create a new custom form right inside Discord",
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
&discord.ApplicationCommandOptionAttachment{
|
||||
Name: "json",
|
||||
Description: "Your edited form file",
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
&discord.ApplicationCommandOptionSubCommand{
|
||||
Name: "add",
|
||||
Description: "Adds existing forms to this channel",
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
&discord.ApplicationCommandOptionChannel{
|
||||
Name: "result_channel",
|
||||
Description: "Where the form results should appear",
|
||||
ChannelTypes: []discord.ChannelType{discord.ChannelTypeGuildText},
|
||||
},
|
||||
&discord.ApplicationCommandOptionMentionable{
|
||||
Name: "moderator",
|
||||
Description: "Who can interact with moderating buttons.",
|
||||
},
|
||||
&discord.ApplicationCommandOptionString{
|
||||
Name: "type",
|
||||
Description: "Which type of form you want to add",
|
||||
Autocomplete: true,
|
||||
},
|
||||
&discord.ApplicationCommandOptionString{
|
||||
Name: "title",
|
||||
Description: "The title the form should have",
|
||||
},
|
||||
&discord.ApplicationCommandOptionChannel{
|
||||
Name: "approve_channel",
|
||||
Description: "Channel for results that need to be accepted by a moderator before sending it to the result channel",
|
||||
ChannelTypes: []discord.ChannelType{discord.ChannelTypeGuildText},
|
||||
},
|
||||
&discord.ApplicationCommandOptionBool{
|
||||
Name: "mods_can_answer",
|
||||
Description: "Moderators can open a new channel on the form result, which then pings the user who submitted it",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Interact: func(e *events.ApplicationCommandInteractionCreate) {
|
||||
switch *e.SlashCommandInteractionData().SubCommandName {
|
||||
case "help":
|
||||
fileData, err := shared.FormTemplates.ReadFile("form_templates/form_demo.json")
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
fileReader := bytes.NewReader(fileData)
|
||||
err = e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
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.").
|
||||
SetFiles(discord.NewFile("example.json", "json", fileReader)).
|
||||
SetContainerComponents(discord.ActionRowComponent{discord.NewPrimaryButton("Demo", "form_demo").WithEmoji(discord.ComponentEmoji{Name: "📑"})}).SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
case "custom":
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent("Feature not available yet use `/form add` instead").SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
case "add":
|
||||
var title, formID, overwriteTitle, acceptChannelID string
|
||||
var modsCanAnswer bool
|
||||
var resultChannelID string
|
||||
data := e.SlashCommandInteractionData()
|
||||
if data.Channel("result_channel").ID.String() != "0" {
|
||||
resultChannelID = data.Channel("result_channel").ID.String()
|
||||
}
|
||||
moderator := data.Role("moderator").ID.String()
|
||||
if moderator == "0" {
|
||||
moderator = e.User().ID.String()
|
||||
}
|
||||
formID = data.String("type")
|
||||
overwriteTitle = data.String("title")
|
||||
if overwriteTitle != "" {
|
||||
title = overwriteTitle
|
||||
}
|
||||
if data.Channel("approve_channel").ID.String() != "0" {
|
||||
acceptChannelID = data.Channel("approve_channel").ID.String()
|
||||
}
|
||||
modsCanAnswer = data.Bool("mods_can_answer")
|
||||
|
||||
if formID == "" {
|
||||
formID = "template_general"
|
||||
}
|
||||
if title == "" {
|
||||
formTitles := map[string]string{
|
||||
"template_ticket": "Make a new ticket",
|
||||
"template_url": "Add your URL",
|
||||
"template_general": "Form",
|
||||
}
|
||||
if val, ok := formTitles[formID]; ok {
|
||||
title = val
|
||||
}
|
||||
}
|
||||
var exists bool = true
|
||||
var formManageID uuid.UUID = uuid.New()
|
||||
for exists {
|
||||
formManageID = uuid.New()
|
||||
exists = getFormManageIdExists(formManageID)
|
||||
}
|
||||
messagebuild := discord.NewMessageCreateBuilder().SetEmbeds(discord.NewEmbedBuilder().
|
||||
SetTitle(title).SetDescription("Press the bottom button to open a form popup.").SetColor(custom.GetColor("primary")).
|
||||
Build()).SetContainerComponents(discord.ActionRowComponent{
|
||||
discord.NewSuccessButton("Submit", "form:"+formManageID.String()).WithEmoji(discord.ComponentEmoji{
|
||||
Name: "anim_rocket",
|
||||
ID: snowflake.MustParse("1215740398706757743"),
|
||||
Animated: true,
|
||||
})}).
|
||||
Build()
|
||||
message, err := e.Client().Rest().CreateMessage(e.Channel().ID(), messagebuild)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
var category string
|
||||
if modsCanAnswer {
|
||||
c, err := e.Client().Rest().CreateGuildChannel(*e.GuildID(), discord.GuildCategoryChannelCreate{Name: title + " mod answers"})
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
category = c.ID().String()
|
||||
}
|
||||
|
||||
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 {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
},
|
||||
DynamicComponentIDs: func() []string { return getFormButtonIDs() },
|
||||
DynamicModalIDs: func() []string { return getFormButtonIDs() },
|
||||
ComponentInteract: func(e *events.ComponentInteractionCreate) {
|
||||
if e.Data.Type() == discord.ComponentTypeButton {
|
||||
if strings.ContainsAny(e.ButtonInteractionData().CustomID(), ";") {
|
||||
var form_manage_id string = strings.TrimPrefix(strings.Split(e.ButtonInteractionData().CustomID(), ";")[0], "form:")
|
||||
switch strings.Split(e.ButtonInteractionData().CustomID(), ";")[1] {
|
||||
case "decline":
|
||||
err := e.Client().Rest().DeleteMessage(e.Channel().ID(), e.Message.ID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
e.CreateMessage(discord.NewMessageCreateBuilder().SetContent("Submission declined!").SetEphemeral(true).Build())
|
||||
case "approve":
|
||||
embed := e.Message.Embeds[0]
|
||||
embed.Description = fmt.Sprintf("This submission was approved by <@%s>.", e.User().ID)
|
||||
_, err := e.Client().Rest().CreateMessage(snowflake.MustParse(getFormResultValues(form_manage_id).ResultChannelID), discord.NewMessageCreateBuilder().
|
||||
SetEmbeds(embed).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
e.CreateMessage(discord.NewMessageCreateBuilder().SetContent("Submission accepted!").SetEphemeral(true).Build())
|
||||
err = e.Client().Rest().DeleteMessage(e.Channel().ID(), e.Message.ID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
case "comment":
|
||||
author := strings.TrimSuffix(strings.Split(e.Message.Embeds[0].Fields[len(e.Message.Embeds[0].Fields)-1].Value, "<@")[1], ">")
|
||||
embed := e.Message.Embeds[0]
|
||||
moderator := e.User().ID
|
||||
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 {
|
||||
if strings.HasPrefix(e.ButtonInteractionData().CustomID(), "form:") {
|
||||
var formManageID string = strings.TrimPrefix(e.ButtonInteractionData().CustomID(), "form:")
|
||||
e.Modal(shared.JsonStringBuildModal(e.User().ID.String(), formManageID, getFormType(formManageID), getFormOverwriteTitle(formManageID)))
|
||||
} else if e.ButtonInteractionData().CustomID() == "form_demo" {
|
||||
e.Modal(shared.JsonStringBuildModal(e.User().ID.String(), "form_demo", "form_demo"))
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
ModalSubmit: func(e *events.ModalSubmitInteractionCreate) {
|
||||
if !strings.HasPrefix(e.Data.CustomID, "form_demo") {
|
||||
var form_manage_id string = strings.Split(e.Data.CustomID, ":")[1]
|
||||
var result FormResult = getFormResultValues(form_manage_id)
|
||||
var fields []discord.EmbedField
|
||||
var modal shared.ModalJson = shared.GetModalByFormID(getFormType(form_manage_id))
|
||||
var overwrite_title string = getFormOverwriteTitle(form_manage_id)
|
||||
if overwrite_title != "" {
|
||||
modal.Title = overwrite_title
|
||||
}
|
||||
var inline bool
|
||||
var index int = 0
|
||||
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,
|
||||
Value: input.Value,
|
||||
Inline: &inline,
|
||||
})
|
||||
index++
|
||||
}
|
||||
|
||||
fields = append(fields, discord.EmbedField{
|
||||
Value: "From <#" + e.Channel().ID().String() + "> by " + e.User().Mention(),
|
||||
})
|
||||
if result.ResultChannelID == "" {
|
||||
if result.CommentCategoryID != "" {
|
||||
channel := createFormComment(form_manage_id, e.User().ID, snowflake.MustParse(result.ModeratorID), "answer", discord.NewEmbedBuilder().
|
||||
SetAuthorName(*e.User().GlobalName).SetAuthorIcon(*e.User().AvatarURL()).SetTitle("\""+modal.Title+"\"").SetDescription("This is the submitted result").
|
||||
SetColor(custom.GetColor("primary")).SetFields(fields...).
|
||||
Build(), *e.GuildID(), e.Client())
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().SetContent("Created channel " + discord.ChannelMention(channel.ID())).SetEphemeral(true).Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
} 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 {
|
||||
if result.AcceptChannelID == "" {
|
||||
_, 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(custom.GetColor("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 {
|
||||
var buttons []discord.InteractiveComponent
|
||||
if result.CommentCategoryID != "" {
|
||||
buttons = []discord.InteractiveComponent{discord.
|
||||
NewButton(discord.ButtonStylePrimary, "Comment", "form:"+form_manage_id+";comment", "").
|
||||
WithEmoji(discord.ComponentEmoji{Name: "👥"})}
|
||||
}
|
||||
buttons = append(buttons, discord.
|
||||
NewButton(discord.ButtonStyleDanger, "Decline", "form:"+form_manage_id+";decline", "").
|
||||
WithEmoji(discord.ComponentEmoji{Name: "🛑"}),
|
||||
discord.
|
||||
NewButton(discord.ButtonStyleSuccess, "Approve", "form:"+form_manage_id+";approve", "").
|
||||
WithEmoji(discord.ComponentEmoji{Name: "🎉"}))
|
||||
_, err := e.Client().Rest().CreateMessage(snowflake.MustParse(result.AcceptChannelID), discord.NewMessageCreateBuilder().
|
||||
SetEmbeds(discord.NewEmbedBuilder().
|
||||
SetAuthorName(*e.User().GlobalName).SetAuthorIcon(*e.User().AvatarURL()).SetTitle("\""+modal.Title+"\"").SetDescription("**This submission needs approval.**").
|
||||
SetColor(custom.GetColor("primary")).SetFields(fields...).
|
||||
Build()).
|
||||
SetContainerComponents(discord.NewActionRow(buttons...)).
|
||||
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 {
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().SetContent("The results would be submited...").SetEphemeral(true).Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
Autocomplete: func(e *events.AutocompleteInteractionCreate) {
|
||||
err := e.AutocompleteResult([]discord.AutocompleteChoice{
|
||||
&discord.AutocompleteChoiceString{
|
||||
Name: "Support Ticket",
|
||||
Value: "template_ticket",
|
||||
},
|
||||
&discord.AutocompleteChoiceString{
|
||||
Name: "Submit URL",
|
||||
Value: "template_url",
|
||||
},
|
||||
&discord.AutocompleteChoiceString{
|
||||
Name: "General",
|
||||
Value: "template_general",
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
Definition: discord.SlashCommandCreate{
|
||||
Name: "ticket",
|
||||
DefaultMemberPermissions: json.NewNullablePtr(discord.PermissionManageChannels),
|
||||
Description: "A quick command to create Ticketpanels. (/form for more)",
|
||||
Contexts: []discord.InteractionContextType{
|
||||
discord.InteractionContextTypeGuild,
|
||||
discord.InteractionContextTypePrivateChannel},
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
&discord.ApplicationCommandOptionString{
|
||||
Name: "title",
|
||||
Description: "The title the ticket should have",
|
||||
},
|
||||
&discord.ApplicationCommandOptionMentionable{
|
||||
Name: "moderator",
|
||||
Description: "Who can interact with moderating buttons.",
|
||||
},
|
||||
},
|
||||
},
|
||||
Interact: func(e *events.ApplicationCommandInteractionCreate) {
|
||||
var title string = "Ticket"
|
||||
var moderator string
|
||||
data := e.SlashCommandInteractionData()
|
||||
if data.String("title") != "" {
|
||||
title = data.String("title")
|
||||
}
|
||||
moderator = data.Role("moderator").ID.String()
|
||||
if moderator == "" {
|
||||
moderator = data.User("moderator").ID.String()
|
||||
}
|
||||
var exists bool = true
|
||||
var formManageID uuid.UUID = uuid.New()
|
||||
for exists {
|
||||
formManageID = uuid.New()
|
||||
exists = getFormManageIdExists(formManageID)
|
||||
}
|
||||
messagebuild := discord.NewMessageCreateBuilder().SetEmbeds(discord.NewEmbedBuilder().
|
||||
SetTitle(title).SetDescription("Press the bottom button to open a form popup.").SetColor(custom.GetColor("primary")).
|
||||
Build()).SetContainerComponents(discord.ActionRowComponent{
|
||||
discord.NewSuccessButton("Submit", "form:"+formManageID.String()).WithEmoji(discord.ComponentEmoji{
|
||||
Name: "anim_rocket",
|
||||
ID: snowflake.MustParse("1215740398706757743"),
|
||||
Animated: true,
|
||||
})}).
|
||||
Build()
|
||||
message, err := e.Client().Rest().CreateMessage(e.Channel().ID(), messagebuild)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
if title == "" {
|
||||
title = "Ticket"
|
||||
}
|
||||
var category string
|
||||
c, err := e.Client().Rest().CreateGuildChannel(*e.GuildID(), discord.GuildCategoryChannelCreate{Name: title + " mod answers"})
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
category = c.ID().String()
|
||||
if title == "Ticket" {
|
||||
title = ""
|
||||
}
|
||||
|
||||
addFormButton(e.GuildID().String(), e.Channel().ID().String(), message.ID.String(), formManageID.String(), "template_ticket", "", title, "", category, moderator)
|
||||
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 {
|
||||
logrus.Error(err)
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// moderator can be userID as well as roleID
|
||||
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 {
|
||||
var category snowflake.ID = snowflake.MustParse(getFormResultValues(form_manage_id).CommentCategoryID)
|
||||
_, err := client.Rest().GetChannel(category)
|
||||
if err != nil {
|
||||
c, err := client.Rest().CreateGuildChannel(guildID, discord.GuildCategoryChannelCreate{Name: strings.Trim(embed.Title, "\"") + " mod " + commentName + "s"})
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
category = c.ID()
|
||||
updateFormCommentCategory(form_manage_id, category.String())
|
||||
}
|
||||
ch, err := client.Rest().CreateGuildChannel(guildID, discord.GuildTextChannelCreate{
|
||||
ParentID: category,
|
||||
Name: strings.ToLower(embed.Author.Name) + "-" + commentName,
|
||||
})
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
var permissionOverwrites []discord.PermissionOverwrite = []discord.PermissionOverwrite{
|
||||
discord.RolePermissionOverwrite{
|
||||
RoleID: guildID,
|
||||
Deny: discord.PermissionViewChannel,
|
||||
}}
|
||||
|
||||
if shared.IsIDRole(client, guildID, moderator) {
|
||||
permissionOverwrites = append(permissionOverwrites, discord.RolePermissionOverwrite{
|
||||
RoleID: moderator,
|
||||
Allow: discord.PermissionViewChannel,
|
||||
})
|
||||
} 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 {
|
||||
logrus.Error(err)
|
||||
}
|
||||
modTypeChar := ""
|
||||
if shared.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 {
|
||||
var IDs []string = []string{"form_demo"}
|
||||
var formButtonIDs []string = getFormManageIDs()
|
||||
for _, buttonID := range formButtonIDs {
|
||||
IDs = append(IDs, "form:"+buttonID)
|
||||
}
|
||||
return IDs
|
||||
}
|
15
plugin_src/forms/tool.go
Normal file
15
plugin_src/forms/tool.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/disgoorg/disgo/bot"
|
||||
"github.com/disgoorg/snowflake/v2"
|
||||
)
|
||||
|
||||
func findAndDeleteUnusedMessages(c bot.Client) {
|
||||
for _, message := range getAllSavedMessages() {
|
||||
_, err := c.Rest().GetMessage(snowflake.MustParse(message.ChannelID), snowflake.MustParse(message.ID))
|
||||
if err != nil {
|
||||
tryDeleteUnusedMessage(message.ID)
|
||||
}
|
||||
}
|
||||
}
|
@@ -3,12 +3,12 @@ package main
|
||||
import (
|
||||
"github.com/disgoorg/disgo/discord"
|
||||
"github.com/disgoorg/disgo/events"
|
||||
"github.com/vaporvee/acecore/cmd"
|
||||
"github.com/vaporvee/acecore/shared"
|
||||
)
|
||||
|
||||
var Plugin = &cmd.Plugin{
|
||||
var Plugin = &shared.Plugin{
|
||||
Name: "Info",
|
||||
Commands: []cmd.Command{
|
||||
Commands: []shared.Command{
|
||||
{
|
||||
Definition: discord.SlashCommandCreate{
|
||||
Name: "info",
|
||||
|
@@ -4,11 +4,11 @@ import (
|
||||
"github.com/disgoorg/disgo/discord"
|
||||
"github.com/disgoorg/disgo/events"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vaporvee/acecore/cmd"
|
||||
"github.com/vaporvee/acecore/custom"
|
||||
"github.com/vaporvee/acecore/shared"
|
||||
)
|
||||
|
||||
var cmd_ask = cmd.Command{
|
||||
var cmd_ask = shared.Command{
|
||||
Definition: discord.SlashCommandCreate{
|
||||
Name: "ask",
|
||||
Description: "Ask anything and get a gif as response!",
|
||||
|
@@ -8,11 +8,11 @@ import (
|
||||
"github.com/disgoorg/disgo/discord"
|
||||
"github.com/disgoorg/disgo/events"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vaporvee/acecore/cmd"
|
||||
"github.com/vaporvee/acecore/custom"
|
||||
"github.com/vaporvee/acecore/shared"
|
||||
)
|
||||
|
||||
var cmd_cat = cmd.Command{
|
||||
var cmd_cat = shared.Command{
|
||||
Definition: discord.SlashCommandCreate{
|
||||
Name: "cat",
|
||||
Description: "Random cat pictures",
|
||||
|
@@ -4,10 +4,10 @@ import (
|
||||
"github.com/disgoorg/disgo/discord"
|
||||
"github.com/disgoorg/disgo/events"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vaporvee/acecore/cmd"
|
||||
"github.com/vaporvee/acecore/shared"
|
||||
)
|
||||
|
||||
var cmd_dadjoke = cmd.Command{
|
||||
var cmd_dadjoke = shared.Command{
|
||||
Definition: discord.SlashCommandCreate{
|
||||
Name: "dadjoke",
|
||||
Description: "Gives you a random joke that is as bad as your dad would tell them",
|
||||
|
@@ -1,20 +0,0 @@
|
||||
module github.com/vaporvee/acecore/simplefun
|
||||
|
||||
go 1.22.1
|
||||
|
||||
require (
|
||||
github.com/disgoorg/disgo v0.18.2
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/vaporvee/acecore v0.0.0-20240414202630-d814d39cf135
|
||||
github.com/vaporvee/acecore/cmd v0.0.0-20240414202630-d814d39cf135
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/disgoorg/json v1.1.0 // indirect
|
||||
github.com/disgoorg/snowflake/v2 v2.0.1 // indirect
|
||||
github.com/gorilla/websocket v1.5.1 // indirect
|
||||
github.com/sasha-s/go-csync v0.0.0-20240107134140-fcbab37b09ad // 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
|
||||
)
|
@@ -1,10 +1,40 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/vaporvee/acecore/cmd"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vaporvee/acecore/shared"
|
||||
)
|
||||
|
||||
var Plugin = &cmd.Plugin{
|
||||
var Plugin = &shared.Plugin{
|
||||
Name: "Simple Fun",
|
||||
Commands: []cmd.Command{cmd_ask, cmd_cat, cmd_dadjoke},
|
||||
Commands: []shared.Command{cmd_ask, cmd_cat, cmd_dadjoke},
|
||||
}
|
||||
|
||||
func simpleGetFromAPI(key string, url string) interface{} {
|
||||
client := &http.Client{}
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
logrus.Error("Error creating request:", err)
|
||||
}
|
||||
req.Header.Set("Accept", "application/json")
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
logrus.Error("Error making request:", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
logrus.Error("Error reading response body:", err)
|
||||
}
|
||||
|
||||
var result map[string]interface{}
|
||||
err = json.Unmarshal(body, &result)
|
||||
if err != nil {
|
||||
logrus.Error("Error decoding JSON:", err)
|
||||
}
|
||||
return result[key]
|
||||
}
|
||||
|
@@ -1,34 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func simpleGetFromAPI(key string, url string) interface{} {
|
||||
client := &http.Client{}
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
logrus.Error("Error creating request:", err)
|
||||
}
|
||||
req.Header.Set("Accept", "application/json")
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
logrus.Error("Error making request:", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
logrus.Error("Error reading response body:", err)
|
||||
}
|
||||
|
||||
var result map[string]interface{}
|
||||
err = json.Unmarshal(body, &result)
|
||||
if err != nil {
|
||||
logrus.Error("Error decoding JSON:", err)
|
||||
}
|
||||
return result[key]
|
||||
}
|
62
plugin_src/stickymessages/data.go
Normal file
62
plugin_src/stickymessages/data.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func addSticky(guildID string, channelID string, messageContent string, messageID string) {
|
||||
_, err := db.Exec("INSERT INTO sticky (guild_id, channel_id, message_id, message_content) VALUES ($1, $2, $3, $4)", guildID, channelID, messageID, messageContent)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func hasSticky(guildID string, channelID string) bool {
|
||||
var exists bool
|
||||
err := db.QueryRow("SELECT EXISTS (SELECT 1 FROM sticky WHERE guild_id = $1 AND channel_id = $2)", guildID, channelID).Scan(&exists)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
return exists
|
||||
}
|
||||
|
||||
func getStickyMessageID(guildID string, channelID string) string {
|
||||
var messageID string
|
||||
exists := hasSticky(guildID, channelID)
|
||||
if exists {
|
||||
err := db.QueryRow("SELECT message_id FROM sticky WHERE guild_id = $1 AND channel_id = $2", guildID, channelID).Scan(&messageID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
return messageID
|
||||
}
|
||||
func getStickyMessageContent(guildID string, channelID string) string {
|
||||
var messageID string
|
||||
exists := hasSticky(guildID, channelID)
|
||||
if exists {
|
||||
err := db.QueryRow("SELECT message_content FROM sticky WHERE guild_id = $1 AND channel_id = $2", guildID, channelID).Scan(&messageID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
return messageID
|
||||
}
|
||||
|
||||
func updateStickyMessageID(guildID string, channelID string, messageID string) {
|
||||
exists := hasSticky(guildID, channelID)
|
||||
if exists {
|
||||
_, err := db.Exec("UPDATE sticky SET message_id = $1 WHERE guild_id = $2 AND channel_id = $3", messageID, guildID, channelID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func removeSticky(guildID string, channelID string) {
|
||||
_, err := db.Exec("DELETE FROM sticky WHERE guild_id = $1 AND channel_id = $2", guildID, channelID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
33
plugin_src/stickymessages/listener.go
Normal file
33
plugin_src/stickymessages/listener.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/disgoorg/disgo/discord"
|
||||
"github.com/disgoorg/disgo/events"
|
||||
"github.com/disgoorg/snowflake/v2"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vaporvee/acecore/custom"
|
||||
)
|
||||
|
||||
func messageCreate(e *events.MessageCreate) {
|
||||
if len(e.Message.Embeds) == 0 || e.Message.Embeds[0].Footer == nil || e.Message.Embeds[0].Footer.Text != "📌 Sticky message" {
|
||||
if hasSticky(e.Message.GuildID.String(), e.Message.ChannelID.String()) {
|
||||
stickymessageID := getStickyMessageID(e.Message.GuildID.String(), e.Message.ChannelID.String())
|
||||
err := e.Client().Rest().DeleteMessage(e.ChannelID, snowflake.MustParse(stickymessageID))
|
||||
stickyMessage, _ := e.Client().Rest().CreateMessage(e.ChannelID, discord.MessageCreate{
|
||||
Embeds: []discord.Embed{
|
||||
{
|
||||
Footer: &discord.EmbedFooter{
|
||||
Text: "📌 Sticky message",
|
||||
},
|
||||
Color: custom.GetColor("primary"),
|
||||
Description: getStickyMessageContent(e.Message.GuildID.String(), e.Message.ChannelID.String()),
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
updateStickyMessageID(e.Message.GuildID.String(), e.Message.ChannelID.String(), stickyMessage.ID.String())
|
||||
}
|
||||
}
|
||||
}
|
145
plugin_src/stickymessages/main.go
Normal file
145
plugin_src/stickymessages/main.go
Normal file
@@ -0,0 +1,145 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"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/sirupsen/logrus"
|
||||
"github.com/vaporvee/acecore/custom"
|
||||
"github.com/vaporvee/acecore/shared"
|
||||
)
|
||||
|
||||
var db *sql.DB
|
||||
|
||||
var dbCreateQuery string = `CREATE TABLE IF NOT EXISTS sticky (
|
||||
message_id TEXT NOT NULL,
|
||||
channel_id TEXT NOT NULL,
|
||||
message_content TEXT NOT NULL,
|
||||
guild_id TEXT NOT NULL,
|
||||
PRIMARY KEY (channel_id, guild_id)
|
||||
);
|
||||
`
|
||||
|
||||
var Plugin = &shared.Plugin{
|
||||
Name: "Sticky Messages",
|
||||
Init: func(d *sql.DB) error {
|
||||
db = d
|
||||
_, err := d.Exec(dbCreateQuery)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
shared.BotConfigs = append(shared.BotConfigs, bot.WithEventListenerFunc(messageCreate))
|
||||
return nil
|
||||
},
|
||||
Commands: []shared.Command{
|
||||
{
|
||||
Definition: discord.SlashCommandCreate{
|
||||
Name: "sticky",
|
||||
Description: "Stick or unstick messages to the bottom of the current channel",
|
||||
DefaultMemberPermissions: json.NewNullablePtr(discord.PermissionManageMessages),
|
||||
Contexts: []discord.InteractionContextType{
|
||||
discord.InteractionContextTypeGuild,
|
||||
discord.InteractionContextTypePrivateChannel},
|
||||
IntegrationTypes: []discord.ApplicationIntegrationType{
|
||||
discord.ApplicationIntegrationTypeGuildInstall},
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
&discord.ApplicationCommandOptionString{
|
||||
Name: "message",
|
||||
Description: "The message you want to stick to the bottom of this channel",
|
||||
Required: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
Interact: func(e *events.ApplicationCommandInteractionCreate) {
|
||||
if len(e.SlashCommandInteractionData().Options) == 0 {
|
||||
if hasSticky(e.GuildID().String(), e.Channel().ID().String()) {
|
||||
err := e.Client().Rest().DeleteMessage(e.Channel().ID(), snowflake.MustParse(getStickyMessageID(e.GuildID().String(), e.Channel().ID().String())))
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
removeSticky(e.GuildID().String(), e.Channel().ID().String())
|
||||
err = e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent("The sticky message was removed from this channel!").SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
} else {
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent("This channel has no sticky message!").SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
inputStickyMessage(e)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
Definition: discord.MessageCommandCreate{
|
||||
Name: "Stick to channel",
|
||||
DefaultMemberPermissions: json.NewNullablePtr(discord.PermissionManageMessages),
|
||||
Contexts: []discord.InteractionContextType{
|
||||
discord.InteractionContextTypeGuild,
|
||||
discord.InteractionContextTypePrivateChannel},
|
||||
IntegrationTypes: []discord.ApplicationIntegrationType{
|
||||
discord.ApplicationIntegrationTypeGuildInstall},
|
||||
},
|
||||
Interact: func(e *events.ApplicationCommandInteractionCreate) {
|
||||
inputStickyMessage(e)
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func inputStickyMessage(e *events.ApplicationCommandInteractionCreate) {
|
||||
var messageText string
|
||||
if e.ApplicationCommandInteraction.Data.Type() == discord.ApplicationCommandTypeMessage {
|
||||
messageText = e.MessageCommandInteractionData().TargetMessage().Content //TODO add more data then just content
|
||||
} else {
|
||||
messageText = e.SlashCommandInteractionData().String("message")
|
||||
}
|
||||
if messageText == "" {
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent("Can't add empty sticky messages!").SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
} else {
|
||||
message, err := e.Client().Rest().CreateMessage(e.Channel().ID(), discord.MessageCreate{Embeds: []discord.Embed{
|
||||
{Description: messageText, Footer: &discord.EmbedFooter{Text: "📌 Sticky message"}, Color: custom.GetColor("primary")}}})
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
|
||||
if hasSticky(e.GuildID().String(), e.Channel().ID().String()) {
|
||||
err = e.Client().Rest().DeleteMessage(e.Channel().ID(), snowflake.MustParse(getStickyMessageID(e.GuildID().String(), e.Channel().ID().String())))
|
||||
if err != nil {
|
||||
logrus.Error(err, getStickyMessageID(e.GuildID().String(), e.Channel().ID().String()))
|
||||
}
|
||||
removeSticky(e.GuildID().String(), e.Channel().ID().String())
|
||||
addSticky(e.GuildID().String(), e.Channel().ID().String(), messageText, message.ID.String())
|
||||
err = e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent("Sticky message in this channel was updated!").SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
} else {
|
||||
addSticky(e.GuildID().String(), e.Channel().ID().String(), messageText, message.ID.String())
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent("Message sticked to the channel!").SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
217
plugin_src/tags/cmd_tag.go
Normal file
217
plugin_src/tags/cmd_tag.go
Normal file
@@ -0,0 +1,217 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"github.com/disgoorg/disgo/discord"
|
||||
"github.com/disgoorg/disgo/events"
|
||||
"github.com/disgoorg/json"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vaporvee/acecore/shared"
|
||||
)
|
||||
|
||||
var db *sql.DB
|
||||
|
||||
var createTableQuery string = `CREATE TABLE IF NOT EXISTS tags (
|
||||
tag_id TEXT NOT NULL,
|
||||
tag_name TEXT NOT NULL,
|
||||
tag_content TEXT NOT NULL,
|
||||
guild_id TEXT NOT NULL,
|
||||
PRIMARY KEY (tag_id, guild_id)
|
||||
);
|
||||
`
|
||||
|
||||
var Plugin = &shared.Plugin{
|
||||
Name: "Tag System",
|
||||
Init: func(d *sql.DB) error {
|
||||
db = d
|
||||
_, err := db.Exec(createTableQuery)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
Commands: []shared.Command{
|
||||
{
|
||||
Definition: discord.SlashCommandCreate{
|
||||
Name: "tag",
|
||||
DefaultMemberPermissions: json.NewNullablePtr(discord.PermissionManageGuild),
|
||||
Description: "A command to show and edit saved presaved messages.",
|
||||
Contexts: []discord.InteractionContextType{
|
||||
discord.InteractionContextTypeGuild,
|
||||
discord.InteractionContextTypePrivateChannel},
|
||||
IntegrationTypes: []discord.ApplicationIntegrationType{
|
||||
discord.ApplicationIntegrationTypeGuildInstall},
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
discord.ApplicationCommandOptionSubCommand{
|
||||
Name: "get",
|
||||
Description: "A command to get messages saved to the bot.",
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
discord.ApplicationCommandOptionString{
|
||||
Name: "tag",
|
||||
Description: "Your predefined tag for the saved message",
|
||||
Required: true,
|
||||
Autocomplete: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
discord.ApplicationCommandOptionSubCommand{
|
||||
Name: "add",
|
||||
Description: "A command to add messages saved to the bot.",
|
||||
},
|
||||
discord.ApplicationCommandOptionSubCommand{
|
||||
Name: "remove",
|
||||
Description: "A command to remove messages saved to the bot.",
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
discord.ApplicationCommandOptionString{
|
||||
Name: "tag",
|
||||
Description: "The tag you want to remove",
|
||||
Required: true,
|
||||
Autocomplete: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Interact: func(e *events.ApplicationCommandInteractionCreate) {
|
||||
switch *e.SlashCommandInteractionData().SubCommandName {
|
||||
case "get":
|
||||
GetTagCommand(e)
|
||||
case "add":
|
||||
AddTagCommand(e)
|
||||
case "remove":
|
||||
removeTag(e.GuildID().String(), e.SlashCommandInteractionData().String("tag"))
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent("Tag removed!").SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
},
|
||||
ModalIDs: []string{"tag_add_modal"},
|
||||
ModalSubmit: func(e *events.ModalSubmitInteractionCreate) {
|
||||
tagName := e.Data.Text("tag_add_modal_name")
|
||||
tagContent := e.Data.Text("tag_add_modal_content")
|
||||
addTag(e.GuildID().String(), tagName, tagContent)
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent("Tag \"" + tagName + "\" added!").SetEphemeral(true).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
},
|
||||
Autocomplete: func(e *events.AutocompleteInteractionCreate) {
|
||||
AutocompleteTag(e)
|
||||
},
|
||||
},
|
||||
{
|
||||
Definition: discord.SlashCommandCreate{
|
||||
Name: "g",
|
||||
Description: "A short command to get presaved messages.",
|
||||
Contexts: []discord.InteractionContextType{
|
||||
discord.InteractionContextTypeGuild,
|
||||
discord.InteractionContextTypePrivateChannel},
|
||||
IntegrationTypes: []discord.ApplicationIntegrationType{
|
||||
discord.ApplicationIntegrationTypeGuildInstall},
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
discord.ApplicationCommandOptionString{
|
||||
Name: "tag",
|
||||
Description: "Your predefined tag for the saved message",
|
||||
Required: true,
|
||||
Autocomplete: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Interact: func(e *events.ApplicationCommandInteractionCreate) {
|
||||
GetTagCommand(e)
|
||||
},
|
||||
Autocomplete: func(e *events.AutocompleteInteractionCreate) {
|
||||
AutocompleteTag(e)
|
||||
},
|
||||
},
|
||||
{
|
||||
Definition: discord.MessageCommandCreate{
|
||||
Name: "Save as tag",
|
||||
DefaultMemberPermissions: json.NewNullablePtr(discord.PermissionManageGuild),
|
||||
Contexts: []discord.InteractionContextType{
|
||||
discord.InteractionContextTypeGuild,
|
||||
discord.InteractionContextTypePrivateChannel},
|
||||
IntegrationTypes: []discord.ApplicationIntegrationType{
|
||||
discord.ApplicationIntegrationTypeGuildInstall},
|
||||
},
|
||||
Interact: func(e *events.ApplicationCommandInteractionCreate) {
|
||||
AddTagCommand(e)
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func GetTagCommand(e *events.ApplicationCommandInteractionCreate) {
|
||||
err := e.CreateMessage(discord.NewMessageCreateBuilder().
|
||||
SetContent(getTagContent(e.GuildID().String(), e.SlashCommandInteractionData().String("tag"))).
|
||||
Build())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func AddTagCommand(e *events.ApplicationCommandInteractionCreate) {
|
||||
var prevalue string
|
||||
if e.ApplicationCommandInteraction.Data.Type() == discord.ApplicationCommandTypeMessage {
|
||||
prevalue = e.MessageCommandInteractionData().TargetMessage().Content
|
||||
}
|
||||
err := e.Modal(discord.ModalCreate{
|
||||
CustomID: "tag_add_modal" + e.User().ID.String(),
|
||||
Title: "Add a custom tag command",
|
||||
Components: []discord.ContainerComponent{
|
||||
discord.ActionRowComponent{
|
||||
discord.TextInputComponent{
|
||||
CustomID: "tag_add_modal_name",
|
||||
Label: "Name",
|
||||
Style: discord.TextInputStyleShort,
|
||||
Required: true,
|
||||
MaxLength: 20,
|
||||
Value: "",
|
||||
},
|
||||
},
|
||||
discord.ActionRowComponent{
|
||||
discord.TextInputComponent{
|
||||
CustomID: "tag_add_modal_content",
|
||||
Label: "Content",
|
||||
Style: discord.TextInputStyleParagraph,
|
||||
Required: true,
|
||||
MaxLength: 2000,
|
||||
Value: prevalue,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func AutocompleteTag(e *events.AutocompleteInteractionCreate) {
|
||||
err := e.AutocompleteResult(generateTagChoices(e.GuildID().String()))
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func generateTagChoices(guildID string) []discord.AutocompleteChoice {
|
||||
choices := []discord.AutocompleteChoice{}
|
||||
IDs, err := getTagIDs(guildID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return choices
|
||||
}
|
||||
for _, id := range IDs {
|
||||
id_name := getTagName(guildID, id)
|
||||
choices = append(choices, &discord.AutocompleteChoiceString{
|
||||
Name: id_name,
|
||||
Value: id,
|
||||
})
|
||||
}
|
||||
return choices
|
||||
}
|
70
plugin_src/tags/data.go
Normal file
70
plugin_src/tags/data.go
Normal file
@@ -0,0 +1,70 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/google/uuid"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func addTag(guildID, tagName, tagContent string) bool {
|
||||
var exists bool = true
|
||||
//TODO: add modify command
|
||||
id := uuid.New()
|
||||
for exists {
|
||||
id = uuid.New()
|
||||
err := db.QueryRow("SELECT EXISTS (SELECT 1 FROM tags WHERE guild_id = $1 AND tag_id = $2)", guildID, id).Scan(&exists)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
_, err := db.Exec("INSERT INTO tags (guild_id, tag_name, tag_content, tag_id) VALUES ($1, $2, $3, $4)", guildID, tagName, tagContent, id)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
|
||||
return exists
|
||||
}
|
||||
func removeTag(guildID string, tagID string) {
|
||||
var exists bool
|
||||
err := db.QueryRow("SELECT EXISTS (SELECT 1 FROM tags WHERE guild_id = $1 AND tag_id = $2)", guildID, tagID).Scan(&exists)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
if exists {
|
||||
_, err = db.Exec("DELETE FROM tags WHERE guild_id = $1 AND tag_id = $2", guildID, tagID)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
func getTagIDs(guildID string) ([]string, error) {
|
||||
var IDs []string
|
||||
rows, err := db.Query("SELECT tag_id FROM tags WHERE guild_id = $1", guildID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var id string
|
||||
if err := rows.Scan(&id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
IDs = append(IDs, id)
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return IDs, nil
|
||||
}
|
||||
func getTagName(guildID string, tagID string) string {
|
||||
var tagName string
|
||||
db.QueryRow("SELECT tag_name FROM tags WHERE guild_id = $1 AND tag_id = $2", guildID, tagID).Scan(&tagName)
|
||||
return tagName
|
||||
}
|
||||
func getTagContent(guildID string, tagID string) string {
|
||||
var tagContent string
|
||||
db.QueryRow("SELECT tag_content FROM tags WHERE guild_id = $1 AND tag_id = $2", guildID, tagID).Scan(&tagContent)
|
||||
return tagContent
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
module github.com/vaporvee/acecore/cmd
|
||||
module github.com/vaporvee/acecore/shared
|
||||
|
||||
go 1.22.1
|
||||
|
||||
@@ -9,6 +9,7 @@ require (
|
||||
github.com/disgoorg/snowflake/v2 v2.0.1 // indirect
|
||||
github.com/gorilla/websocket v1.5.1 // indirect
|
||||
github.com/sasha-s/go-csync v0.0.0-20240107134140-fcbab37b09ad // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // 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
|
@@ -19,10 +19,6 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/vaporvee/acecore v0.0.0-20240414202630-d814d39cf135 h1:LdMezyBJ9Q8/VIugcvc6X37/0L9poxKU6zq36ooJN3U=
|
||||
github.com/vaporvee/acecore v0.0.0-20240414202630-d814d39cf135/go.mod h1:kRHYJwIF7PW99J8BzDqVtV7c0PoitgdpR/e06emJm1s=
|
||||
github.com/vaporvee/acecore/cmd v0.0.0-20240414202630-d814d39cf135 h1:SbwOoMX4LViUCuH8syFUKPsKXBONY3PhSrkKVNmFJYc=
|
||||
github.com/vaporvee/acecore/cmd v0.0.0-20240414202630-d814d39cf135/go.mod h1:03W2NrAPbAqa7gsqAM+2K/wT28stj9BmEhC5NzeGe3A=
|
||||
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.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
@@ -1,13 +1,15 @@
|
||||
package cmd
|
||||
package shared
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"github.com/disgoorg/disgo/bot"
|
||||
"github.com/disgoorg/disgo/discord"
|
||||
"github.com/disgoorg/disgo/events"
|
||||
)
|
||||
|
||||
type Command struct {
|
||||
Ready func(e *events.Ready)
|
||||
Definition discord.ApplicationCommandCreate
|
||||
Interact func(e *events.ApplicationCommandInteractionCreate)
|
||||
Autocomplete func(e *events.AutocompleteInteractionCreate)
|
||||
@@ -21,6 +23,8 @@ type Command struct {
|
||||
|
||||
type Plugin struct {
|
||||
Name string
|
||||
Register func(e *events.Ready, db *sql.DB) error
|
||||
Init func(d *sql.DB) error
|
||||
Commands []Command
|
||||
}
|
||||
|
||||
var BotConfigs []bot.ConfigOpt
|
114
shared/tool.go
Normal file
114
shared/tool.go
Normal file
@@ -0,0 +1,114 @@
|
||||
package shared
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/disgoorg/disgo/bot"
|
||||
"github.com/disgoorg/disgo/discord"
|
||||
"github.com/disgoorg/snowflake/v2"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type ModalJsonField struct {
|
||||
Label string `json:"label"`
|
||||
IsParagraph bool `json:"is_paragraph"`
|
||||
Value string `json:"value"`
|
||||
Required bool `json:"required"`
|
||||
Placeholder string `json:"placeholder"`
|
||||
MinLength int `json:"min_length"`
|
||||
MaxLength int `json:"max_length"`
|
||||
}
|
||||
|
||||
type ModalJson struct {
|
||||
FormType string `json:"form_type"`
|
||||
Title string `json:"title"`
|
||||
Form []ModalJsonField `json:"form"`
|
||||
}
|
||||
|
||||
// Why does the golang compiler care about commands??
|
||||
//
|
||||
//go:embed form_templates/*.json
|
||||
var FormTemplates embed.FS
|
||||
|
||||
func GetModalByFormID(formID string) ModalJson {
|
||||
var modal ModalJson
|
||||
if formID == "" {
|
||||
return modal
|
||||
}
|
||||
entries, err := FormTemplates.ReadDir("form_templates")
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return modal
|
||||
}
|
||||
for _, entry := range entries {
|
||||
if strings.HasPrefix(entry.Name(), formID) {
|
||||
jsonFile, err := FormTemplates.ReadFile("form_templates/" + entry.Name())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
continue
|
||||
}
|
||||
err = json.Unmarshal(jsonFile, &modal)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return modal
|
||||
}
|
||||
|
||||
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),
|
||||
Label: component.Label,
|
||||
Style: style,
|
||||
Placeholder: component.Placeholder,
|
||||
Required: component.Required,
|
||||
MaxLength: component.MaxLength,
|
||||
MinLength: &component.MinLength,
|
||||
Value: component.Value,
|
||||
},
|
||||
})
|
||||
}
|
||||
if overwrite != nil && overwrite[0] != "" {
|
||||
modal.Title = overwrite[0]
|
||||
}
|
||||
|
||||
return discord.ModalCreate{
|
||||
CustomID: "form:" + manageID + ":" + userID,
|
||||
Title: modal.Title,
|
||||
Components: components,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func IsIDRole(c bot.Client, guildID snowflake.ID, id snowflake.ID) bool {
|
||||
_, err1 := c.Rest().GetMember(guildID, id)
|
||||
if err1 == nil {
|
||||
return false
|
||||
}
|
||||
roles, err2 := c.Rest().GetRoles(guildID)
|
||||
if err2 == nil {
|
||||
for _, role := range roles {
|
||||
if role.ID == id {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logrus.Error(err1)
|
||||
logrus.Error(err2)
|
||||
return false
|
||||
}
|
230
tool.go
230
tool.go
@@ -1,230 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/disgoorg/disgo/bot"
|
||||
"github.com/disgoorg/disgo/discord"
|
||||
"github.com/disgoorg/disgo/rest"
|
||||
"github.com/disgoorg/snowflake/v2"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type ModalJsonField struct {
|
||||
Label string `json:"label"`
|
||||
IsParagraph bool `json:"is_paragraph"`
|
||||
Value string `json:"value"`
|
||||
Required bool `json:"required"`
|
||||
Placeholder string `json:"placeholder"`
|
||||
MinLength int `json:"min_length"`
|
||||
MaxLength int `json:"max_length"`
|
||||
}
|
||||
|
||||
type ModalJson struct {
|
||||
FormType string `json:"form_type"`
|
||||
Title string `json:"title"`
|
||||
Form []ModalJsonField `json:"form"`
|
||||
}
|
||||
|
||||
type MessageIDs struct {
|
||||
ID string
|
||||
ChannelID string
|
||||
}
|
||||
|
||||
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),
|
||||
Label: component.Label,
|
||||
Style: style,
|
||||
Placeholder: component.Placeholder,
|
||||
Required: component.Required,
|
||||
MaxLength: component.MaxLength,
|
||||
MinLength: &component.MinLength,
|
||||
Value: component.Value,
|
||||
},
|
||||
})
|
||||
}
|
||||
if overwrite != nil && overwrite[0] != "" {
|
||||
modal.Title = overwrite[0]
|
||||
}
|
||||
|
||||
return discord.ModalCreate{
|
||||
CustomID: "form:" + manageID + ":" + userID,
|
||||
Title: modal.Title,
|
||||
Components: components,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Why does the golang compiler care about commands??
|
||||
//
|
||||
//go:embed form_templates/*.json
|
||||
var formTemplates embed.FS
|
||||
|
||||
func getModalByFormID(formID string) ModalJson {
|
||||
var modal ModalJson
|
||||
if formID == "" {
|
||||
return modal
|
||||
}
|
||||
entries, err := formTemplates.ReadDir("form_templates")
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return modal
|
||||
}
|
||||
for _, entry := range entries {
|
||||
if strings.HasPrefix(entry.Name(), formID) {
|
||||
jsonFile, err := formTemplates.ReadFile("form_templates/" + entry.Name())
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
continue
|
||||
}
|
||||
err = json.Unmarshal(jsonFile, &modal)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return modal
|
||||
}
|
||||
|
||||
func getHighestRole(guildID string, c bot.Client) (*discord.Role, error) {
|
||||
botmember, err := c.Rest().GetMember(snowflake.MustParse(guildID), c.ApplicationID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
roles, err := c.Rest().GetRoles(snowflake.MustParse(guildID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var highestRole *discord.Role
|
||||
for _, roleID := range botmember.RoleIDs {
|
||||
for _, role := range roles {
|
||||
if role.ID == roleID {
|
||||
if highestRole == nil || role.Position > highestRole.Position {
|
||||
highestRole = &role
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return highestRole, nil
|
||||
}
|
||||
|
||||
func simpleGetFromAPI(key string, url string) interface{} {
|
||||
client := &http.Client{}
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
logrus.Error("Error creating request:", err)
|
||||
}
|
||||
req.Header.Set("Accept", "application/json")
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
logrus.Error("Error making request:", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
logrus.Error("Error reading response body:", err)
|
||||
}
|
||||
|
||||
var result map[string]interface{}
|
||||
err = json.Unmarshal(body, &result)
|
||||
if err != nil {
|
||||
logrus.Error("Error decoding JSON:", err)
|
||||
}
|
||||
return result[key]
|
||||
}
|
||||
|
||||
func findAndDeleteUnusedMessages(c bot.Client) {
|
||||
for _, message := range getAllSavedMessages() {
|
||||
_, err := c.Rest().GetMessage(snowflake.MustParse(message.ChannelID), snowflake.MustParse(message.ID))
|
||||
if err != nil {
|
||||
tryDeleteUnusedMessage(message.ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func isIDRole(c bot.Client, guildID snowflake.ID, id snowflake.ID) bool {
|
||||
_, err1 := c.Rest().GetMember(guildID, id)
|
||||
if err1 == nil {
|
||||
return false
|
||||
}
|
||||
roles, err2 := c.Rest().GetRoles(guildID)
|
||||
if err2 == nil {
|
||||
for _, role := range roles {
|
||||
if role.ID == id {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logrus.Error(err1)
|
||||
logrus.Error(err2)
|
||||
return false
|
||||
}
|
||||
|
||||
func isGIFImage(imageData []byte) bool {
|
||||
if len(imageData) < 6 {
|
||||
return false
|
||||
}
|
||||
// Check for the GIF89a header at the beginning of the byte array
|
||||
if string(imageData[0:6]) == "GIF89a" {
|
||||
return true
|
||||
}
|
||||
// Check for the GIF87a header at the beginning of the byte array
|
||||
if string(imageData[0:6]) == "GIF87a" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func messageIsPoll(channelID string, messageID string, client bot.Client) bool {
|
||||
url := rest.DefaultConfig().URL + "/channels/" + channelID + "/messages/" + messageID
|
||||
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return false
|
||||
}
|
||||
|
||||
auth := "Bot " + client.Token()
|
||||
req.Header.Set("Authorization", auth)
|
||||
|
||||
resp, err := client.Rest().HTTPClient().Do(req)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return false
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return false
|
||||
}
|
||||
|
||||
var data map[string]interface{}
|
||||
err = json.Unmarshal(body, &data)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return false
|
||||
}
|
||||
|
||||
_, ok := data["poll"]
|
||||
return ok
|
||||
}
|
@@ -43,7 +43,7 @@
|
||||
services.
|
||||
</li>
|
||||
<li>
|
||||
cmd.Command usage: We store data about some commands that you use within
|
||||
shared.Command usage: We store data about some commands that you use within
|
||||
acecore in order to make the commands usable and functioning.
|
||||
</li>
|
||||
<li>
|
||||
|
Reference in New Issue
Block a user