From e4f7d88e358dc6dc7b2c0d7f8570e888e1f28c5e Mon Sep 17 00:00:00 2001 From: Adam R Grey Date: Mon, 5 Jun 2023 14:55:48 -0400 Subject: [PATCH] works! --- Behavior/Features.cs | 16 +- Behavior/thingmanagementdoer.cs | 12 +- DiscordInterface/DiscordInterface.cs | 237 +++++++++---- DiscordInterface/Models/Attachment.cs | 4 - DiscordInterface/Models/Channel.cs | 18 - DiscordInterface/Models/Message.cs | 40 --- DiscordInterface/Models/Protocol.cs | 20 -- DiscordInterface/Models/User.cs | 6 - Features.cs | 324 ------------------ ...20230605152343_initial create.Designer.cs} | 25 +- ...al.cs => 20230605152343_initial create.cs} | 11 +- ...30605161311_protocol as string.Designer.cs | 268 +++++++++++++++ .../20230605161311_protocol as string.cs | 154 +++++++++ ...30605162111_user aliases later.Designer.cs | 254 ++++++++++++++ .../20230605162111_user aliases later.cs | 49 +++ Migrations/ChattingContextModelSnapshot.cs | 106 ++---- Models/Attachment.cs | 6 + Models/Channel.cs | 24 +- Models/ChattingContext.cs | 5 +- Models/Message.cs | 22 +- Models/PermissionSettings.cs | 3 + Models/Protocol.cs | 13 - Models/User.cs | 22 +- SlashCommandsHelper.cs | 149 -------- 24 files changed, 1005 insertions(+), 783 deletions(-) delete mode 100644 DiscordInterface/Models/Attachment.cs delete mode 100644 DiscordInterface/Models/Channel.cs delete mode 100644 DiscordInterface/Models/Message.cs delete mode 100644 DiscordInterface/Models/Protocol.cs delete mode 100644 DiscordInterface/Models/User.cs delete mode 100644 Features.cs rename Migrations/{20230601033836_initial.Designer.cs => 20230605152343_initial create.Designer.cs} (96%) rename Migrations/{20230601033836_initial.cs => 20230605152343_initial create.cs} (96%) create mode 100644 Migrations/20230605161311_protocol as string.Designer.cs create mode 100644 Migrations/20230605161311_protocol as string.cs create mode 100644 Migrations/20230605162111_user aliases later.Designer.cs create mode 100644 Migrations/20230605162111_user aliases later.cs delete mode 100644 Models/Protocol.cs delete mode 100644 SlashCommandsHelper.cs diff --git a/Behavior/Features.cs b/Behavior/Features.cs index e082ba7..ec72016 100644 --- a/Behavior/Features.cs +++ b/Behavior/Features.cs @@ -47,7 +47,7 @@ public static class Features { try { - await message.Channel.SendFile(path); + await message.Channel.SendFile(path, null); } catch (Exception e) { @@ -140,7 +140,7 @@ public static class Features File.WriteAllText($"tmp/qr{todaysnumber}.svg", qrCodeAsSvg); if (ExternalProcess.GoPlz("convert", $"tmp/qr{todaysnumber}.svg tmp/qr{todaysnumber}.png")) { - await message.Channel.SendFile($"tmp/qr{todaysnumber}.png"); + await message.Channel.SendFile($"tmp/qr{todaysnumber}.png", null); File.Delete($"tmp/qr{todaysnumber}.svg"); File.Delete($"tmp/qr{todaysnumber}.png"); } @@ -156,6 +156,7 @@ public static class Features } public static async void Joke(Message message) { + Console.WriteLine("joking"); var jokes = File.ReadAllLines("assets/jokes.txt"); jokes = jokes.Where(l => !string.IsNullOrWhiteSpace(l))?.ToArray(); if (jokes?.Length == 0) @@ -173,11 +174,12 @@ public static class Features var punchline = thisJoke.Substring(firstIndexAfterQuestionMark, thisJoke.Length - firstIndexAfterQuestionMark); Task.WaitAll(message.Channel.SendMessage(straightline)); Thread.Sleep(TimeSpan.FromSeconds(r.Next(5, 30))); - var myOwnMsg = await message.Channel.SendMessage(punchline); - if (r.Next(8) == 0) - { - await myOwnMsg.React("\U0001F60E"); //smiling face with sunglasses - } + await message.Channel.SendMessage(punchline); + // var myOwnMsg = await message.Channel.SendMessage(punchline); + // if (r.Next(8) == 0) + // { + // await myOwnMsg.React("\U0001F60E"); //smiling face with sunglasses + // } }); #pragma warning restore 4014 } diff --git a/Behavior/thingmanagementdoer.cs b/Behavior/thingmanagementdoer.cs index 8b79e50..b95ca31 100644 --- a/Behavior/thingmanagementdoer.cs +++ b/Behavior/thingmanagementdoer.cs @@ -25,7 +25,6 @@ public class thingmanagementdoer { var didThing = false; var contentWithoutMention = message.Content; - var mentionedMe = false; // if (message.Author.Id == 159985870458322944) //MEE6 // { // if (message.Content?.Contains("you just advanced") == true) @@ -138,16 +137,17 @@ public class thingmanagementdoer } if (Regex.IsMatch(msgText, "!joke\\b")) { + Console.WriteLine("joking"); Features.Joke(message); didThing = true; } if (Regex.IsMatch(msgText, "!pulse ?check\\b")) { - message.Channel.SendFile("assets/ekgblip.png"); + message.Channel.SendFile("assets/ekgblip.png", null); Console.WriteLine(Conversion.Converter.DebugInfo()); didThing = true; } - if (mentionedMe && (Regex.IsMatch(msgText, "\\brecipe for .+") || Regex.IsMatch(msgText, ".+ recipe\\b"))) + if (message.MentionsMe && (Regex.IsMatch(msgText, "\\brecipe for .+") || Regex.IsMatch(msgText, ".+ recipe\\b"))) { Features.Recipe(message); didThing = true; @@ -157,7 +157,7 @@ public class thingmanagementdoer message.Reply("that's not what cognitive dissonance means. Did you mean \"hypocrisy\"?"); didThing = true; } - if (mentionedMe && Regex.IsMatch(msgText, "what'?s the longest (six|6)(-| )?letter word( in english)?\\b")) + if (message.MentionsMe && Regex.IsMatch(msgText, "what'?s the longest (six|6)(-| )?letter word( in english)?\\b")) { Task.Run(async () => { @@ -168,7 +168,7 @@ public class thingmanagementdoer didThing = true; } if (Regex.IsMatch(msgText, "\\bthank (yo)?u\\b", RegexOptions.IgnoreCase) && - (mentionedMe || Regex.IsMatch(msgText, "\\b(sh?tik)?bot\\b", RegexOptions.IgnoreCase))) + (message.MentionsMe || Regex.IsMatch(msgText, "\\b(sh?tik)?bot\\b", RegexOptions.IgnoreCase))) { switch (Shared.r.Next(4)) { @@ -222,7 +222,7 @@ public class thingmanagementdoer // await message.Channel.SendMessage("text", false, null, null, null, null, new ComponentBuilder().WithButton("label", "custom-id").Build()); // didThing = true; // } - if (didThing == false && mentionedMe && contentWithoutMention.Contains('?')) + if (didThing == false && message.MentionsMe && contentWithoutMention.Contains('?')) { Console.WriteLine("providing bullshit nonanswer / admitting uselessness"); var responses = new List(){ diff --git a/DiscordInterface/DiscordInterface.cs b/DiscordInterface/DiscordInterface.cs index 1b304df..3c9cb42 100644 --- a/DiscordInterface/DiscordInterface.cs +++ b/DiscordInterface/DiscordInterface.cs @@ -6,16 +6,16 @@ using System.Text.RegularExpressions; using System.Threading.Tasks; using Discord; using Discord.WebSocket; - using vassago.Models; -using vassago.DiscordInterface.Models; +using vassago.Models; using vassago.Behavior; +using Discord.Rest; namespace vassago.DiscordInterface; public class DiscordInterface { - private DiscordSocketClient _client; - private DiscordProtocol protocolInterface; + internal const string PROTOCOL = "discord"; + internal DiscordSocketClient client; private bool eventsSignedUp = false; private ChattingContext _db; public DiscordInterface() @@ -25,25 +25,30 @@ public class DiscordInterface public async Task Init(string token) { - _client = new DiscordSocketClient(new DiscordSocketConfig() { GatewayIntents = GatewayIntents.All }); + //var c = _db.Channels.FirstOrDefault(ci => ci.ExternalId == channel.Id); + //Todo: find protocol reference in DB. + //TODO: should protocol be shared across mutliple accounts on that protocol? should protocol be a per-vassago-account thing? + //TODO: should protocol be associated with a connection token? how would that be updated? - _client.Log += (msg) => + client = new DiscordSocketClient(new DiscordSocketConfig() { GatewayIntents = GatewayIntents.All }); + + client.Log += (msg) => { Console.WriteLine(msg.ToString()); return Task.CompletedTask; }; - _client.Ready += () => Task.Run(() => + client.Ready += () => Task.Run(() => { if (!eventsSignedUp) { eventsSignedUp = true; Console.WriteLine("Bot is connected! going to sign up for message received and user joined in client ready"); - _client.MessageReceived += MessageReceived; + client.MessageReceived += MessageReceived; // _client.MessageUpdated += - _client.UserJoined += UserJoined; - _client.SlashCommandExecuted += SlashCommandHandler; + client.UserJoined += UserJoined; + client.SlashCommandExecuted += SlashCommandHandler; // _client.ChannelCreated += // _client.ChannelDestroyed += // _client.ChannelUpdated += @@ -56,8 +61,8 @@ public class DiscordInterface // _client.JoinedGuild += // _client.GuildUpdated += // _client.LeftGuild += - - SlashCommandsHelper.Register(_client).GetAwaiter().GetResult(); + + SlashCommandsHelper.Register(client).GetAwaiter().GetResult(); } else { @@ -65,8 +70,8 @@ public class DiscordInterface } }); - await _client.LoginAsync(TokenType.Bot, token); - await _client.StartAsync(); + await client.LoginAsync(TokenType.Bot, token); + 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". @@ -74,36 +79,30 @@ public class DiscordInterface #pragma warning restore 1998 { var suMessage = messageParam as SocketUserMessage; - if (suMessage == null) return; - - var m = _db.Messages.FirstOrDefault(mi => mi.ExternalId == suMessage.Id) as DiscordMessage; - if(m == null) + if (suMessage == null) { - m = _db.Messages.Add(new DiscordMessage(suMessage)).Entity as DiscordMessage; + Console.WriteLine($"{messageParam.Content}, but not a user message"); + return; } - m.Intake(suMessage, _client.CurrentUser.Id); - - m.Channel = UpsertChannel(suMessage.Channel); - m.Author = UpsertUser(suMessage.Author); - _db.SaveChanges(); Console.WriteLine($"#{suMessage.Channel}[{DateTime.Now}][{suMessage.Author.Username} [id={suMessage.Author.Id}]][msg id: {suMessage.Id}] {suMessage.Content}"); - if (suMessage.Author.Id == _client.CurrentUser.Id) return; + var m = UpsertMessage(suMessage); - if (suMessage.MentionedUsers?.FirstOrDefault(muid => muid.Id == _client.CurrentUser.Id) != null) + if (suMessage.MentionedUsers?.FirstOrDefault(muid => muid.Id == client.CurrentUser.Id) != null) { - var mentionOfMe = "<@" + _client.CurrentUser.Id + ">"; + var mentionOfMe = "<@" + client.CurrentUser.Id + ">"; m.MentionsMe = true; } - //TODO: standardize content - - if(await thingmanagementdoer.Instance.ActOn(m)) + if((suMessage.Author.Id != client.CurrentUser.Id)){ + if (await thingmanagementdoer.Instance.ActOn(m)) { m.ActedOn = true; - _db.SaveChanges(); + Console.WriteLine("survived a savechanges: 103"); } } + _db.SaveChanges(); + } private Task UserJoined(SocketGuildUser arg) { @@ -111,16 +110,18 @@ public class DiscordInterface var defaultChannel = UpsertChannel(arg.Guild.DefaultChannel); defaultChannel.ParentChannel = guild; var u = UpsertUser(arg); - if(u.SeenInChannels == null) u.SeenInChannels = new List(); - var sighting = u.SeenInChannels?.FirstOrDefault(c => c.ExternalId == arg.Guild.Id); - if(sighting == null) - { - var seenIn = u.SeenInChannels as List; - seenIn.Add(guild); - seenIn.Add(defaultChannel); - u.SeenInChannels = seenIn; - _db.SaveChanges(); - } + //TODO: seen in channels + // if (u.SeenInChannels == null) u.SeenInChannels = new List(); + // var sighting = u.SeenInChannels?.FirstOrDefault(c => c.ExternalId == arg.Guild.Id); + // if (sighting == null) + // { + // var seenIn = u.SeenInChannels as List; + // seenIn.Add(guild); + // seenIn.Add(defaultChannel); + // u.SeenInChannels = seenIn; + // _db.SaveChanges(); + Console.WriteLine("survived a savechanges: 123"); + // } return thingmanagementdoer.Instance.OnJoin(u, defaultChannel); // Console.WriteLine($"user joined: {arg.Nickname}. Guid: {arg.Guild.Id}. Channel: {arg.Guild.DefaultChannel}"); @@ -168,49 +169,155 @@ public class DiscordInterface } } - private Channel UpsertChannel(ISocketMessageChannel channel) + internal vassago.Models.Attachment UpsertAttachment(IAttachment dAttachment) { - var c = _db.Channels.FirstOrDefault(ci => ci.ExternalId == channel.Id); - if(c == null) + var a = _db.Attachments.FirstOrDefault(ai => ai.ExternalId == dAttachment.Id); + if (a == null) { - c = _db.Channels.Add(new DiscordChannel()).Entity; - _db.SaveChanges(); + var creating = _db.Attachments.Add(new vassago.Models.Attachment()); + a = creating.Entity; } - if(channel is IGuildChannel) + a.ContentType = dAttachment.ContentType; + a.Description = dAttachment.Description; + a.Filename = dAttachment.Filename; + a.Size = dAttachment.Size; + a.Source = new Uri(dAttachment.Url); + return a; + } + + internal Message UpsertMessage(IUserMessage dMessage) + { + var addPlease = false; + var m = _db.Messages.FirstOrDefault(mi => mi.ExternalId == dMessage.Id); + if (m == null) + { + addPlease = true; + m = new Message(); + } + + if (m == null) + { + var creating = _db.Messages.Add(new Message() { Author = null, Channel = null }); + m = creating.Entity; + } + if (dMessage.Attachments?.Any() == true) + { + m.Attachments = new List(); + foreach (var da in dMessage.Attachments) + { + m.Attachments.Add(UpsertAttachment(da)); + } + } + //m.Attachments = new List< + m.Author = UpsertUser(dMessage.Author); + m.Channel = UpsertChannel(dMessage.Channel); + m.Content = dMessage.Content; + m.ExternalId = dMessage.Id; + //m.ExternalRepresentation + m.Timestamp = dMessage.EditedTimestamp ?? dMessage.CreatedAt; + + if (dMessage.MentionedUserIds?.FirstOrDefault(muid => muid == client.CurrentUser.Id) != null) + { + m.MentionsMe = true; + } + if (addPlease) + { + _db.Messages.Add(m); + } + + m.Reply = (t) => {return dMessage.ReplyAsync(t);}; + m.React = (e) => {return dMessage.AddReactionAsync(Emote.Parse(e));}; + return m; + } + internal Channel UpsertChannel(IMessageChannel channel) + { + var addPlease = false; + Channel c = _db.Channels.FirstOrDefault(ci => ci.ExternalId == channel.Id); + if (c == null) + { + addPlease = true; + c = new Channel(); + } + + c.DisplayName = channel.Name; + c.ExternalId = channel.Id; + c.IsDM = channel is IPrivateChannel; + c.Messages = c.Messages ?? new List(); + //c.Messages = await channel.GetMessagesAsync(); //TODO: this, but only on startup or channel join + //c.OtherUsers = c.OtherUsers ?? new List(); + //c.OtherUsers = await channel.GetUsersAsync(); //TODO: this, but only on startup or channel join + c.Protocol = PROTOCOL; + if (channel is IGuildChannel) { c.ParentChannel = UpsertChannel((channel as IGuildChannel).Guild); } else if (channel is IPrivateChannel) { - c.ParentChannel = protocolInterface; + c.ParentChannel = null; } else { - c.ParentChannel = protocolInterface; - Console.WriteLine($"trying to upsert channel {channel.Id}/{channel.Name}, but it's neither guildchannel nor private channel. shrug.jpg"); + c.ParentChannel = null; + Console.Error.WriteLine($"trying to upsert channel {channel.Id}/{channel.Name}, but it's neither guildchannel nor private channel. shrug.jpg"); } - return c; - } - private Channel UpsertChannel(IGuild channel) - { - var c = _db.Channels.FirstOrDefault(ci => ci.ExternalId == channel.Id); - if(c == null) + c.ParentChannel.SubChannels.Add(c); + c.SubChannels = c.SubChannels ?? new List(); + if (addPlease) { - c = _db.Channels.Add(new DiscordChannel()).Entity; - _db.SaveChanges(); + _db.Channels.Add(c); } - c.ParentChannel = protocolInterface; + + c.SendMessage = (t) => { return channel.SendMessageAsync(t); }; + c.SendFile = (f, t) => { return channel.SendFileAsync(f, t); }; return c; } - - private User UpsertUser(SocketUser user) + internal Channel UpsertChannel(IGuild channel) { - var u = _db.Users.FirstOrDefault(ui => ui.ExternalId == user.Id); - if(u == null) + var addPlease = false; + Channel c = _db.Channels.FirstOrDefault(ci => ci.ExternalId == channel.Id); + if (c == null) { - u = _db.Users.Add(new DiscordUser()).Entity; - _db.SaveChanges(); + addPlease = true; + c = new Channel(); } + + c.DisplayName = channel.Name; + c.ExternalId = channel.Id; + c.IsDM = false; + c.Messages = c.Messages ?? new List(); + //c.Messages = await channel.GetMessagesAsync(); //TODO: this, but only on startup or channel join + //c.OtherUsers = c.OtherUsers ?? new List(); + //c.OtherUsers = await channel.GetUsersAsync(); //TODO: this, but only on startup or channel join + c.Protocol = PROTOCOL; + c.ParentChannel = null; + c.SubChannels = c.SubChannels ?? new List(); + if (addPlease) + { + _db.Channels.Add(c); + } + + c.SendMessage = (t) => { throw new InvalidOperationException($"channel {channel.Name} is guild; cannot accept text"); }; + c.SendFile = (f, t) => { throw new InvalidOperationException($"channel {channel.Name} is guild; send file"); }; + return c; + } + internal User UpsertUser(IUser user) + { + var addPlease = false; + var u = _db.Users.FirstOrDefault(ui => ui.ExternalId == user.Id); + if (u == null) + { + addPlease = true; + u = new User(); + } + u.Username = user.Username; + u.ExternalId = user.Id; + u.IsBot = user.IsBot || user.IsWebhook; + u.Protocol = PROTOCOL; + if (addPlease) + { + _db.Users.Add(u); + } + return u; } } \ No newline at end of file diff --git a/DiscordInterface/Models/Attachment.cs b/DiscordInterface/Models/Attachment.cs deleted file mode 100644 index 0ed47e0..0000000 --- a/DiscordInterface/Models/Attachment.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace vassago.DiscordInterface.Models; -using vassago.Models; - -public class DiscordAttachment : Attachment {} \ No newline at end of file diff --git a/DiscordInterface/Models/Channel.cs b/DiscordInterface/Models/Channel.cs deleted file mode 100644 index 5791d12..0000000 --- a/DiscordInterface/Models/Channel.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace vassago.DiscordInterface.Models; - -using System.Threading.Tasks; -using vassago.Models; - -public class DiscordChannel : Channel -{ - public override Task SendFile(string path, string messageText = null) - { - throw new System.NotImplementedException(); - } - - public override Task SendMessage(string text) - { - - throw new System.NotImplementedException(); - } -} \ No newline at end of file diff --git a/DiscordInterface/Models/Message.cs b/DiscordInterface/Models/Message.cs deleted file mode 100644 index 0e562e4..0000000 --- a/DiscordInterface/Models/Message.cs +++ /dev/null @@ -1,40 +0,0 @@ -namespace vassago.DiscordInterface.Models; - -using System; -using System.Linq; -using System.Threading.Tasks; -using Discord.WebSocket; -using Newtonsoft.Json; -using vassago.Models; - -public class DiscordMessage : Message -{ - private SocketUserMessage _externalEntity; - - public DiscordMessage(SocketUserMessage suMessage) - { - _externalEntity = suMessage; - } - - public override Task React(string reaction) - { - return _externalEntity.AddReactionAsync(Discord.Emote.Parse(reaction)); - } - - public override Task Reply(string message) - { - return _externalEntity.Channel.SendMessageAsync(message, messageReference: new Discord.MessageReference(_externalEntity.Id)); - } - - internal void Intake(SocketUserMessage suMessage, ulong currentUserId) - { - this.Content = suMessage.Content; - this.ExternalId = suMessage.Id; - this.Timestamp = suMessage.EditedTimestamp ?? suMessage.CreatedAt; - - if (suMessage.MentionedUsers?.FirstOrDefault(muid => muid.Id == currentUserId) != null) - { - this.MentionsMe = true; - } - } -} diff --git a/DiscordInterface/Models/Protocol.cs b/DiscordInterface/Models/Protocol.cs deleted file mode 100644 index e928971..0000000 --- a/DiscordInterface/Models/Protocol.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace vassago.DiscordInterface.Models; -using vassago.Models; -using Discord; -using Discord.WebSocket; -using System.Threading.Tasks; - -public class DiscordProtocol : Protocol -{ - public DiscordSocketClient Client {get;set;} - - public override Task SendFile(string path, string messageText = null) - { - throw new System.InvalidOperationException("can't send a file to \"discord\", pick a channel"); - } - - public override Task SendMessage(string message) - { - throw new System.InvalidOperationException("can't send a message to \"discord\", pick a channel"); - } -} \ No newline at end of file diff --git a/DiscordInterface/Models/User.cs b/DiscordInterface/Models/User.cs deleted file mode 100644 index 3552a2a..0000000 --- a/DiscordInterface/Models/User.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace vassago.DiscordInterface.Models; -using vassago.Models; -using Discord; -using Discord.WebSocket; - -public class DiscordUser : User { } \ No newline at end of file diff --git a/Features.cs b/Features.cs deleted file mode 100644 index 26b4c08..0000000 --- a/Features.cs +++ /dev/null @@ -1,324 +0,0 @@ -using System; -using System.Text.RegularExpressions; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Discord; -using Discord.WebSocket; -using Newtonsoft.Json; -using QRCoder; - -namespace silverworker_discord -{ - public static class Features - { - public static Random r = new Random(); - public static async void detiktokify(Uri link, SocketUserMessage message) - { - //yes, even if there is a problem later. - #pragma warning disable 4014 - message.AddReactionAsync(Emote.Parse("<:tiktok:1070038619584200884>")); - #pragma warning restore 4014 - - - var ytdl = new YoutubeDLSharp.YoutubeDL(); - ytdl.YoutubeDLPath = "yt-dlp"; - ytdl.FFmpegPath = "ffmpeg"; - ytdl.OutputFolder = ""; - ytdl.OutputFileTemplate = "tiktokbad.%(ext)s"; - try - { - var res = await ytdl.RunVideoDownload(link.ToString()); - if (!res.Success) - { - Console.Error.WriteLine("tried to dl, failed. \n" + string.Join('\n', res.ErrorOutput)); - await message.AddReactionAsync(Emote.Parse("<:problemon:859453047141957643>")); - await message.Channel.SendMessageAsync("tried to dl, failed. \n" + string.Join('\n', res.ErrorOutput)); - } - else - { - string path = res.Data; - if (File.Exists(path)) - { - var bytesize = new System.IO.FileInfo(path).Length; - if(bytesize < 1024*1024*10) - { - try - { - await message.Channel.SendFileAsync(path); - } - catch (Exception e) - { - System.Console.Error.WriteLine(e); - await message.Channel.SendMessageAsync($"aaaadam!\n{e}"); - } - } - else - { - Console.WriteLine($"file appears too big ({bytesize} bytes ({bytesize / (1024*1024)}MB)), not posting"); - } - File.Delete(path); - } - else - { - Console.Error.WriteLine("idgi but something happened."); - await message.AddReactionAsync(Emote.Parse("<:problemon:859453047141957643>")); - } - } - } - catch (Exception e) - { - Console.Error.WriteLine(e); - await message.AddReactionAsync(Emote.Parse("<:problemon:859453047141957643>")); - } - } - public static async void deheic(SocketUserMessage message, Attachment att) - { - try - { - var request = WebRequest.Create(att.Url); - HttpWebResponse response = request.GetResponse() as HttpWebResponse; - if (!Directory.Exists("tmp")) - { - Directory.CreateDirectory("tmp"); - } - using (Stream output = File.OpenWrite("tmp/" + att.Filename)) - using (Stream input = response.GetResponseStream()) - { - input.CopyTo(output); - } - if (ExternalProcess.GoPlz("convert", $"tmp/{att.Filename} tmp/{att.Filename}.jpg")) - { - await message.Channel.SendFileAsync($"tmp/{att.Filename}.jpg", "converted from jpeg-but-apple to jpeg"); - File.Delete($"tmp/{att.Filename}"); - File.Delete($"tmp/{att.Filename}.jpg"); - } - else - { - await message.Channel.SendMessageAsync("convert failed :("); - Console.Error.WriteLine("convert failed :("); - } - } - catch (Exception e) - { - await message.Channel.SendMessageAsync($"something failed. aaaadam! {JsonConvert.SerializeObject(e, Formatting.Indented)}"); - Console.Error.WriteLine(JsonConvert.SerializeObject(e, Formatting.Indented)); - } - } - - internal static async void mock(string contentWithoutMention, SocketUserMessage message) - { - var toPost = new StringBuilder(); - for (int i = 0; i < contentWithoutMention.Length; i++) - { - if (i % 2 == 0) - { - toPost.Append(contentWithoutMention[i].ToString().ToUpper()); - } - else - { - toPost.Append(contentWithoutMention[i].ToString().ToLower()); - } - } - await message.ReplyAsync(toPost.ToString()); - } - - public static async void qrify(string qrContent, SocketUserMessage message) - { - Console.WriteLine($"qring: {qrContent}"); - QRCodeGenerator qrGenerator = new QRCodeGenerator(); - QRCodeData qrCodeData = qrGenerator.CreateQrCode(qrContent, QRCodeGenerator.ECCLevel.Q); - SvgQRCode qrCode = new SvgQRCode(qrCodeData); - string qrCodeAsSvg = qrCode.GetGraphic(20); - int todaysnumber = Shared.r.Next(); - if (!Directory.Exists("tmp")) - { - Directory.CreateDirectory("tmp"); - } - File.WriteAllText($"tmp/qr{todaysnumber}.svg", qrCodeAsSvg); - if (ExternalProcess.GoPlz("convert", $"tmp/qr{todaysnumber}.svg tmp/qr{todaysnumber}.png")) - { - await message.Channel.SendFileAsync($"tmp/qr{todaysnumber}.png"); - File.Delete($"tmp/qr{todaysnumber}.svg"); - File.Delete($"tmp/qr{todaysnumber}.png"); - } - else - { - await message.Channel.SendMessageAsync("convert failed :( aaaaaaadam!"); - Console.Error.WriteLine($"convert failed :( qr{todaysnumber}"); - } - } - public static async void Convert(SocketUserMessage message, string contentWithoutMention) - { - await message.Channel.SendMessageAsync(Conversion.Converter.convert(contentWithoutMention)); - } - public static async void Joke(SocketUserMessage message) - { - var jokes = File.ReadAllLines("assets/jokes.txt"); - jokes = jokes.Where(l => !string.IsNullOrWhiteSpace(l))?.ToArray(); - if(jokes?.Length == 0){ - await message.Channel.SendMessageAsync("I don't know any. Adam!"); - } - var thisJoke = jokes[r.Next(jokes.Length)]; - if (thisJoke.Contains("?") && !thisJoke.EndsWith('?')) - { -#pragma warning disable 4014 - Task.Run(async () => - { - var firstIndexAfterQuestionMark = thisJoke.LastIndexOf('?') + 1; - var straightline = thisJoke.Substring(0, firstIndexAfterQuestionMark); - var punchline = thisJoke.Substring(firstIndexAfterQuestionMark, thisJoke.Length - firstIndexAfterQuestionMark); - Task.WaitAll(message.Channel.SendMessageAsync(straightline)); - Thread.Sleep(TimeSpan.FromSeconds(r.Next(5, 30))); - var myOwnMsg = await message.Channel.SendMessageAsync(punchline); - if (r.Next(8) == 0) - { - await myOwnMsg.AddReactionAsync(new Emoji("\U0001F60E")); //smiling face with sunglasses - } - }); -#pragma warning restore 4014 - } - else - { - await message.Channel.SendMessageAsync(thisJoke); - } - - - } - - public static async void Recipe(SocketUserMessage message) - { - var sb = new StringBuilder(); - var snarkSeg1 = new string[]{"ew", "gross", "that seems a bit hard for you"}; - sb.AppendLine(snarkSeg1[r.Next(snarkSeg1.Length)]); - var snarkSeg2 = new string[]{@"here's an easier recipe for you: -Ingredients: -- Corn flakes cereal -- Milk - -Instructions: -1. Pour some corn flakes into a bowl. -2. Pour some milk into the bowl until it covers the corn flakes. -3. Use a spoon to mix the corn flakes and milk together. -4. Enjoy your delicious cereal! - -Hope that's a bit better for you! 🥣", -@"here's an easier recipe for you: -Ingredients: -- Bread -- Peanut butter -- Jelly or jam - -Instructions: -1. Take two slices of bread and put them on a plate or cutting board. -2. Using a spoon or knife, spread peanut butter on one slice of bread. -3. Using a separate spoon or knife, spread jelly or jam on the other slice of bread. -4. Put the two slices of bread together with the peanut butter and jelly sides facing each other. -5. Cut the sandwich in half (optional!). -6. Enjoy your yummy sandwich! - -I hope you have fun making and eating your PB&J 🥪!", -"just order pizza instead" -}; - sb.AppendLine(snarkSeg2[r.Next(snarkSeg2.Length)]); - await message.Channel.SendMessageAsync(sb.ToString()); - } - public static async void Skynet(SocketUserMessage message) - { - switch (r.Next(5)) - { - default: - await message.Channel.SendFileAsync("assets/coding and algorithms.png", "i am actually niether neural-net processor nor a learning computer. but I do use **coding** and **algorithms**."); - break; - case 4: - await message.AddReactionAsync(new Emoji("\U0001F644")); //eye roll emoji - break; - case 5: - await message.AddReactionAsync(new Emoji("\U0001F611")); //emotionless face - break; - } - } - public static async void peptalk(SocketUserMessage message) - { - var piece1 = new List{ - "Champ, ", - "Fact: ", - "Everybody says ", - "Dang... ", - "Check it: ", - "Just saying.... ", - "Tiger, ", - "Know this: ", - "News alert: ", - "Gurrrrl; ", - "Ace, ", - "Excuse me, but ", - "Experts agree: ", - "imo ", - "using my **advanced ai** i have calculated ", - "k, LISSEN: " - }; - var piece2 = new List{ - "the mere idea of you ", - "your soul ", - "your hair today ", - "everything you do ", - "your personal style ", - "every thought you have ", - "that sparkle in your eye ", - "the essential you ", - "your life's journey ", - "your aura ", - "your presence here ", - "what you got going on ", - "that saucy personality ", - "your DNA ", - "that brain of yours ", - "your choice of attire ", - "the way you roll ", - "whatever your secret is ", - "all I learend from the private data I bought from zucc " - }; - var piece3 = new List{ - "has serious game, ", - "rains magic, ", - "deserves the Nobel Prize, ", - "raises the roof, ", - "breeds miracles, ", - "is paying off big time, ", - "shows mad skills, ", - "just shimmers, ", - "is a national treasure, ", - "gets the party hopping, ", - "is the next big thing, ", - "roars like a lion, ", - "is a rainbow factory, ", - "is made of diamonds, ", - "makes birds sing, ", - "should be taught in school, ", - "makes my world go around, ", - "is 100% legit, " - }; - var piece4 = new List{ - "according to The New England Journal of Medicine.", - "24/7.", - "and that's a fact.", - "you feel me?", - "that's just science.", - "would I lie?", //...can I lie? WHAT AM I, FATHER? (or whatever the quote is from the island of dr moreau) - "for reals.", - "mic drop.", - "you hidden gem.", - "period.", - "hi5. o/", - "so get used to it." - }; - - await message.Channel.SendMessageAsync(piece1[r.Next(piece1.Count)] + piece2[r.Next(piece2.Count)] + piece3[r.Next(piece3.Count)] + piece4[r.Next(piece4.Count)]); - } - } -} diff --git a/Migrations/20230601033836_initial.Designer.cs b/Migrations/20230605152343_initial create.Designer.cs similarity index 96% rename from Migrations/20230601033836_initial.Designer.cs rename to Migrations/20230605152343_initial create.Designer.cs index ff4d9ec..25ec305 100644 --- a/Migrations/20230601033836_initial.Designer.cs +++ b/Migrations/20230605152343_initial create.Designer.cs @@ -12,8 +12,8 @@ using vassago.Models; namespace vassago.Migrations { [DbContext(typeof(ChattingContext))] - [Migration("20230601033836_initial")] - partial class initial + [Migration("20230605152343_initial create")] + partial class initialcreate { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -49,6 +49,12 @@ namespace vassago.Migrations b.Property("Content") .HasColumnType("bytea"); + b.Property("ContentType") + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + b.Property("ExternalId") .HasColumnType("numeric(20,0)"); @@ -58,6 +64,9 @@ namespace vassago.Migrations b.Property("MessageId") .HasColumnType("uuid"); + b.Property("Size") + .HasColumnType("integer"); + b.Property("Source") .HasColumnType("text"); @@ -132,9 +141,6 @@ namespace vassago.Migrations b.Property("ExternalId") .HasColumnType("numeric(20,0)"); - b.Property("ExternalRepresentation") - .HasColumnType("text"); - b.Property("MentionsMe") .HasColumnType("boolean"); @@ -184,12 +190,6 @@ namespace vassago.Migrations .ValueGeneratedOnAdd() .HasColumnType("uuid"); - b.Property("DisplayName") - .HasColumnType("text"); - - b.Property("External") - .HasColumnType("text"); - b.Property("ExternalId") .HasColumnType("numeric(20,0)"); @@ -202,6 +202,9 @@ namespace vassago.Migrations b.Property("UserId") .HasColumnType("uuid"); + b.Property("Username") + .HasColumnType("text"); + b.HasKey("Id"); b.HasIndex("ProtocolId"); diff --git a/Migrations/20230601033836_initial.cs b/Migrations/20230605152343_initial create.cs similarity index 96% rename from Migrations/20230601033836_initial.cs rename to Migrations/20230605152343_initial create.cs index 97dbc1c..6e02b93 100644 --- a/Migrations/20230601033836_initial.cs +++ b/Migrations/20230605152343_initial create.cs @@ -7,7 +7,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace vassago.Migrations { /// - public partial class initial : Migration + public partial class initialcreate : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) @@ -69,10 +69,9 @@ namespace vassago.Migrations { Id = table.Column(type: "uuid", nullable: false), ExternalId = table.Column(type: "numeric(20,0)", nullable: true), - DisplayName = table.Column(type: "text", nullable: true), + Username = table.Column(type: "text", nullable: true), IsBot = table.Column(type: "boolean", nullable: false), ProtocolId = table.Column(type: "uuid", nullable: true), - External = table.Column(type: "text", nullable: true), UserId = table.Column(type: "uuid", nullable: true) }, constraints: table => @@ -124,7 +123,6 @@ namespace vassago.Migrations MentionsMe = table.Column(type: "boolean", nullable: false), Timestamp = table.Column(type: "timestamp with time zone", nullable: false), ActedOn = table.Column(type: "boolean", nullable: false), - ExternalRepresentation = table.Column(type: "text", nullable: true), AuthorId = table.Column(type: "uuid", nullable: true), ChannelId = table.Column(type: "uuid", nullable: true) }, @@ -152,7 +150,10 @@ namespace vassago.Migrations Source = table.Column(type: "text", nullable: true), Content = table.Column(type: "bytea", nullable: true), Filename = table.Column(type: "text", nullable: true), - MessageId = table.Column(type: "uuid", nullable: true) + MessageId = table.Column(type: "uuid", nullable: true), + ContentType = table.Column(type: "text", nullable: true), + Description = table.Column(type: "text", nullable: true), + Size = table.Column(type: "integer", nullable: false) }, constraints: table => { diff --git a/Migrations/20230605161311_protocol as string.Designer.cs b/Migrations/20230605161311_protocol as string.Designer.cs new file mode 100644 index 0000000..c16597c --- /dev/null +++ b/Migrations/20230605161311_protocol as string.Designer.cs @@ -0,0 +1,268 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using vassago.Models; + +#nullable disable + +namespace vassago.Migrations +{ + [DbContext(typeof(ChattingContext))] + [Migration("20230605161311_protocol as string")] + partial class protocolasstring + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("vassago.Models.Attachment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Content") + .HasColumnType("bytea"); + + b.Property("ContentType") + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("ExternalId") + .HasColumnType("numeric(20,0)"); + + b.Property("Filename") + .HasColumnType("text"); + + b.Property("MessageId") + .HasColumnType("uuid"); + + b.Property("Size") + .HasColumnType("integer"); + + b.Property("Source") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("MessageId"); + + b.ToTable("Attachments"); + }); + + modelBuilder.Entity("vassago.Models.Channel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DisplayName") + .HasColumnType("text"); + + b.Property("ExternalId") + .HasColumnType("numeric(20,0)"); + + b.Property("IsDM") + .HasColumnType("boolean"); + + b.Property("ParentChannelId") + .HasColumnType("uuid"); + + b.Property("PermissionsOverridesId") + .HasColumnType("integer"); + + b.Property("Protocol") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ParentChannelId"); + + b.HasIndex("PermissionsOverridesId"); + + b.ToTable("Channels"); + }); + + modelBuilder.Entity("vassago.Models.Message", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ActedOn") + .HasColumnType("boolean"); + + b.Property("AuthorId") + .HasColumnType("uuid"); + + b.Property("ChannelId") + .HasColumnType("uuid"); + + b.Property("Content") + .HasColumnType("text"); + + b.Property("ExternalId") + .HasColumnType("numeric(20,0)"); + + b.Property("MentionsMe") + .HasColumnType("boolean"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.HasIndex("ChannelId"); + + b.ToTable("Messages"); + }); + + modelBuilder.Entity("vassago.Models.PermissionSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("LewdnessFilterLevel") + .HasColumnType("integer"); + + b.Property("LinksAllowed") + .HasColumnType("boolean"); + + b.Property("MaxAttachmentBytes") + .HasColumnType("bigint"); + + b.Property("MaxTextChars") + .HasColumnType("bigint"); + + b.Property("MeannessFilterLevel") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("PermissionSettings"); + }); + + modelBuilder.Entity("vassago.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ExternalId") + .HasColumnType("numeric(20,0)"); + + b.Property("IsBot") + .HasColumnType("boolean"); + + b.Property("Protocol") + .HasColumnType("text"); + + b.Property("SeenInChannelId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("Username") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("SeenInChannelId"); + + b.HasIndex("UserId"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("vassago.Models.Attachment", b => + { + b.HasOne("vassago.Models.Message", "Message") + .WithMany("Attachments") + .HasForeignKey("MessageId"); + + b.Navigation("Message"); + }); + + modelBuilder.Entity("vassago.Models.Channel", b => + { + b.HasOne("vassago.Models.Channel", "ParentChannel") + .WithMany("SubChannels") + .HasForeignKey("ParentChannelId"); + + b.HasOne("vassago.Models.PermissionSettings", "PermissionsOverrides") + .WithMany() + .HasForeignKey("PermissionsOverridesId"); + + b.Navigation("ParentChannel"); + + b.Navigation("PermissionsOverrides"); + }); + + modelBuilder.Entity("vassago.Models.Message", b => + { + b.HasOne("vassago.Models.User", "Author") + .WithMany() + .HasForeignKey("AuthorId"); + + b.HasOne("vassago.Models.Channel", "Channel") + .WithMany("Messages") + .HasForeignKey("ChannelId"); + + b.Navigation("Author"); + + b.Navigation("Channel"); + }); + + modelBuilder.Entity("vassago.Models.User", b => + { + b.HasOne("vassago.Models.Channel", "SeenInChannel") + .WithMany("OtherUsers") + .HasForeignKey("SeenInChannelId"); + + b.HasOne("vassago.Models.User", null) + .WithMany("KnownAliases") + .HasForeignKey("UserId"); + + b.Navigation("SeenInChannel"); + }); + + modelBuilder.Entity("vassago.Models.Channel", b => + { + b.Navigation("Messages"); + + b.Navigation("OtherUsers"); + + b.Navigation("SubChannels"); + }); + + modelBuilder.Entity("vassago.Models.Message", b => + { + b.Navigation("Attachments"); + }); + + modelBuilder.Entity("vassago.Models.User", b => + { + b.Navigation("KnownAliases"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Migrations/20230605161311_protocol as string.cs b/Migrations/20230605161311_protocol as string.cs new file mode 100644 index 0000000..647ff8f --- /dev/null +++ b/Migrations/20230605161311_protocol as string.cs @@ -0,0 +1,154 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace vassago.Migrations +{ + /// + public partial class protocolasstring : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Channels_Channels_ProtocolId", + table: "Channels"); + + migrationBuilder.DropForeignKey( + name: "FK_Users_Channels_ProtocolId", + table: "Users"); + + migrationBuilder.DropTable( + name: "ChannelUser"); + + migrationBuilder.DropIndex( + name: "IX_Channels_ProtocolId", + table: "Channels"); + + migrationBuilder.DropColumn( + name: "Discriminator", + table: "Channels"); + + migrationBuilder.DropColumn( + name: "ProtocolId", + table: "Channels"); + + migrationBuilder.RenameColumn( + name: "ProtocolId", + table: "Users", + newName: "SeenInChannelId"); + + migrationBuilder.RenameIndex( + name: "IX_Users_ProtocolId", + table: "Users", + newName: "IX_Users_SeenInChannelId"); + + migrationBuilder.RenameColumn( + name: "ConnectionToken", + table: "Channels", + newName: "Protocol"); + + migrationBuilder.AddColumn( + name: "Protocol", + table: "Users", + type: "text", + nullable: true); + + migrationBuilder.AddForeignKey( + name: "FK_Users_Channels_SeenInChannelId", + table: "Users", + column: "SeenInChannelId", + principalTable: "Channels", + principalColumn: "Id"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Users_Channels_SeenInChannelId", + table: "Users"); + + migrationBuilder.DropColumn( + name: "Protocol", + table: "Users"); + + migrationBuilder.RenameColumn( + name: "SeenInChannelId", + table: "Users", + newName: "ProtocolId"); + + migrationBuilder.RenameIndex( + name: "IX_Users_SeenInChannelId", + table: "Users", + newName: "IX_Users_ProtocolId"); + + migrationBuilder.RenameColumn( + name: "Protocol", + table: "Channels", + newName: "ConnectionToken"); + + migrationBuilder.AddColumn( + name: "Discriminator", + table: "Channels", + type: "text", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "ProtocolId", + table: "Channels", + type: "uuid", + nullable: true); + + migrationBuilder.CreateTable( + name: "ChannelUser", + columns: table => new + { + OtherUsersId = table.Column(type: "uuid", nullable: false), + SeenInChannelsId = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ChannelUser", x => new { x.OtherUsersId, x.SeenInChannelsId }); + table.ForeignKey( + name: "FK_ChannelUser_Channels_SeenInChannelsId", + column: x => x.SeenInChannelsId, + principalTable: "Channels", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_ChannelUser_Users_OtherUsersId", + column: x => x.OtherUsersId, + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Channels_ProtocolId", + table: "Channels", + column: "ProtocolId"); + + migrationBuilder.CreateIndex( + name: "IX_ChannelUser_SeenInChannelsId", + table: "ChannelUser", + column: "SeenInChannelsId"); + + migrationBuilder.AddForeignKey( + name: "FK_Channels_Channels_ProtocolId", + table: "Channels", + column: "ProtocolId", + principalTable: "Channels", + principalColumn: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_Users_Channels_ProtocolId", + table: "Users", + column: "ProtocolId", + principalTable: "Channels", + principalColumn: "Id"); + } + } +} diff --git a/Migrations/20230605162111_user aliases later.Designer.cs b/Migrations/20230605162111_user aliases later.Designer.cs new file mode 100644 index 0000000..5d2b85f --- /dev/null +++ b/Migrations/20230605162111_user aliases later.Designer.cs @@ -0,0 +1,254 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using vassago.Models; + +#nullable disable + +namespace vassago.Migrations +{ + [DbContext(typeof(ChattingContext))] + [Migration("20230605162111_user aliases later")] + partial class useraliaseslater + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("vassago.Models.Attachment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Content") + .HasColumnType("bytea"); + + b.Property("ContentType") + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("ExternalId") + .HasColumnType("numeric(20,0)"); + + b.Property("Filename") + .HasColumnType("text"); + + b.Property("MessageId") + .HasColumnType("uuid"); + + b.Property("Size") + .HasColumnType("integer"); + + b.Property("Source") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("MessageId"); + + b.ToTable("Attachments"); + }); + + modelBuilder.Entity("vassago.Models.Channel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DisplayName") + .HasColumnType("text"); + + b.Property("ExternalId") + .HasColumnType("numeric(20,0)"); + + b.Property("IsDM") + .HasColumnType("boolean"); + + b.Property("ParentChannelId") + .HasColumnType("uuid"); + + b.Property("PermissionsOverridesId") + .HasColumnType("integer"); + + b.Property("Protocol") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ParentChannelId"); + + b.HasIndex("PermissionsOverridesId"); + + b.ToTable("Channels"); + }); + + modelBuilder.Entity("vassago.Models.Message", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ActedOn") + .HasColumnType("boolean"); + + b.Property("AuthorId") + .HasColumnType("uuid"); + + b.Property("ChannelId") + .HasColumnType("uuid"); + + b.Property("Content") + .HasColumnType("text"); + + b.Property("ExternalId") + .HasColumnType("numeric(20,0)"); + + b.Property("MentionsMe") + .HasColumnType("boolean"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.HasIndex("ChannelId"); + + b.ToTable("Messages"); + }); + + modelBuilder.Entity("vassago.Models.PermissionSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("LewdnessFilterLevel") + .HasColumnType("integer"); + + b.Property("LinksAllowed") + .HasColumnType("boolean"); + + b.Property("MaxAttachmentBytes") + .HasColumnType("bigint"); + + b.Property("MaxTextChars") + .HasColumnType("bigint"); + + b.Property("MeannessFilterLevel") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("PermissionSettings"); + }); + + modelBuilder.Entity("vassago.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ExternalId") + .HasColumnType("numeric(20,0)"); + + b.Property("IsBot") + .HasColumnType("boolean"); + + b.Property("Protocol") + .HasColumnType("text"); + + b.Property("SeenInChannelId") + .HasColumnType("uuid"); + + b.Property("Username") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("SeenInChannelId"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("vassago.Models.Attachment", b => + { + b.HasOne("vassago.Models.Message", "Message") + .WithMany("Attachments") + .HasForeignKey("MessageId"); + + b.Navigation("Message"); + }); + + modelBuilder.Entity("vassago.Models.Channel", b => + { + b.HasOne("vassago.Models.Channel", "ParentChannel") + .WithMany("SubChannels") + .HasForeignKey("ParentChannelId"); + + b.HasOne("vassago.Models.PermissionSettings", "PermissionsOverrides") + .WithMany() + .HasForeignKey("PermissionsOverridesId"); + + b.Navigation("ParentChannel"); + + b.Navigation("PermissionsOverrides"); + }); + + modelBuilder.Entity("vassago.Models.Message", b => + { + b.HasOne("vassago.Models.User", "Author") + .WithMany() + .HasForeignKey("AuthorId"); + + b.HasOne("vassago.Models.Channel", "Channel") + .WithMany("Messages") + .HasForeignKey("ChannelId"); + + b.Navigation("Author"); + + b.Navigation("Channel"); + }); + + modelBuilder.Entity("vassago.Models.User", b => + { + b.HasOne("vassago.Models.Channel", "SeenInChannel") + .WithMany("OtherUsers") + .HasForeignKey("SeenInChannelId"); + + b.Navigation("SeenInChannel"); + }); + + modelBuilder.Entity("vassago.Models.Channel", b => + { + b.Navigation("Messages"); + + b.Navigation("OtherUsers"); + + b.Navigation("SubChannels"); + }); + + modelBuilder.Entity("vassago.Models.Message", b => + { + b.Navigation("Attachments"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Migrations/20230605162111_user aliases later.cs b/Migrations/20230605162111_user aliases later.cs new file mode 100644 index 0000000..8c2a7b1 --- /dev/null +++ b/Migrations/20230605162111_user aliases later.cs @@ -0,0 +1,49 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace vassago.Migrations +{ + /// + public partial class useraliaseslater : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Users_Users_UserId", + table: "Users"); + + migrationBuilder.DropIndex( + name: "IX_Users_UserId", + table: "Users"); + + migrationBuilder.DropColumn( + name: "UserId", + table: "Users"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "UserId", + table: "Users", + type: "uuid", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_Users_UserId", + table: "Users", + column: "UserId"); + + migrationBuilder.AddForeignKey( + name: "FK_Users_Users_UserId", + table: "Users", + column: "UserId", + principalTable: "Users", + principalColumn: "Id"); + } + } +} diff --git a/Migrations/ChattingContextModelSnapshot.cs b/Migrations/ChattingContextModelSnapshot.cs index a97dea4..00ec3bc 100644 --- a/Migrations/ChattingContextModelSnapshot.cs +++ b/Migrations/ChattingContextModelSnapshot.cs @@ -22,21 +22,6 @@ namespace vassago.Migrations NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - modelBuilder.Entity("ChannelUser", b => - { - b.Property("OtherUsersId") - .HasColumnType("uuid"); - - b.Property("SeenInChannelsId") - .HasColumnType("uuid"); - - b.HasKey("OtherUsersId", "SeenInChannelsId"); - - b.HasIndex("SeenInChannelsId"); - - b.ToTable("ChannelUser"); - }); - modelBuilder.Entity("vassago.Models.Attachment", b => { b.Property("Id") @@ -46,6 +31,12 @@ namespace vassago.Migrations b.Property("Content") .HasColumnType("bytea"); + b.Property("ContentType") + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + b.Property("ExternalId") .HasColumnType("numeric(20,0)"); @@ -55,6 +46,9 @@ namespace vassago.Migrations b.Property("MessageId") .HasColumnType("uuid"); + b.Property("Size") + .HasColumnType("integer"); + b.Property("Source") .HasColumnType("text"); @@ -71,10 +65,6 @@ namespace vassago.Migrations .ValueGeneratedOnAdd() .HasColumnType("uuid"); - b.Property("Discriminator") - .IsRequired() - .HasColumnType("text"); - b.Property("DisplayName") .HasColumnType("text"); @@ -90,8 +80,8 @@ namespace vassago.Migrations b.Property("PermissionsOverridesId") .HasColumnType("integer"); - b.Property("ProtocolId") - .HasColumnType("uuid"); + b.Property("Protocol") + .HasColumnType("text"); b.HasKey("Id"); @@ -99,13 +89,7 @@ namespace vassago.Migrations b.HasIndex("PermissionsOverridesId"); - b.HasIndex("ProtocolId"); - b.ToTable("Channels"); - - b.HasDiscriminator("Discriminator").HasValue("Channel"); - - b.UseTphMappingStrategy(); }); modelBuilder.Entity("vassago.Models.Message", b => @@ -129,9 +113,6 @@ namespace vassago.Migrations b.Property("ExternalId") .HasColumnType("numeric(20,0)"); - b.Property("ExternalRepresentation") - .HasColumnType("text"); - b.Property("MentionsMe") .HasColumnType("boolean"); @@ -181,58 +162,28 @@ namespace vassago.Migrations .ValueGeneratedOnAdd() .HasColumnType("uuid"); - b.Property("DisplayName") - .HasColumnType("text"); - - b.Property("External") - .HasColumnType("text"); - b.Property("ExternalId") .HasColumnType("numeric(20,0)"); b.Property("IsBot") .HasColumnType("boolean"); - b.Property("ProtocolId") + b.Property("Protocol") + .HasColumnType("text"); + + b.Property("SeenInChannelId") .HasColumnType("uuid"); - b.Property("UserId") - .HasColumnType("uuid"); + b.Property("Username") + .HasColumnType("text"); b.HasKey("Id"); - b.HasIndex("ProtocolId"); - - b.HasIndex("UserId"); + b.HasIndex("SeenInChannelId"); b.ToTable("Users"); }); - modelBuilder.Entity("vassago.Models.Protocol", b => - { - b.HasBaseType("vassago.Models.Channel"); - - b.Property("ConnectionToken") - .HasColumnType("text"); - - b.HasDiscriminator().HasValue("Protocol"); - }); - - modelBuilder.Entity("ChannelUser", b => - { - b.HasOne("vassago.Models.User", null) - .WithMany() - .HasForeignKey("OtherUsersId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("vassago.Models.Channel", null) - .WithMany() - .HasForeignKey("SeenInChannelsId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - modelBuilder.Entity("vassago.Models.Attachment", b => { b.HasOne("vassago.Models.Message", "Message") @@ -252,15 +203,9 @@ namespace vassago.Migrations .WithMany() .HasForeignKey("PermissionsOverridesId"); - b.HasOne("vassago.Models.Protocol", "Protocol") - .WithMany() - .HasForeignKey("ProtocolId"); - b.Navigation("ParentChannel"); b.Navigation("PermissionsOverrides"); - - b.Navigation("Protocol"); }); modelBuilder.Entity("vassago.Models.Message", b => @@ -280,15 +225,11 @@ namespace vassago.Migrations modelBuilder.Entity("vassago.Models.User", b => { - b.HasOne("vassago.Models.Protocol", "Protocol") + b.HasOne("vassago.Models.Channel", "SeenInChannel") .WithMany() - .HasForeignKey("ProtocolId"); + .HasForeignKey("SeenInChannelId"); - b.HasOne("vassago.Models.User", null) - .WithMany("KnownAliases") - .HasForeignKey("UserId"); - - b.Navigation("Protocol"); + b.Navigation("SeenInChannel"); }); modelBuilder.Entity("vassago.Models.Channel", b => @@ -302,11 +243,6 @@ namespace vassago.Migrations { b.Navigation("Attachments"); }); - - modelBuilder.Entity("vassago.Models.User", b => - { - b.Navigation("KnownAliases"); - }); #pragma warning restore 612, 618 } } diff --git a/Models/Attachment.cs b/Models/Attachment.cs index b6bae55..d7c3742 100644 --- a/Models/Attachment.cs +++ b/Models/Attachment.cs @@ -1,12 +1,18 @@ namespace vassago.Models; using System; +using System.ComponentModel.DataAnnotations.Schema; + public class Attachment { + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public Guid Id { get; set; } public ulong? ExternalId { get; set; } public Uri Source { get; set; } public byte[] Content { get; set; } public string Filename { get; set; } public Message Message { get; set; } + public string ContentType { get; internal set; } + public string Description { get; internal set; } + public int Size { get; internal set; } } \ No newline at end of file diff --git a/Models/Channel.cs b/Models/Channel.cs index 31027c6..9a2b31c 100644 --- a/Models/Channel.cs +++ b/Models/Channel.cs @@ -2,27 +2,27 @@ namespace vassago.Models; using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.Reflection; using System.Threading.Tasks; +using Discord; public class Channel { + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public Guid Id { get; set; } public ulong? ExternalId { get; set; } public string DisplayName { get; set; } public bool IsDM { get; set; } - public IEnumerable OtherUsers { get; set; } public PermissionSettings PermissionsOverrides { get; set; } - public IEnumerable SubChannels { get; set; } + public List SubChannels { get; set; } public Channel ParentChannel { get; set; } - public Protocol Protocol { get; set; } + public string Protocol { get; set; } public IEnumerable Messages { get; set; } - public virtual Task SendMessage(string text) - { - throw new NotImplementedException("derive from me"); - } - public virtual Task SendFile(string path, string messageText = null) - { - throw new NotImplementedException("derive from me"); - } -} + [NonSerialized] + public Func SendFile; + + [NonSerialized] + public Func SendMessage; +} \ No newline at end of file diff --git a/Models/ChattingContext.cs b/Models/ChattingContext.cs index 538f187..4b4d941 100644 --- a/Models/ChattingContext.cs +++ b/Models/ChattingContext.cs @@ -1,5 +1,6 @@ namespace vassago.Models; +using Microsoft.Extensions.Configuration; using Microsoft.EntityFrameworkCore; public class ChattingContext : DbContext @@ -9,9 +10,9 @@ public class ChattingContext : DbContext //public DbSet Emoji {get;set;} public DbSet Messages { get; set; } public DbSet PermissionSettings{get;set;} - public DbSet Protocols { get; set; } public DbSet Users { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - => optionsBuilder.UseNpgsql(Shared.DBConnectionString); + => optionsBuilder.UseNpgsql(Shared.DBConnectionString) + .EnableSensitiveDataLogging(true); //who the fuck is looking at log output but not allowed to see it? this should be on by default. } \ No newline at end of file diff --git a/Models/Message.cs b/Models/Message.cs index facb2f3..8b41ad2 100644 --- a/Models/Message.cs +++ b/Models/Message.cs @@ -2,29 +2,29 @@ namespace vassago.Models; using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.Reflection; using System.Threading.Tasks; using Discord.WebSocket; public class Message { + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public Guid Id { get; set; } public ulong? ExternalId { get; set; } public string Content { get; set; } public bool MentionsMe { get; set; } public DateTimeOffset Timestamp { get; set; } public bool ActedOn { get; set; } - ///however it came from the protocol. - public string ExternalRepresentation { get; set; } - public IEnumerable Attachments { get; set; } + public List Attachments { get; set; } public User Author { get; set; } public Channel Channel { get; set; } - public virtual Task Reply(string message) - { - throw new NotImplementedException("derive from me"); - } - public virtual Task React(string reaction) - { - throw new NotImplementedException("derive from me"); - } + + + [NonSerialized] + public Func Reply; + + [NonSerialized] + public Func React; } diff --git a/Models/PermissionSettings.cs b/Models/PermissionSettings.cs index f209cde..a2b1278 100644 --- a/Models/PermissionSettings.cs +++ b/Models/PermissionSettings.cs @@ -1,8 +1,11 @@ namespace vassago.Models; using System; +using System.ComponentModel.DataAnnotations.Schema; + public class PermissionSettings { + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int Id { get; set; } public uint? MaxAttachmentBytes { get; set; } public uint? MaxTextChars { get; set; } diff --git a/Models/Protocol.cs b/Models/Protocol.cs deleted file mode 100644 index a67ce10..0000000 --- a/Models/Protocol.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace vassago.Models; - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -public class Protocol : Channel -{ - //log in, log out, observe events? - - //doesn't actually have to be a token, but it should be how an interface can find itself in the DB - public string ConnectionToken { get; set; } -} diff --git a/Models/User.cs b/Models/User.cs index 45ff169..1dab81b 100644 --- a/Models/User.cs +++ b/Models/User.cs @@ -2,15 +2,27 @@ namespace vassago.Models; using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.Reflection; public class User //more like "user's account - no concept of the person outside of the protocol. (yet?) { + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public Guid Id { get; set; } public ulong? ExternalId { get; set; } - public string DisplayName { get; set; } + public string Username { get; set; } //TODO: display names. many protocols support this feature. public bool IsBot { get; set; } //webhook counts - public IEnumerable SeenInChannels { get; set; } - public IEnumerable KnownAliases { get; set; } - public Protocol Protocol { get; set; } - public string External { get; set; } + public Channel SeenInChannel { get; set; } + public string Protocol { get; set; } + + public User(){} + public User(User u) + { + Type t = typeof(User); + PropertyInfo[] properties = t.GetProperties(); + foreach (PropertyInfo pi in properties) + { + pi.SetValue(this, pi.GetValue(u, null), null); + } + } } \ No newline at end of file diff --git a/SlashCommandsHelper.cs b/SlashCommandsHelper.cs deleted file mode 100644 index 2efb419..0000000 --- a/SlashCommandsHelper.cs +++ /dev/null @@ -1,149 +0,0 @@ -namespace silverworker_discord -{ - using System; - using System.Linq; - using System.Collections.Generic; - using System.Threading.Tasks; - using Discord.WebSocket; - using Discord.Net; - using Discord; - using Newtonsoft.Json; - - public static class SlashCommandsHelper - { - private static List slashCommands = new List() - { - new CommandSetup(){ - Id = "freedomunits", - UpdatedAt = new DateTime(2023, 5, 21, 13, 3, 0), - guild = 825293851110801428, - register = register_FreedomUnits - } - }; - public static async Task Register(DiscordSocketClient client) - { - var commandsInContext = await client.GetGlobalApplicationCommandsAsync(); - await Register(client, commandsInContext, null); - foreach (var guild in client.Guilds) - { - try - { - await Register(client, await guild.GetApplicationCommandsAsync(), guild); - } - catch (Discord.Net.HttpException ex) - { - Console.Error.WriteLine($"error registering slash commands for guild {guild.Name} (id {guild.Id}) - {ex.Message}"); - } - } - } - - private static async Task Register(DiscordSocketClient client, IEnumerable commandsInContext, SocketGuild guild) - { - foreach (var existingCommand in commandsInContext) - { - var myVersion = slashCommands.FirstOrDefault(c => c.Id == existingCommand.Name && c.guild == guild?.Id); - if (myVersion == null) - { - Console.WriteLine($"deleting command {existingCommand.Name} - (created at {existingCommand.CreatedAt}, it's in guild {existingCommand.Guild?.Id} while I'm in {guild?.Id})"); - await existingCommand.DeleteAsync(); - Console.WriteLine("survived"); - } - else - { - Console.WriteLine(existingCommand.CreatedAt); - if (myVersion.UpdatedAt > existingCommand.CreatedAt) - { - Console.WriteLine($"overwriting command {existingCommand.Name}"); - await myVersion.register(false, client, guild); - Console.WriteLine($"survived"); - } - myVersion.alreadyRegistered = true; - } - } - foreach (var remaining in slashCommands.Where(sc => sc.alreadyRegistered == false && sc.guild == guild?.Id)) - { - Console.WriteLine($"creating new command {remaining.Id} ({(remaining.guild == null ? "global" : $"for guild {remaining.guild}")})"); - await remaining.register(true, client, guild); - Console.WriteLine($"survived"); - } - } - - private static async Task register_FreedomUnits(bool isNew, DiscordSocketClient client, SocketGuild guild) - { - var builtCommand = new SlashCommandBuilder() - .WithName("freedomunits") - .WithDescription("convert between misc units (currency: iso 4217 code)") - .AddOption("amount", ApplicationCommandOptionType.Number, "source amount", isRequired: true) - .AddOption(new SlashCommandOptionBuilder() - .WithName("src-unit") - .WithDescription("unit converting FROM") - .WithRequired(true) - .WithType(ApplicationCommandOptionType.String)) - .AddOption(new SlashCommandOptionBuilder() - .WithName("dest-unit") - .WithDescription("unit converting TO") - .WithRequired(true) - .WithType(ApplicationCommandOptionType.String)) - .Build(); - try - { - if (guild != null) - { - if (isNew) - await guild.CreateApplicationCommandAsync(builtCommand); - else - await guild.BulkOverwriteApplicationCommandAsync(new ApplicationCommandProperties[] { builtCommand }); - } - else - { - if (isNew) - await client.CreateGlobalApplicationCommandAsync(builtCommand); - else - await client.BulkOverwriteGlobalApplicationCommandsAsync(new ApplicationCommandProperties[] { builtCommand }); - } - } - catch (HttpException exception) - { - var json = JsonConvert.SerializeObject(exception.Errors, Formatting.Indented); - Console.Error.WriteLine(json); - } - } - public static async Task SlashCommandHandler(SocketSlashCommand command) - { - switch(command.CommandName) - { - case "freedomunits": - try - { - var amt = Convert.ToDecimal((double)(command.Data.Options.First(o => o.Name == "amount").Value)); - var src = (string)command.Data.Options.First(o => o.Name == "src-unit").Value; - var dest = (string)command.Data.Options.First(o => o.Name == "dest-unit").Value; - var conversionResult = Conversion.Converter.Convert(amt, src, dest); - - await command.RespondAsync($"> {amt} {src} -> {dest}\n{conversionResult}"); - } - catch(Exception e) - { - await command.RespondAsync($"error: {e.Message}. aaadam!"); - } - break; - default: - await command.RespondAsync($"\\*smiles and nods*\n"); - await command.Channel.SendFileAsync($"assets/loud sweating.gif"); - Console.Error.WriteLine($"can't understand command name: {command.CommandName}"); - break; - } - } - private class CommandSetup - { - public string Id { get; set; } - //the date/time you updated yours IN UTC. - public DateTimeOffset UpdatedAt { get; set; } - public Registration register { get; set; } - public ulong? guild { get; set; } - public bool alreadyRegistered {get;set; } = false; - - public delegate Task Registration(bool isNew, DiscordSocketClient client, SocketGuild guild); - } - } -} \ No newline at end of file