96 lines
2.8 KiB
Go
96 lines
2.8 KiB
Go
package haccerinteractions
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"math/rand"
|
|
"net/http"
|
|
"net/url"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/bwmarrin/discordgo"
|
|
)
|
|
|
|
type haccerInteractionsRunner struct {
|
|
Session *discordgo.Session
|
|
commandRunLock map[string]*sync.Mutex
|
|
}
|
|
|
|
func (hir *haccerInteractionsRunner) getCommandMutex(name string) *sync.Mutex {
|
|
if _, ok := hir.commandRunLock[name]; !ok {
|
|
newMutex := sync.Mutex{}
|
|
hir.commandRunLock[name] = &newMutex
|
|
return &newMutex
|
|
}
|
|
return hir.commandRunLock[name]
|
|
}
|
|
|
|
// Create a command runner
|
|
func NewRunner(s *discordgo.Session) haccerInteractionsRunner {
|
|
s.StateEnabled = true
|
|
s.Identify.Intents = discordgo.IntentsAll
|
|
s.Open()
|
|
newRunner := haccerInteractionsRunner{
|
|
Session: s,
|
|
commandRunLock: make(map[string]*sync.Mutex),
|
|
}
|
|
return newRunner
|
|
}
|
|
|
|
// Get slash commands in a channel. Limit is ignored if application id is set.
|
|
func (hir haccerInteractionsRunner) GuildChannelGetSlashCommands(channelID string, limit int, applicationID string) (*[]Command, error) {
|
|
payload := url.Values{}
|
|
payload.Add("type", "1")
|
|
if applicationID != "" {
|
|
payload.Add("application_id", applicationID)
|
|
} else {
|
|
payload.Add("limit", fmt.Sprint(limit))
|
|
}
|
|
response, err := hir.Session.Request(http.MethodGet, fmt.Sprintf(`https://discord.com/api/v9/channels/%s/application-commands/search?%s`, channelID, payload.Encode()), nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
searchResponse := CommandSearchResponse{}
|
|
json.Unmarshal(response, &searchResponse)
|
|
return &searchResponse.Commands, nil
|
|
}
|
|
|
|
// Interact with a component
|
|
// Remember that the top level components in a message are action rows.
|
|
func (hir haccerInteractionsRunner) GuildChannelComponentRequest(gc GuildChannel, messageID string, botID string, customID string, data interface{}) error {
|
|
var dataMap map[string]interface{}
|
|
jsonEncoded, err := json.Marshal(data)
|
|
if err != nil {
|
|
return errors.New("error encoding data to json for component type detection: " + err.Error())
|
|
}
|
|
json.Unmarshal(jsonEncoded, &dataMap)
|
|
var componentType discordgo.ComponentType
|
|
switch data.(type) {
|
|
case ButtonClickRequestData:
|
|
componentType = discordgo.ButtonComponent
|
|
case SelectMenuSelectRequestData:
|
|
componentType = dataMap["type"].(discordgo.ComponentType)
|
|
}
|
|
|
|
dataMap["component_type"] = componentType
|
|
dataMap["custom_id"] = customID
|
|
source := rand.NewSource(int64(time.Now().Nanosecond()))
|
|
gen := rand.New(source)
|
|
requestStruct := ComponentInteractRequest{
|
|
Type: discordgo.InteractionMessageComponent,
|
|
Flags: 0,
|
|
SessionID: hir.Session.State.SessionID,
|
|
Nonce: fmt.Sprint(gen.Intn(99999999999999)),
|
|
GuildID: gc.GuildID,
|
|
ChannelID: gc.ChannelID,
|
|
MessageID: messageID,
|
|
BotID: botID,
|
|
Data: dataMap,
|
|
}
|
|
_, err = hir.Session.Request(http.MethodPost, "https://discord.com/api/v9/interactions", requestStruct)
|
|
return err
|
|
}
|