From 22ee1d256720e9dc9f24f4aa8f608b81035460cb Mon Sep 17 00:00:00 2001 From: adam Date: Fri, 23 May 2025 15:17:44 -0400 Subject: [PATCH] UAC descriptions see #40 --- Behaver.cs | 4 +- Behavior/TwitchSummon.cs | 48 ++- Behavior/TwitchUnsummon.cs | 46 --- Behavior/Webhook.cs | 17 +- .../20250523181842_channelAliases.Designer.cs | 386 ++++++++++++++++++ Migrations/20250523181842_channelAliases.cs | 45 ++ Migrations/ChattingContextModelSnapshot.cs | 8 + Models/Channel.cs | 15 +- appsettings.json | 8 +- 9 files changed, 515 insertions(+), 62 deletions(-) delete mode 100644 Behavior/TwitchUnsummon.cs create mode 100644 Migrations/20250523181842_channelAliases.Designer.cs create mode 100644 Migrations/20250523181842_channelAliases.cs diff --git a/Behaver.cs b/Behaver.cs index 6cb6d23..10b2da0 100644 --- a/Behaver.cs +++ b/Behaver.cs @@ -1,7 +1,7 @@ namespace vassago; -#pragma warning disable 4014 +#pragma warning disable 4014 //the "not awaited" error using gray_messages.chat; -using franz;//the "not awaited" error +using franz; using vassago.Behavior; using vassago.Models; using System; diff --git a/Behavior/TwitchSummon.cs b/Behavior/TwitchSummon.cs index ea5a0da..3e9521b 100644 --- a/Behavior/TwitchSummon.cs +++ b/Behavior/TwitchSummon.cs @@ -17,14 +17,16 @@ public class TwitchSummon : Behavior public TwitchSummon() { myUAC = Rememberer.SearchUAC(uac => uac.OwnerId == uacID); - if(myUAC == null) + if (myUAC == null) { myUAC = new() { OwnerId = uacID, - DisplayName = Name + DisplayName = Name, + Description = @"matching this means you can summon the bot to any twitch channel" }; } + Rememberer.RememberUAC(myUAC); } public override bool ShouldAct(Message message) { @@ -44,7 +46,7 @@ public class TwitchSummon : Behavior public override async Task ActOn(Message message) { var ti = ProtocolInterfaces.ProtocolList.twitchs.FirstOrDefault(); - if(ti != null) + if (ti != null) { var channelTarget = message.Content.Substring(message.Content.IndexOf(Trigger) + Trigger.Length + 1).Trim(); await message.Channel.SendMessage(ti.AttemptJoin(channelTarget)); @@ -55,4 +57,44 @@ public class TwitchSummon : Behavior } return true; } + [StaticPlz] + public class TwitchDismiss : Behavior + { + public override string Name => "Twitch Dismiss"; + + public override string Trigger => "begone, @[me]"; + + public override bool ShouldAct(Message message) + { + var ti = ProtocolInterfaces.ProtocolList.twitchs.FirstOrDefault(); + // Console.WriteLine($"TwitchDismiss checking. menions me? {message.MentionsMe}"); + if (message.MentionsMe && + (Regex.IsMatch(message.Content.ToLower(), "\\bbegone\\b") || Regex.IsMatch(message.Content.ToLower(), "\\bfuck off\\b"))) + { + var channelTarget = message.Content.Substring(message.Content.IndexOf(Trigger) + Trigger.Length + 1).Trim(); + ti.AttemptLeave(channelTarget); + //TODO: PERMISSION! who can dismiss me? pretty simple list: + //1) anyone in the channel with authority* + //2) whoever summoned me + //* i don't know if the twitch *chat* interface will tell me if someone's a mod. + return true; + } + return false; + } + + public override async Task ActOn(Message message) + { + var ti = ProtocolInterfaces.ProtocolList.twitchs.FirstOrDefault(); + + if (ti != null) + { + ti.AttemptLeave(message.Channel.DisplayName); + } + else + { + await message.Reply("i don't have a twitch interface running :("); + } + return true; + } + } } diff --git a/Behavior/TwitchUnsummon.cs b/Behavior/TwitchUnsummon.cs deleted file mode 100644 index d6e336b..0000000 --- a/Behavior/TwitchUnsummon.cs +++ /dev/null @@ -1,46 +0,0 @@ -namespace vassago.Behavior; - -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using vassago.Models; - -[StaticPlz] -public class TwitchDismiss : Behavior -{ - public override string Name => "Twitch Dismiss"; - - public override string Trigger => "begone, @[me]"; - - public override bool ShouldAct(Message message) - { - var ti = ProtocolInterfaces.ProtocolList.twitchs.FirstOrDefault(); - // Console.WriteLine($"TwitchDismiss checking. menions me? {message.MentionsMe}"); - if(message.MentionsMe && - (Regex.IsMatch(message.Content.ToLower(), "\\bbegone\\b") || Regex.IsMatch(message.Content.ToLower(), "\\bfuck off\\b"))) - { - var channelTarget = message.Content.Substring(message.Content.IndexOf(Trigger) + Trigger.Length + 1).Trim(); - ti.AttemptLeave(channelTarget); - //TODO: PERMISSION! who can dismiss me? pretty simple list: - //1) anyone in the channel with authority* - //2) whoever summoned me - //* i don't know if the twitch *chat* interface will tell me if someone's a mod. - return true; - } - return false; - } - - public override async Task ActOn(Message message) - { - var ti = ProtocolInterfaces.ProtocolList.twitchs.FirstOrDefault(); - - if(ti != null) - { - ti.AttemptLeave(message.Channel.DisplayName); - } - else - { - await message.Reply("i don't have a twitch interface running :("); - } - return true; - } -} diff --git a/Behavior/Webhook.cs b/Behavior/Webhook.cs index 575f121..e91dc08 100644 --- a/Behavior/Webhook.cs +++ b/Behavior/Webhook.cs @@ -36,14 +36,17 @@ public class Webhook : Behavior { Console.WriteLine($"{kvp[0]}: {kvp[1]}"); } + var changed = false; var myUAC = Rememberer.SearchUAC(uac => uac.OwnerId == conf.uacID); if (myUAC == null) { myUAC = new() { OwnerId = conf.uacID, - DisplayName = confName + DisplayName = confName, + Description = conf.Description }; + changed = true; Rememberer.RememberUAC(myUAC); } else @@ -51,9 +54,16 @@ public class Webhook : Behavior if (myUAC.DisplayName != confName) { myUAC.DisplayName = confName; - Rememberer.RememberUAC(myUAC); + changed = true; + } + if (myUAC.Description != conf.Description) + { + myUAC.Description = conf.Description; + changed = true; } } + if (changed) + Rememberer.RememberUAC(myUAC); } } @@ -160,7 +170,7 @@ public class Webhook : Behavior } private string translate(WebhookActionOrder actionOrder, Message message) { - if(string.IsNullOrWhiteSpace(actionOrder.Conf.Content)) + if (string.IsNullOrWhiteSpace(actionOrder.Conf.Content)) return ""; var msgContent = actionOrder.Conf.Content.Replace("{text}", actionOrder.webhookContent); msgContent = msgContent.Replace("{msgid}", message.Id.ToString()); @@ -179,6 +189,7 @@ public class WebhookConf public Enumerations.HttpVerb Method { get; set; } public List> Headers { get; set; } public string Content { get; set; } + public string Description { get; set; } } public class WebhookActionOrder { diff --git a/Migrations/20250523181842_channelAliases.Designer.cs b/Migrations/20250523181842_channelAliases.Designer.cs new file mode 100644 index 0000000..dcb88fc --- /dev/null +++ b/Migrations/20250523181842_channelAliases.Designer.cs @@ -0,0 +1,386 @@ +// +using System; +using System.Collections.Generic; +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("20250523181842_channelAliases")] + partial class channelAliases + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "hstore"); + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("AccountUAC", b => + { + b.Property("AccountInChannelsId") + .HasColumnType("uuid"); + + b.Property("UACsId") + .HasColumnType("uuid"); + + b.HasKey("AccountInChannelsId", "UACsId"); + + b.HasIndex("UACsId"); + + b.ToTable("AccountUAC"); + }); + + modelBuilder.Entity("ChannelUAC", b => + { + b.Property("ChannelsId") + .HasColumnType("uuid"); + + b.Property("UACsId") + .HasColumnType("uuid"); + + b.HasKey("ChannelsId", "UACsId"); + + b.HasIndex("UACsId"); + + b.ToTable("ChannelUAC"); + }); + + modelBuilder.Entity("UACUser", b => + { + b.Property("UACsId") + .HasColumnType("uuid"); + + b.Property("UsersId") + .HasColumnType("uuid"); + + b.HasKey("UACsId", "UsersId"); + + b.HasIndex("UsersId"); + + b.ToTable("UACUser"); + }); + + modelBuilder.Entity("vassago.Models.Account", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DisplayName") + .HasColumnType("text"); + + b.Property("ExternalId") + .HasColumnType("text"); + + b.Property("IsBot") + .HasColumnType("boolean"); + + b.Property("IsUserId") + .HasColumnType("uuid"); + + b.Property("Protocol") + .HasColumnType("text"); + + b.Property("SeenInChannelId") + .HasColumnType("uuid"); + + b.Property("Username") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("IsUserId"); + + b.HasIndex("SeenInChannelId"); + + b.ToTable("Accounts"); + }); + + 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>("Aliases") + .HasColumnType("hstore"); + + b.Property("ChannelType") + .HasColumnType("integer"); + + b.Property("DisplayName") + .HasColumnType("text"); + + b.Property("ExternalId") + .HasColumnType("text"); + + b.Property("LewdnessFilterLevel") + .HasColumnType("integer"); + + b.Property("LinksAllowed") + .HasColumnType("boolean"); + + b.Property("MaxAttachmentBytes") + .HasColumnType("numeric(20,0)"); + + b.Property("MaxTextChars") + .HasColumnType("bigint"); + + b.Property("MeannessFilterLevel") + .HasColumnType("integer"); + + b.Property("ParentChannelId") + .HasColumnType("uuid"); + + b.Property("Protocol") + .HasColumnType("text"); + + b.Property("ReactionsPossible") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("ParentChannelId"); + + 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("text"); + + b.Property("MentionsMe") + .HasColumnType("boolean"); + + b.Property("Protocol") + .HasColumnType("text"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.HasIndex("ChannelId"); + + b.ToTable("Messages"); + }); + + modelBuilder.Entity("vassago.Models.UAC", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("DisplayName") + .HasColumnType("text"); + + b.Property("OwnerId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("UACs"); + }); + + modelBuilder.Entity("vassago.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("AccountUAC", b => + { + b.HasOne("vassago.Models.Account", null) + .WithMany() + .HasForeignKey("AccountInChannelsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("vassago.Models.UAC", null) + .WithMany() + .HasForeignKey("UACsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ChannelUAC", b => + { + b.HasOne("vassago.Models.Channel", null) + .WithMany() + .HasForeignKey("ChannelsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("vassago.Models.UAC", null) + .WithMany() + .HasForeignKey("UACsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("UACUser", b => + { + b.HasOne("vassago.Models.UAC", null) + .WithMany() + .HasForeignKey("UACsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("vassago.Models.User", null) + .WithMany() + .HasForeignKey("UsersId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("vassago.Models.Account", b => + { + b.HasOne("vassago.Models.User", "IsUser") + .WithMany("Accounts") + .HasForeignKey("IsUserId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("vassago.Models.Channel", "SeenInChannel") + .WithMany("Users") + .HasForeignKey("SeenInChannelId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("IsUser"); + + b.Navigation("SeenInChannel"); + }); + + modelBuilder.Entity("vassago.Models.Attachment", b => + { + b.HasOne("vassago.Models.Message", "Message") + .WithMany("Attachments") + .HasForeignKey("MessageId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("Message"); + }); + + modelBuilder.Entity("vassago.Models.Channel", b => + { + b.HasOne("vassago.Models.Channel", "ParentChannel") + .WithMany("SubChannels") + .HasForeignKey("ParentChannelId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("ParentChannel"); + }); + + modelBuilder.Entity("vassago.Models.Message", b => + { + b.HasOne("vassago.Models.Account", "Author") + .WithMany() + .HasForeignKey("AuthorId"); + + b.HasOne("vassago.Models.Channel", "Channel") + .WithMany("Messages") + .HasForeignKey("ChannelId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("Author"); + + b.Navigation("Channel"); + }); + + modelBuilder.Entity("vassago.Models.Channel", b => + { + b.Navigation("Messages"); + + b.Navigation("SubChannels"); + + b.Navigation("Users"); + }); + + modelBuilder.Entity("vassago.Models.Message", b => + { + b.Navigation("Attachments"); + }); + + modelBuilder.Entity("vassago.Models.User", b => + { + b.Navigation("Accounts"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Migrations/20250523181842_channelAliases.cs b/Migrations/20250523181842_channelAliases.cs new file mode 100644 index 0000000..5bb25e7 --- /dev/null +++ b/Migrations/20250523181842_channelAliases.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace vassago.Migrations +{ + /// + public partial class channelAliases : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterDatabase() + .Annotation("Npgsql:PostgresExtension:hstore", ",,"); + + migrationBuilder.AddColumn( + name: "Description", + table: "UACs", + type: "text", + nullable: true); + + migrationBuilder.AddColumn>( + name: "Aliases", + table: "Channels", + type: "hstore", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Description", + table: "UACs"); + + migrationBuilder.DropColumn( + name: "Aliases", + table: "Channels"); + + migrationBuilder.AlterDatabase() + .OldAnnotation("Npgsql:PostgresExtension:hstore", ",,"); + } + } +} diff --git a/Migrations/ChattingContextModelSnapshot.cs b/Migrations/ChattingContextModelSnapshot.cs index 15593f0..505991b 100644 --- a/Migrations/ChattingContextModelSnapshot.cs +++ b/Migrations/ChattingContextModelSnapshot.cs @@ -1,5 +1,6 @@ // using System; +using System.Collections.Generic; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; @@ -20,6 +21,7 @@ namespace vassago.Migrations .HasAnnotation("ProductVersion", "7.0.5") .HasAnnotation("Relational:MaxIdentifierLength", 63); + NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "hstore"); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); modelBuilder.Entity("AccountUAC", b => @@ -146,6 +148,9 @@ namespace vassago.Migrations .ValueGeneratedOnAdd() .HasColumnType("uuid"); + b.Property>("Aliases") + .HasColumnType("hstore"); + b.Property("ChannelType") .HasColumnType("integer"); @@ -231,6 +236,9 @@ namespace vassago.Migrations .ValueGeneratedOnAdd() .HasColumnType("uuid"); + b.Property("Description") + .HasColumnType("text"); + b.Property("DisplayName") .HasColumnType("text"); diff --git a/Models/Channel.cs b/Models/Channel.cs index d51f7dc..de9bbdc 100644 --- a/Models/Channel.cs +++ b/Models/Channel.cs @@ -25,7 +25,7 @@ public class Channel public List Messages { get; set; } [DeleteBehavior(DeleteBehavior.Cascade)] public List Users { get; set; } - public ChannelType ChannelType {get; set; } + public ChannelType ChannelType { get; set; } //Permissions public ulong? MaxAttachmentBytes { get; set; } @@ -34,8 +34,9 @@ public class Channel public bool? ReactionsPossible { get; set; } public Enumerations.LewdnessFilterLevel? LewdnessFilterLevel { get; set; } public Enumerations.MeannessFilterLevel? MeannessFilterLevel { get; set; } - public List UACs { get; set; } + //both incoming and outgoing + //public Dictionary Aliases { get; set; } [NonSerialized] public Func SendFile; @@ -51,14 +52,14 @@ public class Channel var path = new Stack(); //omg i actually get to use a data structure from university var walker = this; path.Push(this); - while(walker.ParentChannel != null) + while (walker.ParentChannel != null) { walker = walker.ParentChannel; path.Push(walker); } DefinitePermissionSettings toReturn = new DefinitePermissionSettings(); - - while(path.Count > 0) + + while (path.Count > 0) { walker = path.Pop(); toReturn.LewdnessFilterLevel = walker.LewdnessFilterLevel ?? toReturn.LewdnessFilterLevel; @@ -76,7 +77,7 @@ public class Channel { get { - if(this.ParentChannel != null) + if (this.ParentChannel != null) { return this.ParentChannel.LineageSummary + '/' + this.DisplayName; } @@ -94,7 +95,7 @@ public class Channel { var toReturn = this.MemberwiseClone() as Channel; toReturn.ParentChannel = null; - if(toReturn.Users?.Count > 0) + if (toReturn.Users?.Count > 0) { foreach (var account in toReturn.Users) { diff --git a/appsettings.json b/appsettings.json index 35fb96e..de251d1 100644 --- a/appsettings.json +++ b/appsettings.json @@ -19,7 +19,13 @@ { "uacID": "9a94855a-e5a2-43b5-8420-ce670472ce95", "Trigger": "test", - "Uri": "http://localhost" + "Description": "test", + "Uri": "http://localhost", + "Method": "POST", + "Headers": [ + ["Content-Type", "application/json"] + ], + "Content": "{\"content\": \"Hello, this is a message from my webhook: {text}. username: {account}, user: {user}\"}" } ], "KafkaBootstrap":"http://localhost:9092",