This commit is contained in:
Adam R Grey 2023-06-05 14:55:48 -04:00
parent 3031779e24
commit e4f7d88e35
24 changed files with 1005 additions and 783 deletions

View File

@ -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
}

View File

@ -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<string>(){

View File

@ -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<Channel>();
var sighting = u.SeenInChannels?.FirstOrDefault(c => c.ExternalId == arg.Guild.Id);
if(sighting == null)
{
var seenIn = u.SeenInChannels as List<Channel>;
seenIn.Add(guild);
seenIn.Add(defaultChannel);
u.SeenInChannels = seenIn;
_db.SaveChanges();
}
//TODO: seen in channels
// if (u.SeenInChannels == null) u.SeenInChannels = new List<Channel>();
// var sighting = u.SeenInChannels?.FirstOrDefault(c => c.ExternalId == arg.Guild.Id);
// if (sighting == null)
// {
// var seenIn = u.SeenInChannels as List<Channel>;
// 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<vassago.Models.Attachment>();
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<Message>();
//c.Messages = await channel.GetMessagesAsync(); //TODO: this, but only on startup or channel join
//c.OtherUsers = c.OtherUsers ?? new List<User>();
//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<Channel>();
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<Message>();
//c.Messages = await channel.GetMessagesAsync(); //TODO: this, but only on startup or channel join
//c.OtherUsers = c.OtherUsers ?? new List<User>();
//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<Channel>();
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;
}
}

View File

@ -1,4 +0,0 @@
namespace vassago.DiscordInterface.Models;
using vassago.Models;
public class DiscordAttachment : Attachment {}

View File

@ -1,18 +0,0 @@
namespace vassago.DiscordInterface.Models;
using System.Threading.Tasks;
using vassago.Models;
public class DiscordChannel : Channel
{
public override Task<Message> SendFile(string path, string messageText = null)
{
throw new System.NotImplementedException();
}
public override Task<Message> SendMessage(string text)
{
throw new System.NotImplementedException();
}
}

View File

@ -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;
}
}
}

View File

@ -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<Message> SendFile(string path, string messageText = null)
{
throw new System.InvalidOperationException("can't send a file to \"discord\", pick a channel");
}
public override Task<Message> SendMessage(string message)
{
throw new System.InvalidOperationException("can't send a message to \"discord\", pick a channel");
}
}

View File

@ -1,6 +0,0 @@
namespace vassago.DiscordInterface.Models;
using vassago.Models;
using Discord;
using Discord.WebSocket;
public class DiscordUser : User { }

View File

@ -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<string>{
"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<string>{
"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<string>{
"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<string>{
"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)]);
}
}
}

View File

@ -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
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
@ -49,6 +49,12 @@ namespace vassago.Migrations
b.Property<byte[]>("Content")
.HasColumnType("bytea");
b.Property<string>("ContentType")
.HasColumnType("text");
b.Property<string>("Description")
.HasColumnType("text");
b.Property<decimal?>("ExternalId")
.HasColumnType("numeric(20,0)");
@ -58,6 +64,9 @@ namespace vassago.Migrations
b.Property<Guid?>("MessageId")
.HasColumnType("uuid");
b.Property<int>("Size")
.HasColumnType("integer");
b.Property<string>("Source")
.HasColumnType("text");
@ -132,9 +141,6 @@ namespace vassago.Migrations
b.Property<decimal?>("ExternalId")
.HasColumnType("numeric(20,0)");
b.Property<string>("ExternalRepresentation")
.HasColumnType("text");
b.Property<bool>("MentionsMe")
.HasColumnType("boolean");
@ -184,12 +190,6 @@ namespace vassago.Migrations
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("DisplayName")
.HasColumnType("text");
b.Property<string>("External")
.HasColumnType("text");
b.Property<decimal?>("ExternalId")
.HasColumnType("numeric(20,0)");
@ -202,6 +202,9 @@ namespace vassago.Migrations
b.Property<Guid?>("UserId")
.HasColumnType("uuid");
b.Property<string>("Username")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("ProtocolId");

View File

@ -7,7 +7,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace vassago.Migrations
{
/// <inheritdoc />
public partial class initial : Migration
public partial class initialcreate : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
@ -69,10 +69,9 @@ namespace vassago.Migrations
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
ExternalId = table.Column<decimal>(type: "numeric(20,0)", nullable: true),
DisplayName = table.Column<string>(type: "text", nullable: true),
Username = table.Column<string>(type: "text", nullable: true),
IsBot = table.Column<bool>(type: "boolean", nullable: false),
ProtocolId = table.Column<Guid>(type: "uuid", nullable: true),
External = table.Column<string>(type: "text", nullable: true),
UserId = table.Column<Guid>(type: "uuid", nullable: true)
},
constraints: table =>
@ -124,7 +123,6 @@ namespace vassago.Migrations
MentionsMe = table.Column<bool>(type: "boolean", nullable: false),
Timestamp = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
ActedOn = table.Column<bool>(type: "boolean", nullable: false),
ExternalRepresentation = table.Column<string>(type: "text", nullable: true),
AuthorId = table.Column<Guid>(type: "uuid", nullable: true),
ChannelId = table.Column<Guid>(type: "uuid", nullable: true)
},
@ -152,7 +150,10 @@ namespace vassago.Migrations
Source = table.Column<string>(type: "text", nullable: true),
Content = table.Column<byte[]>(type: "bytea", nullable: true),
Filename = table.Column<string>(type: "text", nullable: true),
MessageId = table.Column<Guid>(type: "uuid", nullable: true)
MessageId = table.Column<Guid>(type: "uuid", nullable: true),
ContentType = table.Column<string>(type: "text", nullable: true),
Description = table.Column<string>(type: "text", nullable: true),
Size = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{

View File

@ -0,0 +1,268 @@
// <auto-generated />
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
{
/// <inheritdoc />
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<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<byte[]>("Content")
.HasColumnType("bytea");
b.Property<string>("ContentType")
.HasColumnType("text");
b.Property<string>("Description")
.HasColumnType("text");
b.Property<decimal?>("ExternalId")
.HasColumnType("numeric(20,0)");
b.Property<string>("Filename")
.HasColumnType("text");
b.Property<Guid?>("MessageId")
.HasColumnType("uuid");
b.Property<int>("Size")
.HasColumnType("integer");
b.Property<string>("Source")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("MessageId");
b.ToTable("Attachments");
});
modelBuilder.Entity("vassago.Models.Channel", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("DisplayName")
.HasColumnType("text");
b.Property<decimal?>("ExternalId")
.HasColumnType("numeric(20,0)");
b.Property<bool>("IsDM")
.HasColumnType("boolean");
b.Property<Guid?>("ParentChannelId")
.HasColumnType("uuid");
b.Property<int?>("PermissionsOverridesId")
.HasColumnType("integer");
b.Property<string>("Protocol")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("ParentChannelId");
b.HasIndex("PermissionsOverridesId");
b.ToTable("Channels");
});
modelBuilder.Entity("vassago.Models.Message", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<bool>("ActedOn")
.HasColumnType("boolean");
b.Property<Guid?>("AuthorId")
.HasColumnType("uuid");
b.Property<Guid?>("ChannelId")
.HasColumnType("uuid");
b.Property<string>("Content")
.HasColumnType("text");
b.Property<decimal?>("ExternalId")
.HasColumnType("numeric(20,0)");
b.Property<bool>("MentionsMe")
.HasColumnType("boolean");
b.Property<DateTimeOffset>("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<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int?>("LewdnessFilterLevel")
.HasColumnType("integer");
b.Property<bool?>("LinksAllowed")
.HasColumnType("boolean");
b.Property<long?>("MaxAttachmentBytes")
.HasColumnType("bigint");
b.Property<long?>("MaxTextChars")
.HasColumnType("bigint");
b.Property<int?>("MeannessFilterLevel")
.HasColumnType("integer");
b.HasKey("Id");
b.ToTable("PermissionSettings");
});
modelBuilder.Entity("vassago.Models.User", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<decimal?>("ExternalId")
.HasColumnType("numeric(20,0)");
b.Property<bool>("IsBot")
.HasColumnType("boolean");
b.Property<string>("Protocol")
.HasColumnType("text");
b.Property<Guid?>("SeenInChannelId")
.HasColumnType("uuid");
b.Property<Guid?>("UserId")
.HasColumnType("uuid");
b.Property<string>("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
}
}
}

View File

@ -0,0 +1,154 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace vassago.Migrations
{
/// <inheritdoc />
public partial class protocolasstring : Migration
{
/// <inheritdoc />
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<string>(
name: "Protocol",
table: "Users",
type: "text",
nullable: true);
migrationBuilder.AddForeignKey(
name: "FK_Users_Channels_SeenInChannelId",
table: "Users",
column: "SeenInChannelId",
principalTable: "Channels",
principalColumn: "Id");
}
/// <inheritdoc />
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<string>(
name: "Discriminator",
table: "Channels",
type: "text",
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<Guid>(
name: "ProtocolId",
table: "Channels",
type: "uuid",
nullable: true);
migrationBuilder.CreateTable(
name: "ChannelUser",
columns: table => new
{
OtherUsersId = table.Column<Guid>(type: "uuid", nullable: false),
SeenInChannelsId = table.Column<Guid>(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");
}
}
}

View File

@ -0,0 +1,254 @@
// <auto-generated />
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
{
/// <inheritdoc />
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<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<byte[]>("Content")
.HasColumnType("bytea");
b.Property<string>("ContentType")
.HasColumnType("text");
b.Property<string>("Description")
.HasColumnType("text");
b.Property<decimal?>("ExternalId")
.HasColumnType("numeric(20,0)");
b.Property<string>("Filename")
.HasColumnType("text");
b.Property<Guid?>("MessageId")
.HasColumnType("uuid");
b.Property<int>("Size")
.HasColumnType("integer");
b.Property<string>("Source")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("MessageId");
b.ToTable("Attachments");
});
modelBuilder.Entity("vassago.Models.Channel", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("DisplayName")
.HasColumnType("text");
b.Property<decimal?>("ExternalId")
.HasColumnType("numeric(20,0)");
b.Property<bool>("IsDM")
.HasColumnType("boolean");
b.Property<Guid?>("ParentChannelId")
.HasColumnType("uuid");
b.Property<int?>("PermissionsOverridesId")
.HasColumnType("integer");
b.Property<string>("Protocol")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("ParentChannelId");
b.HasIndex("PermissionsOverridesId");
b.ToTable("Channels");
});
modelBuilder.Entity("vassago.Models.Message", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<bool>("ActedOn")
.HasColumnType("boolean");
b.Property<Guid?>("AuthorId")
.HasColumnType("uuid");
b.Property<Guid?>("ChannelId")
.HasColumnType("uuid");
b.Property<string>("Content")
.HasColumnType("text");
b.Property<decimal?>("ExternalId")
.HasColumnType("numeric(20,0)");
b.Property<bool>("MentionsMe")
.HasColumnType("boolean");
b.Property<DateTimeOffset>("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<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int?>("LewdnessFilterLevel")
.HasColumnType("integer");
b.Property<bool?>("LinksAllowed")
.HasColumnType("boolean");
b.Property<long?>("MaxAttachmentBytes")
.HasColumnType("bigint");
b.Property<long?>("MaxTextChars")
.HasColumnType("bigint");
b.Property<int?>("MeannessFilterLevel")
.HasColumnType("integer");
b.HasKey("Id");
b.ToTable("PermissionSettings");
});
modelBuilder.Entity("vassago.Models.User", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<decimal?>("ExternalId")
.HasColumnType("numeric(20,0)");
b.Property<bool>("IsBot")
.HasColumnType("boolean");
b.Property<string>("Protocol")
.HasColumnType("text");
b.Property<Guid?>("SeenInChannelId")
.HasColumnType("uuid");
b.Property<string>("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
}
}
}

View File

@ -0,0 +1,49 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace vassago.Migrations
{
/// <inheritdoc />
public partial class useraliaseslater : Migration
{
/// <inheritdoc />
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");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<Guid>(
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");
}
}
}

View File

@ -22,21 +22,6 @@ namespace vassago.Migrations
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("ChannelUser", b =>
{
b.Property<Guid>("OtherUsersId")
.HasColumnType("uuid");
b.Property<Guid>("SeenInChannelsId")
.HasColumnType("uuid");
b.HasKey("OtherUsersId", "SeenInChannelsId");
b.HasIndex("SeenInChannelsId");
b.ToTable("ChannelUser");
});
modelBuilder.Entity("vassago.Models.Attachment", b =>
{
b.Property<Guid>("Id")
@ -46,6 +31,12 @@ namespace vassago.Migrations
b.Property<byte[]>("Content")
.HasColumnType("bytea");
b.Property<string>("ContentType")
.HasColumnType("text");
b.Property<string>("Description")
.HasColumnType("text");
b.Property<decimal?>("ExternalId")
.HasColumnType("numeric(20,0)");
@ -55,6 +46,9 @@ namespace vassago.Migrations
b.Property<Guid?>("MessageId")
.HasColumnType("uuid");
b.Property<int>("Size")
.HasColumnType("integer");
b.Property<string>("Source")
.HasColumnType("text");
@ -71,10 +65,6 @@ namespace vassago.Migrations
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Discriminator")
.IsRequired()
.HasColumnType("text");
b.Property<string>("DisplayName")
.HasColumnType("text");
@ -90,8 +80,8 @@ namespace vassago.Migrations
b.Property<int?>("PermissionsOverridesId")
.HasColumnType("integer");
b.Property<Guid?>("ProtocolId")
.HasColumnType("uuid");
b.Property<string>("Protocol")
.HasColumnType("text");
b.HasKey("Id");
@ -99,13 +89,7 @@ namespace vassago.Migrations
b.HasIndex("PermissionsOverridesId");
b.HasIndex("ProtocolId");
b.ToTable("Channels");
b.HasDiscriminator<string>("Discriminator").HasValue("Channel");
b.UseTphMappingStrategy();
});
modelBuilder.Entity("vassago.Models.Message", b =>
@ -129,9 +113,6 @@ namespace vassago.Migrations
b.Property<decimal?>("ExternalId")
.HasColumnType("numeric(20,0)");
b.Property<string>("ExternalRepresentation")
.HasColumnType("text");
b.Property<bool>("MentionsMe")
.HasColumnType("boolean");
@ -181,58 +162,28 @@ namespace vassago.Migrations
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("DisplayName")
.HasColumnType("text");
b.Property<string>("External")
.HasColumnType("text");
b.Property<decimal?>("ExternalId")
.HasColumnType("numeric(20,0)");
b.Property<bool>("IsBot")
.HasColumnType("boolean");
b.Property<Guid?>("ProtocolId")
b.Property<string>("Protocol")
.HasColumnType("text");
b.Property<Guid?>("SeenInChannelId")
.HasColumnType("uuid");
b.Property<Guid?>("UserId")
.HasColumnType("uuid");
b.Property<string>("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<string>("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
}
}

View File

@ -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; }
}

View File

@ -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<User> OtherUsers { get; set; }
public PermissionSettings PermissionsOverrides { get; set; }
public IEnumerable<Channel> SubChannels { get; set; }
public List<Channel> SubChannels { get; set; }
public Channel ParentChannel { get; set; }
public Protocol Protocol { get; set; }
public string Protocol { get; set; }
public IEnumerable<Message> Messages { get; set; }
public virtual Task<Message> SendMessage(string text)
{
throw new NotImplementedException("derive from me");
}
public virtual Task<Message> SendFile(string path, string messageText = null)
{
throw new NotImplementedException("derive from me");
}
}
[NonSerialized]
public Func<string, string, Task> SendFile;
[NonSerialized]
public Func<string, Task> SendMessage;
}

View File

@ -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> Emoji {get;set;}
public DbSet<Message> Messages { get; set; }
public DbSet<PermissionSettings> PermissionSettings{get;set;}
public DbSet<Protocol> Protocols { get; set; }
public DbSet<User> 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.
}

View File

@ -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<Attachment> Attachments { get; set; }
public List<Attachment> 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<string, Task> Reply;
[NonSerialized]
public Func<string, Task> React;
}

View File

@ -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; }

View File

@ -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; }
}

View File

@ -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<Channel> SeenInChannels { get; set; }
public IEnumerable<User> 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);
}
}
}

View File

@ -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<CommandSetup> slashCommands = new List<CommandSetup>()
{
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<SocketApplicationCommand> 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);
}
}
}