diff --git a/src/Nullinside.Api.TwitchBot/ChatRules/BestCheapViewers.cs b/src/Nullinside.Api.TwitchBot/ChatRules/BestCheapViewers.cs
index 5c8b995..7626a50 100644
--- a/src/Nullinside.Api.TwitchBot/ChatRules/BestCheapViewers.cs
+++ b/src/Nullinside.Api.TwitchBot/ChatRules/BestCheapViewers.cs
@@ -13,7 +13,10 @@ public class BestCheapViewers : AChatRule {
///
/// The strings that we expect to receive if this is a bot.
///
- public readonly string[] EXPECTED = ["best viewers on", "cheap viewers on"];
+ public readonly string[] EXPECTED = [
+ "best viewers on",
+ "cheap viewers on"
+ ];
///
public override bool ShouldRun(TwitchUserConfig config) {
diff --git a/src/Nullinside.Api.TwitchBot/ChatRules/IfYouWantViewers.cs b/src/Nullinside.Api.TwitchBot/ChatRules/IfYouWantViewers.cs
new file mode 100644
index 0000000..1e01a71
--- /dev/null
+++ b/src/Nullinside.Api.TwitchBot/ChatRules/IfYouWantViewers.cs
@@ -0,0 +1,46 @@
+using Nullinside.Api.Common.Twitch;
+using Nullinside.Api.Model;
+using Nullinside.Api.Model.Ddl;
+
+using TwitchLib.Client.Models;
+
+namespace Nullinside.Api.TwitchBot.ChatRules;
+
+///
+/// "if you want viewers, go to [link]" scam.
+///
+public class IfYouWantViewers : AChatRule {
+ ///
+ /// The strings that we expect to receive if this is a bot.
+ ///
+ public readonly string[] EXPECTED = [
+ "if you want more viewers for your stream, go to"
+ ];
+
+ ///
+ public override bool ShouldRun(TwitchUserConfig config) {
+ return config is { Enabled: true, BanKnownBots: true };
+ }
+
+ ///
+ public override async Task Handle(string channelId, TwitchApiProxy botProxy, ChatMessage message,
+ NullinsideContext db, CancellationToken stoppingToken = new()) {
+ if (!message.IsFirstMessage) {
+ return true;
+ }
+
+ // The number of spaces per message may chance, so normalize that and lowercase it for comparison.
+ string normalized = string.Join(' ', message.Message.Split(" ").Where(s => !string.IsNullOrWhiteSpace(s)))
+ .ToLowerInvariant();
+
+ foreach (var expected in EXPECTED) {
+ if (normalized.Contains(expected, StringComparison.InvariantCultureIgnoreCase)) {
+ await BanAndLog(channelId, botProxy, new[] { (message.UserId, message.Username) },
+ "[Bot] Spam (If You Want Viewers)", db, stoppingToken);
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
\ No newline at end of file