generated from Happypig375/Nitro-Scam-Watcher-Selfbot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBot.fsx
141 lines (138 loc) · 8.93 KB
/
Bot.fsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// Initialize 1
let env = System.Environment.GetEnvironmentVariable
let token = env "TOKEN" // https://discordhelp.net/discord-token
let commandGuildId = uint64 (env "COMMAND_GUILD_ID")
let commandChannelId = uint64 (env "COMMAND_CHANNEL_ID") // A channel in commandGuildId
let logChannelId = uint64 (env "LOG_CHANNEL_ID") // A channel in commandGuildId
let targetFreshmenGuildId = uint64 (env "TARGET_FRESHMEN_GUILD_ID")
let logWebhook = env "LOG_WEBHOOK"
#r "nuget: System.Threading.RateLimiting, 7.0.0-preview.4.22229.4"
#r "nuget: Leaf.xNet, 5.2.10"
#r "nuget: Newtonsoft.Json, 13.0.1"
#r "nuget: System.Drawing.Common, 7.0.0-preview.2.22152.2"
#r "nuget: websocketsharp.core, 1.0.0"
#r "Anarchy.dll" // Custom built from https://github.com/not-ilinked/Anarchy/pull/3302
open Discord
open Discord.Gateway
open System.Threading.RateLimiting
(task {
let completion = System.Threading.Tasks.TaskCompletionSource()
let mutable finishedInit = false
// Initialize 2
let loggedInMsg = "Logged in"
let http = new System.Net.Http.HttpClient()
let send obj = // https://birdie0.github.io/discord-webhooks-guide
task {
let json = System.Net.Http.Json.JsonContent.Create obj
let! _ = http.PostAsync(logWebhook, json)
()
}
let log, error =
let log (color: int) (message: string) =
printfn $"{message}"
send {|
embeds = [
{|
color = color
description = message
|}
]
|}
log 1127128, log 16711680
try
// Initialize 3
let client = new Gateway.DiscordSocketClient()
client.Login token
let emojisRateLimiter = new FixedWindowRateLimiter(FixedWindowRateLimiterOptions(0, QueueProcessingOrder.NewestFirst, 0, System.TimeSpan.FromSeconds 15.))
let reactRateLimiter = new FixedWindowRateLimiter(FixedWindowRateLimiterOptions(0, QueueProcessingOrder.NewestFirst, 30, System.TimeSpan.FromSeconds 3.))
let messageRateLimiter = new FixedWindowRateLimiter(FixedWindowRateLimiterOptions(0, QueueProcessingOrder.NewestFirst, 0, System.TimeSpan.FromSeconds 5.))
let reactCheckRateLimiter = new FixedWindowRateLimiter(FixedWindowRateLimiterOptions(0, QueueProcessingOrder.NewestFirst, 50, System.TimeSpan.FromSeconds 1.))
let mutable emojis = Array.empty :> System.Collections.Generic.IReadOnlyList<DiscordEmoji>
let mutable messageReceivedHandler = fun _ _ -> ()
let mutable reactionAddedHandler = fun _ _ -> ()
client.add_OnMessageReceived (fun client args -> messageReceivedHandler client args)
client.add_OnMessageReactionAdded (fun client args -> reactionAddedHandler client args)
// Main
messageReceivedHandler <- fun client args ->
task {
try
if args.Message.Guild <> null then
if args.Message.Guild.Id = targetFreshmenGuildId then
if args.Message.Content |> isNull |> not then
let content = args.Message.Content.ToLower()
let contains (s: string) = content.Contains s
let split = content.Split()
let containsOnItsOwn (s: string) = Array.contains s split
let tryReact name fallbackImageUrl = task {
use! lease = emojisRateLimiter.WaitAsync 1
if lease.IsAcquired then
let! newEmojis = client.GetGuildEmojisAsync targetFreshmenGuildId
emojis <- newEmojis
match emojis |> Seq.tryFind (fun e -> e.Name = name) with
| Some emoji ->
use! lease = reactRateLimiter.WaitAsync 1
if lease.IsAcquired then
do! args.Message.AddReactionAsync(name, emoji.Id)
| None ->
use! lease = messageRateLimiter.WaitAsync 1
if lease.IsAcquired then
let! _ = client.SendMessageAsync(args.Message.Channel.Id, MessageProperties(Content = fallbackImageUrl))
()
}
if contains "mark" || contains "cag" || containsOnItsOwn "4.3" then
do! tryReact "mark" "https://cdn.discordapp.com/emojis/978324790337228800.webp?size=20&quality=lossless"
if contains "kram" then
do! tryReact "kram" "https://cdn.discordapp.com/emojis/978690377710207050.webp?size=20&quality=lossless"
if containsOnItsOwn ":>" then
do! tryReact "wallace" "https://cdn.discordapp.com/emojis/960527234278510632.webp?size=20&quality=lossless"
let oCount = Seq.filter ((=) 'o') content |> Seq.length
if containsOnItsOwn ":o" || float oCount / float content.Length > 0.8 then
do! tryReact "wallaceO" "https://cdn.discordapp.com/emojis/971743699753140244.webp?size=20&quality=lossless"
if containsOnItsOwn ":<" then
do! tryReact "wallacent" "https://cdn.discordapp.com/emojis/961550530965045298.webp?size=20&quality=lossless"
if containsOnItsOwn "mok" || containsOnItsOwn "perry" then
do! tryReact "oxford" "https://cdn.discordapp.com/emojis/898106541117411378.webp?size=20&quality=lossless"
if containsOnItsOwn "100" then
use! lease = reactRateLimiter.WaitAsync 1
if lease.IsAcquired then
do! args.Message.AddReactionAsync "🤖"
elif args.Message.Guild.Id = commandGuildId then
let stop() = task {
do! args.Message.AddReactionAsync "✅"
client.Logout()
http.Dispose()
client.Dispose()
emojisRateLimiter.Dispose()
reactRateLimiter.Dispose()
messageRateLimiter.Dispose()
exit 0
}
if args.Message.Channel.Id = logChannelId then
if args.Message.Embed <> null && args.Message.Embed.Description = loggedInMsg then
if finishedInit then do! stop() else finishedInit <- true
elif args.Message.Channel.Id = commandChannelId then
match args.Message.Content with
| "stop" -> do! stop()
| _ -> do! args.Message.AddReactionAsync "❓"
with e -> do! error (string e)
} |> ignore
reactionAddedHandler <- fun client args ->
task {
try
if args.Reaction.Guild <> null && args.Reaction.Guild.Id = targetFreshmenGuildId && args.Reaction.UserId <> client.User.Id then // HKUST Freshmen server
use! lease = reactCheckRateLimiter.WaitAsync 1
if lease.IsAcquired then
let! reacts = client.GetMessageReactionsAsync(args.Reaction.Channel.Id, args.Reaction.MessageId, ReactionQuery(ReactionId = args.Reaction.Emoji.Id, ReactionName = args.Reaction.Emoji.Name))
if reacts |> Seq.exists (fun reacter -> reacter.Id = client.User.Id) |> not then
use! lease = reactRateLimiter.WaitAsync 1
if lease.IsAcquired then
do! client.AddMessageReactionAsync(args.Reaction.Channel.Id, args.Reaction.MessageId, args.Reaction.Emoji.Name, args.Reaction.Emoji.Id)
with e -> do! error (string e)
} |> ignore
// Only for GitHub Actions: Wait indefinitely until stop
do! log loggedInMsg
do! System.Threading.Tasks.Task.Delay (System.TimeSpan.FromSeconds 20.) // Ignore any logged in messages generated by this instance
if not finishedInit then finishedInit <- true
do! completion.Task
with e -> do! error (string e)
}).Wait()