diff --git a/src/Nullinside.Api.TwitchBot.Tests/ChatRules/DiscordTests.cs b/src/Nullinside.Api.TwitchBot.Tests/ChatRules/DiscordTests.cs new file mode 100644 index 0000000..5174193 --- /dev/null +++ b/src/Nullinside.Api.TwitchBot.Tests/ChatRules/DiscordTests.cs @@ -0,0 +1,16 @@ +namespace Nullinside.Api.TwitchBot.Tests.ChatRules; + +public class DiscordTests +{ + [Test] + [TestCase("Hello mate you stream pretty cool that's why I follow I would love to be a fan of yours if you don't mind kindly add me on Discord: 👉👉lacaster5")] + [TestCase("Hello, I just recently found your channel and can already tell that your content is great, and I would love to stick with you long term. If you're open to it, I'd be willing to connect with you on Discord. My username is teecash1000")] + [TestCase("Hey there 👋 You stream pretty cool that’s why I followed you. I will like to make you a friend and be a fan, if you don’t mind Kindly chat me on Discord, my Discord username is tuckzay")] + [TestCase("Hi! Just wanted to say that I absolutely love your gameplay and content.l'd love to connect better with you on Discord if that's possible. Looking forward to more awesome streams from you! My username is 👉👉👉 edisonpires")] + [TestCase("What's up Friend, great stream! I'm having a blast watching you stream. Let's move the conversation to Discord, where we can discuss more about streaming in more detail and get to know each other better. See you there! My discord username is 👉john_6029")] + public void TestKnownStrings(string badString) + { + // Need to put interfaces in front of the classes before we can do this. + Assert.Pass(); + } +} \ No newline at end of file diff --git a/src/Nullinside.Api.TwitchBot/ChatRules/BestCheapViewers.cs b/src/Nullinside.Api.TwitchBot/ChatRules/BestCheapViewers.cs index 2af2fa6..5c8b995 100644 --- a/src/Nullinside.Api.TwitchBot/ChatRules/BestCheapViewers.cs +++ b/src/Nullinside.Api.TwitchBot/ChatRules/BestCheapViewers.cs @@ -23,6 +23,10 @@ public override bool ShouldRun(TwitchUserConfig config) { /// 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(); diff --git a/src/Nullinside.Api.TwitchBot/ChatRules/Discord.cs b/src/Nullinside.Api.TwitchBot/ChatRules/Discord.cs index 33727a6..247c6e8 100644 --- a/src/Nullinside.Api.TwitchBot/ChatRules/Discord.cs +++ b/src/Nullinside.Api.TwitchBot/ChatRules/Discord.cs @@ -10,7 +10,11 @@ namespace Nullinside.Api.TwitchBot.ChatRules; /// Handles the add me on discord bots. /// public class Discord : AChatRule { - private const string _spam = "I would like to be on of your fans if you don't mind kindly add me up on discord"; + private readonly string[] KNOWN_PHRASES = [ + "add me on discord", + "my username is", + "my discord username is" + ]; /// public override bool ShouldRun(TwitchUserConfig config) { @@ -20,11 +24,24 @@ public override bool ShouldRun(TwitchUserConfig config) { /// public override async Task Handle(string channelId, TwitchApiProxy botProxy, ChatMessage message, NullinsideContext db, CancellationToken stoppingToken = new()) { - if (message.IsFirstMessage && - message.Message.Contains(_spam, StringComparison.InvariantCultureIgnoreCase)) { - await BanAndLog(channelId, botProxy, new[] { (message.UserId, message.Username) }, - "[Bot] Spam (Discord Freaks)", db, stoppingToken); - return false; + 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(); + + if (!normalized.Contains("discord", StringComparison.InvariantCultureIgnoreCase)) { + return true; + } + + foreach (var phrase in KNOWN_PHRASES) { + if (normalized.Contains(phrase, StringComparison.InvariantCultureIgnoreCase)) { + await BanAndLog(channelId, botProxy, new[] { (message.UserId, message.Username) }, + "[Bot] Spam (Discord Scammers)", db, stoppingToken); + return false; + } } return true; diff --git a/src/Nullinside.Api.TwitchBot/ChatRules/Dogehype.cs b/src/Nullinside.Api.TwitchBot/ChatRules/Dogehype.cs index c0ca798..f9a65ce 100644 --- a/src/Nullinside.Api.TwitchBot/ChatRules/Dogehype.cs +++ b/src/Nullinside.Api.TwitchBot/ChatRules/Dogehype.cs @@ -23,7 +23,7 @@ public override async Task Handle(string channelId, TwitchApiProxy botProx .ToLowerInvariant(); // Message will start with any of these variations. - if (normalized.Contains("dogehype")) { + if (message.IsFirstMessage && normalized.Contains("dogehype")) { await BanAndLog(channelId, botProxy, new[] { (message.UserId, message.Username) }, "[Bot] Spam (Dogehype)", db, stoppingToken); return false; diff --git a/src/Nullinside.Api.TwitchBot/ChatRules/StreamRise.cs b/src/Nullinside.Api.TwitchBot/ChatRules/StreamRise.cs index 6fb64d5..ef84d1e 100644 --- a/src/Nullinside.Api.TwitchBot/ChatRules/StreamRise.cs +++ b/src/Nullinside.Api.TwitchBot/ChatRules/StreamRise.cs @@ -24,7 +24,7 @@ public override bool ShouldRun(TwitchUserConfig config) { /// public override async Task Handle(string channelId, TwitchApiProxy botProxy, ChatMessage message, NullinsideContext db, CancellationToken stoppingToken = new()) { - if (_spam.Equals(message.Message, StringComparison.InvariantCultureIgnoreCase)) { + if (message.IsFirstMessage && _spam.Equals(message.Message, StringComparison.InvariantCultureIgnoreCase)) { await BanAndLog(channelId, botProxy, new[] { (message.UserId, message.Username) }, "[Bot] Spam (StreamRise)", db, stoppingToken); return false; diff --git a/src/Nullinside.Api.TwitchBot/ChatRules/StreamViewers.cs b/src/Nullinside.Api.TwitchBot/ChatRules/StreamViewers.cs index fb47def..d208175 100644 --- a/src/Nullinside.Api.TwitchBot/ChatRules/StreamViewers.cs +++ b/src/Nullinside.Api.TwitchBot/ChatRules/StreamViewers.cs @@ -23,6 +23,10 @@ public override bool ShouldRun(TwitchUserConfig config) { /// public override async Task Handle(string channelId, TwitchApiProxy botProxy, ChatMessage message, NullinsideContext db, CancellationToken stoppingToken = new()) { + if (!message.IsFirstMessage) { + return true; + } + List parts = message.Message .Split(" ") .Where(s => !string.IsNullOrWhiteSpace(s)) diff --git a/src/Nullinside.Api.TwitchBot/Services/MainService.cs b/src/Nullinside.Api.TwitchBot/Services/MainService.cs index 61b1e30..5ed4c89 100644 --- a/src/Nullinside.Api.TwitchBot/Services/MainService.cs +++ b/src/Nullinside.Api.TwitchBot/Services/MainService.cs @@ -117,7 +117,7 @@ protected override Task ExecuteAsync(CancellationToken stoppingToken) { } catch (Exception ex) { _log.LogError(ex, "Main Failed"); - await Task.Delay(TimeSpan.FromSeconds(10)); + await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken); } } }, stoppingToken);