Initial commit

This commit is contained in:
jacks0n9 2023-06-30 10:34:13 -07:00
commit 7d554f3c9e
7 changed files with 263 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.env

63
command_structs.go Normal file
View File

@ -0,0 +1,63 @@
package haccerinteractions
import "github.com/bwmarrin/discordgo"
type Command struct {
Type int `json:"type"`
ID string `json:"id"`
ApplicationID string `json:"application_id"`
Name string `json:"name"`
Version string `json:"version"`
Options []CommandOption `json:"options"`
}
type GuildChannel struct {
GuildID string
ChannelID string
}
type commandRunRequest struct {
Type int `json:"type"`
BotID string `json:"application_id"`
GuildID string `json:"guild_id"`
ChannelID string `json:"channel_id"`
SessionID string `json:"session_id"`
Data commandRunData `json:"data"`
}
type commandRunData struct {
ID string `json:"id"`
Type int `json:"type"`
Name string `json:"name"`
Version string `json:"version"`
Options []CommandRunOption `json:"options"`
}
type CommandRunOption struct {
Type int `json:"type"`
Name string `json:"name"`
Value string `json:"value"`
}
type CommandSearchResponse struct {
Commands []Command `json:"application_commands"`
}
type CommandOption struct {
Type int `json:"type"`
Name string `json:"name"`
}
type ComponentInteractRequest struct {
Type discordgo.InteractionType `json:"type"`
Flags int `json:"message_flags"`
SessionID string `json:"session_id"`
Nonce string `json:"nonce"`
GuildID string `json:"guild_id"`
ChannelID string `json:"channel_id"`
MessageID string `json:"message_id"`
BotID string `json:"application_id"`
Data interface{} `json:"data"`
}
type ButtonClickRequestData struct{}
type SelectMenuSelectRequestData struct {
Type discordgo.SelectMenuType `json:"type"`
Values []string `json:"values"`
}

11
go.mod Normal file
View File

@ -0,0 +1,11 @@
module github.com/jacks0n9/haccerinteractions
go 1.20
require github.com/bwmarrin/discordgo v0.27.1
require (
github.com/gorilla/websocket v1.4.2 // indirect
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b // indirect
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 // indirect
)

12
go.sum Normal file
View File

@ -0,0 +1,12 @@
github.com/bwmarrin/discordgo v0.27.1 h1:ib9AIc/dom1E/fSIulrBwnez0CToJE113ZGt4HoliGY=
github.com/bwmarrin/discordgo v0.27.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b h1:7mWr3k41Qtv8XlltBkDkl8LoP3mpSgBW8BUoxtEdbXg=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

95
haccerinteractions.go Normal file
View File

@ -0,0 +1,95 @@
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
}

35
readme.md Normal file
View File

@ -0,0 +1,35 @@
# Haccerinteractions
## Welcome to Haccerinteractions, a package for advanced selfbotters
Haccerinteractions is a package that expands the selfbotting capabilities of discordgo by giving you the ability to run slash commands, get their output, and interact with message components like buttons.
## Getting started
After installing and importing Haccerinteractions, follow these steps.
### Create a new discordgo session
Because Haccerinteractions is powered by discordgo, you first need to make a session with this code:
```go
session,_:=discordgo.New("insert_token_here")
```
### Create a Haccerinteractions runner
This will be the thing that runs commands and clicks buttons. Use this code to make a runner:
```go
runner:=haccerinteractions.NewRunner(session)
```
This will configure required parameters within your session as well as opening a gateway connection.
### Get commands
You first must get commands for a channel with this code:
```go
// You can leave the application/bot id empty.
// The limit is ignored when the bot_id is set, however
commands,err:=runner.GuildChannelGetSlashCommands("channel_id_here",10,"bot_id_here")
```
### Run Commands
```go
// Run a command.
// Set arguments to nil to pass no arguments
responseMessage,err:=runner.GuildChannelRunCommand(commands[0],nil,"channel_id_here")
```
### Interact with components
```go
// You can interact with various components by using different request data structs
button:=responseMessage.Components[0].(*discordgo.ActionsRow).Components[0].(*discordgo.Button)
runner.GuildChannelComponentRequest("channel_id_here",responseMessage.ID,"bot_id_here",button.CustomID,haccerinteractions.ButtonClickRequestData{})
```

46
run_command.go Normal file
View File

@ -0,0 +1,46 @@
package haccerinteractions
import (
"net/http"
"github.com/bwmarrin/discordgo"
)
// Run a command in a channel
func (hir *haccerInteractionsRunner) GuildChannelRunCommand(c Command, args *[]CommandRunOption, gc GuildChannel) (*discordgo.Message, error) {
if args == nil {
args = &[]CommandRunOption{}
}
reqData := commandRunRequest{
Type: 2,
BotID: c.ApplicationID,
GuildID: gc.GuildID,
ChannelID: gc.ChannelID,
SessionID: hir.Session.State.SessionID,
Data: commandRunData{
ID: c.ID,
Type: c.Type,
Name: c.Name,
Version: c.Version,
Options: *args,
},
}
_, err := hir.Session.Request(http.MethodPost, "https://discord.com/api/v9/interactions", reqData)
if err != nil {
return nil, err
}
cmdMutex := hir.getCommandMutex(c.Name)
cmdMutex.Lock()
commandRespChan := make(chan discordgo.Message)
hir.Session.AddHandler(func(s *discordgo.Session, m *discordgo.MessageCreate) {
if m.Interaction == nil {
return
}
if m.Interaction.User.ID == s.State.User.ID && m.Interaction.Name == c.Name {
commandRespChan <- *m.Message
cmdMutex.Unlock()
}
})
cmdRespMsg := <-commandRespChan
return &cmdRespMsg, nil
}