2020-08-31 16:20:52 +00:00
|
|
|
package discord
|
|
|
|
|
|
|
|
import (
|
2022-10-20 22:32:49 +00:00
|
|
|
"bytes"
|
2020-08-31 16:20:52 +00:00
|
|
|
"errors"
|
2020-09-09 17:21:39 +00:00
|
|
|
"fmt"
|
2021-07-28 15:32:59 +00:00
|
|
|
"net/http"
|
2021-08-23 15:28:08 +00:00
|
|
|
"strconv"
|
2020-09-09 17:21:39 +00:00
|
|
|
"strings"
|
2022-05-30 20:34:42 +00:00
|
|
|
"time"
|
2020-08-31 16:20:52 +00:00
|
|
|
|
|
|
|
"github.com/velour/catbase/bot/msg"
|
|
|
|
|
|
|
|
"github.com/bwmarrin/discordgo"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
|
|
"github.com/velour/catbase/bot"
|
|
|
|
"github.com/velour/catbase/bot/user"
|
|
|
|
"github.com/velour/catbase/config"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Discord struct {
|
|
|
|
config *config.Config
|
|
|
|
client *discordgo.Session
|
|
|
|
|
|
|
|
event bot.Callback
|
|
|
|
|
|
|
|
emojiCache map[string]string
|
2021-08-23 15:28:08 +00:00
|
|
|
|
|
|
|
// store IDs -> nick and vice versa for quick conversion
|
|
|
|
uidCache map[string]string
|
2022-07-22 21:04:51 +00:00
|
|
|
|
|
|
|
registeredCmds []*discordgo.ApplicationCommand
|
2022-07-23 04:17:44 +00:00
|
|
|
cmdHandlers map[string]CmdHandler
|
2022-09-18 21:43:44 +00:00
|
|
|
|
|
|
|
guildID string
|
2020-08-31 16:20:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func New(config *config.Config) *Discord {
|
2021-08-20 00:37:53 +00:00
|
|
|
client, err := discordgo.New("Bot " + config.Get("DISCORDBOTTOKEN", ""))
|
2020-08-31 16:20:52 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal().Err(err).Msg("Could not connect to Discord")
|
|
|
|
}
|
2022-09-18 21:43:44 +00:00
|
|
|
guildID := config.Get("discord.guildid", "")
|
|
|
|
if guildID == "" {
|
|
|
|
log.Fatal().Msgf("You must set either DISCORD_GUILDID env or discord.guildid db config")
|
|
|
|
}
|
2020-08-31 16:20:52 +00:00
|
|
|
d := &Discord{
|
2022-07-23 04:17:44 +00:00
|
|
|
config: config,
|
|
|
|
client: client,
|
|
|
|
uidCache: map[string]string{},
|
|
|
|
registeredCmds: []*discordgo.ApplicationCommand{},
|
|
|
|
cmdHandlers: map[string]CmdHandler{},
|
2022-09-18 21:43:44 +00:00
|
|
|
guildID: guildID,
|
2022-07-23 04:17:44 +00:00
|
|
|
}
|
|
|
|
d.client.AddHandler(func(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
|
|
if h, ok := d.cmdHandlers[i.ApplicationCommandData().Name]; ok {
|
|
|
|
h(s, i)
|
|
|
|
}
|
|
|
|
})
|
2020-08-31 16:20:52 +00:00
|
|
|
return d
|
|
|
|
}
|
2021-07-28 15:32:59 +00:00
|
|
|
func (d *Discord) GetRouter() (http.Handler, string) {
|
|
|
|
return nil, ""
|
|
|
|
}
|
2020-08-31 16:20:52 +00:00
|
|
|
|
|
|
|
func (d *Discord) RegisterEvent(callback bot.Callback) {
|
|
|
|
d.event = callback
|
|
|
|
}
|
|
|
|
|
2022-03-22 01:32:44 +00:00
|
|
|
func (d Discord) Send(kind bot.Kind, args ...any) (string, error) {
|
2020-08-31 16:20:52 +00:00
|
|
|
|
|
|
|
switch kind {
|
2020-10-24 13:54:18 +00:00
|
|
|
case bot.Ephemeral:
|
|
|
|
return d.sendMessage(args[0].(string), args[2].(string), false, args...)
|
2020-08-31 16:20:52 +00:00
|
|
|
case bot.Message:
|
2020-09-09 17:21:39 +00:00
|
|
|
return d.sendMessage(args[0].(string), args[1].(string), false, args...)
|
|
|
|
case bot.Action:
|
|
|
|
return d.sendMessage(args[0].(string), args[1].(string), true, args...)
|
|
|
|
case bot.Edit:
|
|
|
|
st, err := d.client.ChannelMessageEdit(args[0].(string), args[1].(string), args[2].(string))
|
2020-08-31 16:20:52 +00:00
|
|
|
return st.ID, err
|
2020-09-09 17:21:39 +00:00
|
|
|
case bot.Reply:
|
|
|
|
original, err := d.client.ChannelMessage(args[0].(string), args[1].(string))
|
|
|
|
msg := args[2].(string)
|
|
|
|
if err != nil {
|
|
|
|
log.Error().Err(err).Msg("could not get original")
|
|
|
|
} else {
|
2020-10-09 14:54:09 +00:00
|
|
|
msg = fmt.Sprintf("> %v\n%s", original, msg)
|
2020-09-09 17:21:39 +00:00
|
|
|
}
|
|
|
|
return d.sendMessage(args[0].(string), msg, false, args...)
|
|
|
|
case bot.Reaction:
|
|
|
|
msg := args[2].(msg.Message)
|
|
|
|
err := d.client.MessageReactionAdd(args[0].(string), msg.ID, args[1].(string))
|
|
|
|
return args[1].(string), err
|
|
|
|
case bot.Delete:
|
|
|
|
ch := args[0].(string)
|
|
|
|
id := args[1].(string)
|
|
|
|
err := d.client.ChannelMessageDelete(ch, id)
|
|
|
|
if err != nil {
|
|
|
|
log.Error().Err(err).Msg("cannot delete message")
|
|
|
|
}
|
|
|
|
return id, err
|
2020-08-31 16:20:52 +00:00
|
|
|
default:
|
|
|
|
log.Error().Msgf("discord.Send: unknown kind, %+v", kind)
|
|
|
|
return "", errors.New("unknown message type")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-22 01:32:44 +00:00
|
|
|
func (d *Discord) sendMessage(channel, message string, meMessage bool, args ...any) (string, error) {
|
2020-09-09 17:21:39 +00:00
|
|
|
if meMessage && !strings.HasPrefix(message, "_") && !strings.HasSuffix(message, "_") {
|
|
|
|
message = "_" + message + "_"
|
|
|
|
}
|
|
|
|
|
2022-09-06 21:21:45 +00:00
|
|
|
embeds := []*discordgo.MessageEmbed{}
|
2022-10-20 22:32:49 +00:00
|
|
|
files := []*discordgo.File{}
|
2020-09-09 17:21:39 +00:00
|
|
|
|
|
|
|
for _, arg := range args {
|
|
|
|
switch a := arg.(type) {
|
2022-09-06 21:21:45 +00:00
|
|
|
case bot.EmbedAuthor:
|
|
|
|
embed := &discordgo.MessageEmbed{}
|
|
|
|
embed.Author = &discordgo.MessageEmbedAuthor{
|
|
|
|
Name: a.Who,
|
|
|
|
IconURL: a.IconURL,
|
|
|
|
}
|
|
|
|
embeds = append(embeds, embed)
|
2020-09-09 17:21:39 +00:00
|
|
|
case bot.ImageAttachment:
|
2022-09-06 21:21:45 +00:00
|
|
|
embed := &discordgo.MessageEmbed{}
|
|
|
|
embed.Description = a.AltTxt
|
|
|
|
embed.Image = &discordgo.MessageEmbedImage{
|
2020-09-09 17:21:39 +00:00
|
|
|
URL: a.URL,
|
|
|
|
Width: a.Width,
|
|
|
|
Height: a.Height,
|
|
|
|
}
|
2022-09-06 21:21:45 +00:00
|
|
|
embeds = append(embeds, embed)
|
2022-10-20 22:32:49 +00:00
|
|
|
case bot.File:
|
|
|
|
files = append(files, &discordgo.File{
|
|
|
|
Name: a.FileName(),
|
|
|
|
ContentType: a.ContentType(),
|
|
|
|
Reader: bytes.NewBuffer(a.Data),
|
|
|
|
})
|
2020-09-09 17:21:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
data := &discordgo.MessageSend{
|
|
|
|
Content: message,
|
2022-09-06 21:21:45 +00:00
|
|
|
Embeds: embeds,
|
2022-10-20 22:32:49 +00:00
|
|
|
Files: files,
|
2020-09-09 17:21:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
log.Debug().
|
|
|
|
Interface("data", data).
|
|
|
|
Msg("sending message")
|
|
|
|
|
|
|
|
st, err := d.client.ChannelMessageSendComplex(channel, data)
|
|
|
|
|
|
|
|
//st, err := d.client.ChannelMessageSend(channel, message)
|
|
|
|
if err != nil {
|
2021-08-23 15:28:08 +00:00
|
|
|
log.Error().
|
|
|
|
Interface("data", data).
|
|
|
|
Str("channel", channel).
|
|
|
|
Err(err).
|
|
|
|
Msg("Error sending message")
|
2020-09-09 17:21:39 +00:00
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
return st.ID, err
|
|
|
|
}
|
|
|
|
|
2022-06-08 20:57:24 +00:00
|
|
|
func (d *Discord) GetEmojiList(force bool) map[string]string {
|
|
|
|
if d.emojiCache != nil && !force {
|
2020-08-31 16:20:52 +00:00
|
|
|
return d.emojiCache
|
|
|
|
}
|
2022-09-18 21:43:44 +00:00
|
|
|
e, err := d.client.GuildEmojis(d.guildID)
|
2020-08-31 16:20:52 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Error().Err(err).Msg("could not retrieve emojis")
|
|
|
|
return map[string]string{}
|
|
|
|
}
|
|
|
|
emojis := map[string]string{}
|
|
|
|
for _, e := range e {
|
|
|
|
emojis[e.ID] = e.Name
|
|
|
|
}
|
|
|
|
return emojis
|
|
|
|
}
|
|
|
|
|
2022-06-08 20:57:24 +00:00
|
|
|
func (d *Discord) GetEmojySnowflake(name string) string {
|
|
|
|
list := d.GetEmojiList(true)
|
|
|
|
for k, v := range list {
|
|
|
|
if name == v {
|
|
|
|
return k
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return name
|
|
|
|
}
|
|
|
|
|
2021-08-23 17:15:26 +00:00
|
|
|
// Who gets the users in the guild
|
|
|
|
// Note that the channel ID does not matter in this particular case
|
2020-08-31 16:20:52 +00:00
|
|
|
func (d *Discord) Who(id string) []string {
|
|
|
|
users := []string{}
|
2021-08-23 17:15:26 +00:00
|
|
|
for name, _ := range d.uidCache {
|
|
|
|
users = append(users, name)
|
2020-08-31 16:20:52 +00:00
|
|
|
}
|
|
|
|
return users
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Discord) Profile(id string) (user.User, error) {
|
2021-08-23 15:28:08 +00:00
|
|
|
if _, err := strconv.Atoi(id); err != nil {
|
|
|
|
if newID, ok := d.uidCache[id]; ok {
|
|
|
|
id = newID
|
|
|
|
} else {
|
|
|
|
return user.User{}, fmt.Errorf("invalid ID snowflake: %s", id)
|
|
|
|
}
|
|
|
|
}
|
2020-08-31 16:20:52 +00:00
|
|
|
u, err := d.client.User(id)
|
|
|
|
if err != nil {
|
|
|
|
log.Error().Err(err).Msg("Error getting user")
|
|
|
|
return user.User{}, err
|
|
|
|
}
|
2021-08-23 15:28:08 +00:00
|
|
|
user := d.convertUser(u)
|
|
|
|
d.uidCache[user.Name] = user.ID
|
|
|
|
return *user, nil
|
2020-08-31 16:20:52 +00:00
|
|
|
}
|
|
|
|
|
2020-09-09 17:21:39 +00:00
|
|
|
func (d *Discord) convertUser(u *discordgo.User) *user.User {
|
2021-10-22 20:44:36 +00:00
|
|
|
log.Debug().
|
|
|
|
Str("u.ID", u.ID).
|
|
|
|
Msg("")
|
2020-09-09 17:21:39 +00:00
|
|
|
img, err := d.client.UserAvatar(u.ID)
|
|
|
|
if err != nil {
|
|
|
|
log.Error().Err(err).Msg("error getting avatar")
|
|
|
|
}
|
2021-08-20 17:47:33 +00:00
|
|
|
nick := u.Username
|
|
|
|
|
2022-09-18 21:43:44 +00:00
|
|
|
mem, err := d.client.GuildMember(d.guildID, u.ID)
|
|
|
|
if err != nil {
|
|
|
|
log.Error().Err(err).Msg("could not get guild member")
|
|
|
|
} else if mem.Nick != "" {
|
|
|
|
nick = mem.Nick
|
2021-08-20 17:47:33 +00:00
|
|
|
}
|
|
|
|
|
2020-08-31 16:20:52 +00:00
|
|
|
return &user.User{
|
2020-09-09 17:21:39 +00:00
|
|
|
ID: u.ID,
|
2021-08-20 17:47:33 +00:00
|
|
|
Name: nick,
|
2020-09-09 17:21:39 +00:00
|
|
|
Admin: false,
|
2021-02-18 22:59:05 +00:00
|
|
|
Icon: d.client.State.User.AvatarURL("64"),
|
2020-09-09 17:21:39 +00:00
|
|
|
IconImg: img,
|
2020-08-31 16:20:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Discord) Serve() error {
|
|
|
|
log.Debug().Msg("starting discord serve function")
|
|
|
|
|
2022-05-30 20:34:42 +00:00
|
|
|
d.client.Identify.Intents = discordgo.MakeIntent(
|
|
|
|
discordgo.IntentsGuilds |
|
|
|
|
discordgo.IntentsGuildMessages |
|
2022-08-11 10:25:22 +00:00
|
|
|
discordgo.IntentsDirectMessages |
|
2022-05-30 20:34:42 +00:00
|
|
|
discordgo.IntentsGuildEmojis |
|
|
|
|
discordgo.IntentsGuildMessageReactions)
|
2020-08-31 16:20:52 +00:00
|
|
|
|
|
|
|
err := d.client.Open()
|
|
|
|
if err != nil {
|
2021-08-20 00:37:53 +00:00
|
|
|
log.Fatal().Err(err).Msg("error opening client")
|
2020-08-31 16:20:52 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Debug().Msg("discord connection open")
|
|
|
|
|
|
|
|
d.client.AddHandler(d.messageCreate)
|
2022-05-30 20:34:42 +00:00
|
|
|
d.client.AddHandler(d.messageReactAdd)
|
2020-08-31 16:20:52 +00:00
|
|
|
|
2020-09-09 17:21:39 +00:00
|
|
|
return nil
|
2020-08-31 16:20:52 +00:00
|
|
|
}
|
|
|
|
|
2022-05-30 20:34:42 +00:00
|
|
|
func (d *Discord) messageReactAdd(s *discordgo.Session, m *discordgo.MessageReactionAdd) {
|
|
|
|
log.Debug().Msg("messageReactAdd")
|
|
|
|
author, _ := d.Profile(m.UserID)
|
|
|
|
ch, err := s.Channel(m.ChannelID)
|
|
|
|
if err != nil {
|
|
|
|
log.Error().Err(err).Msg("error getting channel info")
|
|
|
|
}
|
|
|
|
msg := msg.Message{
|
|
|
|
ID: m.MessageID,
|
2022-05-31 15:19:37 +00:00
|
|
|
Kind: bot.Reaction,
|
2022-05-30 20:34:42 +00:00
|
|
|
User: &author,
|
|
|
|
Channel: m.ChannelID,
|
|
|
|
ChannelName: ch.Name,
|
|
|
|
Body: m.Emoji.Name,
|
|
|
|
Time: time.Now(),
|
|
|
|
AdditionalData: map[string]string{
|
|
|
|
"messageFormat": m.Emoji.MessageFormat(),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
d.event(d, bot.Reaction, msg)
|
|
|
|
}
|
|
|
|
|
2020-08-31 16:20:52 +00:00
|
|
|
func (d *Discord) messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
|
2021-08-23 15:28:08 +00:00
|
|
|
// if we haven't seen this user, we need to resolve their nick before continuing
|
|
|
|
author, _ := d.Profile(m.Author.ID)
|
|
|
|
|
2020-08-31 16:20:52 +00:00
|
|
|
if m.Author.ID == s.State.User.ID {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-09-09 17:21:39 +00:00
|
|
|
ch, err := s.Channel(m.ChannelID)
|
|
|
|
if err != nil {
|
|
|
|
log.Error().Err(err).Msg("error getting channel info")
|
|
|
|
}
|
|
|
|
|
|
|
|
isCmd, text := bot.IsCmd(d.config, m.Content)
|
|
|
|
|
2022-03-22 13:41:11 +00:00
|
|
|
tStamp := m.Timestamp
|
2020-09-09 17:21:39 +00:00
|
|
|
|
2020-08-31 16:20:52 +00:00
|
|
|
msg := msg.Message{
|
2020-09-09 17:21:39 +00:00
|
|
|
ID: m.ID,
|
2022-05-31 15:19:37 +00:00
|
|
|
Kind: bot.Message,
|
2021-08-23 15:28:08 +00:00
|
|
|
User: &author,
|
2020-08-31 16:20:52 +00:00
|
|
|
Channel: m.ChannelID,
|
2020-09-09 17:21:39 +00:00
|
|
|
ChannelName: ch.Name,
|
|
|
|
Body: text,
|
|
|
|
Command: isCmd,
|
|
|
|
Time: tStamp,
|
2020-08-31 16:20:52 +00:00
|
|
|
}
|
|
|
|
|
2020-10-09 16:04:43 +00:00
|
|
|
d.event(d, bot.Message, msg)
|
2020-08-31 16:20:52 +00:00
|
|
|
}
|
2020-12-02 14:53:57 +00:00
|
|
|
|
|
|
|
func (d *Discord) Emojy(name string) string {
|
|
|
|
e := d.config.GetMap("discord.emojy", map[string]string{})
|
|
|
|
if emojy, ok := e[name]; ok {
|
|
|
|
return emojy
|
|
|
|
}
|
|
|
|
return name
|
|
|
|
}
|
|
|
|
|
2022-06-08 20:57:24 +00:00
|
|
|
func (d *Discord) UploadEmojy(emojy, path string) error {
|
|
|
|
defaultRoles := d.config.GetArray("discord.emojyRoles", []string{})
|
2022-09-18 21:43:44 +00:00
|
|
|
_, err := d.client.GuildEmojiCreate(d.guildID, &discordgo.EmojiParams{
|
2022-09-06 21:21:45 +00:00
|
|
|
emojy, path, defaultRoles,
|
|
|
|
})
|
2022-06-08 20:57:24 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Discord) DeleteEmojy(emojy string) error {
|
|
|
|
emojyID := d.GetEmojySnowflake(emojy)
|
2022-09-18 21:43:44 +00:00
|
|
|
return d.client.GuildEmojiDelete(d.guildID, emojyID)
|
2022-06-08 20:57:24 +00:00
|
|
|
}
|
|
|
|
|
2020-12-02 14:53:57 +00:00
|
|
|
func (d *Discord) URLFormat(title, url string) string {
|
|
|
|
return fmt.Sprintf("%s (%s)", title, url)
|
|
|
|
}
|
2021-04-28 20:48:02 +00:00
|
|
|
|
|
|
|
// GetChannelName returns the channel ID for a human-friendly name (if possible)
|
|
|
|
func (d *Discord) GetChannelID(name string) string {
|
2022-09-18 21:43:44 +00:00
|
|
|
chs, err := d.client.GuildChannels(d.guildID)
|
2021-04-28 20:48:02 +00:00
|
|
|
if err != nil {
|
|
|
|
return name
|
|
|
|
}
|
|
|
|
for _, ch := range chs {
|
|
|
|
if ch.Name == name {
|
|
|
|
return ch.ID
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return name
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetChannelName returns the human-friendly name for an ID (if possible)
|
|
|
|
func (d *Discord) GetChannelName(id string) string {
|
|
|
|
ch, err := d.client.Channel(id)
|
|
|
|
if err != nil {
|
|
|
|
return id
|
|
|
|
}
|
|
|
|
return ch.Name
|
|
|
|
}
|
2021-11-20 20:28:53 +00:00
|
|
|
|
|
|
|
func (d *Discord) GetRoles() ([]bot.Role, error) {
|
|
|
|
ret := []bot.Role{}
|
|
|
|
|
2022-09-18 21:43:44 +00:00
|
|
|
roles, err := d.client.GuildRoles(d.guildID)
|
2021-11-20 20:28:53 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, r := range roles {
|
|
|
|
ret = append(ret, bot.Role{
|
|
|
|
ID: r.ID,
|
|
|
|
Name: r.Name,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Discord) SetRole(userID, roleID string) error {
|
2022-09-18 21:43:44 +00:00
|
|
|
member, err := d.client.GuildMember(d.guildID, userID)
|
2021-11-20 20:28:53 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
for _, r := range member.Roles {
|
|
|
|
if r == roleID {
|
2022-09-18 21:43:44 +00:00
|
|
|
return d.client.GuildMemberRoleRemove(d.guildID, userID, roleID)
|
2021-11-20 20:28:53 +00:00
|
|
|
}
|
|
|
|
}
|
2022-09-18 21:43:44 +00:00
|
|
|
return d.client.GuildMemberRoleAdd(d.guildID, userID, roleID)
|
2021-11-20 20:28:53 +00:00
|
|
|
}
|
2022-07-22 21:04:51 +00:00
|
|
|
|
2022-07-23 04:17:44 +00:00
|
|
|
type CmdHandler func(s *discordgo.Session, i *discordgo.InteractionCreate)
|
|
|
|
|
|
|
|
func (d *Discord) RegisterSlashCmd(c discordgo.ApplicationCommand, handler CmdHandler) error {
|
2022-09-18 21:43:44 +00:00
|
|
|
cmd, err := d.client.ApplicationCommandCreate(d.client.State.User.ID, d.guildID, &c)
|
2022-07-23 04:17:44 +00:00
|
|
|
d.cmdHandlers[c.Name] = handler
|
2022-07-22 21:04:51 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
d.registeredCmds = append(d.registeredCmds, cmd)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Discord) Shutdown() {
|
|
|
|
log.Debug().Msgf("Shutting down and deleting %d slash commands", len(d.registeredCmds))
|
|
|
|
for _, c := range d.registeredCmds {
|
2022-09-18 21:43:44 +00:00
|
|
|
if err := d.client.ApplicationCommandDelete(d.client.State.User.ID, d.guildID, c.ID); err != nil {
|
2022-07-22 21:04:51 +00:00
|
|
|
log.Error().Err(err).Msgf("could not delete command %s", c.Name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-08-02 17:26:49 +00:00
|
|
|
|
|
|
|
func (d *Discord) Nick(nick string) error {
|
2022-09-18 21:43:44 +00:00
|
|
|
return d.client.GuildMemberNickname(d.guildID, "@me", nick)
|
2022-08-02 17:26:49 +00:00
|
|
|
}
|
2022-08-16 23:55:07 +00:00
|
|
|
|
|
|
|
func (d *Discord) Topic(channelID string) (string, error) {
|
|
|
|
channel, err := d.client.Channel(channelID)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
return channel.Topic, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Discord) SetTopic(channelID, topic string) error {
|
|
|
|
ce := &discordgo.ChannelEdit{
|
|
|
|
Topic: topic,
|
|
|
|
}
|
|
|
|
_, err := d.client.ChannelEditComplex(channelID, ce)
|
|
|
|
return err
|
|
|
|
}
|
2022-09-18 21:43:44 +00:00
|
|
|
|
|
|
|
type ThreadStart struct {
|
|
|
|
Name string `json:"name"`
|
|
|
|
AutoArchiveDuration int `json:"auto_archive_duration,omitempty"`
|
|
|
|
RateLimitPerUser int `json:"rate_limit_per_user,omitempty"`
|
|
|
|
AppliedTags []string `json:"applied_tags,omitempty"`
|
|
|
|
Message ForumMessageData `json:"message"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type ForumMessageData struct {
|
|
|
|
Content string `json:"content"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Discord) CreateRoom(name, message, parent string, duration int) (string, error) {
|
|
|
|
data := &ThreadStart{
|
|
|
|
Name: name,
|
|
|
|
AutoArchiveDuration: duration,
|
|
|
|
Message: ForumMessageData{message},
|
|
|
|
}
|
|
|
|
ch := &discordgo.Channel{}
|
|
|
|
endpoint := discordgo.EndpointChannelThreads(parent)
|
|
|
|
body, err := d.client.RequestWithBucketID("POST", endpoint, data, endpoint)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err = discordgo.Unmarshal(body, &ch); err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
return ch.ID, nil
|
|
|
|
}
|