Cursed command but it will do.
All checks were successful
Build and push container image / build (push) Successful in 38s

This commit is contained in:
toast 2023-10-20 16:18:13 +11:00
parent c134338b1e
commit fb3e0da610
6 changed files with 216 additions and 15 deletions

View File

@ -16,11 +16,34 @@ func commandsJSON() (commandList []discord.ApplicationCommandCreate) {
commandList = []discord.ApplicationCommandCreate{ commandList = []discord.ApplicationCommandCreate{
discord.SlashCommandCreate{ discord.SlashCommandCreate{
Name: "host-stats", Name: "host-stats",
Description: "Returns host statistics like OS, CPU Usage, etc", Description: "Host statistics like OS, CPU Usage, etc",
}, },
discord.SlashCommandCreate{ discord.SlashCommandCreate{
Name: "invite", Name: "repository",
Description: "Add the bot to your community server", Description: "A casual button that forwards you to the bot's repository",
},
discord.SlashCommandCreate{
Name: "config",
Description: "View or change the bot's configuration",
DMPermission: &FALSE,
Options: []discord.ApplicationCommandOption{
discord.ApplicationCommandOptionChannel{
Name: "ban-records",
Description: "Set a channel that will be used to display ban records via Google Sheets",
Required: false,
ChannelTypes: []discord.ChannelType{
discord.ChannelTypeGuildText,
discord.ChannelTypeGuildForum,
discord.ChannelTypeGuildPublicThread,
discord.ChannelTypeGuildPrivateThread,
},
},
discord.ApplicationCommandOptionString{
Name: "google-sheets",
Description: "Set the Google Sheets URL that will be used to display ban records",
Required: false,
},
},
}, },
} }
return commandList return commandList

View File

@ -5,6 +5,7 @@ services:
image: 'git.toast-server.net/toast/corn-utility:main@sha256:d966d1c466e60617d0059a4d9a3a147baf9228d2a90ed2dbceab4e9ad392e49e' image: 'git.toast-server.net/toast/corn-utility:main@sha256:d966d1c466e60617d0059a4d9a3a147baf9228d2a90ed2dbceab4e9ad392e49e'
volumes: volumes:
- ./tokens.json:/home/corn-util/tokens.json:ro - ./tokens.json:/home/corn-util/tokens.json:ro
- ./config.json:/home/corn-util/config.json:rw
expose: expose:
- 23242:23242 - 23242:23242
restart: unless-stopped restart: unless-stopped

View File

@ -1,7 +1,9 @@
package botEvents package botEvents
import ( import (
"corn-util/bot/loaders"
"corn-util/bot/toolbox" "corn-util/bot/toolbox"
"encoding/json"
"fmt" "fmt"
"runtime" "runtime"
"strings" "strings"
@ -20,6 +22,8 @@ import (
var ( var (
mainEmbedColor = 0xff69b4 //0xf9c62c - main embed color for the bot (saffron / yellow) mainEmbedColor = 0xff69b4 //0xf9c62c - main embed color for the bot (saffron / yellow)
noPermText = "You need to have a role with `Manage Server` permission to use this command." noPermText = "You need to have a role with `Manage Server` permission to use this command."
attemptFailText = "There was an attempt..."
noConfigValText = "Unconfigured"
) )
func ListenForCommand(e *events.ApplicationCommandInteractionCreate) { func ListenForCommand(e *events.ApplicationCommandInteractionCreate) {
@ -83,19 +87,118 @@ func ListenForCommand(e *events.ApplicationCommandInteractionCreate) {
DumpErrToConsole(err) DumpErrToConsole(err)
} }
break break
case "invite": case "repository":
e.CreateMessage(discord.MessageCreate{ e.CreateMessage(discord.MessageCreate{
Components: []discord.ContainerComponent{ Components: []discord.ContainerComponent{
discord.ActionRowComponent{ discord.ActionRowComponent{
discord.ButtonComponent{ discord.ButtonComponent{
Label: "Invite me!", Label: "Check out the repsotiry!",
Style: discord.ButtonStyleLink, Style: discord.ButtonStyleLink,
URL: fmt.Sprintf("https://discord.com/api/oauth2/authorize?client_id=%v&permissions=19456&scope=bot", e.Client().ApplicationID()), URL: "https://git.toast-server.net/toast/Corn-Utility.git",
}, },
}, },
}, },
}) })
break break
case "config":
type jsonDataStruct struct {
BanRecords string `json:"banRecords"`
GoogleSheets string `json:"googleSheets"`
}
readData, _ := loaders.DataLoader.Read(&loaders.JSON{}, "config.json")
jsonData := jsonDataStruct{}
jsonDataBytes, _ := json.Marshal(readData)
json.Unmarshal(jsonDataBytes, &jsonData)
fmt.Println(jsonData)
banRecordsCh, _ := e.SlashCommandInteractionData().OptChannel("ban-records")
googleSheetsURL, _ := e.SlashCommandInteractionData().OptString("google-sheets")
if !isGuildManager(e) {
DumpErrToInteraction(e, fmt.Errorf(noPermText))
return
}
if len(e.SlashCommandInteractionData().Options) == 0 {
e.CreateMessage(discord.MessageCreate{
Embeds: []discord.Embed{
{
Title: "Current configuration",
Description: "You can configure the bot using the options below.",
Fields: []discord.EmbedField{
{
Name: "Ban Records",
Value: func() string {
if jsonData.BanRecords == "" || jsonData.BanRecords == "0" {
return noConfigValText
} else {
return fmt.Sprintf("<#%v>", jsonData.BanRecords)
}
}(),
Inline: &TRUE,
},
{
Name: "Google Sheets",
Value: func() string {
if jsonData.GoogleSheets == "" {
return noConfigValText
} else {
return fmt.Sprintf("`%v`", jsonData.GoogleSheets)
}
}(),
Inline: &TRUE,
},
},
Color: mainEmbedColor,
},
},
})
return
}
if banRecordsCh.Permissions.Has(discord.PermissionSendMessages, discord.PermissionEmbedLinks) {
// Create a placeholder embed in the configured channel.
if _, err := e.Client().Rest().CreateMessage(banRecordsCh.ID, discord.MessageCreate{
Embeds: []discord.Embed{
{
Description: "This is a placeholder embed for ban records.\n" +
"Once the bot is configured, this will be updated with the latest ban records from Google Sheets.",
Color: mainEmbedColor,
},
},
}); err != nil {
DumpErrToChannel(e, err)
return
}
}
fmt.Printf("google-sheets: %v\n", googleSheetsURL)
if err := e.CreateMessage(discord.MessageCreate{
Embeds: []discord.Embed{{Title: "Config saved!", Color: mainEmbedColor}},
}); err != nil {
DumpErrToInteraction(e, err)
return
}
// Update the config file with the new configuration.
data := map[string]interface{}{}
if banRecordsCh.ID.String() != "0" {
data["banRecords"] = banRecordsCh.ID
} else {
data["banRecords"] = jsonData.BanRecords
}
if googleSheetsURL != "" {
data["googleSheets"] = googleSheetsURL
} else {
data["googleSheets"] = jsonData.GoogleSheets
}
err := loaders.DataLoader.Write(&loaders.JSON{}, "config.json", data)
if err != nil {
DumpErrToChannel(e, err)
return
}
} }
} }
@ -107,7 +210,7 @@ func DumpErrToInteraction(e *events.ApplicationCommandInteractionCreate, err err
if err := e.CreateMessage(discord.MessageCreate{ if err := e.CreateMessage(discord.MessageCreate{
Embeds: []discord.Embed{ Embeds: []discord.Embed{
{ {
Title: "There was an attempt...", Title: attemptFailText,
Description: fmt.Sprintf("```%v```", err.Error()), Description: fmt.Sprintf("```%v```", err.Error()),
Color: 0x560000, Color: 0x560000,
}, },
@ -121,7 +224,7 @@ func DumpErrToChannel(e *events.ApplicationCommandInteractionCreate, err error)
if _, err := e.Client().Rest().CreateMessage(e.Channel().ID(), discord.MessageCreate{ if _, err := e.Client().Rest().CreateMessage(e.Channel().ID(), discord.MessageCreate{
Embeds: []discord.Embed{ Embeds: []discord.Embed{
{ {
Title: "There was an attempt...", Title: attemptFailText,
Description: fmt.Sprintf("```%v```", err.Error()), Description: fmt.Sprintf("```%v```", err.Error()),
Color: 0x560000, Color: 0x560000,
}, },
@ -132,8 +235,7 @@ func DumpErrToChannel(e *events.ApplicationCommandInteractionCreate, err error)
} }
func isGuildManager(e *events.ApplicationCommandInteractionCreate) bool { func isGuildManager(e *events.ApplicationCommandInteractionCreate) bool {
member := e.Member() if e.Member().Permissions.Has(discord.PermissionManageGuild) {
if member.Permissions.Has(discord.PermissionManageGuild) {
return true return true
} else { } else {
return false return false

68
loaders/db.go Normal file
View File

@ -0,0 +1,68 @@
package loaders
import (
"encoding/json"
"os"
)
/*
This is a simple database system that peforms CRUD operations on a JSON file.
It will be a proper database system in the future, but for now it will be a JSON file.
Hope this is understandable for future coders.
*/
type DataLoader interface {
Read(filename string) (interface{}, error)
Write(filename string, data interface{}) error
}
type JSON struct{}
func (l *JSON) Read(filename string) (interface{}, error) {
file, err := os.Open(filename)
if err != nil {
return nil, err
}
defer file.Close()
bytes, err := os.ReadFile(filename)
if err != nil {
return nil, err
}
data := make(map[string]interface{})
err = json.Unmarshal(bytes, &data)
if err != nil {
return nil, err
}
return data, nil
}
func (l *JSON) Write(filename string, data interface{}) error {
existingData, err := l.Read(filename)
if err != nil {
return err
}
newData := data.(map[string]interface{})
for k, v := range existingData.(map[string]interface{}) {
if newV, ok := newData[k]; ok {
newData[k] = newV
} else {
newData[k] = v
}
}
bytes, err := json.MarshalIndent(newData, "", " ")
if err != nil {
return err
}
err = os.WriteFile(filename, bytes, 0644)
if err != nil {
return err
}
return nil
}

View File

@ -3,7 +3,6 @@ package main
import ( import (
botEvents "corn-util/bot/events" botEvents "corn-util/bot/events"
"corn-util/bot/loaders" "corn-util/bot/loaders"
"fmt"
"os" "os"
"os/signal" "os/signal"
"runtime" "runtime"
@ -44,8 +43,8 @@ func main() {
log.Infof("Commands deployment is disabled") log.Infof("Commands deployment is disabled")
} }
fmt.Printf("Client ready!\n") log.Infof("Client ready!")
fmt.Printf("Running Disgo %v & Go %v\n", disgo.Version, strings.TrimPrefix(runtime.Version(), "go")) log.Infof("Running Disgo %v & Go %v", disgo.Version, strings.TrimPrefix(runtime.Version(), "go"))
client.Rest().CreateWebhookMessage(snowflake.MustParse(loaders.TokenLoader("hookId")), loaders.TokenLoader("hookToken"), discord.WebhookMessageCreate{ client.Rest().CreateWebhookMessage(snowflake.MustParse(loaders.TokenLoader("hookId")), loaders.TokenLoader("hookToken"), discord.WebhookMessageCreate{
Content: "Container has been reloaded.", Content: "Container has been reloaded.",
}, true, 0) }, true, 0)

View File

@ -2,8 +2,16 @@ package toolbox
import "time" import "time"
/*
System/OS-related utilities such as uptime.
*/
var timerStart = time.Now() var timerStart = time.Now()
/*
Nor the Go or the Disgo library has a built-in
Client/Process uptime function, so I had to get creative.
*/
func GetUptime() string { func GetUptime() string {
uptime := time.Since(timerStart) uptime := time.Since(timerStart)
return uptime.Round(time.Second).String() return uptime.Round(time.Second).String()