Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
V4NSH4J
GitHub Repository: V4NSH4J/discord-mass-DM-GO
Path: blob/main/discord/mass_dm.go
310 views
1
// Copyright (C) 2021 github.com/V4NSH4J
2
//
3
// This source code has been released under the GNU Affero General Public
4
// License v3.0. A copy of this license is available at
5
// https://www.gnu.org/licenses/agpl-3.0.en.html
6
7
package discord
8
9
import (
10
"encoding/json"
11
"errors"
12
"fmt"
13
"io"
14
"math/rand"
15
"os"
16
"os/exec"
17
"strconv"
18
"strings"
19
"sync"
20
"time"
21
22
"github.com/V4NSH4J/discord-mass-dm-GO/instance"
23
"github.com/V4NSH4J/discord-mass-dm-GO/utilities"
24
)
25
26
func LaunchMassDM() {
27
members, err := utilities.ReadLines("memberids.txt")
28
if err != nil {
29
utilities.LogErr("Error while opening MemberIDs file %s", err)
30
return
31
}
32
cfg, instances, err := instance.GetEverything()
33
if err != nil {
34
utilities.LogErr("Error while getting config or instances %s", err)
35
return
36
}
37
var tokenFile, completedUsersFile, failedUsersFile, lockedFile, quarantinedFile, logsFile string
38
if cfg.OtherSettings.Logs {
39
path := fmt.Sprintf(`logs/mass_dm/DMDGO-MASSDM-%s-%s`, time.Now().Format(`2006-01-02 15-04-05`), utilities.RandStringBytes(5))
40
err := os.MkdirAll(path, 0755)
41
if err != nil && !os.IsExist(err) {
42
utilities.LogErr("Error creating logs directory: %s", err)
43
utilities.ExitSafely()
44
}
45
tokenFileX, err := os.Create(fmt.Sprintf(`%s/token.txt`, path))
46
if err != nil {
47
utilities.LogErr("Error creating token file: %s", err)
48
utilities.ExitSafely()
49
}
50
tokenFileX.Close()
51
completedUsersFileX, err := os.Create(fmt.Sprintf(`%s/success.txt`, path))
52
if err != nil {
53
utilities.LogErr("Error creating success file: %s", err)
54
utilities.ExitSafely()
55
}
56
completedUsersFileX.Close()
57
failedUsersFileX, err := os.Create(fmt.Sprintf(`%s/failed.txt`, path))
58
if err != nil {
59
utilities.LogErr("Error creating failed file: %s", err)
60
utilities.ExitSafely()
61
}
62
failedUsersFileX.Close()
63
lockedFileX, err := os.Create(fmt.Sprintf(`%s/locked.txt`, path))
64
if err != nil {
65
utilities.LogErr("Error creating failed file: %s", err)
66
utilities.ExitSafely()
67
}
68
lockedFileX.Close()
69
quarantinedFileX, err := os.Create(fmt.Sprintf(`%s/quarantined.txt`, path))
70
if err != nil {
71
utilities.LogErr("Error creating failed file: %s", err)
72
utilities.ExitSafely()
73
}
74
quarantinedFileX.Close()
75
LogsX, err := os.Create(fmt.Sprintf(`%s/logs.txt`, path))
76
if err != nil {
77
utilities.LogErr("Error creating failed file: %s", err)
78
utilities.ExitSafely()
79
}
80
LogsX.Close()
81
tokenFile, completedUsersFile, failedUsersFile, lockedFile, quarantinedFile, logsFile = tokenFileX.Name(), completedUsersFileX.Name(), failedUsersFileX.Name(), lockedFileX.Name(), quarantinedFileX.Name(), LogsX.Name()
82
for i := 0; i < len(instances); i++ {
83
instances[i].WriteInstanceToFile(tokenFile)
84
}
85
}
86
if cfg.OtherSettings.Logs {
87
utilities.WriteLinesPath(logsFile, fmt.Sprintf("Start Time: %v", time.Now()))
88
}
89
var msg instance.Message
90
messagechoice := utilities.UserInputInteger("Enter 1 to use message from file, 2 to use message from console: ")
91
if messagechoice != 1 && messagechoice != 2 {
92
utilities.LogErr("Invalid choice")
93
return
94
}
95
if messagechoice == 2 {
96
text := utilities.UserInput("Enter your message, use \\n for changing lines. You can also set a constant message in message.json")
97
msg.Content = text
98
msg.Content = strings.Replace(msg.Content, "\\n", "\n", -1)
99
var msgs []instance.Message
100
msgs = append(msgs, msg)
101
err := instance.SetMessages(instances, msgs)
102
if err != nil {
103
utilities.LogErr("Error while setting messages: %s", err)
104
return
105
}
106
} else {
107
var msgs []instance.Message
108
err := instance.SetMessages(instances, msgs)
109
if err != nil {
110
utilities.LogErr("Error while setting messages: %s", err)
111
return
112
}
113
}
114
if cfg.OtherSettings.Logs {
115
if len(instances) > 0 {
116
utilities.WriteLinesPath(logsFile, fmt.Sprintf("Messages Loaded: %v", instances[0].Messages))
117
}
118
}
119
advancedchoice := utilities.UserInputInteger("Do you wish to use Advanced Settings? 0: No, 1: Yes: ")
120
121
var checkchoice int
122
var serverid string
123
var tryjoinchoice int
124
var invite string
125
var maxattempts int
126
if advancedchoice != 0 && advancedchoice != 1 {
127
utilities.LogErr("Invalid choice")
128
return
129
}
130
if advancedchoice == 1 {
131
checkchoice := utilities.UserInputInteger("Do you wish to check if token is still in server before every DM? [0: No, 1: Yes]")
132
if checkchoice != 0 && checkchoice != 1 {
133
utilities.LogErr("Invalid choice")
134
return
135
}
136
if checkchoice == 1 {
137
serverid = utilities.UserInput("Enter the server ID: ")
138
tryjoinchoice := utilities.UserInputInteger("Do you wish to try rejoining the server if token is not in server? [0: No, 1: Yes]")
139
if tryjoinchoice != 0 && tryjoinchoice != 1 {
140
utilities.LogErr("Invalid choice")
141
return
142
}
143
if tryjoinchoice == 1 {
144
invite = utilities.UserInput("Enter a permanent invite code")
145
maxattempts = utilities.UserInputInteger("Enter max rejoin attempts")
146
}
147
}
148
}
149
// Also initiate variables and slices for logging and counting
150
var session []string
151
var completed []string
152
var failed []string
153
var dead []string
154
var failedCount = 0
155
var openedChannels = 0
156
completed, err = utilities.ReadLines("completed.txt")
157
if err != nil {
158
utilities.LogErr("Error while opening completed.txt %s", err)
159
return
160
}
161
if cfg.DirectMessage.Skip {
162
members = utilities.RemoveSubset(members, completed)
163
if cfg.OtherSettings.Logs {
164
utilities.WriteLinesPath(logsFile, fmt.Sprintf("Users blacklisted from completed.txt: %v", len(completed)))
165
}
166
}
167
if cfg.DirectMessage.SkipFailed {
168
failedSkip, err := utilities.ReadLines("failed.txt")
169
if err != nil {
170
utilities.LogErr("Error while opening failed.txt %s", err)
171
return
172
}
173
if cfg.OtherSettings.Logs {
174
utilities.WriteLinesPath(logsFile, fmt.Sprintf("Users blacklisted from failed.txt: %v", len(failedSkip)))
175
}
176
members = utilities.RemoveSubset(members, failedSkip)
177
}
178
if len(instances) == 0 {
179
utilities.LogErr("Enter your tokens in tokens.txt")
180
if cfg.OtherSettings.Logs {
181
utilities.WriteLinesPath(logsFile, fmt.Sprintf("Tokens loaded: %v", len(instances)))
182
}
183
return
184
}
185
if len(members) == 0 {
186
utilities.LogErr("Enter your memberids and ensure they're not all in completed.txt or failed.txt")
187
return
188
}
189
if len(members) < len(instances) {
190
instances = instances[:len(members)]
191
}
192
if cfg.OtherSettings.Logs {
193
utilities.WriteLinesPath(logsFile, fmt.Sprintf("Unique members loaded: %v", len(members)))
194
}
195
msgs := instances[0].Messages
196
for i := 0; i < len(msgs); i++ {
197
if msgs[i].Content == "" && msgs[i].Embeds == nil {
198
utilities.LogWarn("Message %v is empty", i)
199
}
200
}
201
// Send members to a channel
202
mem := make(chan string, len(members))
203
go func() {
204
for i := 0; i < len(members); i++ {
205
mem <- members[i]
206
}
207
}()
208
ticker := make(chan bool)
209
// Setting information to windows titlebar by github.com/foxzsz
210
go func() {
211
Out:
212
for {
213
select {
214
case <-ticker:
215
break Out
216
default:
217
cmd := exec.Command("cmd", "/C", "title", fmt.Sprintf(`DMDGO [%d sent, %v failed, %d locked, %v avg. dms, %v avg. channels, %d tokens left]`, len(session), len(failed), len(dead), len(session)/len(instances), openedChannels/len(instances), len(instances)-len(dead)))
218
_ = cmd.Run()
219
}
220
221
}
222
}()
223
var wg sync.WaitGroup
224
start := time.Now()
225
for i := 0; i < len(instances); i++ {
226
// Offset goroutines by a few milliseconds. Makes a big difference and allows for better concurrency
227
time.Sleep(time.Duration(cfg.DirectMessage.Offset) * time.Millisecond)
228
wg.Add(1)
229
go func(i int) {
230
defer wg.Done()
231
for {
232
// Get a member from the channel
233
if len(mem) == 0 {
234
break
235
}
236
member := <-mem
237
instances[i].LastIDstr = ""
238
// Breaking loop if maximum DMs reached
239
if cfg.DirectMessage.MaxDMS != 0 && instances[i].Count >= cfg.DirectMessage.MaxDMS {
240
utilities.LogInfo("Maximum DMs reached for %v", instances[i].CensorToken())
241
if cfg.OtherSettings.Logs {
242
utilities.WriteLinesPath(logsFile, fmt.Sprintf("[%v][Success:%v][Failed:%v] %v token max DMs reached", time.Now().Format("15:04:05"), len(session), len(failed), instances[i].CensorToken()))
243
}
244
break
245
}
246
// Start websocket connection if not already connected and reconnect if dead
247
if cfg.DirectMessage.Websocket && instances[i].Ws == nil {
248
err := instances[i].StartWS()
249
if err != nil {
250
utilities.LogFailed("Error while opening websocket: %v", err)
251
} else {
252
utilities.LogSuccess("Websocket opened %v", instances[i].CensorToken())
253
}
254
}
255
// Check if token is valid
256
status := instances[i].CheckToken()
257
if status != 200 && status != 204 && status != 429 && status != -1 {
258
failedCount++
259
if cfg.OtherSettings.Logs {
260
utilities.WriteLinesPath(failedUsersFile, member)
261
}
262
utilities.LogLocked("Token %v might be locked - Stopping instance and adding members to failed list. %v [%v]", instances[i].CensorToken(), status, failedCount)
263
if cfg.OtherSettings.Logs {
264
utilities.WriteLinesPath(logsFile, fmt.Sprintf("[%v][Success:%v][Failed:%v] %v token locked", time.Now().Format("15:04:05"), len(session), len(failed), instances[i].CensorToken()))
265
}
266
failed = append(failed, member)
267
dead = append(dead, instances[i].Token)
268
if cfg.OtherSettings.Logs {
269
instances[i].WriteInstanceToFile(lockedFile)
270
}
271
err := utilities.WriteLines("failed.txt", member)
272
if err != nil {
273
utilities.LogErr("Error while writing to failed.txt %s", err)
274
}
275
if cfg.DirectMessage.Stop {
276
break
277
}
278
}
279
// Advanced Options
280
if advancedchoice == 1 {
281
if checkchoice == 1 {
282
r, err := instances[i].ServerCheck(serverid)
283
if err != nil {
284
utilities.LogErr("Error while checking server %s", err)
285
continue
286
}
287
if r != 200 && r != 204 && r != 429 {
288
if tryjoinchoice == 0 {
289
utilities.LogFailed("Token %s is not present in server %s", instances[i].CensorToken(), serverid)
290
if cfg.OtherSettings.Logs {
291
utilities.WriteLinesPath(logsFile, fmt.Sprintf("[%v][Success:%v][Failed:%v] %v token not present in server %v", time.Now().Format("15:04:05"), len(session), len(failed), instances[i].CensorToken(), serverid))
292
}
293
break
294
} else {
295
if instances[i].Retry >= maxattempts {
296
if cfg.OtherSettings.Logs {
297
utilities.WriteLinesPath(logsFile, fmt.Sprintf("[%v][Success:%v][Failed:%v] %v token max rejoin attempts", time.Now().Format("15:04:05"), len(session), len(failed), instances[i].CensorToken()))
298
}
299
utilities.LogFailed("Stopping token %v [Max server rejoin attempts]", instances[i].CensorToken())
300
break
301
}
302
err := instances[i].Invite(invite)
303
if err != nil {
304
utilities.LogFailed("Error while joining server: %v", err)
305
if cfg.OtherSettings.Logs {
306
utilities.WriteLinesPath(logsFile, fmt.Sprintf("[%v][Success:%v][Failed:%v] %v token error while joining server %v", time.Now().Format("15:04:05"), len(session), len(failed), instances[i].CensorToken(), err))
307
}
308
instances[i].Retry++
309
continue
310
}
311
}
312
}
313
}
314
}
315
var user string
316
user = member
317
// Check Mutual
318
if cfg.DirectMessage.Mutual {
319
info, err := instances[i].UserInfo(member)
320
if err != nil {
321
failedCount++
322
if cfg.OtherSettings.Logs {
323
utilities.WriteLinesPath(failedUsersFile, member)
324
}
325
utilities.LogErr("Error while getting user info: %v [%v]", err, failedCount)
326
err = utilities.WriteLine("input/failed.txt", member)
327
if err != nil {
328
utilities.LogErr("Error while writing to failed.txt %s", err)
329
}
330
failed = append(failed, member)
331
332
continue
333
}
334
if len(info.Mutual) == 0 {
335
failedCount++
336
if cfg.OtherSettings.Logs {
337
utilities.WriteLinesPath(failedUsersFile, member)
338
}
339
utilities.LogFailed("Token %v failed to DM %v [No Mutual Server] [%v]", instances[i].CensorToken(), info.User.Username+info.User.Discriminator, failedCount)
340
if cfg.OtherSettings.Logs {
341
utilities.WriteLinesPath(logsFile, fmt.Sprintf("[%v][Success:%v][Failed:%v] %v token failed to DM %v [No mutuals]", time.Now().Format("15:04:05"), len(session), len(failed), instances[i].CensorToken(), member))
342
}
343
err = utilities.WriteLine("input/failed.txt", member)
344
if err != nil {
345
utilities.LogErr("Error while writing to failed.txt %s", err)
346
}
347
failed = append(failed, member)
348
continue
349
}
350
user = info.User.Username + "#" + info.User.Discriminator
351
// Used only if Websocket is enabled as Unwebsocketed Tokens get locked if they attempt to send friend requests.
352
if cfg.DirectMessage.Friend && cfg.DirectMessage.Websocket {
353
x, err := strconv.Atoi(info.User.Discriminator)
354
if err != nil {
355
utilities.LogErr("Error while converting discriminator to int: %v", err)
356
continue
357
}
358
resp, err := instances[i].Friend(info.User.Username, x)
359
if err != nil {
360
utilities.LogErr("Error while sending friend request: %v", err)
361
continue
362
}
363
defer resp.Body.Close()
364
if resp.StatusCode != 204 && err != nil {
365
if !errors.Is(err, io.ErrUnexpectedEOF) {
366
body, err := utilities.ReadBody(*resp)
367
if err != nil {
368
utilities.LogErr("Error while reading body: %v", err)
369
continue
370
}
371
utilities.LogFailed("Error while sending friend request: %v", body)
372
continue
373
}
374
utilities.LogErr("Error while sending friend request: %v", err)
375
continue
376
} else {
377
utilities.LogSuccess("Friend request sent to %v", info.User.Username+info.User.Discriminator)
378
if cfg.OtherSettings.Logs {
379
utilities.WriteLinesPath(logsFile, fmt.Sprintf("[%v][Success:%v][Failed:%v] %v token friended %v", time.Now().Format("15:04:05"), len(session), len(failed), instances[i].CensorToken(), member))
380
}
381
}
382
}
383
}
384
// Open channel to get snowflake
385
snowflake, err := instances[i].OpenChannel(member)
386
if err != nil {
387
failedCount++
388
if cfg.OtherSettings.Logs {
389
utilities.WriteLinesPath(failedUsersFile, member)
390
}
391
utilities.LogErr("Error while opening DM channel: %v [%v]", err, failedCount)
392
if cfg.OtherSettings.Logs {
393
utilities.WriteLinesPath(logsFile, fmt.Sprintf("[%v][Success:%v][Failed:%v] %v token error %v while opening channel", time.Now().Format("15:04:05"), len(session), len(failed), instances[i].CensorToken(), err))
394
}
395
err = utilities.WriteLine("input/failed.txt", member)
396
if err != nil {
397
utilities.LogErr("Error while writing to failed.txt %s", err)
398
}
399
failed = append(failed, member)
400
if instances[i].Quarantined {
401
break
402
}
403
continue
404
}
405
if cfg.SuspicionAvoidance.RandomDelayOpenChannel != 0 {
406
time.Sleep(time.Duration(rand.Intn(cfg.SuspicionAvoidance.RandomDelayOpenChannel)) * time.Second)
407
}
408
respCode, body, err := instances[i].SendMessage(snowflake, member)
409
openedChannels++
410
if err != nil {
411
failedCount++
412
if cfg.OtherSettings.Logs {
413
utilities.WriteLinesPath(failedUsersFile, member)
414
}
415
utilities.LogErr("Error while sending message: %v [%v]", err, failedCount)
416
err = utilities.WriteLine("input/failed.txt", member)
417
if err != nil {
418
utilities.LogErr("Error while writing to failed.txt %s", err)
419
}
420
failed = append(failed, member)
421
continue
422
}
423
var response jsonResponse
424
errx := json.Unmarshal(body, &response)
425
if errx != nil {
426
failedCount++
427
if cfg.OtherSettings.Logs {
428
utilities.WriteLinesPath(failedUsersFile, member)
429
}
430
utilities.LogErr("Error while unmarshalling body: %v [%v]", errx, failedCount)
431
err = utilities.WriteLine("input/failed.txt", member)
432
if err != nil {
433
utilities.LogErr("Error while writing to failed.txt %s", err)
434
}
435
failed = append(failed, member)
436
continue
437
}
438
// Everything is fine, continue as usual
439
if respCode == 200 {
440
err = utilities.WriteLine("input/completed.txt", member)
441
if err != nil {
442
utilities.LogErr("Error while writing to completed.txt %s", err)
443
}
444
if cfg.OtherSettings.Logs {
445
utilities.WriteLinesPath(completedUsersFile, member)
446
}
447
completed = append(completed, member)
448
session = append(session, member)
449
utilities.LogSuccess("[DM-%v] Token %v sent DM to %v", len(session), instances[i].CensorToken(), user)
450
if cfg.DirectMessage.Websocket && cfg.DirectMessage.Call && instances[i].Ws != nil {
451
err := instances[i].Call(snowflake)
452
if err != nil {
453
utilities.LogErr("Token %v Error while calling %v: %v", instances[i].CensorToken(), user, err)
454
}
455
// Unfriended people can't ring.
456
//
457
// resp, err := instance.Ring(instances[i].Client, instances[i].Token, snowflake)
458
// if err != nil {
459
// color.Red("%v Error while ringing %v: %v", instances[i].Token, user, err)
460
// }
461
// if resp == 200 || resp == 204 {
462
// color.Green("%v Ringed %v", instances[i].Token, user)
463
// } else {
464
// color.Red("%v Error while ringing %v: %v", instances[i].Token, user, resp)
465
// }
466
467
}
468
if cfg.DirectMessage.Block {
469
r, err := instances[i].BlockUser(member)
470
if err != nil {
471
utilities.LogErr("Error while blocking user: %v", err)
472
} else {
473
if r == 204 {
474
utilities.LogSuccess("Blocked %v", user)
475
if cfg.OtherSettings.Logs {
476
utilities.WriteLinesPath(logsFile, fmt.Sprintf("[%v][Success:%v][Failed:%v] %v token blocked user %v", time.Now().Format("15:04:05"), len(session), len(failed), instances[i].CensorToken(), member))
477
}
478
} else {
479
utilities.LogErr("Error while blocking user: %v", r)
480
}
481
}
482
}
483
if cfg.DirectMessage.Close {
484
r, err := instances[i].CloseDMS(snowflake)
485
if err != nil {
486
utilities.LogErr("Error while closing DM: %v", err)
487
} else {
488
if r == 200 {
489
utilities.LogSuccess("Closed %v", user)
490
if cfg.OtherSettings.Logs {
491
utilities.WriteLinesPath(logsFile, fmt.Sprintf("[%v][Success:%v][Failed:%v] %v token closed DM of user %v", time.Now().Format("15:04:05"), len(session), len(failed), instances[i].CensorToken(), member))
492
}
493
} else {
494
utilities.LogErr("Error while closing DM: %v", r)
495
}
496
}
497
}
498
// Forbidden - Token is being rate limited
499
} else if response.Code == 20026 {
500
utilities.LogLocked("Token %v is Quarantined, considering it locked", instances[i].CensorToken())
501
if cfg.OtherSettings.Logs {
502
utilities.WriteLinesPath(logsFile, fmt.Sprintf("[%v][Success:%v][Failed:%v] %v token quarantined", time.Now().Format("15:04:05"), len(session), len(failed), instances[i].CensorToken()))
503
}
504
if cfg.OtherSettings.Logs {
505
utilities.WriteLinesPath(failedUsersFile, member)
506
}
507
dead = append(dead, instances[i].Token)
508
if cfg.OtherSettings.Logs {
509
instances[i].WriteInstanceToFile(lockedFile)
510
}
511
// Stop token if locked or disabled
512
if cfg.DirectMessage.Stop {
513
break
514
}
515
if cfg.OtherSettings.Logs {
516
instances[i].WriteInstanceToFile(quarantinedFile)
517
utilities.WriteLinesPath(logsFile, fmt.Sprintf("[%v][Success:%v][Failed:%v] %v token quarantined", time.Now().Format("15:04:05"), len(session), len(failed), instances[i].CensorToken()))
518
}
519
mem <- member
520
521
} else if respCode == 403 && response.Code == 40003 {
522
mem <- member
523
utilities.LogInfo("Token %v sleeping for %v minutes!", instances[i].CensorToken(), int(cfg.DirectMessage.LongDelay/60))
524
if cfg.OtherSettings.Logs {
525
utilities.WriteLinesPath(logsFile, fmt.Sprintf("[%v][Success:%v][Failed:%v] %v token rate limited, sleeping for %v seconds", time.Now().Format("15:04:05"), len(session), len(failed), instances[i].CensorToken(), cfg.DirectMessage.LongDelay))
526
}
527
time.Sleep(time.Duration(cfg.DirectMessage.LongDelay) * time.Second)
528
if cfg.SuspicionAvoidance.RandomRateLimitDelay != 0 {
529
time.Sleep(time.Duration(rand.Intn(cfg.SuspicionAvoidance.RandomRateLimitDelay)) * time.Second)
530
}
531
utilities.LogInfo("Token %v continuing!", instances[i].CensorToken())
532
if cfg.OtherSettings.Logs {
533
utilities.WriteLinesPath(logsFile, fmt.Sprintf("[%v][Success:%v][Failed:%v] %v token continuing", time.Now().Format("15:04:05"), len(session), len(failed), instances[i].CensorToken()))
534
}
535
// Forbidden - DM's are closed
536
} else if respCode == 403 && response.Code == 50007 {
537
failedCount++
538
if cfg.OtherSettings.Logs {
539
utilities.WriteLinesPath(failedUsersFile, member)
540
}
541
failed = append(failed, member)
542
err = utilities.WriteLine("input/failed.txt", member)
543
if err != nil {
544
utilities.LogErr("Error while writing to failed.txt %s", err)
545
}
546
utilities.LogFailed("Token %v failed to DM %v User has DMs closed or not present in server ", instances[i].CensorToken(), user)
547
if cfg.OtherSettings.Logs {
548
utilities.WriteLinesPath(logsFile, fmt.Sprintf("[%v][Success:%v][Failed:%v] %v token failed to DM %v [DMs closed or no mutual servers]", time.Now().Format("15:04:05"), len(session), len(failed), instances[i].CensorToken(), member))
549
}
550
// Forbidden - Locked or Disabled
551
} else if (respCode == 403 && response.Code == 40002) || respCode == 401 || respCode == 405 {
552
if cfg.OtherSettings.Logs {
553
utilities.WriteLinesPath(failedUsersFile, member)
554
}
555
utilities.LogFailed("Token %v is locked or disabled. Stopping instance. %v %v", instances[i].CensorToken(), respCode, string(body))
556
if cfg.OtherSettings.Logs {
557
utilities.WriteLinesPath(logsFile, fmt.Sprintf("[%v][Success:%v][Failed:%v] %v token locked or disabled", time.Now().Format("15:04:05"), len(session), len(failed), instances[i].CensorToken()))
558
}
559
dead = append(dead, instances[i].Token)
560
if cfg.OtherSettings.Logs {
561
instances[i].WriteInstanceToFile(lockedFile)
562
}
563
// Stop token if locked or disabled
564
if cfg.DirectMessage.Stop {
565
break
566
}
567
mem <- member
568
// Forbidden - Invalid token
569
} else if respCode == 403 && response.Code == 50009 {
570
failedCount++
571
if cfg.OtherSettings.Logs {
572
utilities.WriteLinesPath(failedUsersFile, member)
573
}
574
failed = append(failed, member)
575
err = utilities.WriteLine("input/failed.txt", member)
576
if err != nil {
577
utilities.LogErr("Error while writing to failed.txt %s", err)
578
}
579
utilities.LogFailed("Token %v can't DM %v. It may not have bypassed membership screening or it's verification level is too low or the server requires new members to wait 10 minutes before they can interact in the server. %v", instances[i].CensorToken(), user, string(body))
580
if cfg.OtherSettings.Logs {
581
utilities.WriteLinesPath(logsFile, fmt.Sprintf("[%v][Success:%v][Failed:%v] %v token channel verification level too high", time.Now().Format("15:04:05"), len(session), len(failed), instances[i].CensorToken()))
582
}
583
// General case - Continue loop. If problem with instance, it will be stopped at start of loop.
584
} else if respCode == 429 {
585
utilities.LogFailed("Token %v is being rate limited. Sleeping for 10 seconds", instances[i].CensorToken())
586
if cfg.OtherSettings.Logs {
587
utilities.WriteLinesPath(logsFile, fmt.Sprintf("[%v][Success:%v][Failed:%v] %v token rate limited", time.Now().Format("15:04:05"), len(session), len(failed), instances[i].CensorToken()))
588
}
589
mem <- member
590
time.Sleep(10 * time.Second)
591
} else if respCode == 400 && strings.Contains(string(body), "captcha") {
592
mem <- member
593
utilities.LogFailed("Token %v Captcha was solved incorrectly", instances[i].CensorToken())
594
if instances[i].Config.CaptchaSettings.CaptchaAPI == "anti-captcha.com" {
595
err := instances[i].ReportIncorrectRecaptcha()
596
if err != nil {
597
utilities.LogFailed("Error while reporting incorrect hcaptcha: %v", err)
598
} else {
599
utilities.LogSuccess("Succesfully reported incorrect hcaptcha [%v]", instances[i].LastID)
600
}
601
}
602
instances[i].Retry++
603
if instances[i].Retry >= cfg.CaptchaSettings.MaxCaptchaDM && cfg.CaptchaSettings.MaxCaptchaDM != 0 {
604
utilities.LogFailed("Stopping token %v max captcha solves reached", instances[i].CensorToken())
605
break
606
}
607
} else {
608
failedCount++
609
if cfg.OtherSettings.Logs {
610
utilities.WriteLinesPath(failedUsersFile, member)
611
}
612
failed = append(failed, member)
613
err = utilities.WriteLine("input/failed.txt", member)
614
if err != nil {
615
utilities.LogErr("Error while writing to failed.txt %s", err)
616
}
617
utilities.LogFailed("Token %v couldn't DM %v Error Code: %v; Status: %v; Message: %v", instances[i].CensorToken(), user, response.Code, respCode, response.Message)
618
if cfg.OtherSettings.Logs {
619
utilities.WriteLinesPath(logsFile, fmt.Sprintf("[%v][Success:%v][Failed:%v] %v token failed to DM %v error %v", time.Now().Format("15:04:05"), len(session), len(failed), instances[i].CensorToken(), user, response.Message))
620
}
621
}
622
time.Sleep(time.Duration(cfg.DirectMessage.Delay) * time.Second)
623
if cfg.SuspicionAvoidance.RandomIndividualDelay != 0 {
624
time.Sleep(time.Duration(rand.Intn(cfg.SuspicionAvoidance.RandomIndividualDelay)) * time.Second)
625
}
626
}
627
}(i)
628
}
629
wg.Wait()
630
631
utilities.LogSuccess("Threads have finished! Writing to file")
632
ticker <- true
633
elapsed := time.Since(start)
634
utilities.LogSuccess("DM advertisement took %v. Successfully sent DMs to %v IDs. Failed to send DMs to %v IDs. %v tokens are dis-functional & %v tokens are functioning", elapsed.Seconds(), len(session), len(failed), len(dead), len(instances)-len(dead))
635
if cfg.OtherSettings.Logs {
636
utilities.WriteLinesPath(logsFile, fmt.Sprintf("DM advertisement took %v. Successfully sent DMs to %v IDs. Failed to send DMs to %v IDs. %v tokens are dis-functional & %v tokens are functioning", elapsed.Seconds(), len(session), len(failed), len(dead), len(instances)-len(dead)))
637
}
638
var left []string
639
if cfg.DirectMessage.Remove {
640
for i := 0; i < len(instances); i++ {
641
if !utilities.Contains(dead, instances[i].Token) {
642
if instances[i].Password == "" {
643
left = append(left, instances[i].Token)
644
} else {
645
left = append(left, fmt.Sprintf(`%v:%v:%v`, instances[i].Email, instances[i].Password, instances[i].Token))
646
}
647
}
648
}
649
err := utilities.Truncate("input/tokens.txt", left)
650
if err != nil {
651
utilities.LogErr("Error while writing to failed.txt %s", err)
652
}
653
utilities.LogSuccess("Updated tokens.txt")
654
}
655
if cfg.DirectMessage.RemoveM {
656
m := utilities.RemoveSubset(members, completed)
657
err := utilities.Truncate("input/memberids.txt", m)
658
if err != nil {
659
utilities.LogErr("Error while writing to failed.txt %s", err)
660
}
661
utilities.LogSuccess("Updated memberids.txt")
662
663
}
664
if cfg.DirectMessage.Websocket {
665
for i := 0; i < len(instances); i++ {
666
if instances[i].Ws != nil {
667
instances[i].Ws.Close()
668
}
669
}
670
}
671
672
}
673
674
type jsonResponse struct {
675
Message string `json:"message"`
676
Code int `json:"code"`
677
}
678
679
func LaunchSingleDM() {
680
choice := utilities.UserInputInteger("Enter 0 for one message; Enter 1 for continuous spam")
681
cfg, instances, err := instance.GetEverything()
682
if err != nil {
683
utilities.LogErr("Error while getting config or instances%s", err)
684
return
685
}
686
var msg instance.Message
687
messagechoice := utilities.UserInputInteger("Enter 1 to use message from file, 2 to use message from console: ")
688
if messagechoice != 1 && messagechoice != 2 {
689
utilities.LogErr("Invalid choice")
690
return
691
}
692
if messagechoice == 2 {
693
text := utilities.UserInput("Enter your message, use \\n for changing lines. You can also set a constant message in message.json")
694
msg.Content = text
695
msg.Content = strings.Replace(msg.Content, "\\n", "\n", -1)
696
var msgs []instance.Message
697
msgs = append(msgs, msg)
698
err := instance.SetMessages(instances, msgs)
699
if err != nil {
700
utilities.LogErr("Error while setting messages: %s", err)
701
return
702
}
703
} else {
704
var msgs []instance.Message
705
err := instance.SetMessages(instances, msgs)
706
if err != nil {
707
utilities.LogErr("Error while setting messages: %s", err)
708
return
709
}
710
}
711
712
victim := utilities.UserInput("Ensure a common link and enter victim's ID: ")
713
var wg sync.WaitGroup
714
wg.Add(len(instances))
715
if choice == 0 {
716
for i := 0; i < len(instances); i++ {
717
time.Sleep(time.Duration(cfg.DirectMessage.Offset) * time.Millisecond)
718
go func(i int) {
719
defer wg.Done()
720
snowflake, err := instances[i].OpenChannel(victim)
721
if err != nil {
722
utilities.LogErr("Error while opening channel %s", err)
723
}
724
respCode, body, err := instances[i].SendMessage(snowflake, victim)
725
if err != nil {
726
utilities.LogErr("Error while sending message%s", err)
727
}
728
if respCode == 200 {
729
utilities.LogSuccess("Token %v DM'd %v", instances[i].Token, victim)
730
} else {
731
utilities.LogFailed("Token %v failed to DM %v [%v]", instances[i].Token, victim, string(body))
732
}
733
}(i)
734
}
735
wg.Wait()
736
}
737
if choice == 1 {
738
for i := 0; i < len(instances); i++ {
739
time.Sleep(time.Duration(cfg.DirectMessage.Offset) * time.Millisecond)
740
go func(i int) {
741
defer wg.Done()
742
743
var c int
744
for {
745
snowflake, err := instances[i].OpenChannel(victim)
746
if err != nil {
747
utilities.LogErr("Error while opening channel %s", err)
748
}
749
respCode, _, err := instances[i].SendMessage(snowflake, victim)
750
if err != nil {
751
utilities.LogErr("Error while sending message %s", err)
752
}
753
if respCode == 200 {
754
utilities.LogSuccess("Token %v DM'd %v [%v]", instances[i].CensorToken(), victim, c)
755
} else {
756
utilities.LogFailed("Token %v failed to DM %v", instances[i].CensorToken(), victim)
757
}
758
c++
759
}
760
}(i)
761
wg.Wait()
762
}
763
}
764
utilities.LogSuccess("All threads finished")
765
}
766
767