forked from adam/discord-bot-shtik
This commit is contained in:
parent
9f7493c5e5
commit
544dc95db1
@ -21,46 +21,13 @@ public class Webhook : Behavior
|
|||||||
|
|
||||||
public override string Description => "call a webhook";
|
public override string Description => "call a webhook";
|
||||||
|
|
||||||
private static List<WebhookConf> configuredWebhooks = new List<WebhookConf>();
|
private static List<vassago.Models.Webhook> configuredWebhooks = new List<vassago.Models.Webhook>();
|
||||||
private ConcurrentDictionary<Guid, WebhookActionOrder> authedCache = new ConcurrentDictionary<Guid, WebhookActionOrder>();
|
private ConcurrentDictionary<Guid, WebhookActionOrder> authedCache = new ConcurrentDictionary<Guid, WebhookActionOrder>();
|
||||||
private HttpClient hc = new HttpClient();
|
private HttpClient hc = new HttpClient();
|
||||||
|
|
||||||
public static void SetupWebhooks(IEnumerable<string> confSection)
|
public static void SetupWebhooks()
|
||||||
{
|
{
|
||||||
//configuredWebhooks = confSection.Get<List<vassago.Behavior.WebhookConf>>();
|
configuredWebhooks = rememberer.Webhooks();
|
||||||
if (confSection != null) foreach (var confLine in confSection)
|
|
||||||
{
|
|
||||||
var conf = JsonConvert.DeserializeObject<WebhookConf>(confLine);
|
|
||||||
var confName = $"Webhook: {conf.Trigger}";
|
|
||||||
var changed = false;
|
|
||||||
var myUAC = rememberer.SearchUAC(uac => uac.OwnerId == conf.uacID);
|
|
||||||
if (myUAC == null)
|
|
||||||
{
|
|
||||||
myUAC = new()
|
|
||||||
{
|
|
||||||
OwnerId = conf.uacID,
|
|
||||||
DisplayName = confName,
|
|
||||||
Description = conf.Description
|
|
||||||
};
|
|
||||||
changed = true;
|
|
||||||
rememberer.RememberUAC(myUAC);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (myUAC.DisplayName != confName)
|
|
||||||
{
|
|
||||||
myUAC.DisplayName = confName;
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
if (myUAC.Description != conf.Description)
|
|
||||||
{
|
|
||||||
myUAC.Description = conf.Description;
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (changed)
|
|
||||||
rememberer.RememberUAC(myUAC);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool ShouldAct(Message message, List<UAC> matchedUACs)
|
public override bool ShouldAct(Message message, List<UAC> matchedUACs)
|
||||||
@ -70,9 +37,11 @@ public class Webhook : Behavior
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Console.WriteLine($"{configuredWebhooks.Count()} configured webhooks.");
|
||||||
foreach (var wh in configuredWebhooks)
|
foreach (var wh in configuredWebhooks)
|
||||||
{
|
{
|
||||||
var triggerTarget = wh.Trigger;
|
var triggerTarget = wh.Trigger;
|
||||||
|
Console.WriteLine(triggerTarget);
|
||||||
foreach (var uacMatch in matchedUACs)
|
foreach (var uacMatch in matchedUACs)
|
||||||
{
|
{
|
||||||
foreach (var substitution in uacMatch.CommandAlterations)
|
foreach (var substitution in uacMatch.CommandAlterations)
|
||||||
@ -80,12 +49,12 @@ public class Webhook : Behavior
|
|||||||
triggerTarget = new Regex(substitution.Key).Replace(triggerTarget, substitution.Value);
|
triggerTarget = new Regex(substitution.Key).Replace(triggerTarget, substitution.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Regex.IsMatch(message.TranslatedContent, $"\\b{triggerTarget}\\b", RegexOptions.IgnoreCase))
|
Console.WriteLine($"translated, {triggerTarget}");
|
||||||
|
if (Regex.IsMatch(message.TranslatedContent, $"{triggerTarget}\\b", RegexOptions.IgnoreCase))
|
||||||
{
|
{
|
||||||
var webhookableMessageContent = message.Content.Substring(message.Content.IndexOf(triggerTarget) + triggerTarget.Length + 1);
|
var webhookableMessageContent = message.Content.Substring(message.Content.IndexOf(triggerTarget) + triggerTarget.Length + 1);
|
||||||
Console.WriteLine($"webhookable content: {webhookableMessageContent}");
|
Console.WriteLine($"webhookable content: {webhookableMessageContent}");
|
||||||
var uacConf = rememberer.SearchUAC(uac => uac.OwnerId == wh.uacID);
|
if (wh.Uac.Users.Contains(message.Author.IsUser) || wh.Uac.Channels.Contains(message.Channel) || wh.Uac.AccountInChannels.Contains(message.Author))
|
||||||
if (uacConf.Users.Contains(message.Author.IsUser) || uacConf.Channels.Contains(message.Channel) || uacConf.AccountInChannels.Contains(message.Author))
|
|
||||||
{
|
{
|
||||||
Console.WriteLine("webhook UAC passed, preparing WebhookActionOrder");
|
Console.WriteLine("webhook UAC passed, preparing WebhookActionOrder");
|
||||||
authedCache.TryAdd(message.Id, new WebhookActionOrder()
|
authedCache.TryAdd(message.Id, new WebhookActionOrder()
|
||||||
@ -97,6 +66,10 @@ public class Webhook : Behavior
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{message.TranslatedContent} didn't match {triggerTarget}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -109,27 +82,40 @@ public class Webhook : Behavior
|
|||||||
Console.Error.WriteLine($"{message.Id} was supposed to act, but authedCache doesn't have it! it has {authedCache?.Count()} other stuff, though.");
|
Console.Error.WriteLine($"{message.Id} was supposed to act, but authedCache doesn't have it! it has {authedCache?.Count()} other stuff, though.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine("acquired actionorder");
|
||||||
|
}
|
||||||
var msg = translate(actionOrder, message);
|
var msg = translate(actionOrder, message);
|
||||||
var req = new HttpRequestMessage(new HttpMethod(actionOrder.Conf.Method.ToString()), actionOrder.Conf.Uri);
|
var req = new HttpRequestMessage(new HttpMethod(actionOrder.Conf.Method.ToString()), actionOrder.Conf.Uri);
|
||||||
var theContentHeader = actionOrder.Conf.Headers?.FirstOrDefault(h => h?.ToLower().StartsWith("content-type:") ?? false);
|
var theContentHeader = actionOrder.Conf.Headers?.FirstOrDefault(h => h?.ToLower().StartsWith("content-type:") ?? false);
|
||||||
var contentHeaderVal = theContentHeader?.Split(':')?[1]?.ToLower();
|
Console.WriteLine($"found content header: {theContentHeader}");
|
||||||
|
var contentHeaderVal = theContentHeader?.Split(':')?[1]?.ToLower().Trim();
|
||||||
|
Console.WriteLine($"contentHeaderrVal: {contentHeaderVal}");
|
||||||
if (contentHeaderVal != null)
|
if (contentHeaderVal != null)
|
||||||
{
|
{
|
||||||
switch (contentHeaderVal)
|
if(contentHeaderVal =="multipart/form-data")
|
||||||
{
|
{
|
||||||
//json content is constructed some other weird way.
|
Console.WriteLine($"wish my errors weren't vanishing. 2");
|
||||||
case "multipart/form-data":
|
req.Content = new System.Net.Http.MultipartFormDataContent(msg);
|
||||||
req.Content = new System.Net.Http.MultipartFormDataContent(msg);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
req.Content = new System.Net.Http.StringContent(msg);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
req.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(contentHeaderVal);
|
Console.WriteLine($"wish my errors weren't vanishing. 3");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
req.Content = new System.Net.Http.StringContent(msg);
|
||||||
|
req.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(contentHeaderVal);
|
||||||
|
}
|
||||||
|
catch (Exception e){
|
||||||
|
Console.Error.WriteLine("sorry I have to swallow this exception because something else is somewhere and I have no idea where.");
|
||||||
|
Console.Error.WriteLine(JsonConvert.SerializeObject(e));
|
||||||
|
}
|
||||||
|
Console.WriteLine($"wish my errors weren't vanishing. 4");
|
||||||
}
|
}
|
||||||
if (req.Content == null)
|
if(req.Content == null)
|
||||||
{
|
{
|
||||||
|
Console.WriteLine($"wish my errors weren't vanishing. 5");
|
||||||
req.Content = new System.Net.Http.StringContent(msg);
|
req.Content = new System.Net.Http.StringContent(msg);
|
||||||
|
Console.WriteLine($"wish my errors weren't vanishing. 6");
|
||||||
}
|
}
|
||||||
Console.WriteLine($"survived translating string content. request content: {req.Content}");
|
Console.WriteLine($"survived translating string content. request content: {req.Content}");
|
||||||
if (actionOrder.Conf.Headers?.ToList().Count > 0)
|
if (actionOrder.Conf.Headers?.ToList().Count > 0)
|
||||||
@ -143,7 +129,7 @@ public class Webhook : Behavior
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.WriteLine($"adding header; {header}");
|
Console.WriteLine($"adding header; {header}");
|
||||||
req.Headers.Add(header.Split(':')[0], header.Split(':')[1]);
|
req.Headers.Add(header.Split(':')[0], header.Split(':')[0]);
|
||||||
Console.WriteLine("survived.");
|
Console.WriteLine("survived.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -153,7 +139,7 @@ public class Webhook : Behavior
|
|||||||
Console.WriteLine("no headers to add.");
|
Console.WriteLine("no headers to add.");
|
||||||
}
|
}
|
||||||
Console.WriteLine("about to Send.");
|
Console.WriteLine("about to Send.");
|
||||||
var response = hc.Send(req);
|
var response = await hc.SendAsync(req);
|
||||||
Console.WriteLine($"{response.StatusCode} - {response.ReasonPhrase}");
|
Console.WriteLine($"{response.StatusCode} - {response.ReasonPhrase}");
|
||||||
if (!response.IsSuccessStatusCode)
|
if (!response.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
@ -179,19 +165,8 @@ public class Webhook : Behavior
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class WebhookConf
|
|
||||||
{
|
|
||||||
public Guid uacID { get; set; }
|
|
||||||
public string Trigger { get; set; }
|
|
||||||
public Uri Uri { get; set; }
|
|
||||||
//public HttpMethod Method { get; set; }
|
|
||||||
public Enumerations.HttpVerb Method { get; set; }
|
|
||||||
public List<string> Headers { get; set; }
|
|
||||||
public string Content { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
}
|
|
||||||
public class WebhookActionOrder
|
public class WebhookActionOrder
|
||||||
{
|
{
|
||||||
public WebhookConf Conf { get; set; }
|
public vassago.Models.Webhook Conf { get; set; }
|
||||||
public string webhookContent { get; set; }
|
public string webhookContent { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -73,6 +73,7 @@ namespace vassago
|
|||||||
}
|
}
|
||||||
Conversion.Converter.Load(confEntity.ExchangePairsLocation);
|
Conversion.Converter.Load(confEntity.ExchangePairsLocation);
|
||||||
Telefranz.Configure(confEntity.KafkaName, confEntity.KafkaBootstrap);
|
Telefranz.Configure(confEntity.KafkaName, confEntity.KafkaBootstrap);
|
||||||
|
vassago.Behavior.Webhook.SetupWebhooks();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
467
Migrations/20250709204232_WebhookObjects.Designer.cs
generated
Normal file
467
Migrations/20250709204232_WebhookObjects.Designer.cs
generated
Normal file
@ -0,0 +1,467 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
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("20250709204232_WebhookObjects")]
|
||||||
|
partial class WebhookObjects
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
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<Guid>("AccountInChannelsId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<Guid>("UACsId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.HasKey("AccountInChannelsId", "UACsId");
|
||||||
|
|
||||||
|
b.HasIndex("UACsId");
|
||||||
|
|
||||||
|
b.ToTable("AccountUAC");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("ChannelUAC", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("ChannelsId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<Guid>("UACsId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.HasKey("ChannelsId", "UACsId");
|
||||||
|
|
||||||
|
b.HasIndex("UACsId");
|
||||||
|
|
||||||
|
b.ToTable("ChannelUAC");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("UACUser", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("UACsId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<Guid>("UsersId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.HasKey("UACsId", "UsersId");
|
||||||
|
|
||||||
|
b.HasIndex("UsersId");
|
||||||
|
|
||||||
|
b.ToTable("UACUser");
|
||||||
|
});
|
||||||
|
|
||||||
|
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<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<int>("ChannelType")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<string>("DisplayName")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("ExternalId")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
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<Guid?>("ParentChannelId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Protocol")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<bool?>("ReactionsPossible")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ParentChannelId");
|
||||||
|
|
||||||
|
b.ToTable("Channels");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("vassago.Models.Configuration", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<List<string>>("DiscordTokens")
|
||||||
|
.HasColumnType("text[]");
|
||||||
|
|
||||||
|
b.Property<string>("ExchangePairsLocation")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("KafkaBootstrap")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("KafkaName")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<bool>("SetupDiscordSlashCommands")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<List<string>>("TwitchConfigs")
|
||||||
|
.HasColumnType("text[]");
|
||||||
|
|
||||||
|
b.Property<string>("reportedApiUrl")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Configurations");
|
||||||
|
});
|
||||||
|
|
||||||
|
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.Property<string>("TranslatedContent")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("AuthorId");
|
||||||
|
|
||||||
|
b.HasIndex("ChannelId");
|
||||||
|
|
||||||
|
b.ToTable("Messages");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("vassago.Models.UAC", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<Dictionary<string, string>>("CommandAlterations")
|
||||||
|
.HasColumnType("hstore");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("DisplayName")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<Guid>("OwnerId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<Dictionary<string, string>>("Translations")
|
||||||
|
.HasColumnType("hstore");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("UACs");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("vassago.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Users");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("vassago.Models.Webhook", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<List<string>>("Headers")
|
||||||
|
.HasColumnType("text[]");
|
||||||
|
|
||||||
|
b.Property<int>("Method")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<string>("Trigger")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<Guid?>("UacId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Uri")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UacId");
|
||||||
|
|
||||||
|
b.ToTable("Webhooks");
|
||||||
|
});
|
||||||
|
|
||||||
|
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.Webhook", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("vassago.Models.UAC", "Uac")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UacId");
|
||||||
|
|
||||||
|
b.Navigation("Uac");
|
||||||
|
});
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
51
Migrations/20250709204232_WebhookObjects.cs
Normal file
51
Migrations/20250709204232_WebhookObjects.cs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace vassago.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class WebhookObjects : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Webhooks",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
UacId = table.Column<Guid>(type: "uuid", nullable: true),
|
||||||
|
Trigger = table.Column<string>(type: "text", nullable: true),
|
||||||
|
Uri = table.Column<string>(type: "text", nullable: true),
|
||||||
|
Method = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
Headers = table.Column<List<string>>(type: "text[]", nullable: true),
|
||||||
|
Content = table.Column<string>(type: "text", nullable: true),
|
||||||
|
Description = table.Column<string>(type: "text", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Webhooks", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Webhooks_UACs_UacId",
|
||||||
|
column: x => x.UacId,
|
||||||
|
principalTable: "UACs",
|
||||||
|
principalColumn: "Id");
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Webhooks_UacId",
|
||||||
|
table: "Webhooks",
|
||||||
|
column: "UacId");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Webhooks");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -299,6 +299,40 @@ namespace vassago.Migrations
|
|||||||
b.ToTable("Users");
|
b.ToTable("Users");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("vassago.Models.Webhook", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<List<string>>("Headers")
|
||||||
|
.HasColumnType("text[]");
|
||||||
|
|
||||||
|
b.Property<int>("Method")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<string>("Trigger")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<Guid?>("UacId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Uri")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UacId");
|
||||||
|
|
||||||
|
b.ToTable("Webhooks");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("AccountUAC", b =>
|
modelBuilder.Entity("AccountUAC", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("vassago.Models.Account", null)
|
b.HasOne("vassago.Models.Account", null)
|
||||||
@ -397,6 +431,15 @@ namespace vassago.Migrations
|
|||||||
b.Navigation("Channel");
|
b.Navigation("Channel");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("vassago.Models.Webhook", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("vassago.Models.UAC", "Uac")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UacId");
|
||||||
|
|
||||||
|
b.Navigation("Uac");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("vassago.Models.Channel", b =>
|
modelBuilder.Entity("vassago.Models.Channel", b =>
|
||||||
{
|
{
|
||||||
b.Navigation("Messages");
|
b.Navigation("Messages");
|
||||||
|
@ -12,12 +12,13 @@ public class ChattingContext : DbContext
|
|||||||
public DbSet<Account> Accounts { get; set; }
|
public DbSet<Account> Accounts { get; set; }
|
||||||
public DbSet<User> Users { get; set; }
|
public DbSet<User> Users { get; set; }
|
||||||
public DbSet<Configuration> Configurations {get; set;}
|
public DbSet<Configuration> Configurations {get; set;}
|
||||||
|
public DbSet<Webhook> Webhooks {get; set;}
|
||||||
|
|
||||||
public ChattingContext(DbContextOptions<ChattingContext> options) : base(options) { }
|
public ChattingContext(DbContextOptions<ChattingContext> options) : base(options) { }
|
||||||
public ChattingContext() : base() { }
|
public ChattingContext() : base() { }
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||||
{
|
{
|
||||||
optionsBuilder.UseNpgsql(Shared.DBConnectionString);
|
optionsBuilder.UseNpgsql(Shared.DBConnectionString);
|
||||||
//.EnableSensitiveDataLogging(true); //"sensitive" is one thing. writing "did something" every time you think a thought is a different thing.
|
//.EnableSensitiveDataLogging(true); //"sensitive" is one thing. writing "did something" every time you think a thought is a different, stupid thing.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ public class Webhook
|
|||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
public Guid Id { get; set; }
|
public Guid Id { get; set; }
|
||||||
public UAC Uac {get;set;}
|
public UAC Uac {get;set;}
|
||||||
public string Trigger { get; set; }
|
public string Trigger { get; set; }
|
||||||
public Uri Uri { get; set; }
|
public Uri Uri { get; set; }
|
||||||
public Enumerations.HttpVerb Method { get; set; }
|
public Enumerations.HttpVerb Method { get; set; }
|
||||||
public List<string> Headers { get; set; }
|
public List<string> Headers { get; set; }
|
||||||
|
@ -262,7 +262,7 @@ public class Rememberer
|
|||||||
if (channelCacheDirty)
|
if (channelCacheDirty)
|
||||||
Task.Run(() => cacheChannels()).Wait();
|
Task.Run(() => cacheChannels()).Wait();
|
||||||
var ch = channels.Find(c => c.Id == Id);
|
var ch = channels.Find(c => c.Id == Id);
|
||||||
if(accounts)
|
if (accounts)
|
||||||
ch.Users = SearchAccounts(a => a.SeenInChannel == ch);
|
ch.Users = SearchAccounts(a => a.SeenInChannel == ch);
|
||||||
if (messages)
|
if (messages)
|
||||||
ch.Messages = SearchMessages(m => m.ChannelId == ch.Id);
|
ch.Messages = SearchMessages(m => m.ChannelId == ch.Id);
|
||||||
@ -361,4 +361,41 @@ public class Rememberer
|
|||||||
db.SaveChanges();
|
db.SaveChanges();
|
||||||
dbAccessSemaphore.Release();
|
dbAccessSemaphore.Release();
|
||||||
}
|
}
|
||||||
|
public Webhook Webhook(Guid id)
|
||||||
|
{
|
||||||
|
Webhook toReturn;
|
||||||
|
dbAccessSemaphore.Wait();
|
||||||
|
toReturn = db.Webhooks.Include(wh => wh.Uac).FirstOrDefault(wh => wh.Id == id);
|
||||||
|
dbAccessSemaphore.Release();
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
public List<Webhook> Webhooks()
|
||||||
|
{
|
||||||
|
List<Webhook> toReturn;
|
||||||
|
dbAccessSemaphore.Wait();
|
||||||
|
toReturn = db.Webhooks.Include(wh => wh.Uac).ToList();
|
||||||
|
dbAccessSemaphore.Release();
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
public void RememberWebhook(Webhook wh)
|
||||||
|
{
|
||||||
|
dbAccessSemaphore.Wait();
|
||||||
|
db.Update(wh);
|
||||||
|
db.SaveChanges();
|
||||||
|
dbAccessSemaphore.Release();
|
||||||
|
}
|
||||||
|
public void ForgetWebhook(Guid id)
|
||||||
|
{
|
||||||
|
dbAccessSemaphore.Wait();
|
||||||
|
db.Remove(db.Webhooks.Find(id));
|
||||||
|
db.SaveChanges();
|
||||||
|
dbAccessSemaphore.Release();
|
||||||
|
}
|
||||||
|
public void ForgetWebhook(Webhook wh)
|
||||||
|
{
|
||||||
|
dbAccessSemaphore.Wait();
|
||||||
|
db.Remove(wh);
|
||||||
|
db.SaveChanges();
|
||||||
|
dbAccessSemaphore.Release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,20 +23,40 @@ public class HomeController : Controller
|
|||||||
{
|
{
|
||||||
var allAccounts = r.AccountsOverview();
|
var allAccounts = r.AccountsOverview();
|
||||||
var allChannels = r.ChannelsOverview();
|
var allChannels = r.ChannelsOverview();
|
||||||
|
var allWebhooks = r.Webhooks();
|
||||||
Console.WriteLine($"accounts: {allAccounts?.Count ?? 0}, channels: {allChannels?.Count ?? 0}");
|
Console.WriteLine($"accounts: {allAccounts?.Count ?? 0}, channels: {allChannels?.Count ?? 0}");
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
sb.Append('[');
|
sb.Append('[');
|
||||||
|
|
||||||
sb.Append($"{{\"text\": \"<a href=\\\"{Url.ActionLink(action: "Index", controller: "Configuration")}\\\">Configuration</a>\"}},");
|
sb.Append($"{{\"text\": \"<a href=\\\"{Url.ActionLink(action: "Index", controller: "Configuration")}\\\">Configuration</a>\"}},");
|
||||||
|
|
||||||
|
var first = true;
|
||||||
|
//webhooks
|
||||||
|
sb.Append("{text: \"Webhooks\", expanded:true, nodes:[");
|
||||||
|
if(allWebhooks.Any())
|
||||||
|
{
|
||||||
|
foreach(var wh in allWebhooks)
|
||||||
|
{
|
||||||
|
var displayedName = wh.Trigger;
|
||||||
|
if (string.IsNullOrWhiteSpace(displayedName))
|
||||||
|
{
|
||||||
|
displayedName = $"[unnamed - {wh.Id}]";
|
||||||
|
}
|
||||||
|
sb.Append($"{{\"text\": \"<a href=\\\"{Url.ActionLink(action: "Details", controller: "Webhooks", values: new { id = wh.Id })}\\\">{displayedName}</a>\"}},");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.Append($"{{\"text\": \"<a href=\\\"{Url.ActionLink(action: "New", controller: "Webhooks")}\\\">add new</a>\"}}");
|
||||||
|
|
||||||
|
sb.Append("]},");
|
||||||
|
|
||||||
//UACs
|
//UACs
|
||||||
var allUACs = r.UACsOverview();
|
var allUACs = r.UACsOverview();
|
||||||
var first = true;
|
first = true;
|
||||||
if(allUACs.Any())
|
if (allUACs.Any())
|
||||||
{
|
{
|
||||||
sb.Append("{text: \"uacs\", expanded:true, nodes: [");
|
sb.Append("{text: \"uacs\", expanded:true, nodes: [");
|
||||||
first=true;
|
first = true;
|
||||||
foreach(var uac in allUACs)
|
foreach (var uac in allUACs)
|
||||||
{
|
{
|
||||||
if (first)
|
if (first)
|
||||||
{
|
{
|
||||||
@ -47,11 +67,11 @@ public class HomeController : Controller
|
|||||||
sb.Append(',');
|
sb.Append(',');
|
||||||
}
|
}
|
||||||
var displayedName = uac.DisplayName;
|
var displayedName = uac.DisplayName;
|
||||||
if(string.IsNullOrWhiteSpace(displayedName))
|
if (string.IsNullOrWhiteSpace(displayedName))
|
||||||
{
|
{
|
||||||
displayedName = $"[unnamed - {uac.Id}]";
|
displayedName = $"[unnamed - {uac.Id}]";
|
||||||
}
|
}
|
||||||
sb.Append($"{{\"text\": \"<a href=\\\"{Url.ActionLink(action: "Details", controller: "UACs", values: new {id = uac.Id})}\\\">{displayedName}</a>\"}}");
|
sb.Append($"{{\"text\": \"<a href=\\\"{Url.ActionLink(action: "Details", controller: "UACs", values: new { id = uac.Id })}\\\">{displayedName}</a>\"}}");
|
||||||
}
|
}
|
||||||
sb.Append("]}");
|
sb.Append("]}");
|
||||||
}
|
}
|
||||||
@ -62,13 +82,13 @@ public class HomeController : Controller
|
|||||||
|
|
||||||
//users
|
//users
|
||||||
var users = r.UsersOverview();
|
var users = r.UsersOverview();
|
||||||
if(users.Any())
|
if (users.Any())
|
||||||
{
|
{
|
||||||
sb.Append(",{text: \"users\", expanded:true, nodes: [");
|
sb.Append(",{text: \"users\", expanded:true, nodes: [");
|
||||||
first=true;
|
first = true;
|
||||||
//refresh list; we'll be knocking them out again in serializeUser
|
//refresh list; we'll be knocking them out again in serializeUser
|
||||||
allAccounts = r.AccountsOverview();
|
allAccounts = r.AccountsOverview();
|
||||||
foreach(var user in users)
|
foreach (var user in users)
|
||||||
{
|
{
|
||||||
if (first)
|
if (first)
|
||||||
{
|
{
|
||||||
@ -151,7 +171,7 @@ public class HomeController : Controller
|
|||||||
{
|
{
|
||||||
allChannels.Remove(currentChannel);
|
allChannels.Remove(currentChannel);
|
||||||
//"but adam", you say, "there's an href attribute, why make a link?" because that makes the entire bar a link, and trying to expand the node will probably click the link
|
//"but adam", you say, "there's an href attribute, why make a link?" because that makes the entire bar a link, and trying to expand the node will probably click the link
|
||||||
sb.Append($"{{\"text\": \"<a href=\\\"{Url.ActionLink(action: "Details", controller: "Channels", values: new {id = currentChannel.Id})}\\\">{currentChannel.DisplayName}</a>\"");
|
sb.Append($"{{\"text\": \"<a href=\\\"{Url.ActionLink(action: "Details", controller: "Channels", values: new { id = currentChannel.Id })}\\\">{currentChannel.DisplayName}</a>\"");
|
||||||
sb.Append(", expanded:true ");
|
sb.Append(", expanded:true ");
|
||||||
var theseAccounts = allAccounts.Where(a => a.SeenInChannel?.Id == currentChannel.Id).ToList();
|
var theseAccounts = allAccounts.Where(a => a.SeenInChannel?.Id == currentChannel.Id).ToList();
|
||||||
allAccounts.RemoveAll(a => a.SeenInChannel?.Id == currentChannel.Id);
|
allAccounts.RemoveAll(a => a.SeenInChannel?.Id == currentChannel.Id);
|
||||||
@ -159,54 +179,54 @@ public class HomeController : Controller
|
|||||||
if (currentChannel.SubChannels != null || theseAccounts != null)
|
if (currentChannel.SubChannels != null || theseAccounts != null)
|
||||||
{
|
{
|
||||||
sb.Append(", \"nodes\": [");
|
sb.Append(", \"nodes\": [");
|
||||||
if (currentChannel.SubChannels != null)
|
if (currentChannel.SubChannels != null)
|
||||||
{
|
|
||||||
foreach (var subChannel in currentChannel.SubChannels)
|
|
||||||
{
|
{
|
||||||
if (first)
|
foreach (var subChannel in currentChannel.SubChannels)
|
||||||
{
|
{
|
||||||
first = false;
|
if (first)
|
||||||
|
{
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.Append(',');
|
||||||
|
}
|
||||||
|
serializeChannel(ref sb, ref allChannels, ref allAccounts, subChannel);
|
||||||
}
|
}
|
||||||
else
|
if (theseAccounts != null && !first) //"first" here tells us that we have at least one subchannel
|
||||||
{
|
{
|
||||||
sb.Append(',');
|
sb.Append(',');
|
||||||
}
|
}
|
||||||
serializeChannel(ref sb, ref allChannels, ref allAccounts, subChannel);
|
|
||||||
}
|
}
|
||||||
if (theseAccounts != null && !first) //"first" here tells us that we have at least one subchannel
|
if (theseAccounts != null)
|
||||||
{
|
{
|
||||||
sb.Append(',');
|
first = true;
|
||||||
}
|
sb.Append($"{{\"text\": \"(accounts: {theseAccounts.Count()})\", \"expanded\":true, nodes:[");
|
||||||
}
|
foreach (var account in theseAccounts)
|
||||||
if (theseAccounts != null)
|
|
||||||
{
|
|
||||||
first = true;
|
|
||||||
sb.Append($"{{\"text\": \"(accounts: {theseAccounts.Count()})\", \"expanded\":true, nodes:[");
|
|
||||||
foreach (var account in theseAccounts)
|
|
||||||
{
|
|
||||||
if (first)
|
|
||||||
{
|
{
|
||||||
first = false;
|
if (first)
|
||||||
|
{
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.Append(',');
|
||||||
|
}
|
||||||
|
serializeAccount(ref sb, account);
|
||||||
}
|
}
|
||||||
else
|
sb.Append("]}");
|
||||||
{
|
|
||||||
sb.Append(',');
|
|
||||||
}
|
|
||||||
serializeAccount(ref sb, account);
|
|
||||||
}
|
}
|
||||||
sb.Append("]}");
|
|
||||||
}
|
|
||||||
sb.Append(']');
|
sb.Append(']');
|
||||||
}
|
}
|
||||||
sb.Append('}');
|
sb.Append('}');
|
||||||
}
|
}
|
||||||
private void serializeAccount(ref StringBuilder sb, Account currentAccount)
|
private void serializeAccount(ref StringBuilder sb, Account currentAccount)
|
||||||
{
|
{
|
||||||
sb.Append($"{{\"text\": \"<a href=\\\"{Url.ActionLink(action: "Details", controller: "Accounts", values: new {id = currentAccount.Id})}\\\">{currentAccount.DisplayName}</a>\"}}");
|
sb.Append($"{{\"text\": \"<a href=\\\"{Url.ActionLink(action: "Details", controller: "Accounts", values: new { id = currentAccount.Id })}\\\">{currentAccount.DisplayName}</a>\"}}");
|
||||||
}
|
}
|
||||||
private void serializeUser(ref StringBuilder sb, ref List<Account> allAccounts, User currentUser)
|
private void serializeUser(ref StringBuilder sb, ref List<Account> allAccounts, User currentUser)
|
||||||
{
|
{
|
||||||
sb.Append($"{{\"text\": \"<a href=\\\"{Url.ActionLink(action: "Details", controller: "Users", values: new {id = currentUser.Id})}\\\">");
|
sb.Append($"{{\"text\": \"<a href=\\\"{Url.ActionLink(action: "Details", controller: "Users", values: new { id = currentUser.Id })}\\\">");
|
||||||
sb.Append(currentUser.DisplayName);
|
sb.Append(currentUser.DisplayName);
|
||||||
sb.Append("</a>\", ");
|
sb.Append("</a>\", ");
|
||||||
var ownedAccounts = allAccounts.Where(a => a.IsUser == currentUser);
|
var ownedAccounts = allAccounts.Where(a => a.IsUser == currentUser);
|
||||||
@ -217,7 +237,7 @@ public class HomeController : Controller
|
|||||||
var first = true;
|
var first = true;
|
||||||
foreach (var acc in ownedAccounts)
|
foreach (var acc in ownedAccounts)
|
||||||
{
|
{
|
||||||
if(!first)
|
if (!first)
|
||||||
sb.Append(',');
|
sb.Append(',');
|
||||||
serializeAccount(ref sb, acc);
|
serializeAccount(ref sb, acc);
|
||||||
first = false;
|
first = false;
|
||||||
|
74
WebInterface/Controllers/WebhooksController.cs
Normal file
74
WebInterface/Controllers/WebhooksController.cs
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using vassago.Models;
|
||||||
|
using vassago.WebInterface.Models;
|
||||||
|
|
||||||
|
namespace vassago.WebInterface.Controllers;
|
||||||
|
|
||||||
|
public class WebhooksController() : Controller
|
||||||
|
{
|
||||||
|
Rememberer r = Rememberer.Instance;
|
||||||
|
|
||||||
|
public async Task<IActionResult> Details(Guid id)
|
||||||
|
{
|
||||||
|
var webhook = r.Webhook(id);
|
||||||
|
// Console.WriteLine(JsonConvert.SerializeObject(webhook));
|
||||||
|
return webhook != null ?
|
||||||
|
View(webhook) :
|
||||||
|
Problem($"webhook {id} is null.");
|
||||||
|
}
|
||||||
|
|
||||||
|
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||||
|
public IActionResult Error()
|
||||||
|
{
|
||||||
|
return View(new ErrorPageViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
|
||||||
|
}
|
||||||
|
[HttpPost]
|
||||||
|
public IActionResult Submit(Webhook incoming)
|
||||||
|
{
|
||||||
|
var wh = r.Webhook(incoming.Id) ?? new Webhook();
|
||||||
|
wh.Trigger = incoming.Trigger;
|
||||||
|
wh.Uri = incoming.Uri;
|
||||||
|
wh.Method = incoming.Method;
|
||||||
|
wh.Headers = incoming.Headers;
|
||||||
|
wh.Content = incoming.Content;
|
||||||
|
wh.Description = incoming.Description;
|
||||||
|
wh.Uac.DisplayName = "webhook: " + wh.Trigger;
|
||||||
|
r.RememberWebhook(wh);
|
||||||
|
return RedirectToAction("Details", "Webhooks", new {Id = wh.Id});
|
||||||
|
}
|
||||||
|
public IActionResult Delete(Guid id)
|
||||||
|
{
|
||||||
|
r.ForgetWebhook(id);
|
||||||
|
return RedirectToAction("Home", "Index");
|
||||||
|
}
|
||||||
|
public IActionResult New()
|
||||||
|
{
|
||||||
|
var wh = new Webhook();
|
||||||
|
wh.Uac = new UAC();
|
||||||
|
wh.Content = "this webhook needs to be set up";
|
||||||
|
wh.Description = "new webhook";
|
||||||
|
r.RememberWebhook(wh);
|
||||||
|
|
||||||
|
return RedirectToAction("Details", "Webhooks", new {Id = wh.Id});
|
||||||
|
}
|
||||||
|
[HttpPost]
|
||||||
|
public IActionResult RemoveHeader(Guid Id, int index)
|
||||||
|
{
|
||||||
|
var wh = r.Webhook(Id);
|
||||||
|
wh.Headers.RemoveAt(index);
|
||||||
|
r.RememberWebhook(wh);
|
||||||
|
return RedirectToAction("Details", "Webhooks", new {Id = wh.Id});
|
||||||
|
}
|
||||||
|
[HttpPost]
|
||||||
|
public IActionResult AddHeader(Guid id)
|
||||||
|
{
|
||||||
|
var wh = r.Webhook(id);
|
||||||
|
wh.Headers ??= [];
|
||||||
|
wh.Headers.Add(":");
|
||||||
|
r.RememberWebhook(wh);
|
||||||
|
return RedirectToAction("Details", "Webhooks", new {Id = wh.Id});
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
<a href="/">home</a>/configuration
|
<a href="/">home</a>/configuration
|
||||||
<form action="@Url.Action("submit", "Configuration")" method="post" id="theForm">
|
<form action="@Url.Action("submit", "Configuration")" method="post" id="theForm">
|
||||||
|
<input type="hidden" name="Id" value="@Model.Id" />
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -37,14 +37,16 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Translations (@Model.Translations?.Count)</th>
|
<th scope="row">Translations (@Model.Translations?.Count)</th>
|
||||||
<td>
|
<td>
|
||||||
next would be iterating over a dictionary. All reference on the internet implies this should work. I'm sick of trying to figure out why it doesn't. razor says to me, so i say to you: go fuck yourself; edit the db manually.
|
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<tbody>
|
<tbody>
|
||||||
@Html.Raw("<tr>");
|
@for(var i = 0; i < (Model.Translations?.Count() ?? 0); i++)
|
||||||
@Html.Raw("<td><input type=\"text\" name=\"Model.Translations[{i}].Key\" value=\"{Model.Translations.ElementAt(i).Key}\" /></td>");
|
{
|
||||||
@Html.Raw("<td><input type=\"text\" name=\"Model.Translations[{i}].Value\" value=\"{Model.Translations.ElementAt(i).Value}\" /></td>");
|
<tr>
|
||||||
@Html.Raw("<td><button type=\"button\" class=\"btn btn-danger\" onclick=\"removeTranslation()\">delete</button></td>");
|
<td><input type="text" name="Model.Translations[@i].Key" value="@Model.Translations.ElementAt(i).Key" /></td>
|
||||||
@Html.Raw("</tr>");
|
<td><input type="text" name="Model.Translations[@i].Value" value="@Model.Translations.ElementAt(i).Value" /></td>
|
||||||
|
<td><button type="button" class="btn btn-danger" onclick="removeTranslation(@i)">delete</button></td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="3">
|
<td colspan="3">
|
||||||
<button type="button" class="btn btn-primary" onclick="addUAC_Translation()">add translation</button>
|
<button type="button" class="btn btn-primary" onclick="addUAC_Translation()">add translation</button>
|
||||||
|
100
WebInterface/Views/Webhooks/Details.cshtml
Normal file
100
WebInterface/Views/Webhooks/Details.cshtml
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
@model vassago.Models.Webhook
|
||||||
|
@using Newtonsoft.Json;
|
||||||
|
@using vassago.Behavior;
|
||||||
|
@using vassago.Models;
|
||||||
|
@using vassago.TwitchInterface;
|
||||||
|
@using System.Text;
|
||||||
|
|
||||||
|
<a href="/">home</a>/Webhooks/@Model.Id
|
||||||
|
<form action="@Url.Action("Submit", "Webhooks")" method="post" id="theForm">
|
||||||
|
<input type="hidden" name="Id" value="@Model.Id" />
|
||||||
|
<table class="table">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Trigger</th>
|
||||||
|
<td><input type="text" value="@Model.Trigger" name="Trigger" /></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Uri</th>
|
||||||
|
<td><input type="text" value="@Model.Uri" name="Uri" /></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Content</th>
|
||||||
|
<td><input type="text" value="@Model.Content" name="Content" /></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th rowspan="@(2 + Model.Headers?.Count())">Headers</th>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
@for(var i = 0; i < Model.Headers?.Count(); i++)
|
||||||
|
{
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<input type="text" value="@Model.Headers[i]" name="Headers[@i]" />
|
||||||
|
<button type="button" class="btn btn-danger" onclick="removeHeader(@i)">delete</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<button type="button" class="btn btn-normal" onclick="addHeader.submit()">add</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Description</th>
|
||||||
|
<td><input type="text" value="@Model.Description" name="Description" /></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Method</th>
|
||||||
|
<td>
|
||||||
|
<select name="Method">
|
||||||
|
@foreach(Enumerations.HttpVerb method in Enum.GetValues(typeof(Enumerations.HttpVerb)))
|
||||||
|
{
|
||||||
|
<option value="@method" selected="@(Model.Method == method)">@method</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">UAC</th>
|
||||||
|
<td><a href="@Url.Action("Details", "UACs", new {Id = Model.Uac?.Id})">uac</a></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<button type="button" class="btn btn-danger" onclick="deleteDialog.showModal()">delete</button>
|
||||||
|
<button type="submit" class="btn btn-success">save</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</form>
|
||||||
|
<form action="@Url.Action("Delete", "Webhooks")" method="post" id="delete">
|
||||||
|
<input type="hidden" name="Id" value="@Model.Id" />
|
||||||
|
<dialog id="deleteDialog">
|
||||||
|
Are you sure?
|
||||||
|
<button class="btn btn-secondary" type="button" onclick="deleteDialog.close()">cancel</button>
|
||||||
|
<button class="btn btn-danger" type="submit">delete</button>
|
||||||
|
</dialog>
|
||||||
|
</form>
|
||||||
|
<form action="@Url.Action("AddHeader", "Webhooks")" method="post" id="addHeader">
|
||||||
|
<input type="hidden" name="Id" value="@Model.Id" />
|
||||||
|
</form>
|
||||||
|
<dialog id="removeHeaderDialog">
|
||||||
|
<form action="@Url.Action("RemoveHeader", "Webhooks")" method="post">
|
||||||
|
Are you sure?
|
||||||
|
<input type="hidden" name="Id" value="@Model.Id"/>
|
||||||
|
<input type="hidden" name="index" id="removeHeaderTarget" />
|
||||||
|
<button class="btn btn-secondary" type="button" onclick="removeHeaderDialog.close()">cancel</button>
|
||||||
|
<button class="btn btn-danger" type="submit">delete</button>
|
||||||
|
</form>
|
||||||
|
</dialog>
|
||||||
|
|
||||||
|
@section scripts{
|
||||||
|
<script type="text/javascript">
|
||||||
|
function removeHeader(idx){
|
||||||
|
removeHeaderTarget.Value = idx;
|
||||||
|
console.log("removeHeaderTarget is now " + idx);
|
||||||
|
removeHeaderDialog.showModal();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user