Skip to content

Instantly share code, notes, and snippets.

@CarsonSlovoka
Created September 26, 2023 03:56
Show Gist options
  • Save CarsonSlovoka/e44a3e0aea84b3ee326a2510202c0a16 to your computer and use it in GitHub Desktop.
Save CarsonSlovoka/e44a3e0aea84b3ee326a2510202c0a16 to your computer and use it in GitHub Desktop.
re-run slash command by button
/*
USAGE:
-guild=987654321987654321 -token=xxxxx.oooo -rmcmd=true
腳本說明:
當使用者輸入 `/joke` 指令,可以選擇要看哪一則笑話(由chatgpt所提供),
看完之後會出現一個按鈕,可以查看下一則笑話(已經到尾就再從頭開始)
*/
package main
import (
"encoding/json"
"flag"
"fmt"
"github.com/bwmarrin/discordgo"
"log"
"os"
"os/signal"
"time"
)
var (
GuildID = flag.String("guild", "", "Test guild ID. If not passed - bot registers commands globally")
BotToken = flag.String("token", "", "Bot access token: https://discord.com/developers/applications/123456789012345678/bot")
RemoveCommands = flag.Bool("rmcmd", false, "Remove all commands after shutdowning or not")
)
var s *discordgo.Session
func init() { flag.Parse() }
func init() {
var err error
s, err = discordgo.New("Bot " + *BotToken) // 利用Token找到您的機器人
if err != nil {
log.Fatalf("Invalid bot parameters: %v", err)
}
}
var (
integerOptionMinValue = 0.0
commands = []*discordgo.ApplicationCommand{
{
Name: "joke",
Description: "看笑話",
Options: []*discordgo.ApplicationCommandOption{
{
Name: "n",
Type: discordgo.ApplicationCommandOptionInteger,
MinValue: &integerOptionMinValue,
MaxValue: 4,
Description: "第幾則笑話",
Required: true,
},
},
},
}
jokes = []string{
"Why don’t skeletons fight each other? They don’t have the guts!",
"為什麼糖是方的?因為它是方糖!",
"為什麼樹木不喜歡玩隱藏?因為它們害怕被砍掉!",
"雞看到火車來了,為什麼不跑?因為它是火雞!",
"為什麼餅乾總是失敗?因為它總是碎了大事!",
}
jokeHandler = func(s *discordgo.Session, i *discordgo.InteractionCreate) {
n := i.ApplicationCommandData().Options[0].IntValue()
if err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseChannelMessageWithSource,
Data: &discordgo.InteractionResponseData{
Content: jokes[n],
},
}); err != nil {
_, _ = s.FollowupMessageCreate(i.Interaction, true, &discordgo.WebhookParams{
Content: "Something went wrong",
})
return
}
time.AfterFunc(2*time.Second, func() {
/* 可以考慮把輸入參數寫在檔案之中
paraFile := &discordgo.File{
Name: "userInputPara.json",
ContentType: "application/json",
Reader: bytes.NewBuffer([]byte(fmt.Sprintf(`{"n":%d}`, n))),
}
*/
_, _ = s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{
Content: jokes[n],
/*
Files: []*discordgo.File{
paraFile,
},
*/
Components: []discordgo.MessageComponent{
discordgo.ActionsRow{
Components: []discordgo.MessageComponent{
discordgo.Button{
Emoji: discordgo.ComponentEmoji{
Name: "🔄",
},
Label: "看下一則笑話",
Style: discordgo.PrimaryButton,
// URL: fmt.Sprintf(`{"n":%d}`, n), // 用URL來充當Value, 後面會有問題,不曉得甚麼原因,總之行不通
CustomID: "re_joke",
},
discordgo.Button{
Emoji: discordgo.ComponentEmoji{
Name: "ℹ️",
},
Label: "google search",
Style: discordgo.LinkButton,
URL: "https://www.google.com/search?q=joke",
},
discordgo.Button{
Label: fmt.Sprintf(`{"n":%d}`, n),
Style: discordgo.SecondaryButton,
CustomID: "test",
},
},
},
},
})
})
}
// 實作各個commands所要做的事情
commandHandlers = map[string]func(s *discordgo.Session, i *discordgo.InteractionCreate){
"joke": jokeHandler,
}
)
func init() {
s.AddHandler(func(s *discordgo.Session, i *discordgo.InteractionCreate) {
switch i.Type {
case discordgo.InteractionApplicationCommand:
if handlerFunc, exists := commandHandlers[i.ApplicationCommandData().Name]; exists {
handlerFunc(s, i)
}
case discordgo.InteractionMessageComponent:
componentsHandlers := map[string]func(s *discordgo.Session, i *discordgo.InteractionCreate){
"re_joke": jokeHandler,
}
if handlerFunc, exists := componentsHandlers[i.MessageComponentData().CustomID]; exists {
var jokePara struct {
N float64
}
if err := json.Unmarshal([]byte(i.Message.Components[0].(*discordgo.ActionsRow).Components[2].(*discordgo.Button).Label), &jokePara); err != nil {
fmt.Println(err)
return
}
/*
if len(i.Message.Attachments) > 0 {
attachment := i.Message.Attachments[0]
http.Get(attachment.URL)
}
*/
// 這邊可以硬把i改成InteractionApplicationCommand時的i內容
i.Type = discordgo.InteractionApplicationCommandAutocomplete
n := jokePara.N + 1 // 看下一則笑話
if int(n) >= len(jokes) {
n = 0
}
i.Data = discordgo.ApplicationCommandInteractionData{
Options: []*discordgo.ApplicationCommandInteractionDataOption{
{
Name: "n",
Type: discordgo.ApplicationCommandOptionInteger,
Value: n,
},
},
}
handlerFunc(s, i)
}
}
})
}
func main() {
err := s.Open()
if err != nil {
panic(err)
}
defer func() {
_ = s.Close()
}()
log.Println("Adding commands...")
registeredCommands := make([]*discordgo.ApplicationCommand, len(commands))
for i, v := range commands {
cmd, err := s.ApplicationCommandCreate(s.State.User.ID, *GuildID, v)
if err != nil {
log.Panicf("Cannot create '%v' command: %v", v.Name, err)
}
registeredCommands[i] = cmd
}
defer func() {
_ = s.Close()
}()
stop := make(chan os.Signal, 1)
signal.Notify(stop, os.Interrupt)
log.Println("Press Ctrl+C to exit")
<-stop
if *RemoveCommands {
log.Println("Removing commands...")
for _, v := range registeredCommands {
err := s.ApplicationCommandDelete(s.State.User.ID, *GuildID, v.ID)
if err != nil {
log.Panicf("Cannot delete '%v' command: %v", v.Name, err)
}
}
}
log.Println("Gracefully shutting down.")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment