twitch summon and dismiss both exist

and with that: twitch, as a platform, exists.

must sort out permissions.
This commit is contained in:
Adam R Grey 2023-07-04 18:51:27 -04:00
parent 986d433886
commit 5bb64f764c
16 changed files with 432 additions and 10 deletions

View File

@ -24,5 +24,8 @@ public abstract class Behavior
public virtual string Description => Name; public virtual string Description => Name;
} }
///<summary>
///the behavior should be static. I.e., we make one at the start and it's ready to check and go for the whole lifetime.
///As opposed to LaughAtOwnJoke, which only needs to be created to wait for 1 punchline one time.
///</summary>
public class StaticPlzAttribute : Attribute {} public class StaticPlzAttribute : Attribute {}

30
Behavior/TwitchSummon.cs Normal file
View File

@ -0,0 +1,30 @@
namespace vassago.Behavior;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using vassago.Models;
[StaticPlz]
public class TwitchSummon : Behavior
{
public override string Name => "Twitch Summon";
public override string Trigger => "!twitchsummon";
//TODO: Permission!
public override async Task<bool> ActOn(Message message)
{
var ti = ProtocolInterfaces.ProtocolList.twitchs.FirstOrDefault();
if(ti != null)
{
var channelTarget = message.Content.Substring(message.Content.IndexOf(Trigger) + Trigger.Length + 1).Trim();
await message.Channel.SendMessage(ti.AttemptJoin(channelTarget));
}
else
{
await message.Reply("i don't have a twitch interface running :(");
}
return true;
}
}

View File

@ -0,0 +1,39 @@
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)
{
if(message.MentionsMe &&
(Regex.IsMatch(message.Content.ToLower(), "\\bbegone\\b") || Regex.IsMatch(message.Content.ToLower(), "\\bfuck off\\b")))
{
//TODO: PERMISSION!
return true;
}
return false;
}
public override async Task<bool> 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;
}
}

View File

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using Newtonsoft.Json; using Newtonsoft.Json;
using vassago.TwitchInterface;
namespace vassago namespace vassago
{ {

View File

@ -2,12 +2,11 @@ namespace vassago
{ {
using vassago; using vassago;
using vassago.Models; using vassago.Models;
using vassago.TwitchInterface;
internal class ConsoleService : IHostedService internal class ConsoleService : IHostedService
{ {
Configuration config = new Configuration(); Configuration config = new Configuration();
private List<DiscordInterface.DiscordInterface> discords = new List<DiscordInterface.DiscordInterface>();
private List<TwitchInterface.TwitchInterface> twitchs = new List<TwitchInterface.TwitchInterface>();
public ConsoleService(IConfiguration aspConfig) public ConsoleService(IConfiguration aspConfig)
{ {
@ -30,7 +29,7 @@ namespace vassago
{ {
var d = new DiscordInterface.DiscordInterface(); var d = new DiscordInterface.DiscordInterface();
await d.Init(dt); await d.Init(dt);
discords.Add(d); ProtocolInterfaces.ProtocolList.discords.Add(d);
} }
if (config.TwitchConfigs?.Any() ?? false) if (config.TwitchConfigs?.Any() ?? false)
@ -38,7 +37,7 @@ namespace vassago
{ {
var t = new TwitchInterface.TwitchInterface(); var t = new TwitchInterface.TwitchInterface();
await t.Init(tc); await t.Init(tc);
twitchs.Add(t); ProtocolInterfaces.ProtocolList.twitchs.Add(t);
} }
} }

View File

@ -0,0 +1,296 @@
// <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("20230704203907_permissionTagsOnUsers")]
partial class permissionTagsOnUsers
{
/// <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.Account", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("DisplayName")
.HasColumnType("text");
b.Property<string>("ExternalId")
.HasColumnType("text");
b.Property<bool>("IsBot")
.HasColumnType("boolean");
b.Property<Guid?>("IsUserId")
.HasColumnType("uuid");
b.Property<int[]>("PermissionTags")
.HasColumnType("integer[]");
b.Property<string>("Protocol")
.HasColumnType("text");
b.Property<Guid?>("SeenInChannelId")
.HasColumnType("uuid");
b.Property<string>("Username")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("IsUserId");
b.HasIndex("SeenInChannelId");
b.ToTable("Accounts");
});
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<string>("ExternalId")
.HasColumnType("text");
b.Property<bool>("IsDM")
.HasColumnType("boolean");
b.Property<Guid?>("ParentChannelId")
.HasColumnType("uuid");
b.Property<int?>("PermissionsId")
.HasColumnType("integer");
b.Property<string>("Protocol")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("ParentChannelId");
b.HasIndex("PermissionsId");
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<string>("ExternalId")
.HasColumnType("text");
b.Property<bool>("MentionsMe")
.HasColumnType("boolean");
b.Property<string>("Protocol")
.HasColumnType("text");
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<decimal?>("MaxAttachmentBytes")
.HasColumnType("numeric(20,0)");
b.Property<long?>("MaxTextChars")
.HasColumnType("bigint");
b.Property<int?>("MeannessFilterLevel")
.HasColumnType("integer");
b.Property<bool?>("ReactionsPossible")
.HasColumnType("boolean");
b.HasKey("Id");
b.ToTable("PermissionSettings");
});
modelBuilder.Entity("vassago.Models.User", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<int[]>("PermissionTags")
.HasColumnType("integer[]");
b.HasKey("Id");
b.ToTable("Users");
});
modelBuilder.Entity("vassago.Models.Account", b =>
{
b.HasOne("vassago.Models.User", "IsUser")
.WithMany("Accounts")
.HasForeignKey("IsUserId");
b.HasOne("vassago.Models.Channel", "SeenInChannel")
.WithMany("Users")
.HasForeignKey("SeenInChannelId");
b.Navigation("IsUser");
b.Navigation("SeenInChannel");
});
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", "Permissions")
.WithMany()
.HasForeignKey("PermissionsId");
b.Navigation("ParentChannel");
b.Navigation("Permissions");
});
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");
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
}
}
}

View File

@ -0,0 +1,28 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace vassago.Migrations
{
/// <inheritdoc />
public partial class permissionTagsOnUsers : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int[]>(
name: "PermissionTags",
table: "Users",
type: "integer[]",
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "PermissionTags",
table: "Users");
}
}
}

View File

@ -207,6 +207,9 @@ namespace vassago.Migrations
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasColumnType("uuid"); .HasColumnType("uuid");
b.Property<int[]>("PermissionTags")
.HasColumnType("integer[]");
b.HasKey("Id"); b.HasKey("Id");
b.ToTable("Users"); b.ToTable("Users");

View File

@ -4,6 +4,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks;
public class Account public class Account
{ {
@ -25,7 +26,7 @@ public class Account
} }
public bool IsBot { get; set; } //webhook counts public bool IsBot { get; set; } //webhook counts
public Channel SeenInChannel { get; set; } public Channel SeenInChannel { get; set; }
//permissions are per account-in-channel, and always propagate down. and since protocol will be a channel, I'll set the "is adam" permission on myself 1x/protocol. //permissions are per account-in-channel or per-user, and always propagate down. and since protocol will be a channel, I'll set the "is adam" permission on myself 1x/protocol.
public List<Enumerations.WellknownPermissions> PermissionTags{get;set;} public List<Enumerations.WellknownPermissions> PermissionTags{get;set;}
public string Protocol { get; set; } public string Protocol { get; set; }
public User IsUser {get; set;} public User IsUser {get; set;}

View File

@ -29,7 +29,7 @@ public static class Enumerations
public enum WellknownPermissions public enum WellknownPermissions
{ {
Master, //e.g., me. not that I think this would ever be released? Master, //e.g., me. not that I think this would ever be released?
ChannelModerator, TwitchSummon,
} }
public static string GetDescription<T>(this T enumerationValue) public static string GetDescription<T>(this T enumerationValue)

View File

@ -10,4 +10,6 @@ public class User
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; } public Guid Id { get; set; }
public List<Account> Accounts { get; set; } public List<Account> Accounts { get; set; }
//permissions are per account-in-channel or per-user, and always propagate down. and since protocol will be a channel, I'll set the "is adam" permission on myself 1x/protocol.
public List<Enumerations.WellknownPermissions> PermissionTags{get;set;}
} }

View File

@ -0,0 +1,7 @@
namespace vassago.ProtocolInterfaces;
public static class ProtocolList
{
public static List<DiscordInterface.DiscordInterface> discords = new List<DiscordInterface.DiscordInterface>();
public static List<TwitchInterface.TwitchInterface> twitchs = new List<TwitchInterface.TwitchInterface>();
}

View File

@ -1,3 +1,5 @@
namespace vassago.TwitchInterface;
public class TwitchConfig public class TwitchConfig
{ {
public string username {get; set;} public string username {get; set;}

View File

@ -1,3 +1,4 @@
using System.Security.Cryptography.X509Certificates;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using RestSharp; using RestSharp;
using TwitchLib.Api; using TwitchLib.Api;
@ -36,7 +37,7 @@ public class TwitchInterface
{ {
protocolAsChannel = new Channel() protocolAsChannel = new Channel()
{ {
DisplayName = "discord (itself)", DisplayName = "twitch (itself)",
Permissions = new PermissionSettings() Permissions = new PermissionSettings()
{ {
MeannessFilterLevel = Enumerations.MeannessFilterLevel.Medium, MeannessFilterLevel = Enumerations.MeannessFilterLevel.Medium,
@ -126,8 +127,6 @@ public class TwitchInterface
await _db.SaveChangesAsync(); await _db.SaveChangesAsync();
Behaver.Instance.Selves.Add(selfUser); Behaver.Instance.Selves.Add(selfUser);
client.JoinChannel("#homeburger");
client.JoinChannel("homeburger");
Console.WriteLine($"Connected to {e.AutoJoinChannel}"); Console.WriteLine($"Connected to {e.AutoJoinChannel}");
} }
@ -250,4 +249,16 @@ public class TwitchInterface
m.React = (e) => { throw new InvalidOperationException($"twitch cannot react"); }; m.React = (e) => { throw new InvalidOperationException($"twitch cannot react"); };
return m; return m;
} }
public string AttemptJoin(string channelTarget)
{
client.JoinChannel(channelTarget);
return "o7";
}
internal void AttemptLeave(string channelTarget)
{
client.SendMessage(channelTarget, "o7");
client.LeaveChannel(channelTarget);
}
} }