diff --git a/Behavior/Behaver.cs b/Behavior/Behaver.cs index 067e9c1..77817de 100644 --- a/Behavior/Behaver.cs +++ b/Behavior/Behaver.cs @@ -10,17 +10,22 @@ using System.Collections.Generic; public class Behaver { - private static List behaviors { get; set; } = new List(); + private ChattingContext _db; + public List Selves { get; internal set; } = new List(); + public static List Behaviors { get; private set; } = new List(); internal Behaver() { + _db = new ChattingContext(); + var subtypes = AppDomain.CurrentDomain.GetAssemblies() .SelectMany(domainAssembly => domainAssembly.GetTypes()) - .Where(type => type.IsSubclassOf(typeof(Behavior)) && !type.IsAbstract) + .Where(type => type.IsSubclassOf(typeof(Behavior)) && !type.IsAbstract && + type.GetCustomAttributes(typeof(StaticPlzAttribute),false)?.Any() == true) .ToList(); foreach (var subtype in subtypes) { - behaviors.Add((Behavior)Activator.CreateInstance(subtype)); + Behaviors.Add((Behavior)Activator.CreateInstance(subtype)); } } static Behaver() { } @@ -34,7 +39,7 @@ public class Behaver public async Task ActOn(Message message) { - foreach (var behavior in behaviors) + foreach (var behavior in Behaviors) { if (behavior.ShouldAct(message)) { @@ -42,7 +47,7 @@ public class Behaver message.ActedOn = true; } } - if (message.ActedOn == false && message.MentionsMe && message.Content.Contains('?')) + if (message.ActedOn == false && message.MentionsMe && message.Content.Contains('?') && !Behaver.Instance.Selves.Any(acc => acc.Id == message.Author.Id)) { Console.WriteLine("providing bullshit nonanswer / admitting uselessness"); var responses = new List(){ @@ -54,7 +59,7 @@ public class Behaver } if (message.ActedOn) { - Shared.dbContext.SaveChanges(); + _db.SaveChanges(); } return message.ActedOn; } diff --git a/Behavior/Behavior.cs b/Behavior/Behavior.cs index 41b28c0..82949e0 100644 --- a/Behavior/Behavior.cs +++ b/Behavior/Behavior.cs @@ -8,13 +8,14 @@ using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Collections.Generic; -//expect a behavior to be created per mesage public abstract class Behavior { public abstract Task ActOn(Message message); public virtual bool ShouldAct(Message message) { + if(Behaver.Instance.Selves.Any(acc => acc.Id == message.Author.Id)) + return false; return Regex.IsMatch(message.Content, $"{Trigger}\\b", RegexOptions.IgnoreCase); } @@ -22,3 +23,6 @@ public abstract class Behavior public abstract string Trigger { get; } public virtual string Description => Name; } + + +public class StaticPlzAttribute : Attribute {} \ No newline at end of file diff --git a/Behavior/ChatGPTSnark.cs b/Behavior/ChatGPTSnark.cs index 46fb5f2..7df5292 100644 --- a/Behavior/ChatGPTSnark.cs +++ b/Behavior/ChatGPTSnark.cs @@ -8,6 +8,7 @@ using System.Threading; using System.Threading.Tasks; using vassago.Models; +[StaticPlz] public class ChatGPTSnark : Behavior { public override string Name => "ChatGPTSnark"; diff --git a/Behavior/DefinitionSnarkCogDiss.cs b/Behavior/DefinitionSnarkCogDiss.cs index 5338b66..318de64 100644 --- a/Behavior/DefinitionSnarkCogDiss.cs +++ b/Behavior/DefinitionSnarkCogDiss.cs @@ -8,6 +8,7 @@ using System.Threading; using System.Threading.Tasks; using vassago.Models; +[StaticPlz] public class DefinitionSnarkCogDiss : Behavior { public override string Name => "Definition Snarkiness: cognitivie dissonance"; diff --git a/Behavior/DefinitionSnarkGaslight.cs b/Behavior/DefinitionSnarkGaslight.cs index cbea87c..7ca9bed 100644 --- a/Behavior/DefinitionSnarkGaslight.cs +++ b/Behavior/DefinitionSnarkGaslight.cs @@ -8,6 +8,7 @@ using System.Threading; using System.Threading.Tasks; using vassago.Models; +[StaticPlz] public class DefinitionSnarkGaslight : Behavior { public override string Name => "Definition Snarkiness: gaslighting"; diff --git a/Behavior/Detiktokify.cs b/Behavior/Detiktokify.cs index c0b0450..199c38c 100644 --- a/Behavior/Detiktokify.cs +++ b/Behavior/Detiktokify.cs @@ -6,6 +6,8 @@ using System.IO; using System.Linq; using System.Threading.Tasks; using vassago.Models; + +[StaticPlz] public class Detiktokify : Behavior { public override string Name { get => "Detiktokify"; } diff --git a/Behavior/FiximageHeic.cs b/Behavior/FiximageHeic.cs index ad154ef..927683e 100644 --- a/Behavior/FiximageHeic.cs +++ b/Behavior/FiximageHeic.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using Newtonsoft.Json; using vassago.Models; +[StaticPlz] public class FiximageHeic : Behavior { public override string Name => "deheic"; @@ -20,6 +21,8 @@ public class FiximageHeic : Behavior private List heics = new List(); public override bool ShouldAct(Message message) { + if(Behaver.Instance.Selves.Any(acc => acc.Id == message.Author.Id)) + return false; if (message.Attachments?.Count() > 0) { foreach (var att in message.Attachments) diff --git a/Behavior/GeneralSnarkCloudNative.cs b/Behavior/GeneralSnarkCloudNative.cs index ce92552..b0d442b 100644 --- a/Behavior/GeneralSnarkCloudNative.cs +++ b/Behavior/GeneralSnarkCloudNative.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using Newtonsoft.Json; using vassago.Models; +[StaticPlz] public class GeneralSnarkCloudNative : Behavior { public override string Name => "general snarkiness: cloud native"; @@ -17,6 +18,8 @@ public class GeneralSnarkCloudNative : Behavior public override string Trigger => "certain tech buzzwords that no human uses in normal conversation"; public override bool ShouldAct(Message message) { + if(Behaver.Instance.Selves.Any(acc => acc.Id == message.Author.Id)) + return false; return Regex.IsMatch(message.Content, "\\bcloud( |-)?native\\b", RegexOptions.IgnoreCase) || Regex.IsMatch(message.Content, "\\benterprise( |-)?(level|solution)\\b", RegexOptions.IgnoreCase); } diff --git a/Behavior/GeneralSnarkPlaying.cs b/Behavior/GeneralSnarkPlaying.cs index ec358ee..62d13c0 100644 --- a/Behavior/GeneralSnarkPlaying.cs +++ b/Behavior/GeneralSnarkPlaying.cs @@ -9,6 +9,7 @@ using System.Threading; using System.Threading.Tasks; using vassago.Models; +[StaticPlz] public class GeneralSnarkPlaying : Behavior { public override string Name => "playin Snarkiness"; @@ -19,6 +20,8 @@ public class GeneralSnarkPlaying : Behavior public override bool ShouldAct(Message message) { + if(Behaver.Instance.Selves.Any(acc => acc.Id == message.Author.Id)) + return false; return Regex.IsMatch(message.Content, "^(s?he|(yo)?u|y'?all|they) thinks? i'?m (playin|jokin|kiddin)g?$", RegexOptions.IgnoreCase); } public override async Task ActOn(Message message) diff --git a/Behavior/GeneralSnarkSkynet.cs b/Behavior/GeneralSnarkSkynet.cs index ab9ff66..f0d402f 100644 --- a/Behavior/GeneralSnarkSkynet.cs +++ b/Behavior/GeneralSnarkSkynet.cs @@ -8,6 +8,7 @@ using System.Threading; using System.Threading.Tasks; using vassago.Models; +[StaticPlz] public class GeneralSnarkSkynet : Behavior { public override string Name => "Skynet Snarkiness"; diff --git a/Behavior/Gratitude.cs b/Behavior/Gratitude.cs index 7278624..2e07841 100644 --- a/Behavior/Gratitude.cs +++ b/Behavior/Gratitude.cs @@ -9,6 +9,7 @@ using System.Threading; using System.Threading.Tasks; using vassago.Models; +[StaticPlz] public class Gratitude : Behavior { public override string Name => "Gratitude"; @@ -17,6 +18,8 @@ public class Gratitude : Behavior public override bool ShouldAct(Message message) { + if(Behaver.Instance.Selves.Any(acc => acc.Id == message.Author.Id)) + return false; return Regex.IsMatch(message.Content, "\\bthank (yo)?u\\b", RegexOptions.IgnoreCase) && message.MentionsMe; } public override async Task ActOn(Message message) diff --git a/Behavior/Joke.cs b/Behavior/Joke.cs index 38a2404..6be0178 100644 --- a/Behavior/Joke.cs +++ b/Behavior/Joke.cs @@ -9,6 +9,7 @@ using System.Threading; using System.Threading.Tasks; using vassago.Models; +[StaticPlz] public class Joke : Behavior { public override string Name => "Joke"; @@ -34,12 +35,12 @@ public class Joke : Behavior { var firstIndexAfterQuestionMark = thisJoke.LastIndexOf('?') + 1; var straightline = thisJoke.Substring(0, firstIndexAfterQuestionMark); - var punchline = thisJoke.Substring(firstIndexAfterQuestionMark, thisJoke.Length - firstIndexAfterQuestionMark); + var punchline = thisJoke.Substring(firstIndexAfterQuestionMark, thisJoke.Length - firstIndexAfterQuestionMark).Trim(); Task.WaitAll(message.Channel.SendMessage(straightline)); Thread.Sleep(TimeSpan.FromSeconds(Shared.r.Next(5, 30))); //if (Shared.r.Next(8) == 0) { - LaughAtOwnJoke.punchlinesAwaitingReaction.Add(punchline); + Behaver.Behaviors.Add(new LaughAtOwnJoke(punchline)); } await message.Channel.SendMessage(punchline); // var myOwnMsg = await message.Channel.SendMessage(punchline); diff --git a/Behavior/LaughAtOwnJoke.cs b/Behavior/LaughAtOwnJoke.cs index 720ea1a..49c8d41 100644 --- a/Behavior/LaughAtOwnJoke.cs +++ b/Behavior/LaughAtOwnJoke.cs @@ -9,6 +9,7 @@ using System.Threading; using System.Threading.Tasks; using vassago.Models; + public class LaughAtOwnJoke : Behavior { public override string Name => "Laugh at own jokes"; @@ -16,20 +17,23 @@ public class LaughAtOwnJoke : Behavior public override string Trigger => "1 in 8"; public override string Description => Name; - public static List punchlinesAwaitingReaction = new List(); + private string _punchline{get;set;} + public LaughAtOwnJoke(string punchline) + { + _punchline = punchline; + } public override bool ShouldAct(Message message) { - - //TODO: i need to keep track of myself from here somehow - //return false; - return /*message.Author == me &&*/ punchlinesAwaitingReaction.Contains(message.Content); + Console.WriteLine($"{message.Content} == {_punchline}"); + return message.Content == _punchline + && Behaver.Instance.Selves.Any(acc => acc.Id == message.Author.Id); } public override async Task ActOn(Message message) { - punchlinesAwaitingReaction.Remove(message.Content); await message.React("\U0001F60E"); //smiling face with sunglasses + Behaver.Behaviors.Remove(this); return true; } } \ No newline at end of file diff --git a/Behavior/Peptalk.cs b/Behavior/Peptalk.cs index 994ac4d..2f93781 100644 --- a/Behavior/Peptalk.cs +++ b/Behavior/Peptalk.cs @@ -10,6 +10,7 @@ using Newtonsoft.Json; using vassago.Models; using QRCoder; +[StaticPlz] public class PepTalk : Behavior { public override string Name => "PepTalk"; diff --git a/Behavior/PulseCheck.cs b/Behavior/PulseCheck.cs index b53d805..68ad82b 100644 --- a/Behavior/PulseCheck.cs +++ b/Behavior/PulseCheck.cs @@ -8,6 +8,7 @@ using System.Threading; using System.Threading.Tasks; using vassago.Models; +[StaticPlz] public class PulseCheck : Behavior { public override string Name => "pulse check"; diff --git a/Behavior/QRify.cs b/Behavior/QRify.cs index c51107b..37cdd7f 100644 --- a/Behavior/QRify.cs +++ b/Behavior/QRify.cs @@ -10,6 +10,7 @@ using Newtonsoft.Json; using vassago.Models; using QRCoder; +[StaticPlz] public class QRify : Behavior { public override string Name => "qr-ify"; diff --git a/Behavior/UnitConvert.cs b/Behavior/UnitConvert.cs index 33262eb..c829812 100644 --- a/Behavior/UnitConvert.cs +++ b/Behavior/UnitConvert.cs @@ -3,6 +3,8 @@ namespace vassago.Behavior; using System.Text.RegularExpressions; using System.Threading.Tasks; using vassago.Models; + +[StaticPlz] public class UnitConvert : Behavior { public override string Name => "Unit conversion"; @@ -25,7 +27,7 @@ public class UnitConvert : Behavior await message.Channel.SendMessage("mysteriously semi-parsable"); } await message.Channel.SendMessage( "unparsable"); - + return true; } } \ No newline at end of file diff --git a/Behavior/WishLuck.cs b/Behavior/WishLuck.cs index d04131a..550c088 100644 --- a/Behavior/WishLuck.cs +++ b/Behavior/WishLuck.cs @@ -8,6 +8,7 @@ using System.Threading; using System.Threading.Tasks; using vassago.Models; +[StaticPlz] public class WishLuck : Behavior { public override string Name => "wish me luck"; diff --git a/DiscordInterface/DiscordInterface.cs b/DiscordInterface/DiscordInterface.cs index 84a7397..0b51883 100644 --- a/DiscordInterface/DiscordInterface.cs +++ b/DiscordInterface/DiscordInterface.cs @@ -29,7 +29,7 @@ public class DiscordInterface }; public DiscordInterface() { - _db = Shared.dbContext; + _db = new ChattingContext(); } public async Task Init(string token) @@ -41,6 +41,7 @@ public class DiscordInterface Console.WriteLine(msg.ToString()); return Task.CompletedTask; }; + client.Connected += SelfConnected; client.Ready += () => Task.Run(() => { @@ -78,10 +79,18 @@ public class DiscordInterface await client.StartAsync(); } - #pragma warning disable 4014 //the "you're not awaiting this" warning. yeah I know, that's the beauty of an async method lol - #pragma warning disable 1998 //the "it's async but you're not awaiting anything". + private async Task SelfConnected() + { + + var selfUser = UpsertAccount(client.CurrentUser); + await _db.SaveChangesAsync(); + Behaver.Instance.Selves.Add(selfUser); + } + +#pragma warning disable 4014 //the "you're not awaiting this" warning. yeah I know, that's the beauty of an async method lol +#pragma warning disable 1998 //the "it's async but you're not awaiting anything". private async Task MessageReceived(SocketMessage messageParam) - #pragma warning restore 1998 +#pragma warning restore 1998 { var suMessage = messageParam as SocketUserMessage; if (suMessage == null) @@ -99,7 +108,7 @@ public class DiscordInterface m.MentionsMe = true; } -// if ((suMessage.Author.Id != client.CurrentUser.Id)) + // if ((suMessage.Author.Id != client.CurrentUser.Id)) { if (await Behaver.Instance.ActOn(m)) { @@ -112,10 +121,10 @@ public class DiscordInterface private void UserJoined(SocketGuildUser arg) { - var guild = UpsertChannel(arg.Guild); - var defaultChannel = UpsertChannel(arg.Guild.DefaultChannel); - defaultChannel.ParentChannel = guild; - var u = UpsertUser(arg); + var guild = UpsertChannel(arg.Guild); + var defaultChannel = UpsertChannel(arg.Guild.DefaultChannel); + defaultChannel.ParentChannel = guild; + var u = UpsertAccount(arg); } private async Task ButtonHandler(SocketMessageComponent component) { @@ -192,14 +201,14 @@ public class DiscordInterface m.Attachments.Add(UpsertAttachment(da)); } } - m.Author = UpsertUser(dMessage.Author); + m.Author = UpsertAccount(dMessage.Author); m.Channel = UpsertChannel(dMessage.Channel); m.Content = dMessage.Content; m.ExternalId = dMessage.Id; m.Timestamp = dMessage.EditedTimestamp ?? dMessage.CreatedAt; - if (dMessage.MentionedUserIds?.FirstOrDefault(muid => muid == client.CurrentUser.Id) != null) + if(dMessage.Author.Id != client.CurrentUser.Id && dMessage.MentionedUserIds?.FirstOrDefault(muid => muid == client.CurrentUser.Id) != null) { m.MentionsMe = true; } @@ -218,12 +227,17 @@ public class DiscordInterface var c = _db.Channels.FirstOrDefault(c => c.ExternalId == msg.Channel.Id); //var preferredEmote = c.EmoteOverrides?[e] ?? e; //TODO: emote overrides var preferredEmote = e; - Emote emote; - if(!Emote.TryParse(preferredEmote, out emote)) + Emoji emoji; + if (Emoji.TryParse(preferredEmote, out emoji)) { - if(preferredEmote == e) + return msg.AddReactionAsync(emoji); + } + Emote emote; + if (!Emote.TryParse(preferredEmote, out emote)) + { + if (preferredEmote == e) Console.Error.WriteLine($"never heard of emote {e}"); - return null; + return Task.CompletedTask; } return msg.AddReactionAsync(emote); @@ -294,7 +308,7 @@ public class DiscordInterface c.SendFile = (f, t) => { throw new InvalidOperationException($"channel {channel.Name} is guild; send file"); }; return c; } - internal Account UpsertUser(IUser user) + internal Account UpsertAccount(IUser user) { var addPlease = false; var u = _db.Users.FirstOrDefault(ui => ui.ExternalId == user.Id); @@ -322,11 +336,11 @@ public class DiscordInterface //c.OtherUsers = c.OtherUsers ?? new List(); //c.OtherUsers = await channel.GetUsersAsync(); var dChannel = client.GetChannel(channel.ExternalId.Value); - if(dChannel is IGuild) + if (dChannel is IGuild) { var guild = channel as IGuild; } - else if(dChannel is IGuildChannel) + else if (dChannel is IGuildChannel) { var gc = dChannel as IGuildChannel; } diff --git a/Program.cs b/Program.cs index eae45da..f37b11f 100644 --- a/Program.cs +++ b/Program.cs @@ -23,10 +23,9 @@ namespace vassago public async Task MainAsync() { Shared.DBConnectionString = config.DBConnectionString; - Shared.dbContext = new ChattingContext(); - { - Shared.dbContext.Database.EnsureCreated(); - } + var dbc = new ChattingContext(); + dbc.Database.EnsureCreated(); + Conversion.Converter.Load(config.ExchangePairsLocation); if(config.DiscordTokens.Any()) foreach(var dt in config.DiscordTokens) @@ -34,7 +33,7 @@ namespace vassago var d = new DiscordInterface.DiscordInterface(); await d.Init(dt); discords.Add(d); - } + } await Task.Delay(-1); } diff --git a/Shared.cs b/Shared.cs index 921847b..39228f0 100644 --- a/Shared.cs +++ b/Shared.cs @@ -9,6 +9,5 @@ public static class Shared { public static Random r = new Random(); public static string DBConnectionString { get; set; } - public static ChattingContext dbContext { get; set; } public static HttpClient HttpClient { get; internal set; } = new HttpClient(); }