1
- using System . Collections . Immutable ;
2
- using System . Diagnostics ;
3
- using System . Text ;
4
-
5
- using Newtonsoft . Json ;
6
-
7
- using Nullinside . Api . Common . Twitch ;
8
- using Nullinside . Api . Model ;
9
- using Nullinside . Api . Model . Ddl ;
10
- using Nullinside . Api . TwitchBot . Model ;
11
-
12
- using TwitchLib . Api . Helix . Models . Chat . GetChatters ;
13
-
14
- using TwitchUserConfig = Nullinside . Api . Model . Ddl . TwitchUserConfig ;
15
-
16
- namespace Nullinside . Api . TwitchBot . Bots ;
17
-
18
- /// <summary>
19
- /// Searches for and bans known bots when they enter the chat.
20
- /// </summary>
21
- public class BanKnownBots : ABotRule {
22
- /// <summary>
23
- /// Handles refreshing the <see cref="KnownBotListUsername" /> collection.
24
- /// </summary>
25
- private static Task _ = Task . Run ( async ( ) => {
26
- while ( true ) {
27
- Task < ImmutableHashSet < string > ? > twitchInsights = GetTwitchInsightsBots ( ) ;
28
- Task < ImmutableHashSet < string > ? > commanderRoot = GetCommanderRootBots ( ) ;
29
- await Task . WhenAll ( twitchInsights , commanderRoot ) ;
30
- if ( null != twitchInsights . Result ) {
31
- KnownBotListUsername = twitchInsights . Result ;
32
- }
33
-
34
- if ( null != commanderRoot . Result ) {
35
- KnownBotListUserId = commanderRoot . Result ;
36
- }
37
-
38
- // The list is enormous, force garbage collection.
39
- GC . Collect ( ) ;
40
- GC . WaitForPendingFinalizers ( ) ;
41
- await Task . Delay ( TimeSpan . FromMinutes ( 10 ) ) ;
42
- }
43
- } ) ;
44
-
45
- /// <summary>
46
- /// The cache of known bots.
47
- /// </summary>
48
- public static ImmutableHashSet < string > ? KnownBotListUsername { get ; set ; }
49
-
50
- /// <summary>
51
- /// The cache of known bots.
52
- /// </summary>
53
- public static ImmutableHashSet < string > ? KnownBotListUserId { get ; set ; }
54
-
55
- /// <summary>
56
- /// Determine if the rule is enabled in the configuration.
57
- /// </summary>
58
- /// <param name="config">The user's configuration.</param>
59
- /// <returns>True if it should run, false otherwise.</returns>
60
- public override bool ShouldRun ( TwitchUserConfig config ) {
61
- return config is { Enabled : true , BanKnownBots : true } ;
62
- }
63
-
64
- /// <summary>
65
- /// Searches for and bans known bots when they enter the chat.
66
- /// </summary>
67
- /// <param name="user">The user.</param>
68
- /// <param name="config">The user's configuration.</param>
69
- /// <param name="botProxy">The twitch api authenticated as the bot user.</param>
70
- /// <param name="db">The database.</param>
71
- /// <param name="stoppingToken">The cancellation token.</param>
72
- public override async Task Handle ( User user , TwitchUserConfig config , ITwitchApiProxy botProxy ,
73
- INullinsideContext db , CancellationToken stoppingToken = new ( ) ) {
74
- if ( null == user . TwitchId ) {
75
- return ;
76
- }
77
-
78
- // TODO: SKIP MODS AND VIPS
79
-
80
- // Get the list of people in the chat.
81
- List < Chatter > ? chatters =
82
- ( await botProxy . GetChannelUsers ( user . TwitchId , Constants . BotId , stoppingToken ) ) ? . ToList ( ) ;
83
- if ( null == chatters || chatters . Count == 0 ) {
84
- return ;
85
- }
86
-
87
- // Perform the comparison in the lock to prevent multithreading issues.
88
- // The collection is extremely large so we do not want to make a copy of it.
89
- var botsInChatInsights = new List < Chatter > ( ) ;
90
- var botsInChatCommanderRoot = new List < Chatter > ( ) ;
91
- ImmutableHashSet < string > ? knownBotUsernames = KnownBotListUsername ;
92
- ImmutableHashSet < string > ? knownBotUserIds = KnownBotListUserId ;
93
-
94
- if ( null != knownBotUsernames ) {
95
- botsInChatInsights . AddRange ( chatters . Where ( k =>
96
- knownBotUsernames . Contains ( k . UserLogin . ToLowerInvariant ( ) ) ) ) ;
97
- }
98
-
99
- if ( null != knownBotUserIds ) {
100
- botsInChatCommanderRoot . AddRange ( chatters . Where ( k =>
101
- knownBotUserIds . Contains ( k . UserId . ToLowerInvariant ( ) ) ) ) ;
102
- }
103
-
104
- // Remove the whitelisted bots
105
- botsInChatInsights = botsInChatInsights
106
- . Where ( b => ! Constants . WhitelistedBots . Contains ( b . UserLogin . ToLowerInvariant ( ) ) ) . ToList ( ) ;
107
- botsInChatCommanderRoot = botsInChatCommanderRoot
108
- . Where ( b => ! Constants . WhitelistedBots . Contains ( b . UserLogin . ToLowerInvariant ( ) ) ) . ToList ( ) ;
109
-
110
- // Ban them.
111
- if ( botsInChatInsights . Count != 0 ) {
112
- await BanOnce ( botProxy , db , user . TwitchId , botsInChatInsights . Select ( b => ( Id : b . UserId , Username : b . UserLogin ) ) ,
113
- "[Bot] Username on Known Bot List" , stoppingToken ) ;
114
- }
115
-
116
- if ( botsInChatCommanderRoot . Count != 0 ) {
117
- await BanOnce ( botProxy , db , user . TwitchId ,
118
- botsInChatCommanderRoot . Select ( b => ( Id : b . UserId , Username : b . UserLogin ) ) ,
119
- "[Bot] Username on Known Bot List" , stoppingToken ) ;
120
- }
121
- }
122
-
123
- /// <summary>
124
- /// Gets the list of all known bots.
125
- /// </summary>
126
- /// <returns>The list of bots if successful, null otherwise.</returns>
127
- private static async Task < ImmutableHashSet < string > ? > GetTwitchInsightsBots ( ) {
128
- var stopwatch = new Stopwatch ( ) ;
129
- stopwatch . Start ( ) ;
130
- // Reach out to the api and find out what bots are online.
131
- using var http = new HttpClient ( ) ;
132
- HttpResponseMessage response = await http . GetAsync ( "https://api.twitchinsights.net/v1/bots/all" ) ;
133
- if ( ! response . IsSuccessStatusCode ) {
134
- return null ;
135
- }
136
-
137
- byte [ ] ? content = await response . Content . ReadAsByteArrayAsync ( ) ;
138
- string ? jsonString = Encoding . UTF8 . GetString ( content ) ;
139
- var liveBotsResponse = JsonConvert . DeserializeObject < TwitchInsightsLiveBotsResponse > ( jsonString ) ;
140
- if ( null == liveBotsResponse ) {
141
- return null ;
142
- }
143
-
144
- ImmutableHashSet < string > allBots = liveBotsResponse . bots
145
- . Where ( s => ! string . IsNullOrWhiteSpace ( s [ 0 ] . ToString ( ) ) )
146
- #pragma warning disable 8602
147
- . Select ( s => s [ 0 ] . ToString ( ) . ToLowerInvariant ( ) )
148
- #pragma warning restore 8602
149
- . ToImmutableHashSet ( ) ;
150
-
151
- foreach ( List < object > ? list in liveBotsResponse . bots ) {
152
- list . Clear ( ) ;
153
- }
154
-
155
- liveBotsResponse . bots . Clear ( ) ;
156
- liveBotsResponse . bots = null ;
157
- liveBotsResponse = null ;
158
- content = null ;
159
- jsonString = null ;
160
- return allBots ;
161
- }
162
-
163
- /// <summary>
164
- /// Gets the list of all known bots.
165
- /// </summary>
166
- /// <returns>The list of bots if successful, null otherwise.</returns>
167
- private static async Task < ImmutableHashSet < string > ? > GetCommanderRootBots ( ) {
168
- var stopwatch = new Stopwatch ( ) ;
169
- stopwatch . Start ( ) ;
170
- // Reach out to the api and find out what bots are online.
171
- using var http = new HttpClient ( ) ;
172
- using HttpResponseMessage response =
173
- await http . GetAsync ( "https://twitch-tools.rootonline.de/blocklist_manager.php?preset=known_bot_users" ) ;
174
- if ( ! response . IsSuccessStatusCode ) {
175
- return null ;
176
- }
177
-
178
- byte [ ] ? content = await response . Content . ReadAsByteArrayAsync ( ) ;
179
- string ? jsonString = Encoding . UTF8 . GetString ( content ) ;
180
- var liveBotsResponse = JsonConvert . DeserializeObject < List < string > > ( jsonString ) ;
181
- if ( null == liveBotsResponse ) {
182
- return null ;
183
- }
184
-
185
- ImmutableHashSet < string > allBots = liveBotsResponse
186
- #pragma warning disable 8602
187
- . Select ( s => s . ToLowerInvariant ( ) )
188
- #pragma warning restore 8602
189
- . ToImmutableHashSet ( ) ;
190
-
191
- liveBotsResponse . Clear ( ) ;
192
- liveBotsResponse = null ;
193
- liveBotsResponse = null ;
194
- content = null ;
195
- jsonString = null ;
196
- return allBots ;
197
- }
198
- }
1
+ // using System.Collections.Immutable;
2
+ // using System.Diagnostics;
3
+ // using System.Text;
4
+ //
5
+ // using Newtonsoft.Json;
6
+ //
7
+ // using Nullinside.Api.Common.Twitch;
8
+ // using Nullinside.Api.Model;
9
+ // using Nullinside.Api.Model.Ddl;
10
+ // using Nullinside.Api.TwitchBot.Model;
11
+ //
12
+ // using TwitchLib.Api.Helix.Models.Chat.GetChatters;
13
+ //
14
+ // using TwitchUserConfig = Nullinside.Api.Model.Ddl.TwitchUserConfig;
15
+ //
16
+ // namespace Nullinside.Api.TwitchBot.Bots;
17
+ //
18
+ // // / <summary>
19
+ // // / Searches for and bans known bots when they enter the chat.
20
+ // // / </summary>
21
+ // public class BanKnownBots : ABotRule {
22
+ // /// <summary>
23
+ // /// Handles refreshing the <see cref="KnownBotListUsername" /> collection.
24
+ // /// </summary>
25
+ // private static Task _ = Task.Run(async () => {
26
+ // while (true) {
27
+ // Task<ImmutableHashSet<string>?> twitchInsights = GetTwitchInsightsBots();
28
+ // Task<ImmutableHashSet<string>?> commanderRoot = GetCommanderRootBots();
29
+ // await Task.WhenAll(twitchInsights, commanderRoot);
30
+ // if (null != twitchInsights.Result) {
31
+ // KnownBotListUsername = twitchInsights.Result;
32
+ // }
33
+ //
34
+ // if (null != commanderRoot.Result) {
35
+ // KnownBotListUserId = commanderRoot.Result;
36
+ // }
37
+ //
38
+ // // The list is enormous, force garbage collection.
39
+ // GC.Collect();
40
+ // GC.WaitForPendingFinalizers();
41
+ // await Task.Delay(TimeSpan.FromMinutes(10));
42
+ // }
43
+ // });
44
+ //
45
+ // /// <summary>
46
+ // /// The cache of known bots.
47
+ // /// </summary>
48
+ // public static ImmutableHashSet<string>? KnownBotListUsername { get; set; }
49
+ //
50
+ // /// <summary>
51
+ // /// The cache of known bots.
52
+ // /// </summary>
53
+ // public static ImmutableHashSet<string>? KnownBotListUserId { get; set; }
54
+ //
55
+ // /// <summary>
56
+ // /// Determine if the rule is enabled in the configuration.
57
+ // /// </summary>
58
+ // /// <param name="config">The user's configuration.</param>
59
+ // /// <returns>True if it should run, false otherwise.</returns>
60
+ // public override bool ShouldRun(TwitchUserConfig config) {
61
+ // return config is { Enabled: true, BanKnownBots: true };
62
+ // }
63
+ //
64
+ // /// <summary>
65
+ // /// Searches for and bans known bots when they enter the chat.
66
+ // /// </summary>
67
+ // /// <param name="user">The user.</param>
68
+ // /// <param name="config">The user's configuration.</param>
69
+ // /// <param name="botProxy">The twitch api authenticated as the bot user.</param>
70
+ // /// <param name="db">The database.</param>
71
+ // /// <param name="stoppingToken">The cancellation token.</param>
72
+ // public override async Task Handle(User user, TwitchUserConfig config, ITwitchApiProxy botProxy,
73
+ // INullinsideContext db, CancellationToken stoppingToken = new()) {
74
+ // if (null == user.TwitchId) {
75
+ // return;
76
+ // }
77
+ //
78
+ // // TODO: SKIP MODS AND VIPS
79
+ //
80
+ // // Get the list of people in the chat.
81
+ // List<Chatter>? chatters =
82
+ // (await botProxy.GetChannelUsers(user.TwitchId, Constants.BotId, stoppingToken))?.ToList();
83
+ // if (null == chatters || chatters.Count == 0) {
84
+ // return;
85
+ // }
86
+ //
87
+ // // Perform the comparison in the lock to prevent multithreading issues.
88
+ // // The collection is extremely large so we do not want to make a copy of it.
89
+ // var botsInChatInsights = new List<Chatter>();
90
+ // var botsInChatCommanderRoot = new List<Chatter>();
91
+ // ImmutableHashSet<string>? knownBotUsernames = KnownBotListUsername;
92
+ // ImmutableHashSet<string>? knownBotUserIds = KnownBotListUserId;
93
+ //
94
+ // if (null != knownBotUsernames) {
95
+ // botsInChatInsights.AddRange(chatters.Where(k =>
96
+ // knownBotUsernames.Contains(k.UserLogin.ToLowerInvariant())));
97
+ // }
98
+ //
99
+ // if (null != knownBotUserIds) {
100
+ // botsInChatCommanderRoot.AddRange(chatters.Where(k =>
101
+ // knownBotUserIds.Contains(k.UserId.ToLowerInvariant())));
102
+ // }
103
+ //
104
+ // // Remove the whitelisted bots
105
+ // botsInChatInsights = botsInChatInsights
106
+ // .Where(b => !Constants.WhitelistedBots.Contains(b.UserLogin.ToLowerInvariant())).ToList();
107
+ // botsInChatCommanderRoot = botsInChatCommanderRoot
108
+ // .Where(b => !Constants.WhitelistedBots.Contains(b.UserLogin.ToLowerInvariant())).ToList();
109
+ //
110
+ // // Ban them.
111
+ // if (botsInChatInsights.Count != 0) {
112
+ // await BanOnce(botProxy, db, user.TwitchId, botsInChatInsights.Select(b => (Id: b.UserId, Username: b.UserLogin)),
113
+ // "[Bot] Username on Known Bot List", stoppingToken);
114
+ // }
115
+ //
116
+ // if (botsInChatCommanderRoot.Count != 0) {
117
+ // await BanOnce(botProxy, db, user.TwitchId,
118
+ // botsInChatCommanderRoot.Select(b => (Id: b.UserId, Username: b.UserLogin)),
119
+ // "[Bot] Username on Known Bot List", stoppingToken);
120
+ // }
121
+ // }
122
+ //
123
+ // /// <summary>
124
+ // /// Gets the list of all known bots.
125
+ // /// </summary>
126
+ // /// <returns>The list of bots if successful, null otherwise.</returns>
127
+ // private static async Task<ImmutableHashSet<string>?> GetTwitchInsightsBots() {
128
+ // var stopwatch = new Stopwatch();
129
+ // stopwatch.Start();
130
+ // // Reach out to the api and find out what bots are online.
131
+ // using var http = new HttpClient();
132
+ // HttpResponseMessage response = await http.GetAsync("https://api.twitchinsights.net/v1/bots/all");
133
+ // if (!response.IsSuccessStatusCode) {
134
+ // return null;
135
+ // }
136
+ //
137
+ // byte[]? content = await response.Content.ReadAsByteArrayAsync();
138
+ // string? jsonString = Encoding.UTF8.GetString(content);
139
+ // var liveBotsResponse = JsonConvert.DeserializeObject<TwitchInsightsLiveBotsResponse>(jsonString);
140
+ // if (null == liveBotsResponse) {
141
+ // return null;
142
+ // }
143
+ //
144
+ // ImmutableHashSet<string> allBots = liveBotsResponse.bots
145
+ // .Where(s => !string.IsNullOrWhiteSpace(s[0].ToString()))
146
+ // #pragma warning disable 8602
147
+ // .Select(s => s[0].ToString().ToLowerInvariant())
148
+ // #pragma warning restore 8602
149
+ // .ToImmutableHashSet();
150
+ //
151
+ // foreach (List<object>? list in liveBotsResponse.bots) {
152
+ // list.Clear();
153
+ // }
154
+ //
155
+ // liveBotsResponse.bots.Clear();
156
+ // liveBotsResponse.bots = null;
157
+ // liveBotsResponse = null;
158
+ // content = null;
159
+ // jsonString = null;
160
+ // return allBots;
161
+ // }
162
+ //
163
+ // /// <summary>
164
+ // /// Gets the list of all known bots.
165
+ // /// </summary>
166
+ // /// <returns>The list of bots if successful, null otherwise.</returns>
167
+ // private static async Task<ImmutableHashSet<string>?> GetCommanderRootBots() {
168
+ // var stopwatch = new Stopwatch();
169
+ // stopwatch.Start();
170
+ // // Reach out to the api and find out what bots are online.
171
+ // using var http = new HttpClient();
172
+ // using HttpResponseMessage response =
173
+ // await http.GetAsync("https://twitch-tools.rootonline.de/blocklist_manager.php?preset=known_bot_users");
174
+ // if (!response.IsSuccessStatusCode) {
175
+ // return null;
176
+ // }
177
+ //
178
+ // byte[]? content = await response.Content.ReadAsByteArrayAsync();
179
+ // string? jsonString = Encoding.UTF8.GetString(content);
180
+ // var liveBotsResponse = JsonConvert.DeserializeObject<List<string>>(jsonString);
181
+ // if (null == liveBotsResponse) {
182
+ // return null;
183
+ // }
184
+ //
185
+ // ImmutableHashSet<string> allBots = liveBotsResponse
186
+ // #pragma warning disable 8602
187
+ // .Select(s => s.ToLowerInvariant())
188
+ // #pragma warning restore 8602
189
+ // .ToImmutableHashSet();
190
+ //
191
+ // liveBotsResponse.Clear();
192
+ // liveBotsResponse = null;
193
+ // liveBotsResponse = null;
194
+ // content = null;
195
+ // jsonString = null;
196
+ // return allBots;
197
+ // }
198
+ // }
0 commit comments