├── 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 | 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 | 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 | ![Screen Shot](images/screenshot.png) 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 | --------------------------------------------------------------------------------