├── proxies.txt
├── tokens.txt
├── .gitattributes
├── images
└── screenshot.png
├── .gitignore
├── .idea
├── vcs.xml
├── .gitignore
├── discord.xml
├── modules.xml
├── inspectionProfiles
│ └── Project_Default.xml
└── DiscSpam.iml
├── go.mod
├── utils
├── command_line_parser.go
├── logger.go
├── clearScreen.go
├── readTokens.go
├── checkTokens.go
├── fakeDeviceInfo.go
└── webSocket.go
├── constants
└── consts.go
├── cloudflare
└── cf.go
├── LICENSE
├── interact
├── massping.go
├── status.go
├── message.go
├── reactions.go
└── friends.go
├── server
├── leave.go
├── nickname.go
└── join.go
├── go.sum
├── gateway
├── types.go
├── scraping.go
└── gateway.go
├── tools
└── create_client.go
├── README.md
└── main.go
/proxies.txt:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/tokens.txt:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/images/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Soliux/DiscSpam/HEAD/images/screenshot.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | release_ready/
2 | DiscSpam - Linux.tar
3 | DiscSpam - Windows.zip
4 | DiscSpam.exe
5 | tokens.txt
6 | old_tokens.txt
7 | DiscSpam.log
8 | test.py
9 | beans.py
10 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 | # Datasource local storage ignored files
7 | /dataSources/
8 | /dataSources.local.xml
9 |
--------------------------------------------------------------------------------
/.idea/discord.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module Raid-Client
2 |
3 | go 1.16
4 |
5 | require (
6 | github.com/gookit/color v1.4.2
7 | github.com/gorilla/websocket v1.4.2
8 | github.com/kyokomi/emoji/v2 v2.2.8
9 | github.com/patrickmn/go-cache v2.1.0+incompatible
10 | github.com/tidwall/gjson v1.12.1
11 | )
12 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/utils/command_line_parser.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "flag"
5 | )
6 |
7 | func Get_commandline_values() (*bool, *bool) {
8 | log := flag.Bool("log", false, "Log to an external file")
9 | proxy := flag.Bool("proxy", false, "Use proxies when interacting with discord.com")
10 | flag.Parse()
11 | return log, proxy
12 | }
13 |
--------------------------------------------------------------------------------
/.idea/DiscSpam.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/constants/consts.go:
--------------------------------------------------------------------------------
1 | package constants
2 |
3 | import (
4 | "os"
5 | "sync"
6 |
7 | "github.com/gookit/color"
8 | )
9 |
10 | var (
11 | // Define some of our colours so that we can print nicely to the console
12 | White = color.FgWhite.Render
13 | Red = color.FgRed.Render
14 | Green = color.FgGreen.Render
15 | Yellow = color.FgYellow.Render
16 |
17 | // Define some other variables that will exist for the runtime of the program
18 | Tokens []string
19 | Proxies []string
20 | Wg sync.WaitGroup
21 | Logging bool
22 | Proxy bool
23 | LogFile *os.File
24 | )
25 |
--------------------------------------------------------------------------------
/utils/logger.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "Raid-Client/constants"
5 | "fmt"
6 | "log"
7 | "os"
8 | "strings"
9 | )
10 |
11 | func SetupLogger() {
12 | if constants.Logging {
13 | constants.LogFile, _ = os.OpenFile("DiscSpam.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
14 | log.SetOutput(constants.LogFile)
15 | }
16 | }
17 |
18 | func Logger(contents ...interface{}) {
19 | if constants.Logging {
20 | content := formatMessage(contents...)
21 | log.Println(content)
22 |
23 | }
24 | }
25 | func formatMessage(args ...interface{}) string {
26 | msg := fmt.Sprintln(args...)
27 | msg = strings.TrimRight(msg, " \n\r")
28 | return msg
29 | }
30 |
--------------------------------------------------------------------------------
/cloudflare/cf.go:
--------------------------------------------------------------------------------
1 | package cloudflare
2 |
3 | import (
4 | "fmt"
5 | "log"
6 | "net/http"
7 | "time"
8 | )
9 |
10 | func Cookie() string {
11 | url := "https://discord.com"
12 | httpClient := http.Client{
13 | Timeout: time.Second * 2,
14 | }
15 | req, err := http.NewRequest("GET", url, nil)
16 | if err != nil {
17 | log.Fatal(err)
18 | }
19 | resp, err := httpClient.Do(req)
20 | if err != nil {
21 | log.Fatal(err)
22 | }
23 | defer resp.Body.Close()
24 | responseCookies := resp.Cookies()
25 | dfcCookie := responseCookies[0].Value
26 | sdcCookie := responseCookies[1].Value
27 | return fmt.Sprintf("__dcfduid=%s; __sdcfduid=%s; locale=en-GB", dfcCookie, sdcCookie)
28 | }
29 |
--------------------------------------------------------------------------------
/utils/clearScreen.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "os"
5 | "os/exec"
6 | "runtime"
7 | )
8 |
9 | func ClearScreen() {
10 | /*
11 | Here we are creating a cross platform clear screen function. This function has the ability to detect the operating system it is being ran on and then clear the screen accordingly.
12 | */
13 | if runtime.GOOS == "windows" {
14 | cmd := exec.Command("cmd", "/c", "cls")
15 | cmd.Stdout = os.Stdout
16 | cmd.Run()
17 | } else if runtime.GOOS == "linux" {
18 | cmd := exec.Command("clear")
19 | cmd.Stdout = os.Stdout
20 | cmd.Run()
21 | } else {
22 | cmd := exec.Command("clear")
23 | cmd.Stdout = os.Stdout
24 | cmd.Run()
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/utils/readTokens.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "bufio"
5 | "fmt"
6 | "os"
7 | )
8 |
9 | func ReadTokens(path string) ([]string, error) {
10 | file, err := os.Open(path)
11 | if err != nil {
12 | return nil, err
13 | }
14 | defer file.Close()
15 |
16 | var lines []string
17 | scanner := bufio.NewScanner(file)
18 | for scanner.Scan() {
19 | lines = append(lines, scanner.Text())
20 | }
21 | return lines, scanner.Err()
22 | }
23 |
24 | func WriteLines(lines []string, path string) error {
25 | file, err := os.Create(path)
26 | if err != nil {
27 | return err
28 | }
29 | defer file.Close()
30 |
31 | w := bufio.NewWriter(file)
32 | for _, line := range lines {
33 | fmt.Fprintln(w, line)
34 | }
35 | return w.Flush()
36 | }
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Sympthey
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/interact/massping.go:
--------------------------------------------------------------------------------
1 | package interact
2 |
3 | import (
4 | "Raid-Client/utils"
5 | "fmt"
6 | "sync"
7 | "time"
8 | )
9 |
10 | var wg sync.WaitGroup
11 |
12 | func MassPing(guildID, channelID string, scrapedID, tokens []string, amount int) {
13 |
14 | var toSend []string
15 | var message string
16 | for _, ID := range scrapedID {
17 | if len(message) < 1950 {
18 | message += fmt.Sprintf("<@!%s>ඞ", fmt.Sprint(ID))
19 | } else {
20 | toSend = append(toSend, message)
21 | message = ""
22 | }
23 | }
24 | toSend = append(toSend, message)
25 |
26 | /*
27 | Amount = 2
28 | Tokens = 50
29 | Messages = 20
30 |
31 | totalMessages = Amount*(Tokens*Messages)
32 | */
33 | fmt.Println("Sending a total of:", amount*(len(toSend)*len(tokens)), "messages")
34 |
35 | for _, token := range tokens {
36 | wg.Add(1)
37 | go func(t, c, s string, a int) {
38 | defer wg.Done()
39 | for i := 0; i < amount; i++ {
40 | for _, m := range toSend {
41 | time.Sleep(time.Millisecond * 100)
42 | utils.Logger("Sending:", m[:200], t, "Amount:", i)
43 | err := SendMessage(s, c, t, m)
44 | if err != nil {
45 | break
46 | }
47 | }
48 | }
49 | }(token, channelID, guildID, amount)
50 |
51 | }
52 | wg.Wait()
53 | }
54 |
--------------------------------------------------------------------------------
/interact/status.go:
--------------------------------------------------------------------------------
1 | package interact
2 |
3 | import (
4 | "Raid-Client/constants"
5 | "Raid-Client/gateway"
6 | "Raid-Client/utils"
7 | "fmt"
8 | "time"
9 | )
10 |
11 | var TOKENS []string
12 | var updating bool
13 |
14 | func ChangeStatus() {
15 | defer handlePanic()
16 | if !updating {
17 | time.Sleep(100 * time.Millisecond)
18 | for _, token := range TOKENS {
19 | ws := gateway.SetupWebSocket(token)
20 | go gateway.RecieveIncomingPayloads(ws, token)
21 | for {
22 | if gateway.WSConnected {
23 | gateway.SetStatus(gateway.Status, ws)
24 | utils.Logger(fmt.Sprintf("%s has updated their status", token))
25 | fmt.Printf("%s %s\n", constants.White(token), constants.Green("| Successfully set the status"))
26 | ws.Close()
27 | break
28 | }
29 | }
30 | }
31 | }
32 | }
33 |
34 | // Loop presence message every 60s
35 | func loopMessage() {
36 | for {
37 | time.Sleep(100 * time.Second)
38 | updating = true
39 | for _, tkn := range TOKENS {
40 | time.Sleep(100 * time.Millisecond)
41 | ws := gateway.SetupWebSocket(tkn)
42 | go gateway.RecieveIncomingPayloads(ws, tkn)
43 |
44 | for {
45 | if gateway.WSConnected {
46 | gateway.SetStatus(gateway.Status, ws)
47 | ws.Close()
48 | break
49 | }
50 | }
51 | }
52 | updating = false
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/server/leave.go:
--------------------------------------------------------------------------------
1 | package server
2 |
3 | import (
4 | "Raid-Client/cloudflare"
5 | "Raid-Client/constants"
6 | "Raid-Client/tools"
7 | "Raid-Client/utils"
8 | "bytes"
9 | "context"
10 | "encoding/json"
11 | "errors"
12 | "fmt"
13 | "net/http"
14 | "os"
15 | )
16 |
17 | func LeaveServer(serverID string, token string) error {
18 | defer handlePanic()
19 | payload := map[string]string{"lurking": "false"}
20 | payloadBuf := new(bytes.Buffer)
21 | json.NewEncoder(payloadBuf).Encode(payload)
22 | request, err := http.NewRequest("DELETE", fmt.Sprintf("https://discord.com/api/v9/users/@me/guilds/%s", serverID), payloadBuf)
23 | if err != nil {
24 | return err
25 | }
26 | cf := cloudflare.Cookie()
27 | xprop := utils.XSuperProperties()
28 | request.Header = http.Header{
29 | "Accept": []string{"*/*"},
30 | "Accept-language": []string{"en-GB"},
31 | "Authorization": []string{token},
32 | "Content-length": []string{"2"},
33 | "Content-type": []string{"application/json"},
34 | "Cookie": []string{cf},
35 | "Origin": []string{"https://discord.com"},
36 | "Sec-fetch-dest": []string{"empty"},
37 | "Sec-fetch-mode": []string{"cors"},
38 | "Sec-fetch-site": []string{"same-origin"},
39 | "User-agent": []string{"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) discord/0.0.15 Chrome/83.0.4103.122 Electron/9.3.5 Safari/537.36"},
40 | "X-debug-options": []string{"bugReporterEnabled"},
41 | "X-super-properties": []string{xprop},
42 | }
43 |
44 | client := tools.CreateHttpClient()
45 | defer client.CloseIdleConnections()
46 |
47 | res, err := client.Do(request)
48 | if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) || os.IsTimeout(err) {
49 | fmt.Printf("%s %s\n", constants.Yellow(token), constants.Red("[!] Timed out"))
50 | return err
51 | }
52 |
53 | switch res.StatusCode {
54 | case 204:
55 | utils.Logger(fmt.Sprintf("%s has successfully left %s", token, serverID))
56 | fmt.Printf("%s %s %s\n", constants.White(token), constants.Green("| Successfully Left"), constants.White(serverID))
57 | case 200:
58 | utils.Logger(fmt.Sprintf("%s has successfully left %s", token, serverID))
59 | fmt.Printf("%s %s %s\n", constants.White(token), constants.Green("| Successfully Left"), constants.White(serverID))
60 | default:
61 | utils.Logger(fmt.Sprintf("%s was unable to leave %s", token, serverID))
62 | fmt.Printf("%s %s %s\n", constants.White(token), constants.Red("| Cannot Leave"), constants.White(serverID))
63 | }
64 |
65 | return nil
66 | }
67 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
2 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3 | github.com/gookit/color v1.4.2 h1:tXy44JFSFkKnELV6WaMo/lLfu/meqITX3iAV52do7lk=
4 | github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ=
5 | github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
6 | github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
7 | github.com/kyokomi/emoji/v2 v2.2.8 h1:jcofPxjHWEkJtkIbcLHvZhxKgCPl6C7MyjTrD4KDqUE=
8 | github.com/kyokomi/emoji/v2 v2.2.8/go.mod h1:JUcn42DTdsXJo1SWanHh4HKDEyPaR5CqkmoirZZP9qE=
9 | github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
10 | github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
11 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
12 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
13 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
14 | github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
15 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
16 | github.com/tidwall/gjson v1.12.1 h1:ikuZsLdhr8Ws0IdROXUS1Gi4v9Z4pGqpX/CvJkxvfpo=
17 | github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
18 | github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
19 | github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
20 | github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
21 | github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
22 | github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8=
23 | github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
24 | golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44 h1:Bli41pIlzTzf3KEY06n+xnzK/BESIg2ze4Pgfh/aI8c=
25 | golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
26 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
27 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
28 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
29 |
--------------------------------------------------------------------------------
/server/nickname.go:
--------------------------------------------------------------------------------
1 | package server
2 |
3 | import (
4 | "Raid-Client/cloudflare"
5 | "Raid-Client/constants"
6 | "Raid-Client/tools"
7 | "Raid-Client/utils"
8 | "bytes"
9 | "context"
10 | "encoding/json"
11 | "errors"
12 | "fmt"
13 | "net/http"
14 | "os"
15 | )
16 |
17 | func ChangeNickname(ServerID string, Token string, Nickname string) error {
18 | defer handlePanic()
19 | payload := map[string]string{
20 | "nick": Nickname,
21 | }
22 |
23 | payloadBuf := new(bytes.Buffer)
24 | json.NewEncoder(payloadBuf).Encode(payload)
25 |
26 | request, err := http.NewRequest("PATCH", fmt.Sprintf("https://discord.com/api/v9/guilds/%s/members/%s", ServerID, "%40me"), payloadBuf)
27 | if err != nil {
28 | return err
29 | }
30 |
31 | cf := cloudflare.Cookie()
32 | xprop := utils.XSuperProperties()
33 |
34 | request.Header = http.Header{
35 | "Accept": []string{"*/*"},
36 | "Accept-language": []string{"en-GB"},
37 | "Authorization": []string{Token},
38 | "Content-length": []string{"2"},
39 | "Content-type": []string{"application/json"},
40 | "Cookie": []string{cf},
41 | "Origin": []string{"https://discord.com"},
42 | "Referrer": []string{fmt.Sprintf("https://discord.com/channels/%s", ServerID)},
43 | "Sec-fetch-dest": []string{"empty"},
44 | "Sec-fetch-mode": []string{"cors"},
45 | "Sec-fetch-site": []string{"same-origin"},
46 | "User-agent": []string{"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) discord/0.0.15 Chrome/83.0.4103.122 Electron/9.3.5 Safari/537.36"},
47 | "X-debug-options": []string{"bugReporterEnabled"},
48 | "X-super-properties": []string{xprop},
49 | }
50 |
51 | client := tools.CreateHttpClient()
52 | defer client.CloseIdleConnections()
53 |
54 | res, err := client.Do(request)
55 | if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) || os.IsTimeout(err) {
56 | fmt.Printf("%s %s\n", constants.Yellow(Token), constants.Red("[!] Timed out"))
57 | return err
58 | }
59 | defer res.Body.Close()
60 |
61 | switch res.StatusCode {
62 | case 200:
63 | utils.Logger(fmt.Sprintf("%s has successfully updated their nickname to %s", Token, Nickname))
64 | fmt.Printf("%s %s %s\n", constants.Red(Token), constants.Green("Success:"), constants.White(fmt.Sprintf("Changed nickname to %s", Nickname)))
65 | default:
66 | utils.Logger(fmt.Sprintf("%s was unable to update their nickname to %s", Token, Nickname))
67 | fmt.Printf("%s %s\n", constants.White(Token), constants.Red(fmt.Sprintf("Error: Unable to change nickname to %s", Nickname)))
68 | }
69 |
70 | return nil
71 | }
72 |
--------------------------------------------------------------------------------
/gateway/types.go:
--------------------------------------------------------------------------------
1 | package gateway
2 |
3 | import (
4 | "time"
5 |
6 | "github.com/tidwall/gjson"
7 | )
8 |
9 | type Activity struct {
10 | Name string `json:"name"`
11 | Type ActivityType `json:"type"`
12 | }
13 |
14 | type DiscordGatewayPayload struct {
15 | Opcode int `json:"op"`
16 | EventData interface{} `json:"d"`
17 | EventName string `json:"t,omitempty"`
18 | }
19 | type DiscordGatewayFetchMembers struct {
20 | Opcode int `json:"op"`
21 | EventData struct {
22 | GuildID string `json:"guild_id"`
23 | Typing bool `json:"typing,omitempty"`
24 | Threads bool `json:"threads,omitempty"`
25 | Activities bool `json:"activities,omitempty"`
26 | Members []interface{} `json:"members,omitempty"`
27 | Channels interface{} `json:"channels"`
28 | ThreadMemberLists []interface{} `json:"thread_member_lists,omitempty"`
29 | } `json:"d"`
30 | }
31 |
32 | type DiscordGatewayEventDataIdentify struct {
33 | Token string `json:"token"`
34 | Intents int `json:"intents"`
35 | Properties map[string]interface{} `json:"properties"`
36 | }
37 |
38 | type DiscordGatewayEventDataUpdateStatus struct {
39 | TimeSinceIdle *int `json:"since"`
40 | Activities []Activity `json:"activities,omitempty"`
41 | Status string `json:"status"`
42 | IsAfk bool `json:"afk"`
43 | }
44 |
45 | type MemberData struct {
46 | OnlineCount string
47 | MemberCount string
48 | ID string
49 | GuildID string
50 | HoistedRoles gjson.Result
51 | Types []string
52 | Locations gjson.Result
53 | Updates gjson.Result
54 | }
55 |
56 | type Guild struct {
57 | ID string
58 | MemberCount string
59 | }
60 |
61 | type Member struct {
62 | User struct {
63 | Username string `json:"username"`
64 | PublicFlags int `json:"public_flags"`
65 | ID string `json:"id"`
66 | Discriminator string `json:"discriminator"`
67 | Avatar string `json:"avatar"`
68 | } `json:"user"`
69 | Roles []interface{} `json:"roles"`
70 | Presence struct {
71 | User struct {
72 | ID string `json:"id"`
73 | } `json:"user"`
74 | Status string `json:"status"`
75 | ClientStatus struct {
76 | Desktop string `json:"desktop"`
77 | Web string `json:"web"`
78 | } `json:"client_status"`
79 | Activities []interface{} `json:"activities"`
80 | } `json:"presence"`
81 | Mute bool `json:"mute"`
82 | JoinedAt time.Time `json:"joined_at"`
83 | HoistedRole interface{} `json:"hoisted_role"`
84 | Deaf bool `json:"deaf"`
85 | }
86 |
--------------------------------------------------------------------------------
/tools/create_client.go:
--------------------------------------------------------------------------------
1 | package tools
2 |
3 | import (
4 | "Raid-Client/constants"
5 | "Raid-Client/utils"
6 | "fmt"
7 | "io/ioutil"
8 | "log"
9 | "math/rand"
10 | "net/http"
11 | "net/url"
12 | "os"
13 | "strings"
14 | "time"
15 | )
16 |
17 | func CreateHttpClient() *http.Client {
18 | var httpClient *http.Client
19 | if constants.Proxy {
20 | proxy := constants.Proxies[rand.Intn(len(constants.Proxies))]
21 | proxyURL, err := url.Parse(proxy)
22 | if err != nil {
23 | fmt.Println(err)
24 | }
25 | // Create our transport so we can setup our proxy
26 | transport := &http.Transport{
27 | Proxy: http.ProxyURL(proxyURL),
28 | }
29 | // Create our client that is told to run traffic through the proxy
30 | httpClient = &http.Client{
31 | Transport: transport,
32 | Timeout: time.Second * 5,
33 | }
34 | } else {
35 | httpClient = &http.Client{
36 | Timeout: time.Second * 5,
37 | }
38 | }
39 | return httpClient
40 | }
41 |
42 | func PopulateProxies() {
43 | fmt.Println("Populating proxies...")
44 | var err error
45 | constants.Proxies, err = utils.ReadTokens("./proxies.txt")
46 | if err != nil || len(constants.Proxies) == 0 {
47 | utils.Logger("Unable to load in proxies from proxies.txt... scraping the web for proxies.")
48 | fmt.Println("Unable to load in proxies from proxies.txt... scraping the web for proxies.")
49 | ScrapeProxies()
50 | }
51 | }
52 |
53 | func ScrapeProxies() {
54 | fmt.Println("Scraping proxies...")
55 | request, err := http.Get("https://api.proxyscrape.com/?request=displayproxies&proxytype=http&timeout=10000&country=all&anonymity=all&ssl=no")
56 | if err != nil {
57 | log.Fatal(err)
58 | }
59 | // Read the data from the web page I.E Proxies
60 | fmt.Println("Reading proxies...")
61 | data, err := ioutil.ReadAll(request.Body)
62 | if err != nil {
63 | log.Fatal(err)
64 | }
65 | fmt.Println("Writing proxies to file...")
66 | proxies := strings.TrimSuffix(string(data), "\n")
67 | // Append to our proxies file, if it does not exist we are simple going to create it and then append to it.
68 | file, err := os.OpenFile("./proxies.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
69 | if err != nil {
70 | fmt.Println("Proxies File Not Found!...")
71 | os.Exit(0)
72 | }
73 | defer file.Close()
74 | // Write to our file
75 |
76 | _, err = fmt.Fprint(file, proxies)
77 | if err != nil {
78 | file.Close()
79 | log.Fatal(err)
80 | }
81 | fmt.Println("Proxies Scraped and Saved!")
82 | utils.Logger("Scraped the web for proxies and added to proxies.txt")
83 | fmt.Println("Proxies saved to proxies.txt")
84 | // save the proxy list to constants
85 | constants.Proxies, _ = utils.ReadTokens("./proxies.txt")
86 |
87 | }
88 |
--------------------------------------------------------------------------------
/server/join.go:
--------------------------------------------------------------------------------
1 | package server
2 |
3 | import (
4 | "Raid-Client/cloudflare"
5 | "Raid-Client/constants"
6 | "Raid-Client/tools"
7 | "Raid-Client/utils"
8 | "bytes"
9 | "context"
10 | "encoding/json"
11 | "errors"
12 | "fmt"
13 | "io/ioutil"
14 | "net/http"
15 | "os"
16 | "strings"
17 |
18 | "github.com/patrickmn/go-cache"
19 | )
20 |
21 | var C *cache.Cache
22 |
23 | func JoinServer(inviteCode string, token string) error {
24 | defer handlePanic()
25 | code := ""
26 | if strings.Contains(inviteCode, "https://discord") {
27 | j := strings.Split(inviteCode, "/")
28 | code = j[3]
29 | } else {
30 | code = inviteCode
31 | }
32 | payload := map[string]string{"": ""}
33 | payloadBuf := new(bytes.Buffer)
34 | json.NewEncoder(payloadBuf).Encode(payload)
35 | request, err := http.NewRequest("POST", fmt.Sprintf("https://discord.com/api/v9/invites/%s", code), payloadBuf)
36 | if err != nil {
37 | return err
38 | }
39 | cf := cloudflare.Cookie()
40 | xprop := utils.XSuperProperties()
41 | request.Header = http.Header{
42 | "Accept": []string{"*/*"},
43 | "Accept-language": []string{"en-GB"},
44 | "Authorization": []string{token},
45 | "Content-length": []string{"2"},
46 | "Content-type": []string{"application/json"},
47 | "Cookie": []string{cf},
48 | "Origin": []string{"https://discord.com"},
49 | "Sec-fetch-dest": []string{"empty"},
50 | "Sec-fetch-mode": []string{"cors"},
51 | "Sec-fetch-site": []string{"same-origin"},
52 | "User-agent": []string{"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) discord/0.0.15 Chrome/83.0.4103.122 Electron/9.3.5 Safari/537.36"},
53 | "X-debug-options": []string{"bugReporterEnabled"},
54 | "X-super-properties": []string{xprop},
55 | }
56 |
57 | client := tools.CreateHttpClient()
58 | defer client.CloseIdleConnections()
59 |
60 | res, err := client.Do(request)
61 | if err != nil {
62 | return err
63 | }
64 |
65 | body, err := ioutil.ReadAll(res.Body)
66 | if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) || os.IsTimeout(err) {
67 | fmt.Printf("%s %s\n", constants.Yellow(token), constants.Red("[!] Timed out"))
68 | return err
69 | }
70 |
71 | switch res.StatusCode {
72 | case 200:
73 | var responseJson map[string]interface{}
74 | if err := json.Unmarshal(body, &responseJson); err != nil {
75 | return err
76 | }
77 | ParseServerID := responseJson["guild"].(map[string]interface{})
78 | ServerID := ParseServerID["id"].(string)
79 | ServerName := ParseServerID["name"].(string)
80 | C.Set("JoinServerID", ServerID, cache.NoExpiration)
81 | utils.Logger(fmt.Sprintf("%s has successfully joined %s", token, ServerName))
82 | fmt.Printf("%s %s %s\n", constants.White(token), constants.Green("| Successfully Joined"), constants.White(ServerName))
83 | default:
84 | utils.Logger(fmt.Sprintf("%s was unable to join %s", token, code))
85 | fmt.Printf("%s %s %s\n", constants.White(token), constants.Red("| Unable To Join"), constants.White(code))
86 | }
87 |
88 | return nil
89 | }
90 |
91 | func handlePanic() {
92 | if err := recover(); err != nil {
93 |
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/utils/checkTokens.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "Raid-Client/cloudflare"
5 | "Raid-Client/constants"
6 | "context"
7 | "errors"
8 | "fmt"
9 | "net/http"
10 | "os"
11 | "sync"
12 | "time"
13 | )
14 |
15 | var (
16 | wg sync.WaitGroup
17 | mutex sync.Mutex
18 | goodTokens []string
19 | good int
20 | bad int
21 | locked int
22 | )
23 |
24 | func CheckTokens(tokens []string) []string {
25 | defer handlePanic()
26 | good = 0
27 | bad = 0
28 | locked = 0
29 | fmt.Printf("Checking %d tokens\n", len(tokens))
30 | for _, t := range tokens {
31 | wg.Add(1)
32 | go func(t string) {
33 | mutex.Lock()
34 | defer mutex.Unlock()
35 | defer wg.Done()
36 | request, err := http.NewRequest("GET", "https://discord.com/api/v9/users/@me/library", nil)
37 | if err != nil {
38 | fmt.Println(err)
39 | }
40 | cf := cloudflare.Cookie()
41 | xprop := XSuperProperties()
42 | request.Header = http.Header{
43 | "Accept": []string{"*/*"},
44 | "Accept-language": []string{"en-GB"},
45 | "Authorization": []string{t},
46 | "Content-length": []string{"2"},
47 | "Content-type": []string{"application/json"},
48 | "Cookie": []string{cf},
49 | "Origin": []string{"https://discord.com"},
50 | "Sec-fetch-dest": []string{"empty"},
51 | "Sec-fetch-mode": []string{"cors"},
52 | "Sec-fetch-site": []string{"same-origin"},
53 | "User-agent": []string{"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) discord/0.0.15 Chrome/83.0.4103.122 Electron/9.3.5 Safari/537.36"},
54 | "X-debug-options": []string{"bugReporterEnabled"},
55 | "X-super-properties": []string{xprop},
56 | }
57 | client := &http.Client{
58 | Timeout: 5 * time.Second,
59 | }
60 | defer client.CloseIdleConnections()
61 |
62 | res, err := client.Do(request)
63 | if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) || os.IsTimeout(err) {
64 | fmt.Printf("%s %s\n", constants.Yellow(t), constants.Red("[!] Timed out"))
65 | }
66 | defer res.Body.Close()
67 |
68 | switch res.StatusCode {
69 | case 200:
70 | good++
71 | Logger(fmt.Sprintf("%s is valid", t))
72 | fmt.Printf("%s %s \n", constants.White(t), constants.Green("| is Valid"))
73 | goodTokens = append(goodTokens, t)
74 | case 401:
75 | bad++
76 | Logger(fmt.Sprintf("%s is invalid", t))
77 | fmt.Printf("%s %s \n", constants.White(t), constants.Red("| is Invalid"))
78 | case 403:
79 | locked++
80 | Logger(fmt.Sprintf("%s is phone locked", t))
81 | fmt.Printf("%s %s \n", constants.White(t), constants.Red("| is Phone locked"))
82 | default:
83 | bad++
84 | Logger(fmt.Sprintf("%s is invalid", t))
85 | fmt.Printf("%s %s \n", constants.White(t), constants.Red("| is Invalid"))
86 | }
87 | }(t)
88 | }
89 | wg.Wait()
90 | fmt.Printf("%s\n%s%s\n%s%s\n%s%s\n", constants.Green("Finished Checking: "), constants.Green("Good tokens: "), constants.Green(good), constants.Red("Bad tokens: "), constants.Red(bad), constants.Red("Locked tokens: "), constants.Red(locked))
91 | return goodTokens
92 | }
93 |
94 | func handlePanic() {
95 | if err := recover(); err != nil {
96 |
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
DiscSpam
4 |
5 |
6 | Fast, Free, Easy to use Discord.com raid tool
7 |
8 | Report Bug
9 | ,
10 | Request Feature
11 |
12 |
13 |
14 |
15 |
16 | ## About The Project
17 |
18 | 
19 |
20 | There are a few Discord raid tools on GitHub, however, I didn't find that they suited my use case so I decided to make my own one, a much better one then any online at the moment. This tool aims to be the one and only raid tool you need.
21 |
22 | Some unique features:
23 | * When developing this tool the Discord API endpoints were reversed but also some of the function it uses like the X-PROPERTIES header that is passed to identify the device have been recreated.
24 | * The chances of your tokens getting phone locked or terminated from this tool are next to none.
25 | * Cloudflare checking has been reversed and implemented into this tool. On the server side discord will see your requests as a legitimate user using the discord client.
26 |
27 | ## Built With
28 |
29 | This tool has been created in [Go](https://golang.org/). For the speed and concurrency it is also using thread safe go routines these can be spawned, used and destroyed very fast whilst also being lightweight to run.
30 |
31 | ## Getting Started
32 |
33 | Getting started is really simple. Head over the the [release](https://github.com/Zenoryne/DiscSpam/releases) page and download the correct version of the program for your operating system.
34 |
35 | Once you have downloaded the correct version of the program just add all your discord tokens into the `tokens.txt` file and then run the program.
36 |
37 | ### Installation
38 |
39 | 1. Install [Go](https://golang.org/)
40 |
41 | 2. Clone the repo
42 | ```sh
43 | git clone https://github.com/topji/DiscSpam.git
44 | ```
45 |
46 | 3. Install Go Modules
47 | ```sh
48 | go install
49 | ```
50 |
51 | 4. Compile Code
52 | ```sh
53 | go build .
54 | ```
55 |
56 | 5. Add Tokens
57 | ```sh
58 | Add the Discord tokens to tokens.txt
59 | ```
60 |
61 | 6. Run Program
62 | `Simply run the executable file if you're on windows or run the binary files if you're on Linux`
63 |
64 | ### Creating A Pull Request
65 |
66 | 1. Fork the Project
67 | 2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
68 | 3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
69 | 4. Push to the Branch (`git push origin feature/AmazingFeature`)
70 | 5. Open a Pull Request
71 |
72 | ### Roadmap
73 | - Proxy Support
74 | - [x] Add/Remove Friends
75 | - [x] Logger
76 | - Voice Chat Support
77 | - [x] Add Nickname Changing
78 | - [x] Add Ability To Change Status
79 | - [x] Add Ability To Heartbeat Token
80 | - [x] Add Support For Colon Emojis `:joy:`
81 | - [x] Token Checker
82 | - Create, Train, Manage Captcha Solving AI
83 | - Allow Fake Typing
84 | - Anti-Kick, Auto Join Back If Kicked
85 |
86 |
87 | These are just some things I am going to be adding to the tool very soon. If you have any ideas feel free to open a [issue](https://github.com/topji/DiscSpam/issues) request and let me know.
88 |
89 |
90 | ## License
91 |
92 | Distributed under the MIT License. See [LICENSE](https://github.com/topji/DiscSpam/blob/main/LICENSE) for more information.
93 |
--------------------------------------------------------------------------------
/interact/message.go:
--------------------------------------------------------------------------------
1 | package interact
2 |
3 | import (
4 | "Raid-Client/cloudflare"
5 | "Raid-Client/constants"
6 | "Raid-Client/tools"
7 | "Raid-Client/utils"
8 | "bytes"
9 | "context"
10 | "encoding/json"
11 | "errors"
12 | "fmt"
13 | "io/ioutil"
14 | "net/http"
15 | "os"
16 | )
17 |
18 | var BadCount int
19 |
20 | func SendMessage(ServerID string, ChannelID string, Token string, Content string) error {
21 | defer handlePanic()
22 | if BadCount >= 15 {
23 | return errors.New("auto anti token lock feature triggered")
24 | } else {
25 | payload := map[string]string{
26 | "content": Content,
27 | }
28 |
29 | payloadBuf := new(bytes.Buffer)
30 | json.NewEncoder(payloadBuf).Encode(payload)
31 |
32 | request, err := http.NewRequest("POST", fmt.Sprintf("https://discordapp.com/api/v9/channels/%s/messages", ChannelID), payloadBuf)
33 | if err != nil {
34 | return err
35 | }
36 |
37 | cf := cloudflare.Cookie()
38 | xprop := utils.XSuperProperties()
39 |
40 | request.Header = http.Header{
41 | "Accept": []string{"*/*"},
42 | "Accept-language": []string{"en-GB"},
43 | "Authorization": []string{Token},
44 | "Content-type": []string{"application/json"},
45 | "Cookie": []string{cf},
46 | "Origin": []string{"https://discord.com"},
47 | "Referrer": []string{fmt.Sprintf("https://discord.com/channels/%s/%s", ServerID, ChannelID)},
48 | "Sec-fetch-dest": []string{"empty"},
49 | "Sec-fetch-mode": []string{"cors"},
50 | "Sec-fetch-site": []string{"same-origin"},
51 | "User-agent": []string{"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) discord/0.0.15 Chrome/83.0.4103.122 Electron/9.3.5 Safari/537.36"},
52 | "X-debug-options": []string{"bugReporterEnabled"},
53 | "X-super-properties": []string{xprop},
54 | }
55 |
56 | client := tools.CreateHttpClient()
57 | defer client.CloseIdleConnections()
58 |
59 | res, err := client.Do(request)
60 | if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) || os.IsTimeout(err) {
61 | fmt.Printf("%s %s\n", constants.Yellow(Token), constants.Red("[!] Timed out"))
62 | return err
63 | }
64 | defer res.Body.Close()
65 |
66 | body, err := ioutil.ReadAll(res.Body)
67 | if err != nil {
68 | return err
69 | }
70 |
71 | var responseJson map[string]interface{}
72 | if err := json.Unmarshal(body, &responseJson); err != nil {
73 | return err
74 | }
75 |
76 | // Do some parsing of the response to check for issues.
77 | switch responseJson["message"] {
78 | case "Missing Access":
79 | utils.Logger(fmt.Sprintf("%s was not able ot send a message in %s", Token, ServerID))
80 | fmt.Printf("%s %s\n", constants.White(Token), constants.Red("Unable to send message make sure it is the server"))
81 | BadCount++
82 | case "Missing Permissions":
83 | utils.Logger(fmt.Sprintf("%s does not have the correct permissions to send a message in %s", Token, ServerID))
84 | fmt.Printf("%s %s %s\n", constants.Red(Token), constants.Yellow("is missing permissions I.E needs a role to message in"), constants.White(ServerID))
85 | BadCount++
86 | case nil:
87 | utils.Logger(fmt.Sprintf("%s has sent the message %s in %s", Token, Content, ServerID))
88 | fmt.Printf("%s %s %s\n", constants.Red(Token), constants.Green("Success:"), constants.White("Message has been sent to ", ServerID))
89 | BadCount--
90 | }
91 | return nil
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/interact/reactions.go:
--------------------------------------------------------------------------------
1 | package interact
2 |
3 | import (
4 | "Raid-Client/cloudflare"
5 | "Raid-Client/constants"
6 | "Raid-Client/tools"
7 | "Raid-Client/utils"
8 | "context"
9 | "errors"
10 | "fmt"
11 | "net/http"
12 | "os"
13 | "strings"
14 | "time"
15 |
16 | "github.com/kyokomi/emoji/v2"
17 | )
18 |
19 | var cmt int
20 |
21 | func AddReaction(ChannelID string, MessageID string, Token string, Emoji string) error {
22 | defer handlePanic()
23 | if cmt >= 2 {
24 | return errors.New("error working")
25 | } else {
26 | Emoji = strings.TrimSuffix(emoji.Sprint(Emoji), " ")
27 | request, err := http.NewRequest("PUT", fmt.Sprintf("https://discord.com/api/v9/channels/%s/messages/%s/reactions/%s/%s", ChannelID, MessageID, Emoji, "%40me"), nil)
28 | if err != nil {
29 | return err
30 | }
31 | cf := cloudflare.Cookie()
32 | xprop := utils.XSuperProperties()
33 | request.Header = http.Header{
34 | "Accept": []string{"*/*"},
35 | "Accept-language": []string{"en-GB"},
36 | "Authorization": []string{Token},
37 | "Content-length": []string{"2"},
38 | "Content-type": []string{"application/json"},
39 | "Cookie": []string{cf},
40 | "Origin": []string{"https://discord.com"},
41 | "Sec-fetch-dest": []string{"empty"},
42 | "Sec-fetch-mode": []string{"cors"},
43 | "Sec-fetch-site": []string{"same-origin"},
44 | "User-agent": []string{"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) discord/0.0.15 Chrome/83.0.4103.122 Electron/9.3.5 Safari/537.36"},
45 | "X-debug-options": []string{"bugReporterEnabled"},
46 | "X-super-properties": []string{xprop},
47 | }
48 |
49 | client := tools.CreateHttpClient()
50 | defer client.CloseIdleConnections()
51 |
52 | res, err := client.Do(request)
53 | if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) || os.IsTimeout(err) {
54 | fmt.Printf("%s %s\n", constants.Yellow(Token), constants.Red("[!] Timed out"))
55 | return err
56 | }
57 |
58 | switch res.StatusCode {
59 | case 204:
60 | utils.Logger(fmt.Sprintf("%s has successfully added the reaction %s to the message %s", Token, Emoji, MessageID))
61 | fmt.Printf("%s %s %s\n", constants.Red(Token), constants.Green("Success:"), constants.White(fmt.Sprintf("Added reaction %s to %s", Emoji, MessageID)))
62 | cmt--
63 | default:
64 | utils.Logger(fmt.Sprintf("%s was unable to add the reaction %s to %s", Token, Emoji, MessageID))
65 | fmt.Printf("%s %s\n", constants.White(Token), constants.Red(fmt.Sprintf("Error: Unable to add reaction %s to %s", Emoji, MessageID)))
66 | cmt++
67 | }
68 |
69 | return nil
70 | }
71 | }
72 |
73 | func ReactionMessage(ChannelID string, MessageID string, Token string, Word string) error {
74 | letters := map[string]string{
75 | "A": "🇦",
76 | "B": "🇧",
77 | "C": "🇨",
78 | "D": "🇩",
79 | "E": "🇪",
80 | "F": "🇫",
81 | "G": "🇬",
82 | "H": "🇭",
83 | "I": "🇮",
84 | "J": "🇯",
85 | "K": "🇰",
86 | "L": "🇱",
87 | "M": "🇲",
88 | "N": "🇳",
89 | "O": "🇴",
90 | "P": "🇵",
91 | "Q": "🇶",
92 | "R": "🇷",
93 | "S": "🇸",
94 | "T": "🇹",
95 | "U": "🇺",
96 | "V": "🇻",
97 | "W": "🇼",
98 | "X": "🇽",
99 | "Y": "🇾",
100 | "Z": "🇿",
101 | }
102 | for _, letter := range Word {
103 | l := strings.ToUpper(string(letter))
104 | AddReaction(ChannelID, MessageID, Token, letters[l])
105 | time.Sleep(1 * time.Second)
106 | }
107 | return nil
108 | }
109 |
--------------------------------------------------------------------------------
/utils/fakeDeviceInfo.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "encoding/base64"
5 | "encoding/json"
6 | "log"
7 | "math/rand"
8 | "time"
9 | )
10 |
11 | type DeviceInformation struct {
12 | OS string `json:"os"`
13 | Browser string `json:"browser"`
14 | UA string `json:"browser_user_agent"`
15 | BrowserVersion string `json:"browser_version"`
16 | OSVersion string `json:"os_version"`
17 | Referrer string `json:"referrer"`
18 | ReferrerDomain string `json:"referring_domain"`
19 | ReferrerCurrent string `json:"referrer_current"`
20 | ReferreringCurrentDomain string `json:"referring_domain_current"`
21 | ReleaseChannel string `json:"release_channel"`
22 | ClientBuild string `json:"client_build_number"`
23 | ClientEventSource string `json:"client_event_source"`
24 | }
25 |
26 | func FakeDevice() DeviceInformation {
27 | rand.Seed(time.Now().UnixNano())
28 | switch rand.Intn(8-1) + 1 {
29 | case 1:
30 | return DeviceInformation{OS: "Windows", Browser: "Chrome", UA: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36", BrowserVersion: "69.0.3497.100", OSVersion: "10", ReleaseChannel: "stable", ClientBuild: "36127", ClientEventSource: "None"}
31 | case 2:
32 | return DeviceInformation{OS: "Windows", Browser: "Chrome", UA: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/18.17763", BrowserVersion: "18.17763", OSVersion: "10", ReleaseChannel: "stable", ClientBuild: "36127", ClientEventSource: "None"}
33 | case 3:
34 | return DeviceInformation{OS: "Windows", Browser: "Edge", UA: "Mozilla/5.0 (Windows NT 5.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36", BrowserVersion: "60.0.3112.90", OSVersion: "10", ReleaseChannel: "stable", ClientBuild: "36127", ClientEventSource: "None"}
35 | case 4:
36 | return DeviceInformation{OS: "Windows", Browser: "Chrome", UA: "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36", BrowserVersion: "60.0.3112.113", OSVersion: "8.1", ReleaseChannel: "stable", ClientBuild: "36127", ClientEventSource: "None"}
37 | case 5:
38 | return DeviceInformation{OS: "Windows", Browser: "Internet Explorer", UA: "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; rv:11.0) like Gecko", BrowserVersion: "11.0", OSVersion: "7", ReleaseChannel: "stable", ClientBuild: "36127", ClientEventSource: "None"}
39 | case 6:
40 | return DeviceInformation{OS: "Windows", Browser: "FireFox", UA: "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0", BrowserVersion: "54.0", OSVersion: "7", ReleaseChannel: "stable", ClientBuild: "36127", ClientEventSource: "None"}
41 | case 7:
42 | return DeviceInformation{OS: "Windows", Browser: "FireFox", UA: "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:54.0) Gecko/20100101 Firefox/66.0", BrowserVersion: "66.0", OSVersion: "7", ReleaseChannel: "stable", ClientBuild: "36127", ClientEventSource: "None"}
43 | default:
44 | return DeviceInformation{OS: "Windows", Browser: "FireFox", UA: "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:54.0) Gecko/20100101 Firefox/66.0", BrowserVersion: "66.0", OSVersion: "7", ReleaseChannel: "stable", ClientBuild: "36127", ClientEventSource: "None"}
45 | }
46 | }
47 |
48 | func XSuperProperties() string {
49 | fDevice := FakeDevice()
50 | byteArray, err := json.Marshal(fDevice)
51 | if err != nil {
52 | log.Fatal(err)
53 | }
54 | prop := base64.StdEncoding.EncodeToString([]byte(byteArray))
55 | return string(prop)
56 | }
57 |
--------------------------------------------------------------------------------
/utils/webSocket.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "encoding/json"
5 | "time"
6 |
7 | "github.com/gorilla/websocket"
8 | )
9 |
10 | var WSConnected bool
11 | var Looping bool
12 | var Presence []Activity
13 | var Status string
14 |
15 | type Connection struct {
16 | connection *websocket.Conn
17 | }
18 |
19 | type ActivityType int
20 |
21 | const (
22 | ActivityGame = 0
23 | ActivityListening = 2
24 | ActivityWatching = 3
25 | )
26 |
27 | type Activity struct {
28 | Name string `json:"name"`
29 | Type ActivityType `json:"type"`
30 | }
31 |
32 | type DiscordGatewayPayload struct {
33 | Opcode int `json:"op"`
34 | EventData interface{} `json:"d"`
35 | EventName string `json:"t,omitempty"`
36 | }
37 |
38 | type DiscordGatewayEventDataIdentify struct {
39 | Token string `json:"token"`
40 | Intents int `json:"intents"`
41 | Properties map[string]interface{} `json:"properties"`
42 | }
43 |
44 | type DiscordGatewayEventDataUpdateStatus struct {
45 | TimeSinceIdle *int `json:"since"`
46 | Activities []Activity `json:"activities,omitempty"`
47 | Status string `json:"status"`
48 | IsAfk bool `json:"afk"`
49 | }
50 |
51 | func RecieveIncomingPayloads(ws *websocket.Conn, token string) error {
52 | for {
53 | _, p, readErr := ws.ReadMessage()
54 | if readErr != nil {
55 | return readErr
56 | }
57 |
58 | var decodedMessage DiscordGatewayPayload
59 | decodeErr := json.Unmarshal(p, &decodedMessage)
60 | if decodeErr != nil {
61 | return decodeErr
62 | }
63 | //log.Println("recieved payload: ", decodedMessage)
64 |
65 | if decodedMessage.Opcode == 10 {
66 | data := decodedMessage.EventData.(map[string]interface{})
67 | heartbeatInterval := data["heartbeat_interval"].(float64)
68 |
69 | go setupHeartbeat(heartbeatInterval, ws)
70 | identify(ws, token)
71 | }
72 | }
73 | }
74 |
75 | func setupHeartbeat(interval float64, ws *websocket.Conn) error {
76 | c := time.Tick(time.Duration(interval) * time.Millisecond)
77 | for range c {
78 | b, marshalErr := json.Marshal(DiscordGatewayPayload{1, nil, ""})
79 | if marshalErr != nil {
80 | return marshalErr
81 | }
82 |
83 | //log.Println("sending payload (heartbeat): ", string(b))
84 | err := ws.WriteMessage(websocket.TextMessage, b)
85 | if err != nil {
86 | return err
87 | }
88 | }
89 | return nil
90 | }
91 |
92 | func identify(ws *websocket.Conn, token string) error {
93 | b, marshalErr := json.Marshal(DiscordGatewayPayload{2,
94 | DiscordGatewayEventDataIdentify{token, 0, map[string]interface{}{
95 | "$os": "Windows",
96 | "$browser": "Chrome",
97 | "$device": "",
98 | }}, ""})
99 | if marshalErr != nil {
100 | return marshalErr
101 | }
102 |
103 | err := ws.WriteMessage(websocket.TextMessage, b)
104 | if err != nil {
105 | return err
106 | }
107 |
108 | WSConnected = true
109 | return nil
110 | }
111 |
112 | func SetStatus(status string, ws *websocket.Conn) error {
113 | b, marshalErr := json.Marshal(DiscordGatewayPayload{3,
114 | DiscordGatewayEventDataUpdateStatus{
115 | nil,
116 | Presence,
117 | status,
118 | false,
119 | }, ""})
120 | if marshalErr != nil {
121 | return marshalErr
122 | }
123 |
124 | //log.Println("sending payload:", string(b))
125 | err := ws.WriteMessage(websocket.TextMessage, b)
126 | if err != nil {
127 | return err
128 | }
129 | return nil
130 | }
131 |
132 | func SetupWebSocket(Token string) *websocket.Conn {
133 | WSConnected = false
134 | ws := Connection{
135 | connection: &websocket.Conn{},
136 | }
137 |
138 | var dialErr error
139 | ws.connection, _, dialErr = websocket.DefaultDialer.Dial("wss://gateway.discord.gg/?v=9&encoding=json", nil)
140 | if dialErr != nil {
141 | return ws.connection
142 | }
143 | return ws.connection
144 | }
145 |
--------------------------------------------------------------------------------
/gateway/scraping.go:
--------------------------------------------------------------------------------
1 | package gateway
2 |
3 | import (
4 | "Raid-Client/utils"
5 | "encoding/json"
6 | "fmt"
7 | "log"
8 |
9 | "github.com/tidwall/gjson"
10 | )
11 |
12 | func parseMemberData(js string, guildID string) {
13 |
14 | parsed := guildMemberListUpdate(js)
15 |
16 | if parsed.GuildID == guildID && belongsToStrSlice(parsed.Types, "SYNC") || belongsToStrSlice(parsed.Types, "UPDATE") {
17 | //endFetching := false
18 | for k, v := range parsed.Types {
19 | if v == "SYNC" {
20 | p := parsed.Updates.Get(fmt.Sprint(k)).String()
21 | if len(p) == 0 {
22 | finishedFetching <- true
23 | }
24 |
25 | // Parse members
26 | var m []Member
27 | members := parsed.Updates.Get("#.member").String()
28 | err := json.Unmarshal([]byte(members), &m)
29 | if err != nil {
30 | log.Println(err)
31 | }
32 | scrapedMemb = append(scrapedMemb, m...)
33 | utils.Logger(scrapedMemb)
34 |
35 | }
36 | }
37 | }
38 |
39 | }
40 | func guildMemberListUpdate(response string) MemberData {
41 | var types []string
42 | var locations gjson.Result
43 | var updates gjson.Result
44 | d := gjson.Get(response, "d")
45 |
46 | for _, chunk := range d.Get("ops").Array() {
47 | types = append(types, chunk.Get("op").String())
48 |
49 | switch chunk.Get("op").String() {
50 | case "SYNC", "INVALIDATE":
51 | locations = chunk.Get("range")
52 |
53 | if chunk.Get("op").String() == "SYNC" {
54 | updates = chunk.Get("items")
55 | }
56 | case "INSERT", "UPDATE", "DELETE":
57 | locations = chunk.Get("index")
58 | if !(chunk.Get("op").String() == "DELETE") {
59 | updates = chunk.Get("item")
60 | }
61 | }
62 | }
63 | memberData := MemberData{
64 | OnlineCount: d.Get("online_count").String(),
65 | MemberCount: d.Get("member_count").String(),
66 | ID: d.Get("id").String(),
67 | GuildID: d.Get("guild_id").String(),
68 | HoistedRoles: d.Get("groups"),
69 | Types: types,
70 | Locations: locations,
71 | Updates: updates,
72 | }
73 |
74 | return memberData
75 |
76 | }
77 |
78 | // Helper function to retrieve member count
79 | func getGuildsData(d string) {
80 | guilds := gjson.Get(d, "d.guilds")
81 |
82 | for _, guild := range guilds.Array() {
83 | memberCount := guild.Get("member_count")
84 | guildID := guild.Get("id")
85 | ScrapedGuilds = append(ScrapedGuilds, Guild{ID: guildID.String(), MemberCount: memberCount.String()})
86 | }
87 | }
88 | func getRanges(index, multiplier, memberCount int) [][]int { // https://github.com/Merubokkusu/Discord-S.C.U.M/blob/77daf74354415cb5d9411f886899c9817d0bc5b9/discum/gateway/guild/combo.py#L48
89 | initalNum := index * multiplier
90 | rangesList := [][]int{{initalNum, initalNum + 99}}
91 |
92 | if memberCount > initalNum+99 {
93 | rangesList = append(rangesList, []int{initalNum + 100, initalNum + 199})
94 | }
95 | if !belongToIntSlice(rangesList, []int{0, 99}) {
96 | rangesList = append(rangesList, []int{})
97 | insert(rangesList, []int{0, 99}, 0)
98 | }
99 | return rangesList
100 | }
101 |
102 | func getMemberCount(guildID string) string {
103 | var mc string
104 | for _, guild := range ScrapedGuilds {
105 | if guild.ID == guildID {
106 | mc = guild.MemberCount
107 | }
108 | }
109 | return mc
110 | }
111 |
112 | func belongsToStrSlice(input []string, lookup string) bool { // https://stackoverflow.com/a/52710077
113 | for _, val := range input {
114 | if val == lookup {
115 | return true
116 | }
117 | }
118 | return false
119 | }
120 |
121 | func belongToIntSlice(input [][]int, lookup []int) bool { // https://stackoverflow.com/a/52710077
122 | for _, val := range input {
123 | if Equal(val, lookup) {
124 | return true
125 | }
126 | }
127 | return false
128 | }
129 |
130 | func insert(a [][]int, c []int, i int) [][]int { //https://github.com/golang/go/wiki/SliceTricks#insert
131 | return append(a[:i], append([][]int{c}, a[i:]...)...)
132 | }
133 |
134 | func Equal(a, b []int) bool {
135 | if len(a) != len(b) {
136 | return false
137 | }
138 | for i, v := range a {
139 | if v != b[i] {
140 | return false
141 | }
142 | }
143 | return true
144 | }
145 |
--------------------------------------------------------------------------------
/interact/friends.go:
--------------------------------------------------------------------------------
1 | package interact
2 |
3 | import (
4 | "Raid-Client/cloudflare"
5 | "Raid-Client/constants"
6 | "Raid-Client/tools"
7 | "Raid-Client/utils"
8 | "context"
9 | "errors"
10 | "os"
11 |
12 | "bytes"
13 | "encoding/json"
14 | "fmt"
15 | "net/http"
16 | "strings"
17 | "time"
18 | )
19 |
20 | func AddFriend(Token string, User string) error {
21 | username := strings.Split(User, "#")
22 | payload := map[string]string{
23 | "username": username[0],
24 | "discriminator": username[1],
25 | }
26 |
27 | payloadBuf := new(bytes.Buffer)
28 | json.NewEncoder(payloadBuf).Encode(payload)
29 |
30 | request, err := http.NewRequest("POST", fmt.Sprintf("https://discord.com/api/v9/users/%s/relationships", "%40me"), payloadBuf)
31 | if err != nil {
32 | return err
33 | }
34 |
35 | cf := cloudflare.Cookie()
36 | xprop := utils.XSuperProperties()
37 |
38 | request.Header = http.Header{
39 | "Accept": []string{"*/*"},
40 | "Accept-language": []string{"en-GB"},
41 | "Authorization": []string{Token},
42 | "Content-length": []string{"2"},
43 | "Content-type": []string{"application/json"},
44 | "Cookie": []string{cf},
45 | "Origin": []string{"https://discord.com"},
46 | "Sec-fetch-dest": []string{"empty"},
47 | "Sec-fetch-mode": []string{"cors"},
48 | "Sec-fetch-site": []string{"same-origin"},
49 | "User-agent": []string{"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) discord/0.0.15 Chrome/83.0.4103.122 Electron/9.3.5 Safari/537.36"},
50 | "X-debug-options": []string{"bugReporterEnabled"},
51 | "X-super-properties": []string{xprop},
52 | }
53 |
54 | client := &http.Client{
55 | Timeout: 5 * time.Second,
56 | }
57 |
58 | res, err := client.Do(request)
59 | if err != nil {
60 | return err
61 | }
62 | defer res.Body.Close()
63 |
64 | switch res.StatusCode {
65 | case 204:
66 | utils.Logger(fmt.Sprintf("%s has successfully added %s", Token, User))
67 | fmt.Printf("%s %s %s\n", constants.Red(Token), constants.Green("Success:"), constants.White(fmt.Sprintf("Sent friend request to %s", User)))
68 | default:
69 | utils.Logger(fmt.Sprintf("%s was unable to add %s", Token, User))
70 | fmt.Printf("%s %s\n", constants.White(Token), constants.Red(fmt.Sprintf("Error: Unable to send friend request to %s", User)))
71 | }
72 |
73 | return nil
74 | }
75 |
76 | func RemoveFriend(Token string, UserID string) error {
77 | defer handlePanic()
78 | request, err := http.NewRequest("DELETE", fmt.Sprintf("https://discord.com/api/v9/users/%s/relationships/%s", "%40me", UserID), nil)
79 | if err != nil {
80 | return err
81 | }
82 |
83 | cf := cloudflare.Cookie()
84 | xprop := utils.XSuperProperties()
85 |
86 | request.Header = http.Header{
87 | "Accept": []string{"*/*"},
88 | "Accept-language": []string{"en-GB"},
89 | "Authorization": []string{Token},
90 | "Content-length": []string{"2"},
91 | "Content-type": []string{"application/json"},
92 | "Cookie": []string{cf},
93 | "Origin": []string{"https://discord.com"},
94 | "Sec-fetch-dest": []string{"empty"},
95 | "Sec-fetch-mode": []string{"cors"},
96 | "Sec-fetch-site": []string{"same-origin"},
97 | "User-agent": []string{"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) discord/0.0.15 Chrome/83.0.4103.122 Electron/9.3.5 Safari/537.36"},
98 | "X-debug-options": []string{"bugReporterEnabled"},
99 | "X-super-properties": []string{xprop},
100 | }
101 |
102 | client := tools.CreateHttpClient()
103 | defer client.CloseIdleConnections()
104 |
105 | res, err := client.Do(request)
106 | if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) || os.IsTimeout(err) {
107 | fmt.Printf("%s %s\n", constants.Yellow(Token), constants.Red("[!] Timed out"))
108 | return err
109 | }
110 | defer res.Body.Close()
111 |
112 | switch res.StatusCode {
113 | case 204:
114 | utils.Logger(fmt.Sprintf("%s has removed %s", Token, UserID))
115 | fmt.Printf("%s %s %s\n", constants.Red(Token), constants.Green("Success:"), constants.White(fmt.Sprintf("Unfriended user id: %s", UserID)))
116 | default:
117 | utils.Logger(fmt.Sprintf("%s was unable to remove %s", Token, UserID))
118 | fmt.Printf("%s %s\n", constants.White(Token), constants.Red(fmt.Sprintf("Error: Unable to unfriend user id: %s", UserID)))
119 | }
120 |
121 | return nil
122 | }
123 |
124 | func handlePanic() {
125 | if err := recover(); err != nil {
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/gateway/gateway.go:
--------------------------------------------------------------------------------
1 | package gateway
2 |
3 | import (
4 | "encoding/json"
5 | "math"
6 | "strconv"
7 | "sync"
8 | "time"
9 |
10 | "Raid-Client/utils"
11 |
12 | "github.com/gorilla/websocket"
13 | )
14 |
15 | var WSConnected bool
16 | var Looping bool
17 | var Presence []Activity
18 | var Status string
19 |
20 | type Connection struct {
21 | connection *websocket.Conn
22 | }
23 |
24 | type ActivityType int
25 |
26 | const (
27 | ActivityGame = 0
28 | ActivityListening = 2
29 | ActivityWatching = 3
30 | )
31 |
32 | var (
33 | scrapedMemb []Member
34 | ScrapedGuilds []Guild
35 | wg sync.WaitGroup
36 | data = make(chan string)
37 | finishedFetching = make(chan bool)
38 | )
39 |
40 | func RecieveIncomingPayloads(ws *websocket.Conn, token string) error {
41 | for {
42 | _, p, readErr := ws.ReadMessage()
43 | if readErr != nil {
44 | return readErr
45 | }
46 | var decodedMessage DiscordGatewayPayload
47 | decodeErr := json.Unmarshal(p, &decodedMessage)
48 | if decodeErr != nil {
49 | return decodeErr
50 | }
51 | switch {
52 | case decodedMessage.Opcode == 10:
53 | data := decodedMessage.EventData.(map[string]interface{})
54 | heartbeatInterval := data["heartbeat_interval"].(float64)
55 |
56 | go setupHeartbeat(heartbeatInterval, ws)
57 | identify(ws, token)
58 | case decodedMessage.EventName == "READY":
59 | utils.Logger("Received READY event")
60 | go getGuildsData(string(p))
61 | case decodedMessage.EventName == "GUILD_MEMBER_LIST_UPDATE":
62 | data <- string(p)
63 | utils.Logger(string(p))
64 | default:
65 | utils.Logger("received payload:", string(p))
66 | }
67 |
68 | }
69 | }
70 |
71 | func setupHeartbeat(interval float64, ws *websocket.Conn) error {
72 | c := time.Tick(time.Duration(interval) * time.Millisecond)
73 | for range c {
74 | b, marshalErr := json.Marshal(DiscordGatewayPayload{1, nil, ""})
75 | if marshalErr != nil {
76 | return marshalErr
77 | }
78 |
79 | utils.Logger("sending payload (heartbeat): ", string(b))
80 | err := ws.WriteMessage(websocket.TextMessage, b)
81 | if err != nil {
82 | return err
83 | }
84 | }
85 | return nil
86 | }
87 |
88 | func identify(ws *websocket.Conn, token string) error {
89 | b, marshalErr := json.Marshal(DiscordGatewayPayload{2,
90 | DiscordGatewayEventDataIdentify{token, 0, map[string]interface{}{
91 | "$os": "Windows",
92 | "$browser": "Chrome",
93 | "$device": "",
94 | }}, ""})
95 | if marshalErr != nil {
96 | return marshalErr
97 | }
98 |
99 | err := ws.WriteMessage(websocket.TextMessage, b)
100 | if err != nil {
101 | return err
102 | }
103 |
104 | WSConnected = true
105 | return nil
106 | }
107 |
108 | func SetStatus(status string, ws *websocket.Conn) error {
109 | b, marshalErr := json.Marshal(DiscordGatewayPayload{3,
110 | DiscordGatewayEventDataUpdateStatus{
111 | nil,
112 | Presence,
113 | status,
114 | false,
115 | }, ""})
116 | if marshalErr != nil {
117 | return marshalErr
118 | }
119 |
120 | utils.Logger("sending payload:", string(b))
121 | err := ws.WriteMessage(websocket.TextMessage, b)
122 | if err != nil {
123 | return err
124 | }
125 | return nil
126 | }
127 |
128 | func SetupWebSocket(Token string) *websocket.Conn {
129 | WSConnected = false
130 | ws := Connection{
131 | connection: &websocket.Conn{},
132 | }
133 |
134 | var dialErr error
135 | ws.connection, _, dialErr = websocket.DefaultDialer.Dial("wss://gateway.discord.gg/?encoding=json&v=9", nil)
136 | if dialErr != nil {
137 | return ws.connection
138 | }
139 | return ws.connection
140 | }
141 |
142 | /*
143 | https://arandomnewaccount.gitlab.io/discord-unofficial-docs/lazy_guilds.html
144 | */
145 |
146 | func SearchGuildMembers(ws *websocket.Conn, result []Member, guildID, channelID, token, method string, delay int) []Member {
147 | scrapedMemb = []Member{}
148 | result = []Member{}
149 | // Get membercount from READY EVENT
150 | memberCount, _ := strconv.Atoi(getMemberCount(guildID))
151 | var multiplier int
152 | // Get multiplier
153 |
154 | switch method {
155 | case "overlap":
156 | multiplier = 100
157 | case "no-overlap":
158 | multiplier = 200
159 | default:
160 | multiplier = 100
161 | }
162 |
163 | // Listen for data
164 | go captureData(guildID)
165 | wg.Add(1)
166 | // First lazyGuild request that is needed
167 | go func() {
168 | /*
169 | {"op":14,"d":{"guild_id":"632655162875445258","typing":true,"threads":true,"activities":true,"members":[],"channels":{"762838406526402591":[[0,99]]},"thread_member_lists":[]}}
170 | */
171 | // Ugly af but works, still looking for a way to make it look better
172 | defer wg.Done()
173 | first, err := json.Marshal(DiscordGatewayFetchMembers{
174 | Opcode: 14,
175 | EventData: struct {
176 | GuildID string "json:\"guild_id\""
177 | Typing bool "json:\"typing,omitempty\""
178 | Threads bool "json:\"threads,omitempty\""
179 | Activities bool "json:\"activities,omitempty\""
180 | Members []interface{} "json:\"members,omitempty\""
181 | Channels interface{} "json:\"channels\""
182 | ThreadMemberLists []interface{} "json:\"thread_member_lists,omitempty\""
183 | }{
184 | GuildID: guildID,
185 | Typing: true,
186 | Threads: false,
187 | Activities: true,
188 | Members: []interface{}{nil},
189 | Channels: map[string]interface{}{
190 | channelID: [][]int{{0, 99}},
191 | },
192 | ThreadMemberLists: []interface{}{nil},
193 | },
194 | })
195 | if err != nil {
196 | utils.Logger("Error: ", err)
197 | }
198 | utils.Logger("sending payload (HELLO_REQUEST_GUILD_MEMBERS): ", string(first))
199 | err = ws.WriteMessage(websocket.TextMessage, first)
200 | if err != nil {
201 | utils.Logger("Error: ", err)
202 | }
203 | }()
204 | wg.Wait()
205 |
206 | /*
207 | https://arandomnewaccount.gitlab.io/discord-unofficial-docs/lazy_guilds.html#op-14-lazy-request-what-to-send
208 | */
209 | var z int
210 |
211 | if memberCount < 100 {
212 | z = 1
213 | } else {
214 | z = int(math.Round(float64(memberCount / 100)))
215 | }
216 | Fetching:
217 |
218 | for i := 0; i < z+3; i++ { // +3 because in certain small guilds you will need to send more requests
219 | // Gotta work on high members guilds but won't on really small one
220 | select {
221 | case <-finishedFetching:
222 | utils.Logger("Finished Fetching Guild")
223 | result = scrapedMemb
224 | break Fetching
225 | default:
226 | wg.Add(1)
227 | go func(index, mul int) {
228 | defer wg.Done()
229 | ranges := getRanges(index, 200, memberCount)
230 | // Ugly af but works, still looking for a way to make it look better
231 | second, err := json.Marshal(DiscordGatewayFetchMembers{
232 | Opcode: 14,
233 | EventData: struct {
234 | GuildID string "json:\"guild_id\""
235 | Typing bool "json:\"typing,omitempty\""
236 | Threads bool "json:\"threads,omitempty\""
237 | Activities bool "json:\"activities,omitempty\""
238 | Members []interface{} "json:\"members,omitempty\""
239 | Channels interface{} "json:\"channels\""
240 | ThreadMemberLists []interface{} "json:\"thread_member_lists,omitempty\""
241 | }{
242 | GuildID: guildID,
243 | Typing: false,
244 | Threads: false,
245 | Activities: false,
246 | Members: []interface{}{},
247 | Channels: map[string]interface{}{
248 | channelID: ranges,
249 | },
250 | ThreadMemberLists: []interface{}{},
251 | },
252 | })
253 | if err != nil {
254 | utils.Logger("Error: ", err)
255 | }
256 | utils.Logger("sending payload (REQUEST_GUILD_MEMBERS): ", string(second))
257 | time.Sleep(time.Millisecond * time.Duration(delay))
258 | err = ws.WriteMessage(websocket.TextMessage, second)
259 | if err != nil {
260 | if err == websocket.ErrCloseSent {
261 | utils.Logger("Error writing message: ", err)
262 | time.Sleep(time.Second * 1)
263 | result = scrapedMemb
264 | }
265 | utils.Logger("Error writing message: ", err)
266 |
267 | }
268 |
269 | }(i, multiplier)
270 | wg.Wait() // Can't conccurently write to websocket
271 | }
272 | }
273 | scrapedMemb = []Member{}
274 | return result
275 | }
276 |
277 | func captureData(guildID string) {
278 | // loop until channel is closed, we gotta close it after finishing fetching
279 | for d := range data {
280 | // command to exit program
281 | if d == "q" {
282 | return
283 | }
284 |
285 | go parseMemberData(d, guildID)
286 |
287 | }
288 | }
289 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "Raid-Client/constants"
5 | "Raid-Client/gateway"
6 | "Raid-Client/interact"
7 | "Raid-Client/server"
8 | "Raid-Client/tools"
9 | "Raid-Client/utils"
10 | "bufio"
11 | "fmt"
12 | "log"
13 | "os"
14 | "os/user"
15 | "runtime"
16 | "strconv"
17 | "strings"
18 | "time"
19 |
20 | "github.com/patrickmn/go-cache"
21 | )
22 |
23 | func main() {
24 | Help()
25 | for {
26 | text := Input("")
27 | spawner(text)
28 | }
29 | }
30 |
31 | func spawner(Tool string) {
32 | switch Tool {
33 | case "exit", ".exit", "EXIT", "close":
34 | utils.Logger("Exiting...")
35 | os.Exit(0)
36 | case "help", "h", "HELP ME", "menu", "home", "HELP", ".", "ls", "LS":
37 | utils.ClearScreen()
38 | Help()
39 | utils.Logger("Printing help menu")
40 | case "cls", "clear", "CLS", "CLEAR", "Clear", "Cls":
41 | utils.ClearScreen()
42 | utils.Logger("Clearing screen")
43 | case "1", "1.", "join", "join server", "JOIN", "JOIN SERVER":
44 | invite := Input("Enter Server Invite")
45 | utils.Logger("Join server module starting...")
46 | for _, tkn := range constants.Tokens {
47 | constants.Wg.Add(1)
48 | go func(TOKEN string, Server string) {
49 | server.JoinServer(Server, TOKEN)
50 | constants.Wg.Done()
51 | }(tkn, invite)
52 | }
53 | constants.Wg.Wait()
54 | case "2", "2.", "leave", "Leave Server", "leave server", "Leave":
55 | ServerID := Input("Enter Server ID")
56 | utils.Logger("Leave server module starting...")
57 | for _, tkn := range constants.Tokens {
58 | constants.Wg.Add(1)
59 | go func(TOKEN string, Server string) {
60 | server.LeaveServer(Server, TOKEN)
61 | constants.Wg.Done()
62 | }(tkn, ServerID)
63 | }
64 | constants.Wg.Wait()
65 | case "3", "3.", "spam message", "send messages", "message spammer", "spam":
66 | ServerID := Input("Enter Server ID")
67 | ChannelID := Input("Enter Channel ID")
68 | MessageToSpam := Input("Enter Message To Spam")
69 | utils.Logger("Message spammer module starting...")
70 | for _, tkn := range constants.Tokens {
71 | constants.Wg.Add(1)
72 | go func(TOKEN string, Server string, Message string, Channel string) {
73 | interact.SendMessage(Server, Channel, TOKEN, Message)
74 | constants.Wg.Done()
75 | }(tkn, ServerID, MessageToSpam, ChannelID)
76 | }
77 | constants.Wg.Wait()
78 | case "4", "4.", "reaction message", "add reaction":
79 | ChannelID := Input("Enter Channel ID")
80 | MessageID := Input("Enter Message ID")
81 | Emoji := Input("Enter Emoji")
82 | utils.Logger("Add reaction module starting...")
83 | for _, tkn := range constants.Tokens {
84 | constants.Wg.Add(1)
85 | go func(TOKEN string, Emoji string, Message string, Channel string) {
86 | interact.AddReaction(Channel, MessageID, TOKEN, Emoji)
87 | constants.Wg.Done()
88 | }(tkn, Emoji, MessageID, ChannelID)
89 | }
90 | constants.Wg.Wait()
91 | case "5", "5.", "react message", "message reaction":
92 | ChannelID := Input("Enter Channel ID")
93 | MessageID := Input("Enter Message ID")
94 | Word := Input("Enter Word")
95 | utils.Logger("Message reaction module starting...")
96 | for _, tkn := range constants.Tokens {
97 | constants.Wg.Add(1)
98 | go func(TOKEN string, Word string, Message string, Channel string) {
99 | interact.ReactionMessage(Channel, MessageID, TOKEN, Word)
100 | constants.Wg.Done()
101 | }(tkn, Word, MessageID, ChannelID)
102 | }
103 | constants.Wg.Wait()
104 | case "6", "6.", "change nickname", "nick":
105 | ServerID := Input("Enter Server ID")
106 | Nickname := Input("Enter Nickname")
107 | utils.Logger("Nickname changer module starting...")
108 | for _, tkn := range constants.Tokens {
109 | constants.Wg.Add(1)
110 | go func(TOKEN string, Server string, Nick string) {
111 | server.ChangeNickname(ServerID, TOKEN, Nickname)
112 | constants.Wg.Done()
113 | }(tkn, ServerID, Nickname)
114 | }
115 | constants.Wg.Wait()
116 | case "7", "7.", "status", "change status":
117 | Type := 0
118 | fmt.Println("[NOTE] The status will only remain active for 2 minutes")
119 | Content := Input("Enter Status Content (e.g. hello world)")
120 | gateway.Status = Input("Enter Status (e.g. online, idle, dnd)")
121 | Activity := strings.ToLower(Input("Enter Type (e.g. playing, watching, listening)"))
122 |
123 | switch Activity {
124 | case "playing":
125 | Type = gateway.ActivityGame
126 | case "watching":
127 | Type = gateway.ActivityWatching
128 | case "listening":
129 | Type = gateway.ActivityListening
130 | }
131 |
132 | gateway.Presence = []gateway.Activity{{Name: Content, Type: gateway.ActivityType(Type)}}
133 |
134 | constants.Wg.Add(1)
135 | utils.Logger("Status change module starting...")
136 | go func() {
137 | interact.TOKENS = constants.Tokens
138 | interact.ChangeStatus()
139 | constants.Wg.Done()
140 | }()
141 | constants.Wg.Wait()
142 |
143 | case "8", "8.", "friend", "add friends":
144 | Username := Input("Enter Username")
145 | utils.Logger("Add friend module starting...")
146 | for _, tkn := range constants.Tokens {
147 | constants.Wg.Add(1)
148 | go func(TOKEN string, User string) {
149 | interact.AddFriend(TOKEN, Username)
150 | constants.Wg.Done()
151 | }(tkn, Username)
152 | }
153 | constants.Wg.Wait()
154 | case "9", "9.", "unfriend", "remove friends":
155 | UserID := Input("Enter User ID")
156 | utils.Logger("Unfriend module starting...")
157 | for _, tkn := range constants.Tokens {
158 | constants.Wg.Add(1)
159 | go func(TOKEN string, User string) {
160 | interact.RemoveFriend(TOKEN, UserID)
161 | constants.Wg.Done()
162 | }(tkn, UserID)
163 | }
164 | constants.Wg.Wait()
165 |
166 | case "10", "10.", "check", "check token", "token check":
167 | utils.Logger("Token Checker module starting...")
168 | constants.Wg.Add(1)
169 | go func() {
170 | defer constants.Wg.Done()
171 | t := utils.CheckTokens(constants.Tokens)
172 | utils.Logger("Writing old tokens to old_tokens.txt")
173 | utils.WriteLines(constants.Tokens, "./old_tokens.txt")
174 | constants.Tokens = nil
175 | constants.Tokens = t
176 | utils.Logger("Writing working tokens to tokens.txt")
177 | utils.WriteLines(constants.Tokens, "./tokens.txt")
178 | }()
179 | constants.Wg.Wait()
180 | case "11", "11.", "massmention", "massping":
181 | utils.Logger("MassPing module starting...")
182 | constants.Wg.Add(1)
183 | go func() {
184 | defer constants.Wg.Done()
185 | /*
186 | Start Scraping
187 | */
188 | MasterToken := Input("Enter Token that will be used to scrape")
189 | ServerID := Input("Enter Server ID (Your token need to be in this server)")
190 | ChannelID := Input("Enter Channel ID (Select a channel where most of the members have access like a #rules one)")
191 | VictimChannelID := Input("Enter Channel ID where you want the MassPing to occur")
192 | Amount, _ := strconv.Atoi(Input("Number of time each token will repeat (10 is solid)"))
193 | ws := gateway.SetupWebSocket(MasterToken)
194 | go func() {
195 | err := gateway.RecieveIncomingPayloads(ws, MasterToken)
196 | if err != nil {
197 | fmt.Println(err)
198 | }
199 | }()
200 | var z []gateway.Member
201 | var ScrapedID []string
202 | time.Sleep(time.Second * 2)
203 | z = gateway.SearchGuildMembers(ws, z, ServerID, ChannelID, MasterToken, "overlap", 500) // SearchGuildMembers(ws *websocket.Conn, guildID, channelID, token, method string, delay int)
204 | fmt.Printf("Fetched %d members\n", len(z))
205 | ws.Close()
206 | for _, k := range z {
207 | ScrapedID = append(ScrapedID, k.User.ID)
208 | }
209 |
210 | /*
211 | Main routine for MassPing
212 | */
213 | fmt.Printf("Starting MassPing\n")
214 | interact.MassPing(ServerID, VictimChannelID, ScrapedID, constants.Tokens, Amount)
215 | }()
216 | constants.Wg.Wait()
217 | }
218 |
219 | }
220 |
221 | func Input(DisplayText string) string {
222 | var rtnInput string
223 | user, err := user.Current()
224 | if err != nil {
225 | log.Fatal(err)
226 | }
227 | reader := bufio.NewReader(os.Stdin)
228 | if user.Name == "" {
229 | user.Name = "Raider"
230 | }
231 | if DisplayText == "" {
232 | fmt.Printf("%s@DiscSpam > ", user.Name)
233 | } else {
234 | fmt.Printf("%s > ", DisplayText)
235 | }
236 | text, _ := reader.ReadString('\n')
237 | if runtime.GOOS == "windows" {
238 | rtnInput = strings.Replace(text, "\r\n", "", -1)
239 | } else {
240 | rtnInput = strings.Replace(text, "\n", "", -1)
241 | }
242 | return rtnInput
243 | }
244 |
245 | func Help() {
246 | if constants.Proxy {
247 | fmt.Printf("%d Proxies Loaded\n", len(constants.Proxies))
248 | }
249 | fmt.Printf("%d Tokens Loaded\n", len(constants.Tokens))
250 | fmt.Printf("%s %s\n", constants.White("1. Join Server - Params:"), constants.Red(""))
251 | fmt.Printf("%s %s\n", constants.White("2. Leave Server - Params:"), constants.Red(""))
252 | fmt.Printf("%s %s\n", constants.White("3. Spam Message - Params:"), constants.Red(" "))
253 | fmt.Printf("%s %s\n", constants.White("4. Add Reaction - Params:"), constants.Red(" "))
254 | fmt.Printf("%s %s\n", constants.White("5. Add Reaction Message - Params:"), constants.Red(" "))
255 | fmt.Printf("%s %s\n", constants.White("6. Change Nickname - Params:"), constants.Red(" "))
256 | fmt.Printf("%s %s\n", constants.White("7. Change Status - Params:"), constants.Red(" "))
257 | fmt.Printf("%s %s\n", constants.White("8. Add Friend - Params:"), constants.Red(" i.e Wumpus#0000"))
258 | fmt.Printf("%s %s\n", constants.White("9. Remove Friend - Params:"), constants.Red(""))
259 | fmt.Printf("%s %s\n", constants.White("10. Check Tokens - Params"), constants.Red(""))
260 | fmt.Printf("%s %s\n", constants.White("11. Mass Ping - Params"), constants.Red(" "))
261 | }
262 |
263 | func init() {
264 | l, p := utils.Get_commandline_values()
265 | constants.Logging = *l
266 | constants.Proxy = *p
267 |
268 | // Call our logger function and set the file output if needed
269 | go utils.SetupLogger()
270 | if constants.Proxy {
271 | utils.Logger("Proxy module starting...")
272 | constants.Wg.Add(1)
273 | go func() {
274 | defer constants.Wg.Done()
275 | tools.PopulateProxies()
276 | }()
277 | constants.Wg.Wait()
278 | }
279 |
280 | utils.ClearScreen()
281 | server.C = cache.New(60*time.Minute, 120*time.Minute)
282 | tmp, err := utils.ReadTokens("./tokens.txt")
283 | if err != nil {
284 | utils.Logger("Error reading discord tokens from tokens.txt")
285 | fmt.Printf("%s\n", constants.Red("Error reading discord tokens from tokens.txt"))
286 | time.Sleep(1 * time.Second)
287 | os.Exit(0)
288 | }
289 | constants.Tokens = tmp
290 | }
291 |
--------------------------------------------------------------------------------