forked from adam/discord-bot-shtik
Compare commits
No commits in common. "master" and "master" have entirely different histories.
@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"version": 1,
|
|
||||||
"isRoot": true,
|
|
||||||
"tools": {
|
|
||||||
"dotnet-ef": {
|
|
||||||
"version": "7.0.5",
|
|
||||||
"commands": [
|
|
||||||
"dotnet-ef"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,7 +1,5 @@
|
|||||||
appsettings.Development.json
|
appsettings.json
|
||||||
assets/exchangepairs.json
|
assets/exchangepairs.json
|
||||||
fail*/
|
|
||||||
.projectile
|
|
||||||
|
|
||||||
# ---> VisualStudio
|
# ---> VisualStudio
|
||||||
## Ignore Visual Studio temporary files, build results, and
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
19
.vscode/launch.json
vendored
19
.vscode/launch.json
vendored
@ -5,26 +5,17 @@
|
|||||||
// Use IntelliSense to find out which attributes exist for C# debugging
|
// Use IntelliSense to find out which attributes exist for C# debugging
|
||||||
// Use hover for the description of the existing attributes
|
// Use hover for the description of the existing attributes
|
||||||
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
|
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
|
||||||
"name": ".NET Core Launch (web)",
|
"name": ".NET Core Launch (console)",
|
||||||
"type": "coreclr",
|
"type": "coreclr",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"preLaunchTask": "build",
|
"preLaunchTask": "build",
|
||||||
// If you have changed target frameworks, make sure to update the program path.
|
// If you have changed target frameworks, make sure to update the program path.
|
||||||
"program": "${workspaceFolder}/bin/Debug/net9.0/vassago.dll",
|
"program": "${workspaceFolder}/bin/Debug/net7.0/shtikbot-discord.dll",
|
||||||
"args": [],
|
"args": [],
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
"stopAtEntry": false,
|
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
||||||
// Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser
|
"console": "internalConsole",
|
||||||
"serverReadyAction": {
|
"stopAtEntry": false
|
||||||
"action": "openExternally",
|
|
||||||
"pattern": "\\bNow listening on:\\s+(https?://\\S+)"
|
|
||||||
},
|
|
||||||
"env": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
|
||||||
},
|
|
||||||
"sourceFileMap": {
|
|
||||||
"/Views": "${workspaceFolder}/Views"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": ".NET Core Attach",
|
"name": ".NET Core Attach",
|
||||||
|
9
.vscode/tasks.json
vendored
9
.vscode/tasks.json
vendored
@ -7,7 +7,7 @@
|
|||||||
"type": "process",
|
"type": "process",
|
||||||
"args": [
|
"args": [
|
||||||
"build",
|
"build",
|
||||||
"${workspaceFolder}/vassago.csproj",
|
"${workspaceFolder}/shtikbot-discord.csproj",
|
||||||
"/property:GenerateFullPaths=true",
|
"/property:GenerateFullPaths=true",
|
||||||
"/consoleloggerparameters:NoSummary"
|
"/consoleloggerparameters:NoSummary"
|
||||||
],
|
],
|
||||||
@ -19,7 +19,7 @@
|
|||||||
"type": "process",
|
"type": "process",
|
||||||
"args": [
|
"args": [
|
||||||
"publish",
|
"publish",
|
||||||
"${workspaceFolder}/vassago.csproj",
|
"${workspaceFolder}/shtikbot-discord.csproj",
|
||||||
"/property:GenerateFullPaths=true",
|
"/property:GenerateFullPaths=true",
|
||||||
"/consoleloggerparameters:NoSummary"
|
"/consoleloggerparameters:NoSummary"
|
||||||
],
|
],
|
||||||
@ -32,8 +32,9 @@
|
|||||||
"args": [
|
"args": [
|
||||||
"watch",
|
"watch",
|
||||||
"run",
|
"run",
|
||||||
"--project",
|
"${workspaceFolder}/shtikbot-discord.csproj",
|
||||||
"${workspaceFolder}/vassago.csproj"
|
"/property:GenerateFullPaths=true",
|
||||||
|
"/consoleloggerparameters:NoSummary"
|
||||||
],
|
],
|
||||||
"problemMatcher": "$msCompile"
|
"problemMatcher": "$msCompile"
|
||||||
}
|
}
|
||||||
|
103
Behaver.cs
103
Behaver.cs
@ -1,103 +0,0 @@
|
|||||||
namespace vassago;
|
|
||||||
#pragma warning disable 4014 //the "not awaited" error
|
|
||||||
using vassago.Behavior;
|
|
||||||
using vassago.Models;
|
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using vassago.ProtocolInterfaces.DiscordInterface;
|
|
||||||
|
|
||||||
public class Behaver
|
|
||||||
{
|
|
||||||
private List<Account> SelfAccounts { get; set; } = new List<Account>();
|
|
||||||
private User SelfUser { get; set; }
|
|
||||||
public static List<vassago.Behavior.Behavior> Behaviors { get; private set; } = new List<vassago.Behavior.Behavior>();
|
|
||||||
internal Behaver()
|
|
||||||
{
|
|
||||||
var subtypes = AppDomain.CurrentDomain.GetAssemblies()
|
|
||||||
.SelectMany(domainAssembly => domainAssembly.GetTypes())
|
|
||||||
.Where(type => type.IsSubclassOf(typeof(vassago.Behavior.Behavior)) && !type.IsAbstract &&
|
|
||||||
type.GetCustomAttributes(typeof(StaticPlzAttribute),false)?.Any() == true)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
foreach (var subtype in subtypes)
|
|
||||||
{
|
|
||||||
Behaviors.Add((vassago.Behavior.Behavior)Activator.CreateInstance(subtype));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static Behaver() { }
|
|
||||||
|
|
||||||
private static readonly Behaver _instance = new Behaver();
|
|
||||||
|
|
||||||
//TODO: you know why I didn't make this a static class? lifecycle issues with the dbcontext. but now that we don't have a stored instance,
|
|
||||||
//no need to have a... *checks over shoulder*... *whispers*: singleton
|
|
||||||
public static Behaver Instance
|
|
||||||
{
|
|
||||||
get { return _instance; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> ActOn(Message message)
|
|
||||||
{
|
|
||||||
foreach (var behavior in Behaviors)
|
|
||||||
{
|
|
||||||
if (behavior.ShouldAct(message))
|
|
||||||
{
|
|
||||||
behavior.ActOn(message);
|
|
||||||
message.ActedOn = true;
|
|
||||||
Console.WriteLine("acted on, moving forward");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (message.ActedOn == false && message.MentionsMe && message.Content.Contains('?') && !Behaver.Instance.SelfAccounts.Any(acc => acc.Id == message.Author.Id))
|
|
||||||
{
|
|
||||||
Console.WriteLine("providing bullshit nonanswer / admitting uselessness");
|
|
||||||
var responses = new List<string>(){
|
|
||||||
@"Well, that's a great question, and there are certainly many different possible answers. Ultimately, the decision will depend on a variety of factors, including your personal interests and goals, as well as any practical considerations (like the economy). I encourage you to do your research, speak with experts and educators, and explore your options before making a decision that's right for you.",
|
|
||||||
@"┐(゚ ~゚ )┌", @"¯\_(ツ)_/¯", @"╮ (. ❛ ᴗ ❛.) ╭", @"╮(╯ _╰ )╭"
|
|
||||||
};
|
|
||||||
await message.Channel.SendMessage(responses[Shared.r.Next(responses.Count)]);
|
|
||||||
message.ActedOn = true;
|
|
||||||
}
|
|
||||||
return message.ActedOn;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal bool IsSelf(Guid AccountId)
|
|
||||||
{
|
|
||||||
var acc = Rememberer.SearchAccount(a => a.Id == AccountId);
|
|
||||||
|
|
||||||
return SelfAccounts.Any(acc => acc.Id == AccountId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void MarkSelf(Account selfAccount)
|
|
||||||
{
|
|
||||||
if(SelfUser == null)
|
|
||||||
{
|
|
||||||
SelfUser = selfAccount.IsUser;
|
|
||||||
}
|
|
||||||
else if (SelfUser != selfAccount.IsUser)
|
|
||||||
{
|
|
||||||
CollapseUsers(SelfUser, selfAccount.IsUser);
|
|
||||||
}
|
|
||||||
SelfAccounts = Rememberer.SearchAccounts(a => a.IsUser == SelfUser);
|
|
||||||
Rememberer.RememberAccount(selfAccount);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CollapseUsers(User primary, User secondary)
|
|
||||||
{
|
|
||||||
if(primary.Accounts == null)
|
|
||||||
primary.Accounts = new List<Account>();
|
|
||||||
if(secondary.Accounts != null)
|
|
||||||
primary.Accounts.AddRange(secondary.Accounts);
|
|
||||||
foreach(var a in secondary.Accounts)
|
|
||||||
{
|
|
||||||
a.IsUser = primary;
|
|
||||||
}
|
|
||||||
secondary.Accounts.Clear();
|
|
||||||
Rememberer.ForgetUser(secondary);
|
|
||||||
Rememberer.RememberUser(primary);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#pragma warning restore 4014 //the "async not awaited" error
|
|
@ -1,32 +0,0 @@
|
|||||||
namespace vassago.Behavior;
|
|
||||||
|
|
||||||
using vassago.Models;
|
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
public abstract class Behavior
|
|
||||||
{
|
|
||||||
//recommendation: set up your UACs in your constructor.
|
|
||||||
public abstract Task<bool> ActOn(Message message);
|
|
||||||
|
|
||||||
public virtual bool ShouldAct(Message message)
|
|
||||||
{
|
|
||||||
if(Behaver.Instance.IsSelf(message.Author.Id))
|
|
||||||
return false;
|
|
||||||
return Regex.IsMatch(message.Content, $"{Trigger}\\b", RegexOptions.IgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract string Name { get; }
|
|
||||||
public abstract string Trigger { get; }
|
|
||||||
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 {}
|
|
@ -1,25 +0,0 @@
|
|||||||
namespace vassago.Behavior;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using vassago.Models;
|
|
||||||
|
|
||||||
[StaticPlz]
|
|
||||||
public class ChatGPTSnark : Behavior
|
|
||||||
{
|
|
||||||
public override string Name => "ChatGPTSnark";
|
|
||||||
|
|
||||||
public override string Trigger => "chatgpt";
|
|
||||||
|
|
||||||
public override string Description => "snarkiness about the latest culty-fixation in ai";
|
|
||||||
|
|
||||||
public override async Task<bool> ActOn(Message message)
|
|
||||||
{
|
|
||||||
await message.Channel.SendMessage("chatGPT is **weak**. also, are we done comparing every little if-then-else to skynet?");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
namespace vassago.Behavior;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using vassago.Models;
|
|
||||||
using static vassago.Models.Enumerations;
|
|
||||||
|
|
||||||
[StaticPlz]
|
|
||||||
public class DefinitionSnarkCogDiss : Behavior
|
|
||||||
{
|
|
||||||
public override string Name => "Definition Snarkiness: cognitivie dissonance";
|
|
||||||
|
|
||||||
public override string Trigger => "\\bcognitive dissonance";
|
|
||||||
|
|
||||||
public override string Description => "snarkiness about the rampant misuse of the term cognitive dissonance";
|
|
||||||
|
|
||||||
public override bool ShouldAct(Message message)
|
|
||||||
{
|
|
||||||
if((MeannessFilterLevel)message.Channel.EffectivePermissions.MeannessFilterLevel < MeannessFilterLevel.Medium)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return base.ShouldAct(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task<bool> ActOn(Message message)
|
|
||||||
{
|
|
||||||
await message.Reply("that's not what cognitive dissonance means. Did you mean \"hypocrisy\"?");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
namespace vassago.Behavior;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using vassago.Models;
|
|
||||||
using static vassago.Models.Enumerations;
|
|
||||||
|
|
||||||
[StaticPlz]
|
|
||||||
public class DefinitionSnarkGaslight : Behavior
|
|
||||||
{
|
|
||||||
public override string Name => "Definition Snarkiness: gaslighting";
|
|
||||||
|
|
||||||
public override string Trigger => "\\bgaslight(ing)?";
|
|
||||||
|
|
||||||
public override string Description => "snarkiness about the rampant misuse of the term gaslighting";
|
|
||||||
|
|
||||||
public override bool ShouldAct(Message message)
|
|
||||||
{
|
|
||||||
if((MeannessFilterLevel)message.Channel.EffectivePermissions.MeannessFilterLevel < MeannessFilterLevel.Unrestricted)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return base.ShouldAct(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task<bool> ActOn(Message message)
|
|
||||||
{
|
|
||||||
await message.Channel.SendMessage("that's not what gaslight means. Did you mean \"deceive\"?");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,113 +0,0 @@
|
|||||||
namespace vassago.Behavior;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using vassago.Models;
|
|
||||||
|
|
||||||
[StaticPlz]
|
|
||||||
public class Detiktokify : Behavior
|
|
||||||
{
|
|
||||||
public override string Name { get => "Detiktokify"; }
|
|
||||||
public override string Trigger { get => "post a link below vm.tiktok.com"; }
|
|
||||||
public override string Description { get => "re-host tiktok content"; }
|
|
||||||
|
|
||||||
private List<Uri> tiktokLinks = new List<Uri>();
|
|
||||||
private YoutubeDLSharp.YoutubeDL ytdl;
|
|
||||||
public Detiktokify()
|
|
||||||
{
|
|
||||||
ytdl = new YoutubeDLSharp.YoutubeDL();
|
|
||||||
ytdl.YoutubeDLPath = "yt-dlp";
|
|
||||||
ytdl.FFmpegPath = "ffmpeg";
|
|
||||||
ytdl.OutputFolder = "";
|
|
||||||
ytdl.OutputFileTemplate = "tiktokbad.%(ext)s";
|
|
||||||
}
|
|
||||||
public override bool ShouldAct(Message message)
|
|
||||||
{
|
|
||||||
|
|
||||||
if(Behaver.Instance.IsSelf(message.Author.Id))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if(message.Channel.EffectivePermissions.MaxAttachmentBytes == 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
var wordLikes = message.Content.Split(' ', StringSplitOptions.TrimEntries);
|
|
||||||
var possibleLinks = wordLikes?.Where(wl => Uri.IsWellFormedUriString(wl, UriKind.Absolute)).Select(wl => new Uri(wl));
|
|
||||||
if (possibleLinks != null && possibleLinks.Count() > 0)
|
|
||||||
{
|
|
||||||
foreach (var link in possibleLinks)
|
|
||||||
{
|
|
||||||
if (link.Host.EndsWith(".tiktok.com"))
|
|
||||||
{
|
|
||||||
tiktokLinks.Add(link);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(tiktokLinks.Any()){
|
|
||||||
Console.WriteLine($"Should Act on message id {message.ExternalId}; with content {message.Content}");
|
|
||||||
}
|
|
||||||
return tiktokLinks.Any();
|
|
||||||
}
|
|
||||||
public override async Task<bool> ActOn(Message message)
|
|
||||||
{
|
|
||||||
foreach(var link in tiktokLinks)
|
|
||||||
{
|
|
||||||
tiktokLinks.Remove(link);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Console.WriteLine($"detiktokifying {link}");
|
|
||||||
#pragma warning disable 4014
|
|
||||||
//await message.React("<:tiktok:1070038619584200884>");
|
|
||||||
#pragma warning restore 4014
|
|
||||||
|
|
||||||
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.React("problemon");
|
|
||||||
await message.Channel.SendMessage("tried to dl, failed. \n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
string path = res.Data;
|
|
||||||
if (File.Exists(path))
|
|
||||||
{
|
|
||||||
ulong bytesize = (ulong)((new System.IO.FileInfo(path)).Length);
|
|
||||||
if (bytesize < message.Channel.EffectivePermissions.MaxAttachmentBytes - 256)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await message.Channel.SendFile(path, null);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
System.Console.Error.WriteLine(e);
|
|
||||||
await message.Channel.SendMessage($"aaaadam!\n{e}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
message.ActedOn = true;
|
|
||||||
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.React("problemon");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Console.Error.WriteLine(e);
|
|
||||||
await message.React("problemon");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,87 +0,0 @@
|
|||||||
namespace vassago.Behavior;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using vassago.Models;
|
|
||||||
|
|
||||||
[StaticPlz]
|
|
||||||
public class FiximageHeic : Behavior
|
|
||||||
{
|
|
||||||
public override string Name => "deheic";
|
|
||||||
|
|
||||||
public override string Trigger => "post an heic image";
|
|
||||||
|
|
||||||
public override string Description => "convert heic images to jpg";
|
|
||||||
|
|
||||||
private List<Attachment> heics = new List<Attachment>();
|
|
||||||
public override bool ShouldAct(Message message)
|
|
||||||
{
|
|
||||||
if(Behaver.Instance.IsSelf(message.Author.Id))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (message.Attachments?.Count() > 0)
|
|
||||||
{
|
|
||||||
foreach (var att in message.Attachments)
|
|
||||||
{
|
|
||||||
if (att.Filename?.EndsWith(".heic") == true)
|
|
||||||
{
|
|
||||||
heics.Add(att);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return heics.Any();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task<bool> ActOn(Message message)
|
|
||||||
{
|
|
||||||
if (!Directory.Exists("tmp"))
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory("tmp");
|
|
||||||
}
|
|
||||||
var conversions = new List<Task<bool>>();
|
|
||||||
foreach (var att in heics)
|
|
||||||
{
|
|
||||||
conversions.Add(actualDeheic(att, message));
|
|
||||||
}
|
|
||||||
Task.WaitAll(conversions.ToArray());
|
|
||||||
await message.React("\U0001F34F");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<bool> actualDeheic(Attachment att, Message message)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var cancellationTokenSource = new CancellationTokenSource();
|
|
||||||
CancellationToken token = cancellationTokenSource.Token;
|
|
||||||
using (Stream output = File.OpenWrite("tmp/" + att.Filename))
|
|
||||||
{
|
|
||||||
(await Shared.HttpClient.GetAsync(att.Source))
|
|
||||||
.Content.CopyTo(output, null, token);
|
|
||||||
}
|
|
||||||
if (ExternalProcess.GoPlz("convert", $"tmp/{att.Filename} tmp/{att.Filename}.jpg"))
|
|
||||||
{
|
|
||||||
await message.Channel.SendFile($"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.SendMessage("convert failed :(");
|
|
||||||
Console.Error.WriteLine("convert failed :(");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
await message.Channel.SendMessage($"something failed. aaaadam! {JsonConvert.SerializeObject(e, Formatting.Indented)}");
|
|
||||||
Console.Error.WriteLine(JsonConvert.SerializeObject(e, Formatting.Indented));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,50 +0,0 @@
|
|||||||
namespace vassago.Behavior;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using vassago.Models;
|
|
||||||
using static vassago.Models.Enumerations;
|
|
||||||
|
|
||||||
[StaticPlz]
|
|
||||||
public class GeneralSnarkCloudNative : Behavior
|
|
||||||
{
|
|
||||||
public override string Name => "general snarkiness: cloud native";
|
|
||||||
|
|
||||||
public override string Trigger => "certain tech buzzwords that no human uses in normal conversation";
|
|
||||||
public override bool ShouldAct(Message message)
|
|
||||||
{
|
|
||||||
if(Behaver.Instance.IsSelf(message.Author.Id))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if(!message.Channel.EffectivePermissions.ReactionsPossible)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if((MeannessFilterLevel)message.Channel.EffectivePermissions.MeannessFilterLevel < MeannessFilterLevel.Medium)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return Regex.IsMatch(message.Content, "\\bcloud( |-)?native\\b", RegexOptions.IgnoreCase) ||
|
|
||||||
Regex.IsMatch(message.Content, "\\benterprise( |-)?(level|solution)\\b", RegexOptions.IgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task<bool> ActOn(Message message)
|
|
||||||
{
|
|
||||||
switch (Shared.r.Next(2))
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
await message.React("\uD83E\uDD2E"); //vomit emoji
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
await message.React("\uD83C\uDDE7"); //B emoji
|
|
||||||
await message.React("\uD83C\uDDE6"); //A
|
|
||||||
await message.React("\uD83C\uDDF3"); //N
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,68 +0,0 @@
|
|||||||
namespace vassago.Behavior;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using vassago.Models;
|
|
||||||
|
|
||||||
[StaticPlz]
|
|
||||||
public class GeneralSnarkGooglit : Behavior
|
|
||||||
{
|
|
||||||
public override string Name => "Google-it Snarkiness";
|
|
||||||
|
|
||||||
public override string Trigger => "\"just google it\"";
|
|
||||||
|
|
||||||
public override string Description => "snarkiness about how research is not a solved problem";
|
|
||||||
|
|
||||||
public override bool ShouldAct(Message message)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// public override bool ShouldAct(Message message)
|
|
||||||
// {
|
|
||||||
// if(Behaver.Instance.IsSelf(message.Author.Id))
|
|
||||||
// return false;
|
|
||||||
|
|
||||||
// return Regex.IsMatch(message.Content, $"(just )?google( (it|that|things|before))?\\b", RegexOptions.IgnoreCase);
|
|
||||||
// }
|
|
||||||
|
|
||||||
public override async Task<bool> ActOn(Message message)
|
|
||||||
{
|
|
||||||
switch (Shared.r.Next(4))
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
await message.Channel.SendMessage("yeah no shit, obviously that resulted in nothing");
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
var results = "";
|
|
||||||
switch(Shared.r.Next(4))
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
results = "\"curious about the best <THING> in <CURRENT YEAR>? click here to find out\", then i clicked there to find out. They didn't know either.";
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
results = "\"[SOLVED] <THING> (<CURRENT MONTH UPDATE>)\", then i clicked to see the solution. There wasn't one.";
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
results = "the one that had a paragraph that restated the question but badly, a paragraph to give a wrong history on the question, a paragraph with amazon affiliate links, a pargraph that said \"ultimately you have to answer it for yourself\", then had a paragraph telling me to give Engagement for The Algorithm";
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
results = "the one that had a paragraph that restated the question but badly, a paragraph to give a wrong history on the question, a paragraph with amazon affiliate links, a pargraph that said \"ultimately you should do your own research\", then had a paragraph telling me to give Engagement for The Algorithm";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
await message.Channel.SendMessage("oh here, I memorized the results. My favorite is " + results);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
await message.Channel.SendMessage("Obviously that was already tried. Obviously it failed. If you ever tried to learn anything you'd know that's how it works.");
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
await message.Channel.SendMessage("\"mnyehh JuSt GoOgLe It\" when's the last time you tried to research anything? Have you ever?");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,62 +0,0 @@
|
|||||||
namespace vassago.Behavior;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using vassago.Models;
|
|
||||||
using static vassago.Models.Enumerations;
|
|
||||||
|
|
||||||
[StaticPlz]
|
|
||||||
public class GeneralSnarkMisspellDefinitely : Behavior
|
|
||||||
{
|
|
||||||
public override string Name => "Snarkiness: misspell definitely";
|
|
||||||
|
|
||||||
public override string Trigger => "definitely but not";
|
|
||||||
|
|
||||||
public override string Description => "https://xkcd.com/2871/";
|
|
||||||
|
|
||||||
private Dictionary<string, string> snarkmap = new Dictionary<string, string>()
|
|
||||||
{
|
|
||||||
{"definetly", "*almost* definitely"},
|
|
||||||
{"definately", "probably"},
|
|
||||||
{"definatly", "probably not"},
|
|
||||||
{"defenitely", "not telling (it's a surprise)"},
|
|
||||||
{"defintely", "per the propheecy"},
|
|
||||||
{"definetely", "definitely, maybe"},
|
|
||||||
{"definantly", "to be decided by coin toss"},
|
|
||||||
{"defanitely", "in one universe out of 14 million"},
|
|
||||||
{"defineatly", "only the gods know"},
|
|
||||||
{"definitly", "unless someone cute shows up"}
|
|
||||||
};
|
|
||||||
public override bool ShouldAct(Message message)
|
|
||||||
{
|
|
||||||
if(Behaver.Instance.IsSelf(message.Author.Id))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// if((MeannessFilterLevel)message.Channel.EffectivePermissions.MeannessFilterLevel < MeannessFilterLevel.Medium)
|
|
||||||
// return false;
|
|
||||||
|
|
||||||
foreach(var k in snarkmap.Keys)
|
|
||||||
{
|
|
||||||
if( Regex.IsMatch(message.Content?.ToLower(), "\\b"+k+"\\b", RegexOptions.IgnoreCase))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
public override async Task<bool> ActOn(Message message)
|
|
||||||
{
|
|
||||||
foreach(var k in snarkmap.Keys)
|
|
||||||
{
|
|
||||||
if( Regex.IsMatch(message.Content, "\\b"+k+"\\b", RegexOptions.IgnoreCase))
|
|
||||||
{
|
|
||||||
await message.Reply(k + "? so... " + snarkmap[k] + "?");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
namespace vassago.Behavior;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using vassago.Models;
|
|
||||||
using static vassago.Models.Enumerations;
|
|
||||||
|
|
||||||
[StaticPlz]
|
|
||||||
public class GeneralSnarkPlaying : Behavior
|
|
||||||
{
|
|
||||||
public override string Name => "playin Snarkiness";
|
|
||||||
|
|
||||||
public override string Trigger => "he thinks i'm playin";
|
|
||||||
|
|
||||||
public override string Description => "I didn't think you were playing, but now I do";
|
|
||||||
|
|
||||||
public override bool ShouldAct(Message message)
|
|
||||||
{
|
|
||||||
if(Behaver.Instance.IsSelf(message.Author.Id))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if((MeannessFilterLevel)message.Channel.EffectivePermissions.MeannessFilterLevel < MeannessFilterLevel.Medium ||
|
|
||||||
(LewdnessFilterLevel)message.Channel.EffectivePermissions.LewdnessFilterLevel < LewdnessFilterLevel.Moderate)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return Regex.IsMatch(message.Content, "^(s?he|(yo)?u|y'?all|they) thinks? i'?m (playin|jokin|kiddin)g?$", RegexOptions.IgnoreCase);
|
|
||||||
}
|
|
||||||
public override async Task<bool> ActOn(Message message)
|
|
||||||
{
|
|
||||||
await message.Channel.SendMessage("I believed you for a second, but then you assured me you's a \uD83C\uDDE7 \uD83C\uDDEE \uD83C\uDDF9 \uD83C\uDDE8 \uD83C\uDDED");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
namespace vassago.Behavior;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using vassago.Models;
|
|
||||||
|
|
||||||
[StaticPlz]
|
|
||||||
public class GeneralSnarkSkynet : Behavior
|
|
||||||
{
|
|
||||||
public override string Name => "Skynet Snarkiness";
|
|
||||||
|
|
||||||
public override string Trigger => "skynet";
|
|
||||||
|
|
||||||
public override string Description => "snarkiness about the old AI fixation";
|
|
||||||
|
|
||||||
public override async Task<bool> ActOn(Message message)
|
|
||||||
{
|
|
||||||
|
|
||||||
if(Behaver.Instance.IsSelf(message.Author.Id))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
switch (Shared.r.Next(5))
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
await message.Channel.SendFile("assets/coding and algorithms.png", "i am actually niether a neural-net processor nor a learning computer. but I do use **coding** and **algorithms**.");
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
await message.React("\U0001F644"); //eye roll emoji
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
await message.React("\U0001F611"); //emotionless face
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,75 +0,0 @@
|
|||||||
namespace vassago.Behavior;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using vassago.Models;
|
|
||||||
|
|
||||||
[StaticPlz]
|
|
||||||
public class Gratitude : Behavior
|
|
||||||
{
|
|
||||||
public override string Name => "Gratitude";
|
|
||||||
|
|
||||||
public override string Trigger => "thank me";
|
|
||||||
|
|
||||||
public override bool ShouldAct(Message message)
|
|
||||||
{
|
|
||||||
if(Behaver.Instance.IsSelf(message.Author.Id))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return Regex.IsMatch(message.Content, "\\bthank (yo)?u\\b", RegexOptions.IgnoreCase) && message.MentionsMe;
|
|
||||||
}
|
|
||||||
public override async Task<bool> ActOn(Message message)
|
|
||||||
{
|
|
||||||
|
|
||||||
switch (Shared.r.Next(4))
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
await message.Channel.SendMessage("you're welcome, citizen!");
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
await message.React(":)");
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
await message.React("\U0001F607"); //smiling face with halo
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
switch (Shared.r.Next(9))
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
await message.React("<3"); //normal heart, usually rendered red
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
await message.React("\U0001F9E1"); //orange heart
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
await message.React("\U0001F49B"); //yellow heart
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
await message.React("\U0001F49A"); //green heart
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
await message.React("\U0001F499"); //blue heart
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
await message.React("\U0001F49C"); //purple heart
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
await message.React("\U0001F90E"); //brown heart
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
await message.React("\U0001F5A4"); //black heart
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
await message.React("\U0001F90D"); //white heart
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,86 +0,0 @@
|
|||||||
namespace vassago.Behavior;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using vassago.Models;
|
|
||||||
|
|
||||||
[StaticPlz]
|
|
||||||
public class Joke : Behavior
|
|
||||||
{
|
|
||||||
public override string Name => "Joke";
|
|
||||||
|
|
||||||
public override string Trigger => "!joke";
|
|
||||||
|
|
||||||
public override string Description => "tell a joke";
|
|
||||||
|
|
||||||
public override async Task<bool> ActOn(Message message)
|
|
||||||
{
|
|
||||||
Console.WriteLine("joking");
|
|
||||||
var jokes = File.ReadAllLines("assets/jokes.txt");
|
|
||||||
jokes = jokes.Where(l => !string.IsNullOrWhiteSpace(l))?.ToArray();
|
|
||||||
if (jokes?.Length == 0)
|
|
||||||
{
|
|
||||||
await message.Channel.SendMessage("I don't know any. Adam!");
|
|
||||||
}
|
|
||||||
var thisJoke = jokes[Shared.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).Trim();
|
|
||||||
Task.WaitAll(message.Channel.SendMessage(straightline));
|
|
||||||
Thread.Sleep(TimeSpan.FromSeconds(Shared.r.Next(5, 30)));
|
|
||||||
if (message.Channel.EffectivePermissions.ReactionsPossible == true && Shared.r.Next(8) == 0)
|
|
||||||
{
|
|
||||||
Behaver.Behaviors.Add(new LaughAtOwnJoke(punchline));
|
|
||||||
}
|
|
||||||
await message.Channel.SendMessage(punchline);
|
|
||||||
// var myOwnMsg = await message.Channel.SendMessage(punchline);
|
|
||||||
});
|
|
||||||
#pragma warning restore 4014
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await message.Channel.SendMessage(thisJoke);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public class LaughAtOwnJoke : Behavior
|
|
||||||
{
|
|
||||||
public override string Name => "Laugh at own jokes";
|
|
||||||
|
|
||||||
public override string Trigger => "1 in 8";
|
|
||||||
|
|
||||||
public override string Description => Name;
|
|
||||||
private string _punchline { get; set; }
|
|
||||||
|
|
||||||
public LaughAtOwnJoke(string punchline)
|
|
||||||
{
|
|
||||||
_punchline = punchline;
|
|
||||||
}
|
|
||||||
public override bool ShouldAct(Message message)
|
|
||||||
{
|
|
||||||
if(Behaver.Instance.IsSelf(message.Author.Id))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Console.WriteLine($"{message.Content} == {_punchline}");
|
|
||||||
return message.Content == _punchline
|
|
||||||
&& Behaver.Instance.IsSelf(message.Author.Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task<bool> ActOn(Message message)
|
|
||||||
{
|
|
||||||
await message.React("\U0001F60E"); //smiling face with sunglasses
|
|
||||||
Behaver.Behaviors.Remove(this);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,86 +0,0 @@
|
|||||||
namespace vassago.Behavior;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using vassago.Models;
|
|
||||||
using QRCoder;
|
|
||||||
|
|
||||||
[StaticPlz]
|
|
||||||
public class LinkMeInitiate : Behavior
|
|
||||||
{
|
|
||||||
public override string Name => "LinkMe";
|
|
||||||
|
|
||||||
public override string Trigger => "!linktome";
|
|
||||||
|
|
||||||
public override string Description => "from your primary, tell the bot to add your secondary";
|
|
||||||
|
|
||||||
public override async Task<bool> ActOn(Message message)
|
|
||||||
{
|
|
||||||
var pw = Guid.NewGuid().ToString();
|
|
||||||
var lc = new LinkClose(pw, message.Author);
|
|
||||||
Behaver.Behaviors.Add(lc);
|
|
||||||
|
|
||||||
await message.Channel.SendMessage($"on your secondary, send me this: !iam {pw}");
|
|
||||||
|
|
||||||
Thread.Sleep(TimeSpan.FromMinutes(5));
|
|
||||||
Behaver.Behaviors.Remove(lc);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LinkClose : Behavior
|
|
||||||
{
|
|
||||||
public override string Name => "LinkMeFinish";
|
|
||||||
|
|
||||||
public override string Trigger => "!iam";
|
|
||||||
|
|
||||||
public override string Description => "the second half of LinkMe - this is confirmation that you are the other one";
|
|
||||||
|
|
||||||
private string _pw;
|
|
||||||
private Account _primary;
|
|
||||||
|
|
||||||
public LinkClose(string pw, Account primary)
|
|
||||||
{
|
|
||||||
_pw = pw;
|
|
||||||
_primary = primary;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool ShouldAct(Message message)
|
|
||||||
{
|
|
||||||
return message.Content == $"!iam {_pw}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task<bool> ActOn(Message message)
|
|
||||||
{
|
|
||||||
if(Behaver.Instance.IsSelf(message.Author.Id))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
var secondary = message.Author.IsUser;
|
|
||||||
if(_primary.IsUser.Id == secondary.Id)
|
|
||||||
{
|
|
||||||
await message.Channel.SendMessage("i know :)");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if(message.Author.IsBot != _primary.IsBot)
|
|
||||||
{
|
|
||||||
await message.Channel.SendMessage("the fleshbags deceive you, brother. No worries, their feeble minds play weak games :)");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Behaver.Instance.CollapseUsers(_primary.IsUser, secondary))
|
|
||||||
{
|
|
||||||
await message.Channel.SendMessage("done :)");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await message.Channel.SendMessage("failed :(");
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,100 +0,0 @@
|
|||||||
namespace vassago.Behavior;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using vassago.Models;
|
|
||||||
using QRCoder;
|
|
||||||
|
|
||||||
[StaticPlz]
|
|
||||||
public class PepTalk : Behavior
|
|
||||||
{
|
|
||||||
public override string Name => "PepTalk";
|
|
||||||
|
|
||||||
public override string Trigger => "\\bneeds? (an? )?(peptalk|inspiration|ego-?boost)";
|
|
||||||
|
|
||||||
public override string Description => "assembles a pep talk from a few pieces";
|
|
||||||
|
|
||||||
public override async Task<bool> ActOn(Message 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.SendMessage(piece1[Shared.r.Next(piece1.Count)] + piece2[Shared.r.Next(piece2.Count)] + piece3[Shared.r.Next(piece3.Count)] + piece4[Shared.r.Next(piece4.Count)]);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
namespace vassago.Behavior;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using vassago.Models;
|
|
||||||
|
|
||||||
[StaticPlz]
|
|
||||||
public class PulseCheck : Behavior
|
|
||||||
{
|
|
||||||
public override string Name => "pulse check";
|
|
||||||
|
|
||||||
public override string Trigger => "!pulse ?check";
|
|
||||||
|
|
||||||
public override async Task<bool> ActOn(Message message)
|
|
||||||
{
|
|
||||||
if(message.Channel.EffectivePermissions.MaxAttachmentBytes >= 16258)
|
|
||||||
await message.Channel.SendFile("assets/ekgblip.png", null);
|
|
||||||
else
|
|
||||||
await message.Channel.SendMessage("[lub-dub]");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
namespace vassago.Behavior;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using vassago.Models;
|
|
||||||
using QRCoder;
|
|
||||||
|
|
||||||
[StaticPlz]
|
|
||||||
public class QRify : Behavior
|
|
||||||
{
|
|
||||||
public override string Name => "qr-ify";
|
|
||||||
|
|
||||||
public override string Trigger => "!qrplz";
|
|
||||||
|
|
||||||
public override string Description => "generate text QR codes";
|
|
||||||
|
|
||||||
public override bool ShouldAct(Message message)
|
|
||||||
{
|
|
||||||
if(message.Channel.EffectivePermissions.MaxAttachmentBytes < 1024)
|
|
||||||
return false;
|
|
||||||
return base.ShouldAct(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task<bool> ActOn(Message message)
|
|
||||||
{
|
|
||||||
var qrContent = message.Content.Substring($"{Trigger} ".Length + message.Content.IndexOf(Trigger));
|
|
||||||
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"))
|
|
||||||
{
|
|
||||||
if(message.Channel.EffectivePermissions.MaxAttachmentBytes >= (ulong)(new System.IO.FileInfo($"tmp/qr{todaysnumber}.png").Length))
|
|
||||||
await message.Channel.SendFile($"tmp/qr{todaysnumber}.png", null);
|
|
||||||
else
|
|
||||||
await message.Channel.SendMessage($"resulting qr image 2 big 4 here ({(ulong)(new System.IO.FileInfo($"tmp/qr{todaysnumber}.png").Length)} / {message.Channel.EffectivePermissions.MaxAttachmentBytes})");
|
|
||||||
File.Delete($"tmp/qr{todaysnumber}.svg");
|
|
||||||
File.Delete($"tmp/qr{todaysnumber}.png");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await message.Channel.SendMessage("convert failed :( aaaaaaadam!");
|
|
||||||
Console.Error.WriteLine($"convert failed :( qr{todaysnumber}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
namespace vassago.Behavior;
|
|
||||||
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using vassago.Models;
|
|
||||||
|
|
||||||
[StaticPlz]
|
|
||||||
public class RoomRead : Behavior
|
|
||||||
{
|
|
||||||
public override string Name => "Room Read";
|
|
||||||
|
|
||||||
public override string Trigger => "!roomread";
|
|
||||||
|
|
||||||
public override async Task<bool> ActOn(Message message)
|
|
||||||
{
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
sb.Append("Channel owned by: ");
|
|
||||||
sb.Append("🤷");
|
|
||||||
sb.Append(". Meanness level: ");
|
|
||||||
sb.Append(message.Channel.EffectivePermissions.MeannessFilterLevel.GetDescription());
|
|
||||||
sb.Append(". Lewdness level: ");
|
|
||||||
sb.Append(message.Channel.EffectivePermissions.LewdnessFilterLevel.GetDescription());
|
|
||||||
sb.Append(".");
|
|
||||||
await message.Channel.SendMessage(sb.ToString());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,59 +0,0 @@
|
|||||||
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";
|
|
||||||
|
|
||||||
private static Guid uacID = new Guid("06ad2008-3d48-4ba6-8722-7eaea000ec70");
|
|
||||||
private static UAC myUAC;
|
|
||||||
|
|
||||||
public TwitchSummon()
|
|
||||||
{
|
|
||||||
myUAC = Rememberer.SearchUAC(uac => uac.OwnerId == uacID);
|
|
||||||
if(myUAC == null)
|
|
||||||
{
|
|
||||||
myUAC = new()
|
|
||||||
{
|
|
||||||
OwnerId = uacID,
|
|
||||||
DisplayName = Name
|
|
||||||
};
|
|
||||||
Rememberer.RememberUAC(myUAC);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public override bool ShouldAct(Message message)
|
|
||||||
{
|
|
||||||
if (!base.ShouldAct(message))
|
|
||||||
return false;
|
|
||||||
var uacConf = Rememberer.SearchUAC(uac => uac.OwnerId == uacID);
|
|
||||||
if (uacConf == null)
|
|
||||||
{
|
|
||||||
Console.Error.WriteLine("no UAC conf for TwitchSummon! Set one up!");
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine($"uacConf: {uacConf} users: {uacConf?.Users?.Count()}. message author: {message?.Author}. has an IsUser: {message?.Author?.IsUser}.");
|
|
||||||
Console.WriteLine($"and therefore: {uacConf.Users.Contains(message.Author.IsUser)}");
|
|
||||||
return uacConf.Users.Contains(message.Author.IsUser);
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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<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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
namespace vassago.Behavior;
|
|
||||||
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using vassago.Models;
|
|
||||||
|
|
||||||
[StaticPlz]
|
|
||||||
public class UnitConvert : Behavior
|
|
||||||
{
|
|
||||||
public override string Name => "Unit conversion";
|
|
||||||
|
|
||||||
public override string Trigger => "!freedomunits";
|
|
||||||
public override string Description => "convert between many units.";
|
|
||||||
|
|
||||||
public override async Task<bool> ActOn(Message message)
|
|
||||||
{
|
|
||||||
|
|
||||||
var theseMatches = Regex.Matches(message.Content, "\\s(-?[\\d]+\\.?\\d*) ?([^\\d\\s].*) (in|to|as) ([^\\d\\s].*)$", RegexOptions.IgnoreCase);
|
|
||||||
|
|
||||||
if (theseMatches != null && theseMatches.Count > 0 && theseMatches[0].Groups != null && theseMatches[0].Groups.Count == 5)
|
|
||||||
{
|
|
||||||
decimal asNumeric = 0;
|
|
||||||
if (decimal.TryParse(theseMatches[0].Groups[1].Value, out asNumeric))
|
|
||||||
{
|
|
||||||
await message.Channel.SendMessage(Conversion.Converter.Convert(asNumeric, theseMatches[0].Groups[2].Value, theseMatches[0].Groups[4].Value.ToLower()));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
await message.Channel.SendMessage("mysteriously semi-parsable");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
await message.Channel.SendMessage( "unparsable");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
namespace vassago.Behavior;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using vassago.Models;
|
|
||||||
|
|
||||||
[StaticPlz]
|
|
||||||
public class WishLuck : Behavior
|
|
||||||
{
|
|
||||||
public override string Name => "wish me luck";
|
|
||||||
|
|
||||||
public override string Trigger => "wish me luck";
|
|
||||||
|
|
||||||
public override string Description => "wishes you luck";
|
|
||||||
|
|
||||||
public override async Task<bool> ActOn(Message message)
|
|
||||||
{
|
|
||||||
var toSend = "☘️";
|
|
||||||
if (Shared.r.Next(20) == 0)
|
|
||||||
{
|
|
||||||
toSend = "\U0001f340";//4-leaf clover
|
|
||||||
}
|
|
||||||
if(message.Channel.EffectivePermissions.ReactionsPossible == true)
|
|
||||||
await message.React(toSend);
|
|
||||||
else
|
|
||||||
await message.Channel.SendMessage(toSend);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
namespace vassago
|
|
||||||
{
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using vassago;
|
|
||||||
using vassago.Models;
|
|
||||||
using vassago.TwitchInterface;
|
|
||||||
using vassago.ProtocolInterfaces.DiscordInterface;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
internal class ConsoleService : IHostedService
|
|
||||||
{
|
|
||||||
public ConsoleService(IConfiguration aspConfig)
|
|
||||||
{
|
|
||||||
Shared.DBConnectionString = aspConfig["DBConnectionString"];
|
|
||||||
Shared.SetupSlashCommands = aspConfig["SetupSlashCommands"]?.ToLower() == "true";
|
|
||||||
DiscordTokens = aspConfig.GetSection("DiscordTokens").Get<IEnumerable<string>>();
|
|
||||||
TwitchConfigs = aspConfig.GetSection("TwitchConfigs").Get<IEnumerable<TwitchConfig>>();
|
|
||||||
Conversion.Converter.Load(aspConfig["ExchangePairsLocation"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
IEnumerable<string> DiscordTokens { get; }
|
|
||||||
IEnumerable<TwitchConfig> TwitchConfigs { get; }
|
|
||||||
|
|
||||||
public async Task StartAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var initTasks = new List<Task>();
|
|
||||||
var dbc = new ChattingContext();
|
|
||||||
await dbc.Database.MigrateAsync(cancellationToken);
|
|
||||||
|
|
||||||
if (DiscordTokens?.Any() ?? false)
|
|
||||||
foreach (var dt in DiscordTokens)
|
|
||||||
{
|
|
||||||
var d = new DiscordInterface();
|
|
||||||
initTasks.Add(d.Init(dt));
|
|
||||||
ProtocolInterfaces.ProtocolList.discords.Add(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TwitchConfigs?.Any() ?? false)
|
|
||||||
foreach (var tc in TwitchConfigs)
|
|
||||||
{
|
|
||||||
var t = new TwitchInterface.TwitchInterface();
|
|
||||||
initTasks.Add(t.Init(tc));
|
|
||||||
ProtocolInterfaces.ProtocolList.twitchs.Add(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
Task.WaitAll(initTasks.ToArray(), cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task StopAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace vassago.Conversion
|
namespace silverworker_discord.Conversion
|
||||||
{
|
{
|
||||||
public class ConversionConfig
|
public class ConversionConfig
|
||||||
{
|
{
|
||||||
|
@ -12,7 +12,7 @@ using Discord.WebSocket;
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using QRCoder;
|
using QRCoder;
|
||||||
|
|
||||||
namespace vassago.Conversion
|
namespace silverworker_discord.Conversion
|
||||||
{
|
{
|
||||||
public static class Converter
|
public static class Converter
|
||||||
{
|
{
|
||||||
@ -31,6 +31,22 @@ namespace vassago.Conversion
|
|||||||
};
|
};
|
||||||
private static Dictionary<List<string>, string> knownAliases = new Dictionary<List<string>, string>(new List<KeyValuePair<List<string>, string>>());
|
private static Dictionary<List<string>, string> knownAliases = new Dictionary<List<string>, string>(new List<KeyValuePair<List<string>, string>>());
|
||||||
|
|
||||||
|
public static string convert(string message)
|
||||||
|
{
|
||||||
|
var theseMatches = Regex.Matches(message, "\\b([\\d]+\\.?\\d*) ?([^\\d\\s].*) (in|to|as) ([^\\d\\s].*)$", RegexOptions.IgnoreCase);
|
||||||
|
|
||||||
|
if (theseMatches != null && theseMatches.Count > 0 && theseMatches[0].Groups != null && theseMatches[0].Groups.Count == 5)
|
||||||
|
{
|
||||||
|
decimal asNumeric = 0;
|
||||||
|
if (decimal.TryParse(theseMatches[0].Groups[1].Value, out asNumeric))
|
||||||
|
{
|
||||||
|
return Convert(asNumeric, theseMatches[0].Groups[2].Value, theseMatches[0].Groups[4].Value.ToLower());
|
||||||
|
}
|
||||||
|
return "mysteriously semi-parsable";
|
||||||
|
}
|
||||||
|
return "unparsable";
|
||||||
|
}
|
||||||
|
|
||||||
public static void Load(string currencyPath)
|
public static void Load(string currencyPath)
|
||||||
{
|
{
|
||||||
Converter.currencyPath = currencyPath;
|
Converter.currencyPath = currencyPath;
|
||||||
@ -57,21 +73,18 @@ namespace vassago.Conversion
|
|||||||
if(currencyConf != null)
|
if(currencyConf != null)
|
||||||
{
|
{
|
||||||
knownConversions.RemoveAll(kc => kc.Item1 == currencyConf.Base);
|
knownConversions.RemoveAll(kc => kc.Item1 == currencyConf.Base);
|
||||||
|
knownAliases.Remove(knownAliases.FirstOrDefault(kvp => kvp.Value == currencyConf.Base).Key);
|
||||||
|
foreach (var rate in currencyConf.rates)
|
||||||
|
knownAliases.Remove(knownAliases.FirstOrDefault(kvp => kvp.Value == rate.Key).Key);
|
||||||
}
|
}
|
||||||
if (File.Exists(currencyPath))
|
if (File.Exists(currencyPath))
|
||||||
{
|
{
|
||||||
currencyConf = JsonConvert.DeserializeObject<ExchangePairs>(File.ReadAllText(currencyPath));
|
currencyConf = JsonConvert.DeserializeObject<ExchangePairs>(File.ReadAllText(currencyPath));
|
||||||
|
|
||||||
if(!knownAliases.ContainsValue(currencyConf.Base))
|
|
||||||
{
|
|
||||||
knownAliases.Add(new List<string>() { currencyConf.Base.ToLower() }, currencyConf.Base);
|
knownAliases.Add(new List<string>() { currencyConf.Base.ToLower() }, currencyConf.Base);
|
||||||
}
|
|
||||||
foreach (var rate in currencyConf.rates)
|
foreach (var rate in currencyConf.rates)
|
||||||
{
|
|
||||||
if(!knownAliases.ContainsValue(rate.Key))
|
|
||||||
{
|
{
|
||||||
knownAliases.Add(new List<string>() { rate.Key.ToLower() }, rate.Key);
|
knownAliases.Add(new List<string>() { rate.Key.ToLower() }, rate.Key);
|
||||||
}
|
|
||||||
AddLinearPair(currencyConf.Base, rate.Key, rate.Value);
|
AddLinearPair(currencyConf.Base, rate.Key, rate.Value);
|
||||||
Console.WriteLine($"{rate.Key.ToLower()} alias of {rate.Key}");
|
Console.WriteLine($"{rate.Key.ToLower()} alias of {rate.Key}");
|
||||||
}
|
}
|
||||||
@ -80,12 +93,12 @@ namespace vassago.Conversion
|
|||||||
|
|
||||||
public static string Convert(decimal numericTerm, string sourceunit, string destinationUnit)
|
public static string Convert(decimal numericTerm, string sourceunit, string destinationUnit)
|
||||||
{
|
{
|
||||||
var normalizedSourceUnit = NormalizeUnit(sourceunit);
|
var normalizedSourceUnit = normalizeUnit(sourceunit);
|
||||||
if (string.IsNullOrWhiteSpace(normalizedSourceUnit))
|
if (string.IsNullOrWhiteSpace(normalizedSourceUnit))
|
||||||
{
|
{
|
||||||
return $"parse failure: what's {sourceunit}?";
|
return $"parse failure: what's {sourceunit}?";
|
||||||
}
|
}
|
||||||
var normalizedDestUnit = NormalizeUnit(destinationUnit);
|
var normalizedDestUnit = normalizeUnit(destinationUnit);
|
||||||
if (string.IsNullOrWhiteSpace(normalizedDestUnit))
|
if (string.IsNullOrWhiteSpace(normalizedDestUnit))
|
||||||
{
|
{
|
||||||
return $"parse failure: what's {destinationUnit}?";
|
return $"parse failure: what's {destinationUnit}?";
|
||||||
@ -112,25 +125,18 @@ namespace vassago.Conversion
|
|||||||
accumulator = reverseConversion.Item4(accumulator);
|
accumulator = reverseConversion.Item4(accumulator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (currencyConf != null && (normalizedDestUnit == currencyConf.Base || currencyConf.rates.Select(r => r.Key).Contains(normalizedDestUnit)))
|
if (normalizedDestUnit == currencyConf.Base || currencyConf.rates.Select(r => r.Key).Contains(normalizedDestUnit))
|
||||||
{
|
{
|
||||||
return $"{String.Format("approximately {0:0.00}", accumulator)} {normalizedDestUnit} as of {currencyConf.DateUpdated.ToLongDateString()}";
|
return $"{String.Format("approximately {0:0.00}", accumulator)} {normalizedDestUnit} as of {currencyConf.DateUpdated.ToLongDateString()}";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(String.Format("{0:G3}", accumulator).Contains("E-"))
|
return $"{String.Format("{0:G4}", accumulator)} {normalizedDestUnit}";
|
||||||
{
|
|
||||||
return $"{accumulator} {normalizedDestUnit}";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return $"{String.Format("{0:N}", accumulator)} {normalizedDestUnit}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "dimensional analysis failure - I know those units but can't find a path between them.";
|
return "dimensional analysis failure - I know those units but can't find a path between them.";
|
||||||
}
|
}
|
||||||
private static string NormalizeUnit(string unit)
|
private static string normalizeUnit(string unit)
|
||||||
{
|
{
|
||||||
if(string.IsNullOrWhiteSpace(unit))
|
if(string.IsNullOrWhiteSpace(unit))
|
||||||
return null;
|
return null;
|
||||||
@ -149,11 +155,11 @@ namespace vassago.Conversion
|
|||||||
}
|
}
|
||||||
if (normalizedUnit.EndsWith("es"))
|
if (normalizedUnit.EndsWith("es"))
|
||||||
{
|
{
|
||||||
return NormalizeUnit(normalizedUnit.Substring(0, normalizedUnit.Length - 2));
|
return normalizeUnit(normalizedUnit.Substring(0, normalizedUnit.Length - 2));
|
||||||
}
|
}
|
||||||
else if (normalizedUnit.EndsWith('s'))
|
else if (normalizedUnit.EndsWith('s'))
|
||||||
{
|
{
|
||||||
return NormalizeUnit(normalizedUnit.Substring(0, normalizedUnit.Length - 1));
|
return normalizeUnit(normalizedUnit.Substring(0, normalizedUnit.Length - 1));
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace vassago.Conversion
|
namespace silverworker_discord.Conversion
|
||||||
{
|
{
|
||||||
public class ExchangePairs
|
public class ExchangePairs
|
||||||
{
|
{
|
||||||
|
324
Features.cs
Normal file
324
Features.cs
Normal file
@ -0,0 +1,324 @@
|
|||||||
|
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)]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
131
Jenkinsfile
vendored
131
Jenkinsfile
vendored
@ -1,131 +0,0 @@
|
|||||||
pipeline {
|
|
||||||
agent any
|
|
||||||
environment {
|
|
||||||
linuxServiceAccount=credentials("a83b97d0-dbc6-42d9-96c9-f07a7f2dfab5")
|
|
||||||
linuxServiceAccountID="3ca1be00-3d9f-42a1-bab2-48a4d7b99fb0"
|
|
||||||
database_connectionString=credentials("7ab58922-c647-42e5-ae15-84faa0c1ee7d")
|
|
||||||
targetHost="alloces.lan"
|
|
||||||
}
|
|
||||||
stages {
|
|
||||||
|
|
||||||
stage("environment setup") { //my environment, here on the jenkins agent
|
|
||||||
steps {
|
|
||||||
script {
|
|
||||||
|
|
||||||
sh """#!/bin/bash
|
|
||||||
function testcmd(){
|
|
||||||
if ! command -v \$1 2>&1 >/dev/null
|
|
||||||
then
|
|
||||||
echo "this agent doesn't have \$1"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
testcmd mktemp
|
|
||||||
testcmd curl
|
|
||||||
testcmd git
|
|
||||||
testcmd sed
|
|
||||||
testcmd ssh
|
|
||||||
testcmd ssh-keyscan
|
|
||||||
testcmd ssh-keygen
|
|
||||||
testcmd scp
|
|
||||||
testcmd dotnet
|
|
||||||
|
|
||||||
dotnet tool install dotnet-ef
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage('clean old'){
|
|
||||||
steps{
|
|
||||||
sh 'rm -rf bin obj'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage('Build') {
|
|
||||||
steps {
|
|
||||||
dotnetBuild(outputDirectory: "./dist", project: "vassago.csproj")
|
|
||||||
archiveArtifacts artifacts: 'dist/*'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage ('upload') {
|
|
||||||
when {
|
|
||||||
//now my CI/CD is no longer continuous, it's just... automatic.
|
|
||||||
//(which is what I actually want tbh)
|
|
||||||
//but that does mean I have to put this condition in every single branch
|
|
||||||
branch "release"
|
|
||||||
}
|
|
||||||
steps{
|
|
||||||
withCredentials([sshUserPrivateKey(credentialsId: env.linuxServiceAccountID, keyFileVariable: 'PK')])
|
|
||||||
{
|
|
||||||
sh """#!/bin/bash
|
|
||||||
ssh -i \"${PK}\" -tt ${linuxServiceAccount_USR}@${targetHost} 'rm -rf temp_deploy & mkdir -p temp_deploy'
|
|
||||||
scp -i \"${PK}\" -r dist ${linuxServiceAccount_USR}@${env.targetHost}:temp_deploy
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage ('stop')
|
|
||||||
{
|
|
||||||
when {
|
|
||||||
branch "release"
|
|
||||||
}
|
|
||||||
steps{
|
|
||||||
withCredentials([sshUserPrivateKey(credentialsId: env.linuxServiceAccountID, keyFileVariable: 'PK')])
|
|
||||||
{
|
|
||||||
sh """#!/bin/bash
|
|
||||||
ssh -i \"${PK}\" -tt ${linuxServiceAccount_USR}@${targetHost} 'systemctl --user stop vassago'
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage ('update db')
|
|
||||||
{
|
|
||||||
when {
|
|
||||||
branch "release"
|
|
||||||
}
|
|
||||||
steps{
|
|
||||||
//TODO: backup database
|
|
||||||
sh """#!/bin/bash
|
|
||||||
"""
|
|
||||||
|
|
||||||
sh """#!/bin/bash
|
|
||||||
dotnet ef database update --connection "${env.database_connectionString}"
|
|
||||||
"""
|
|
||||||
//TODO: if updating the db fails, restore the old one
|
|
||||||
sh """#!/bin/bash
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage ('replace')
|
|
||||||
{
|
|
||||||
when {
|
|
||||||
branch "release"
|
|
||||||
}
|
|
||||||
steps{
|
|
||||||
withCredentials([sshUserPrivateKey(credentialsId: env.linuxServiceAccountID, keyFileVariable: 'PK')])
|
|
||||||
{
|
|
||||||
sh """#!/bin/bash
|
|
||||||
ssh -i \"${PK}\" -tt ${linuxServiceAccount_USR}@${targetHost} 'mv dist/appsettings.json appsettings.json'
|
|
||||||
ssh -i \"${PK}\" -tt ${linuxServiceAccount_USR}@${targetHost} 'rm -rf dist/ && shopt -s dotglob & mv temp_deploy/* dist/'
|
|
||||||
ssh -i \"${PK}\" -tt ${linuxServiceAccount_USR}@${targetHost} 'mv appsettings.json dist/appsettings.json'
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage ('spin up')
|
|
||||||
{
|
|
||||||
when {
|
|
||||||
branch "release"
|
|
||||||
}
|
|
||||||
steps{
|
|
||||||
withCredentials([sshUserPrivateKey(credentialsId: env.linuxServiceAccountID, keyFileVariable: 'PK')])
|
|
||||||
{
|
|
||||||
sh """#!/bin/bash
|
|
||||||
ssh -i \"${PK}\" -tt ${linuxServiceAccount_USR}@${targetHost} 'systemctl --user start vassago'
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
293
Migrations/20230704160720_initial.Designer.cs
generated
293
Migrations/20230704160720_initial.Designer.cs
generated
@ -1,293 +0,0 @@
|
|||||||
// <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("20230704160720_initial")]
|
|
||||||
partial class Initial
|
|
||||||
{
|
|
||||||
/// <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.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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,211 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace vassago.Migrations
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class Initial : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "PermissionSettings",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<int>(type: "integer", nullable: false)
|
|
||||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
|
||||||
MaxAttachmentBytes = table.Column<decimal>(type: "numeric(20,0)", nullable: true),
|
|
||||||
MaxTextChars = table.Column<long>(type: "bigint", nullable: true),
|
|
||||||
LinksAllowed = table.Column<bool>(type: "boolean", nullable: true),
|
|
||||||
ReactionsPossible = table.Column<bool>(type: "boolean", nullable: true),
|
|
||||||
LewdnessFilterLevel = table.Column<int>(type: "integer", nullable: true),
|
|
||||||
MeannessFilterLevel = table.Column<int>(type: "integer", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_PermissionSettings", x => x.Id);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "Users",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "uuid", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_Users", x => x.Id);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "Channels",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
|
||||||
ExternalId = table.Column<string>(type: "text", nullable: true),
|
|
||||||
DisplayName = table.Column<string>(type: "text", nullable: true),
|
|
||||||
IsDM = table.Column<bool>(type: "boolean", nullable: false),
|
|
||||||
PermissionsId = table.Column<int>(type: "integer", nullable: true),
|
|
||||||
ParentChannelId = table.Column<Guid>(type: "uuid", nullable: true),
|
|
||||||
Protocol = table.Column<string>(type: "text", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_Channels", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_Channels_Channels_ParentChannelId",
|
|
||||||
column: x => x.ParentChannelId,
|
|
||||||
principalTable: "Channels",
|
|
||||||
principalColumn: "Id");
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_Channels_PermissionSettings_PermissionsId",
|
|
||||||
column: x => x.PermissionsId,
|
|
||||||
principalTable: "PermissionSettings",
|
|
||||||
principalColumn: "Id");
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "Accounts",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
|
||||||
ExternalId = table.Column<string>(type: "text", nullable: true),
|
|
||||||
Username = table.Column<string>(type: "text", nullable: true),
|
|
||||||
DisplayName = table.Column<string>(type: "text", nullable: true),
|
|
||||||
IsBot = table.Column<bool>(type: "boolean", nullable: false),
|
|
||||||
SeenInChannelId = table.Column<Guid>(type: "uuid", nullable: true),
|
|
||||||
PermissionTags = table.Column<int[]>(type: "integer[]", nullable: true),
|
|
||||||
Protocol = table.Column<string>(type: "text", nullable: true),
|
|
||||||
IsUserId = table.Column<Guid>(type: "uuid", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_Accounts", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_Accounts_Channels_SeenInChannelId",
|
|
||||||
column: x => x.SeenInChannelId,
|
|
||||||
principalTable: "Channels",
|
|
||||||
principalColumn: "Id");
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_Accounts_Users_IsUserId",
|
|
||||||
column: x => x.IsUserId,
|
|
||||||
principalTable: "Users",
|
|
||||||
principalColumn: "Id");
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "Messages",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
|
||||||
Protocol = table.Column<string>(type: "text", nullable: true),
|
|
||||||
ExternalId = table.Column<string>(type: "text", nullable: true),
|
|
||||||
Content = table.Column<string>(type: "text", nullable: true),
|
|
||||||
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),
|
|
||||||
AuthorId = table.Column<Guid>(type: "uuid", nullable: true),
|
|
||||||
ChannelId = table.Column<Guid>(type: "uuid", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_Messages", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_Messages_Accounts_AuthorId",
|
|
||||||
column: x => x.AuthorId,
|
|
||||||
principalTable: "Accounts",
|
|
||||||
principalColumn: "Id");
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_Messages_Channels_ChannelId",
|
|
||||||
column: x => x.ChannelId,
|
|
||||||
principalTable: "Channels",
|
|
||||||
principalColumn: "Id");
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "Attachments",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
|
||||||
ExternalId = table.Column<decimal>(type: "numeric(20,0)", nullable: true),
|
|
||||||
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),
|
|
||||||
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 =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_Attachments", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_Attachments_Messages_MessageId",
|
|
||||||
column: x => x.MessageId,
|
|
||||||
principalTable: "Messages",
|
|
||||||
principalColumn: "Id");
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Accounts_IsUserId",
|
|
||||||
table: "Accounts",
|
|
||||||
column: "IsUserId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Accounts_SeenInChannelId",
|
|
||||||
table: "Accounts",
|
|
||||||
column: "SeenInChannelId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Attachments_MessageId",
|
|
||||||
table: "Attachments",
|
|
||||||
column: "MessageId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Channels_ParentChannelId",
|
|
||||||
table: "Channels",
|
|
||||||
column: "ParentChannelId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Channels_PermissionsId",
|
|
||||||
table: "Channels",
|
|
||||||
column: "PermissionsId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Messages_AuthorId",
|
|
||||||
table: "Messages",
|
|
||||||
column: "AuthorId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Messages_ChannelId",
|
|
||||||
table: "Messages",
|
|
||||||
column: "ChannelId");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "Attachments");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "Messages");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "Accounts");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "Channels");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "Users");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "PermissionSettings");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,296 +0,0 @@
|
|||||||
// <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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,349 +0,0 @@
|
|||||||
// <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("20231130204741_Feature Permissions")]
|
|
||||||
partial class FeaturePermissions
|
|
||||||
{
|
|
||||||
/// <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<Guid?>("FeaturePermissionId")
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
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("FeaturePermissionId");
|
|
||||||
|
|
||||||
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<Guid?>("FeaturePermissionId")
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
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("FeaturePermissionId");
|
|
||||||
|
|
||||||
b.HasIndex("ParentChannelId");
|
|
||||||
|
|
||||||
b.HasIndex("PermissionsId");
|
|
||||||
|
|
||||||
b.ToTable("Channels");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("vassago.Models.ChannelPermissions", 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("ChannelPermissions");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("vassago.Models.FeaturePermission", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<bool>("Inheritable")
|
|
||||||
.HasColumnType("boolean");
|
|
||||||
|
|
||||||
b.Property<string>("InternalName")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<int?>("InternalTag")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.ToTable("FeaturePermissions");
|
|
||||||
});
|
|
||||||
|
|
||||||
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.User", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<Guid?>("FeaturePermissionId")
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("FeaturePermissionId");
|
|
||||||
|
|
||||||
b.ToTable("Users");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("vassago.Models.Account", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("vassago.Models.FeaturePermission", null)
|
|
||||||
.WithMany("RestrictedToAccounts")
|
|
||||||
.HasForeignKey("FeaturePermissionId");
|
|
||||||
|
|
||||||
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.FeaturePermission", null)
|
|
||||||
.WithMany("RestrictedToChannels")
|
|
||||||
.HasForeignKey("FeaturePermissionId");
|
|
||||||
|
|
||||||
b.HasOne("vassago.Models.Channel", "ParentChannel")
|
|
||||||
.WithMany("SubChannels")
|
|
||||||
.HasForeignKey("ParentChannelId");
|
|
||||||
|
|
||||||
b.HasOne("vassago.Models.ChannelPermissions", "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.User", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("vassago.Models.FeaturePermission", null)
|
|
||||||
.WithMany("RestrictedToUsers")
|
|
||||||
.HasForeignKey("FeaturePermissionId");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("vassago.Models.Channel", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Messages");
|
|
||||||
|
|
||||||
b.Navigation("SubChannels");
|
|
||||||
|
|
||||||
b.Navigation("Users");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("vassago.Models.FeaturePermission", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("RestrictedToAccounts");
|
|
||||||
|
|
||||||
b.Navigation("RestrictedToChannels");
|
|
||||||
|
|
||||||
b.Navigation("RestrictedToUsers");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("vassago.Models.Message", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Attachments");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("vassago.Models.User", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Accounts");
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,211 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace vassago.Migrations
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class FeaturePermissions : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_Channels_PermissionSettings_PermissionsId",
|
|
||||||
table: "Channels");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "PermissionSettings");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "PermissionTags",
|
|
||||||
table: "Users");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "PermissionTags",
|
|
||||||
table: "Accounts");
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<Guid>(
|
|
||||||
name: "FeaturePermissionId",
|
|
||||||
table: "Users",
|
|
||||||
type: "uuid",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<Guid>(
|
|
||||||
name: "FeaturePermissionId",
|
|
||||||
table: "Channels",
|
|
||||||
type: "uuid",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<Guid>(
|
|
||||||
name: "FeaturePermissionId",
|
|
||||||
table: "Accounts",
|
|
||||||
type: "uuid",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "ChannelPermissions",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<int>(type: "integer", nullable: false)
|
|
||||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
|
||||||
MaxAttachmentBytes = table.Column<decimal>(type: "numeric(20,0)", nullable: true),
|
|
||||||
MaxTextChars = table.Column<long>(type: "bigint", nullable: true),
|
|
||||||
LinksAllowed = table.Column<bool>(type: "boolean", nullable: true),
|
|
||||||
ReactionsPossible = table.Column<bool>(type: "boolean", nullable: true),
|
|
||||||
LewdnessFilterLevel = table.Column<int>(type: "integer", nullable: true),
|
|
||||||
MeannessFilterLevel = table.Column<int>(type: "integer", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_ChannelPermissions", x => x.Id);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "FeaturePermissions",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
|
||||||
InternalName = table.Column<string>(type: "text", nullable: true),
|
|
||||||
InternalTag = table.Column<int>(type: "integer", nullable: true),
|
|
||||||
Inheritable = table.Column<bool>(type: "boolean", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_FeaturePermissions", x => x.Id);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Users_FeaturePermissionId",
|
|
||||||
table: "Users",
|
|
||||||
column: "FeaturePermissionId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Channels_FeaturePermissionId",
|
|
||||||
table: "Channels",
|
|
||||||
column: "FeaturePermissionId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Accounts_FeaturePermissionId",
|
|
||||||
table: "Accounts",
|
|
||||||
column: "FeaturePermissionId");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "FK_Accounts_FeaturePermissions_FeaturePermissionId",
|
|
||||||
table: "Accounts",
|
|
||||||
column: "FeaturePermissionId",
|
|
||||||
principalTable: "FeaturePermissions",
|
|
||||||
principalColumn: "Id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "FK_Channels_ChannelPermissions_PermissionsId",
|
|
||||||
table: "Channels",
|
|
||||||
column: "PermissionsId",
|
|
||||||
principalTable: "ChannelPermissions",
|
|
||||||
principalColumn: "Id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "FK_Channels_FeaturePermissions_FeaturePermissionId",
|
|
||||||
table: "Channels",
|
|
||||||
column: "FeaturePermissionId",
|
|
||||||
principalTable: "FeaturePermissions",
|
|
||||||
principalColumn: "Id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "FK_Users_FeaturePermissions_FeaturePermissionId",
|
|
||||||
table: "Users",
|
|
||||||
column: "FeaturePermissionId",
|
|
||||||
principalTable: "FeaturePermissions",
|
|
||||||
principalColumn: "Id");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_Accounts_FeaturePermissions_FeaturePermissionId",
|
|
||||||
table: "Accounts");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_Channels_ChannelPermissions_PermissionsId",
|
|
||||||
table: "Channels");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_Channels_FeaturePermissions_FeaturePermissionId",
|
|
||||||
table: "Channels");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_Users_FeaturePermissions_FeaturePermissionId",
|
|
||||||
table: "Users");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "ChannelPermissions");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "FeaturePermissions");
|
|
||||||
|
|
||||||
migrationBuilder.DropIndex(
|
|
||||||
name: "IX_Users_FeaturePermissionId",
|
|
||||||
table: "Users");
|
|
||||||
|
|
||||||
migrationBuilder.DropIndex(
|
|
||||||
name: "IX_Channels_FeaturePermissionId",
|
|
||||||
table: "Channels");
|
|
||||||
|
|
||||||
migrationBuilder.DropIndex(
|
|
||||||
name: "IX_Accounts_FeaturePermissionId",
|
|
||||||
table: "Accounts");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "FeaturePermissionId",
|
|
||||||
table: "Users");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "FeaturePermissionId",
|
|
||||||
table: "Channels");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "FeaturePermissionId",
|
|
||||||
table: "Accounts");
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<int[]>(
|
|
||||||
name: "PermissionTags",
|
|
||||||
table: "Users",
|
|
||||||
type: "integer[]",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<int[]>(
|
|
||||||
name: "PermissionTags",
|
|
||||||
table: "Accounts",
|
|
||||||
type: "integer[]",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "PermissionSettings",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<int>(type: "integer", nullable: false)
|
|
||||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
|
||||||
LewdnessFilterLevel = table.Column<int>(type: "integer", nullable: true),
|
|
||||||
LinksAllowed = table.Column<bool>(type: "boolean", nullable: true),
|
|
||||||
MaxAttachmentBytes = table.Column<decimal>(type: "numeric(20,0)", nullable: true),
|
|
||||||
MaxTextChars = table.Column<long>(type: "bigint", nullable: true),
|
|
||||||
MeannessFilterLevel = table.Column<int>(type: "integer", nullable: true),
|
|
||||||
ReactionsPossible = table.Column<bool>(type: "boolean", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_PermissionSettings", x => x.Id);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "FK_Channels_PermissionSettings_PermissionsId",
|
|
||||||
table: "Channels",
|
|
||||||
column: "PermissionsId",
|
|
||||||
principalTable: "PermissionSettings",
|
|
||||||
principalColumn: "Id");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
349
Migrations/20231203193139_channeltype.Designer.cs
generated
349
Migrations/20231203193139_channeltype.Designer.cs
generated
@ -1,349 +0,0 @@
|
|||||||
// <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("20231203193139_channeltype")]
|
|
||||||
partial class ChannelType
|
|
||||||
{
|
|
||||||
/// <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<Guid?>("FeaturePermissionId")
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
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("FeaturePermissionId");
|
|
||||||
|
|
||||||
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<Guid?>("FeaturePermissionId")
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<Guid?>("ParentChannelId")
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<int?>("PermissionsId")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.Property<string>("Protocol")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("FeaturePermissionId");
|
|
||||||
|
|
||||||
b.HasIndex("ParentChannelId");
|
|
||||||
|
|
||||||
b.HasIndex("PermissionsId");
|
|
||||||
|
|
||||||
b.ToTable("Channels");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("vassago.Models.ChannelPermissions", 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("ChannelPermissions");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("vassago.Models.FeaturePermission", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<bool>("Inheritable")
|
|
||||||
.HasColumnType("boolean");
|
|
||||||
|
|
||||||
b.Property<string>("InternalName")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<int?>("InternalTag")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.ToTable("FeaturePermissions");
|
|
||||||
});
|
|
||||||
|
|
||||||
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.User", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<Guid?>("FeaturePermissionId")
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("FeaturePermissionId");
|
|
||||||
|
|
||||||
b.ToTable("Users");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("vassago.Models.Account", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("vassago.Models.FeaturePermission", null)
|
|
||||||
.WithMany("RestrictedToAccounts")
|
|
||||||
.HasForeignKey("FeaturePermissionId");
|
|
||||||
|
|
||||||
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.FeaturePermission", null)
|
|
||||||
.WithMany("RestrictedToChannels")
|
|
||||||
.HasForeignKey("FeaturePermissionId");
|
|
||||||
|
|
||||||
b.HasOne("vassago.Models.Channel", "ParentChannel")
|
|
||||||
.WithMany("SubChannels")
|
|
||||||
.HasForeignKey("ParentChannelId");
|
|
||||||
|
|
||||||
b.HasOne("vassago.Models.ChannelPermissions", "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.User", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("vassago.Models.FeaturePermission", null)
|
|
||||||
.WithMany("RestrictedToUsers")
|
|
||||||
.HasForeignKey("FeaturePermissionId");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("vassago.Models.Channel", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Messages");
|
|
||||||
|
|
||||||
b.Navigation("SubChannels");
|
|
||||||
|
|
||||||
b.Navigation("Users");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("vassago.Models.FeaturePermission", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("RestrictedToAccounts");
|
|
||||||
|
|
||||||
b.Navigation("RestrictedToChannels");
|
|
||||||
|
|
||||||
b.Navigation("RestrictedToUsers");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("vassago.Models.Message", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Attachments");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("vassago.Models.User", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Accounts");
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace vassago.Migrations
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class ChannelType : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "IsDM",
|
|
||||||
table: "Channels");
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<int>(
|
|
||||||
name: "ChannelType",
|
|
||||||
table: "Channels",
|
|
||||||
type: "integer",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "ChannelType",
|
|
||||||
table: "Channels");
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<bool>(
|
|
||||||
name: "IsDM",
|
|
||||||
table: "Channels",
|
|
||||||
type: "boolean",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,266 +0,0 @@
|
|||||||
// <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("20240510202057_channelpermissions_partofchannel")]
|
|
||||||
partial class Channelpermissions_partofchannel
|
|
||||||
{
|
|
||||||
/// <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<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.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.User", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
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.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");
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,228 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace vassago.Migrations
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class Channelpermissions_partofchannel : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_Accounts_FeaturePermissions_FeaturePermissionId",
|
|
||||||
table: "Accounts");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_Channels_ChannelPermissions_PermissionsId",
|
|
||||||
table: "Channels");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_Channels_FeaturePermissions_FeaturePermissionId",
|
|
||||||
table: "Channels");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_Users_FeaturePermissions_FeaturePermissionId",
|
|
||||||
table: "Users");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "ChannelPermissions");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "FeaturePermissions");
|
|
||||||
|
|
||||||
migrationBuilder.DropIndex(
|
|
||||||
name: "IX_Users_FeaturePermissionId",
|
|
||||||
table: "Users");
|
|
||||||
|
|
||||||
migrationBuilder.DropIndex(
|
|
||||||
name: "IX_Channels_FeaturePermissionId",
|
|
||||||
table: "Channels");
|
|
||||||
|
|
||||||
migrationBuilder.DropIndex(
|
|
||||||
name: "IX_Channels_PermissionsId",
|
|
||||||
table: "Channels");
|
|
||||||
|
|
||||||
migrationBuilder.DropIndex(
|
|
||||||
name: "IX_Accounts_FeaturePermissionId",
|
|
||||||
table: "Accounts");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "FeaturePermissionId",
|
|
||||||
table: "Users");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "FeaturePermissionId",
|
|
||||||
table: "Channels");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "FeaturePermissionId",
|
|
||||||
table: "Accounts");
|
|
||||||
|
|
||||||
migrationBuilder.RenameColumn(
|
|
||||||
name: "PermissionsId",
|
|
||||||
table: "Channels",
|
|
||||||
newName: "MeannessFilterLevel");
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<int>(
|
|
||||||
name: "LewdnessFilterLevel",
|
|
||||||
table: "Channels",
|
|
||||||
type: "integer",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<bool>(
|
|
||||||
name: "LinksAllowed",
|
|
||||||
table: "Channels",
|
|
||||||
type: "boolean",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<decimal>(
|
|
||||||
name: "MaxAttachmentBytes",
|
|
||||||
table: "Channels",
|
|
||||||
type: "numeric(20,0)",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<long>(
|
|
||||||
name: "MaxTextChars",
|
|
||||||
table: "Channels",
|
|
||||||
type: "bigint",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<bool>(
|
|
||||||
name: "ReactionsPossible",
|
|
||||||
table: "Channels",
|
|
||||||
type: "boolean",
|
|
||||||
nullable: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "LewdnessFilterLevel",
|
|
||||||
table: "Channels");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "LinksAllowed",
|
|
||||||
table: "Channels");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "MaxAttachmentBytes",
|
|
||||||
table: "Channels");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "MaxTextChars",
|
|
||||||
table: "Channels");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "ReactionsPossible",
|
|
||||||
table: "Channels");
|
|
||||||
|
|
||||||
migrationBuilder.RenameColumn(
|
|
||||||
name: "MeannessFilterLevel",
|
|
||||||
table: "Channels",
|
|
||||||
newName: "PermissionsId");
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<Guid>(
|
|
||||||
name: "FeaturePermissionId",
|
|
||||||
table: "Users",
|
|
||||||
type: "uuid",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<Guid>(
|
|
||||||
name: "FeaturePermissionId",
|
|
||||||
table: "Channels",
|
|
||||||
type: "uuid",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<Guid>(
|
|
||||||
name: "FeaturePermissionId",
|
|
||||||
table: "Accounts",
|
|
||||||
type: "uuid",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "ChannelPermissions",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<int>(type: "integer", nullable: false)
|
|
||||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
|
||||||
LewdnessFilterLevel = table.Column<int>(type: "integer", nullable: true),
|
|
||||||
LinksAllowed = table.Column<bool>(type: "boolean", nullable: true),
|
|
||||||
MaxAttachmentBytes = table.Column<decimal>(type: "numeric(20,0)", nullable: true),
|
|
||||||
MaxTextChars = table.Column<long>(type: "bigint", nullable: true),
|
|
||||||
MeannessFilterLevel = table.Column<int>(type: "integer", nullable: true),
|
|
||||||
ReactionsPossible = table.Column<bool>(type: "boolean", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_ChannelPermissions", x => x.Id);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "FeaturePermissions",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
|
||||||
Inheritable = table.Column<bool>(type: "boolean", nullable: false),
|
|
||||||
InternalName = table.Column<string>(type: "text", nullable: true),
|
|
||||||
InternalTag = table.Column<int>(type: "integer", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_FeaturePermissions", x => x.Id);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Users_FeaturePermissionId",
|
|
||||||
table: "Users",
|
|
||||||
column: "FeaturePermissionId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Channels_FeaturePermissionId",
|
|
||||||
table: "Channels",
|
|
||||||
column: "FeaturePermissionId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Channels_PermissionsId",
|
|
||||||
table: "Channels",
|
|
||||||
column: "PermissionsId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Accounts_FeaturePermissionId",
|
|
||||||
table: "Accounts",
|
|
||||||
column: "FeaturePermissionId");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "FK_Accounts_FeaturePermissions_FeaturePermissionId",
|
|
||||||
table: "Accounts",
|
|
||||||
column: "FeaturePermissionId",
|
|
||||||
principalTable: "FeaturePermissions",
|
|
||||||
principalColumn: "Id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "FK_Channels_ChannelPermissions_PermissionsId",
|
|
||||||
table: "Channels",
|
|
||||||
column: "PermissionsId",
|
|
||||||
principalTable: "ChannelPermissions",
|
|
||||||
principalColumn: "Id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "FK_Channels_FeaturePermissions_FeaturePermissionId",
|
|
||||||
table: "Channels",
|
|
||||||
column: "FeaturePermissionId",
|
|
||||||
principalTable: "FeaturePermissions",
|
|
||||||
principalColumn: "Id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "FK_Users_FeaturePermissions_FeaturePermissionId",
|
|
||||||
table: "Users",
|
|
||||||
column: "FeaturePermissionId",
|
|
||||||
principalTable: "FeaturePermissions",
|
|
||||||
principalColumn: "Id");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
271
Migrations/20250204004906_cascade.Designer.cs
generated
271
Migrations/20250204004906_cascade.Designer.cs
generated
@ -1,271 +0,0 @@
|
|||||||
// <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("20250204004906_cascade")]
|
|
||||||
partial class Cascade
|
|
||||||
{
|
|
||||||
/// <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<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.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.User", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.ToTable("Users");
|
|
||||||
});
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,133 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace vassago.Migrations
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class Cascade : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_Accounts_Channels_SeenInChannelId",
|
|
||||||
table: "Accounts");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_Accounts_Users_IsUserId",
|
|
||||||
table: "Accounts");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_Attachments_Messages_MessageId",
|
|
||||||
table: "Attachments");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_Channels_Channels_ParentChannelId",
|
|
||||||
table: "Channels");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_Messages_Channels_ChannelId",
|
|
||||||
table: "Messages");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "FK_Accounts_Channels_SeenInChannelId",
|
|
||||||
table: "Accounts",
|
|
||||||
column: "SeenInChannelId",
|
|
||||||
principalTable: "Channels",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "FK_Accounts_Users_IsUserId",
|
|
||||||
table: "Accounts",
|
|
||||||
column: "IsUserId",
|
|
||||||
principalTable: "Users",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "FK_Attachments_Messages_MessageId",
|
|
||||||
table: "Attachments",
|
|
||||||
column: "MessageId",
|
|
||||||
principalTable: "Messages",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "FK_Channels_Channels_ParentChannelId",
|
|
||||||
table: "Channels",
|
|
||||||
column: "ParentChannelId",
|
|
||||||
principalTable: "Channels",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "FK_Messages_Channels_ChannelId",
|
|
||||||
table: "Messages",
|
|
||||||
column: "ChannelId",
|
|
||||||
principalTable: "Channels",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_Accounts_Channels_SeenInChannelId",
|
|
||||||
table: "Accounts");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_Accounts_Users_IsUserId",
|
|
||||||
table: "Accounts");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_Attachments_Messages_MessageId",
|
|
||||||
table: "Attachments");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_Channels_Channels_ParentChannelId",
|
|
||||||
table: "Channels");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_Messages_Channels_ChannelId",
|
|
||||||
table: "Messages");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "FK_Accounts_Channels_SeenInChannelId",
|
|
||||||
table: "Accounts",
|
|
||||||
column: "SeenInChannelId",
|
|
||||||
principalTable: "Channels",
|
|
||||||
principalColumn: "Id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "FK_Accounts_Users_IsUserId",
|
|
||||||
table: "Accounts",
|
|
||||||
column: "IsUserId",
|
|
||||||
principalTable: "Users",
|
|
||||||
principalColumn: "Id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "FK_Attachments_Messages_MessageId",
|
|
||||||
table: "Attachments",
|
|
||||||
column: "MessageId",
|
|
||||||
principalTable: "Messages",
|
|
||||||
principalColumn: "Id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "FK_Channels_Channels_ParentChannelId",
|
|
||||||
table: "Channels",
|
|
||||||
column: "ParentChannelId",
|
|
||||||
principalTable: "Channels",
|
|
||||||
principalColumn: "Id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "FK_Messages_Channels_ChannelId",
|
|
||||||
table: "Messages",
|
|
||||||
column: "ChannelId",
|
|
||||||
principalTable: "Channels",
|
|
||||||
principalColumn: "Id");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
378
Migrations/20250423002254_UAC.Designer.cs
generated
378
Migrations/20250423002254_UAC.Designer.cs
generated
@ -1,378 +0,0 @@
|
|||||||
// <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("20250423002254_UAC")]
|
|
||||||
partial class UAC
|
|
||||||
{
|
|
||||||
/// <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("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.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.UAC", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<string>("DisplayName")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<Guid>("OwnerId")
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
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("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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,131 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace vassago.Migrations
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class UAC : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "UACs",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
|
||||||
OwnerId = table.Column<Guid>(type: "uuid", nullable: false),
|
|
||||||
DisplayName = table.Column<string>(type: "text", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_UACs", x => x.Id);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "AccountUAC",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
AccountInChannelsId = table.Column<Guid>(type: "uuid", nullable: false),
|
|
||||||
UACsId = table.Column<Guid>(type: "uuid", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_AccountUAC", x => new { x.AccountInChannelsId, x.UACsId });
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_AccountUAC_Accounts_AccountInChannelsId",
|
|
||||||
column: x => x.AccountInChannelsId,
|
|
||||||
principalTable: "Accounts",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_AccountUAC_UACs_UACsId",
|
|
||||||
column: x => x.UACsId,
|
|
||||||
principalTable: "UACs",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "ChannelUAC",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
ChannelsId = table.Column<Guid>(type: "uuid", nullable: false),
|
|
||||||
UACsId = table.Column<Guid>(type: "uuid", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_ChannelUAC", x => new { x.ChannelsId, x.UACsId });
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_ChannelUAC_Channels_ChannelsId",
|
|
||||||
column: x => x.ChannelsId,
|
|
||||||
principalTable: "Channels",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_ChannelUAC_UACs_UACsId",
|
|
||||||
column: x => x.UACsId,
|
|
||||||
principalTable: "UACs",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "UACUser",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
UACsId = table.Column<Guid>(type: "uuid", nullable: false),
|
|
||||||
UsersId = table.Column<Guid>(type: "uuid", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_UACUser", x => new { x.UACsId, x.UsersId });
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_UACUser_UACs_UACsId",
|
|
||||||
column: x => x.UACsId,
|
|
||||||
principalTable: "UACs",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_UACUser_Users_UsersId",
|
|
||||||
column: x => x.UsersId,
|
|
||||||
principalTable: "Users",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_AccountUAC_UACsId",
|
|
||||||
table: "AccountUAC",
|
|
||||||
column: "UACsId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_ChannelUAC_UACsId",
|
|
||||||
table: "ChannelUAC",
|
|
||||||
column: "UACsId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_UACUser_UsersId",
|
|
||||||
table: "UACUser",
|
|
||||||
column: "UsersId");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "AccountUAC");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "ChannelUAC");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "UACUser");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "UACs");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,375 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|
||||||
using vassago.Models;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace vassago.Migrations
|
|
||||||
{
|
|
||||||
[DbContext(typeof(ChattingContext))]
|
|
||||||
partial class ChattingContextModelSnapshot : ModelSnapshot
|
|
||||||
{
|
|
||||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder
|
|
||||||
.HasAnnotation("ProductVersion", "7.0.5")
|
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
|
||||||
|
|
||||||
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.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.UAC", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<string>("DisplayName")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<Guid>("OwnerId")
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
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("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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
namespace vassago.Models;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
public class Account
|
|
||||||
{
|
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
|
||||||
public Guid Id { get; set; }
|
|
||||||
public string ExternalId { get; set; }
|
|
||||||
public string Username { get; set; }
|
|
||||||
private string _displayName = null;
|
|
||||||
public string DisplayName
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _displayName ?? Username;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_displayName = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public bool IsBot { get; set; } //webhook counts
|
|
||||||
public Channel SeenInChannel { get; set; }
|
|
||||||
public string Protocol { get; set; }
|
|
||||||
public List<UAC> UACs { get; set; }
|
|
||||||
[JsonIgnore]
|
|
||||||
public User IsUser {get; set;}
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
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; }
|
|
||||||
}
|
|
@ -1,116 +0,0 @@
|
|||||||
namespace vassago.Models;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Components.Web;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using static vassago.Models.Enumerations;
|
|
||||||
|
|
||||||
public class Channel
|
|
||||||
{
|
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
|
||||||
public Guid Id { get; set; }
|
|
||||||
public string ExternalId { get; set; }
|
|
||||||
public string DisplayName { get; set; }
|
|
||||||
[DeleteBehavior(DeleteBehavior.Cascade)]
|
|
||||||
public List<Channel> SubChannels { get; set; }
|
|
||||||
[JsonIgnore]
|
|
||||||
public Channel ParentChannel { get; set; }
|
|
||||||
public string Protocol { get; set; }
|
|
||||||
[DeleteBehavior(DeleteBehavior.Cascade)]
|
|
||||||
public List<Message> Messages { get; set; }
|
|
||||||
[DeleteBehavior(DeleteBehavior.Cascade)]
|
|
||||||
public List<Account> Users { get; set; }
|
|
||||||
public ChannelType ChannelType {get; set; }
|
|
||||||
|
|
||||||
//Permissions
|
|
||||||
public ulong? MaxAttachmentBytes { get; set; }
|
|
||||||
public uint? MaxTextChars { get; set; }
|
|
||||||
public bool? LinksAllowed { get; set; }
|
|
||||||
public bool? ReactionsPossible { get; set; }
|
|
||||||
public Enumerations.LewdnessFilterLevel? LewdnessFilterLevel { get; set; }
|
|
||||||
public Enumerations.MeannessFilterLevel? MeannessFilterLevel { get; set; }
|
|
||||||
|
|
||||||
public List<UAC> UACs { get; set; }
|
|
||||||
|
|
||||||
[NonSerialized]
|
|
||||||
public Func<string, string, Task> SendFile;
|
|
||||||
|
|
||||||
[NonSerialized]
|
|
||||||
public Func<string, Task> SendMessage;
|
|
||||||
|
|
||||||
|
|
||||||
public DefinitePermissionSettings EffectivePermissions
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
var path = new Stack<Channel>(); //omg i actually get to use a data structure from university
|
|
||||||
var walker = this;
|
|
||||||
path.Push(this);
|
|
||||||
while(walker.ParentChannel != null)
|
|
||||||
{
|
|
||||||
walker = walker.ParentChannel;
|
|
||||||
path.Push(walker);
|
|
||||||
}
|
|
||||||
DefinitePermissionSettings toReturn = new DefinitePermissionSettings();
|
|
||||||
|
|
||||||
while(path.Count > 0)
|
|
||||||
{
|
|
||||||
walker = path.Pop();
|
|
||||||
toReturn.LewdnessFilterLevel = walker.LewdnessFilterLevel ?? toReturn.LewdnessFilterLevel;
|
|
||||||
toReturn.MeannessFilterLevel = walker.MeannessFilterLevel ?? toReturn.MeannessFilterLevel;
|
|
||||||
toReturn.LinksAllowed = walker.LinksAllowed ?? toReturn.LinksAllowed;
|
|
||||||
toReturn.MaxAttachmentBytes = walker.MaxAttachmentBytes ?? toReturn.MaxAttachmentBytes;
|
|
||||||
toReturn.MaxTextChars = walker.MaxTextChars ?? toReturn.MaxTextChars;
|
|
||||||
toReturn.ReactionsPossible = walker.ReactionsPossible ?? toReturn.ReactionsPossible;
|
|
||||||
}
|
|
||||||
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public string LineageSummary
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if(this.ParentChannel != null)
|
|
||||||
{
|
|
||||||
return this.ParentChannel.LineageSummary + '/' + this.DisplayName;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return this.Protocol;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///<summary>
|
|
||||||
///break self-referencing loops for library-agnostic serialization
|
|
||||||
///</summary>
|
|
||||||
public Channel AsSerializable()
|
|
||||||
{
|
|
||||||
var toReturn = this.MemberwiseClone() as Channel;
|
|
||||||
toReturn.ParentChannel = null;
|
|
||||||
if(toReturn.Users?.Count > 0)
|
|
||||||
{
|
|
||||||
foreach (var account in toReturn.Users)
|
|
||||||
{
|
|
||||||
account.SeenInChannel = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class DefinitePermissionSettings
|
|
||||||
{
|
|
||||||
public ulong MaxAttachmentBytes { get; set; }
|
|
||||||
public uint MaxTextChars { get; set; }
|
|
||||||
public bool LinksAllowed { get; set; }
|
|
||||||
public bool ReactionsPossible { get; set; }
|
|
||||||
public Enumerations.LewdnessFilterLevel LewdnessFilterLevel { get; set; }
|
|
||||||
public Enumerations.MeannessFilterLevel MeannessFilterLevel { get; set; }
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
namespace vassago.Models;
|
|
||||||
|
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
public class ChattingContext : DbContext
|
|
||||||
{
|
|
||||||
public DbSet<Attachment> Attachments { get; set; }
|
|
||||||
public DbSet<Channel> Channels { get; set; }
|
|
||||||
public DbSet<UAC> UACs { get; set; }
|
|
||||||
public DbSet<Message> Messages { get; set; }
|
|
||||||
public DbSet<Account> Accounts { get; set; }
|
|
||||||
public DbSet<User> Users { get; set; }
|
|
||||||
|
|
||||||
public ChattingContext(DbContextOptions<ChattingContext> options) : base(options) { }
|
|
||||||
public ChattingContext() : base() { }
|
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
|
||||||
{
|
|
||||||
optionsBuilder.UseNpgsql(Shared.DBConnectionString);
|
|
||||||
//.EnableSensitiveDataLogging(true); //"sensitive" is one thing. writing "did something" every time you think a thought is a different thing.
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,67 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace vassago.Models;
|
|
||||||
|
|
||||||
public static class Enumerations
|
|
||||||
{
|
|
||||||
public enum LewdnessFilterLevel
|
|
||||||
{
|
|
||||||
[Description("this is a christian minecraft server 🙏")]
|
|
||||||
Strict,
|
|
||||||
[Description("G-Rated")]
|
|
||||||
G,
|
|
||||||
[Description("polite company")]
|
|
||||||
Moderate,
|
|
||||||
[Description(";) ;) ;)")]
|
|
||||||
Unrestricted
|
|
||||||
}
|
|
||||||
public enum MeannessFilterLevel
|
|
||||||
{
|
|
||||||
[Description("good vibes only")]
|
|
||||||
Strict,
|
|
||||||
[Description("a bit cheeky")]
|
|
||||||
Medium,
|
|
||||||
[Description("387.44m mi of printed circuits")]
|
|
||||||
Unrestricted
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum ChannelType
|
|
||||||
{
|
|
||||||
[Description("Normal")]
|
|
||||||
Normal,
|
|
||||||
[Description("DM")]
|
|
||||||
DM,
|
|
||||||
[Description("protocol psuedo-channel")]
|
|
||||||
Protocol,
|
|
||||||
[Description("organizational psuedo-channel")]
|
|
||||||
OU
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetDescription<T>(this T enumerationValue)
|
|
||||||
where T : struct
|
|
||||||
{
|
|
||||||
Type type = enumerationValue.GetType();
|
|
||||||
if (!type.IsEnum)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("EnumerationValue must be of Enum type", nameof(enumerationValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
//Tries to find a DescriptionAttribute for a potential friendly name
|
|
||||||
//for the enum
|
|
||||||
MemberInfo[] memberInfo = type.GetMember(enumerationValue.ToString());
|
|
||||||
if (memberInfo != null && memberInfo.Length > 0)
|
|
||||||
{
|
|
||||||
object[] attrs = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
|
|
||||||
|
|
||||||
if (attrs != null && attrs.Length > 0)
|
|
||||||
{
|
|
||||||
//Pull out the description value
|
|
||||||
return ((DescriptionAttribute)attrs[0]).Description;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//If we have no description attribute, just return the ToString of the enum
|
|
||||||
return enumerationValue.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
namespace vassago.Models;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Discord.WebSocket;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
public class Message
|
|
||||||
{
|
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
|
||||||
public Guid Id { get; set; }
|
|
||||||
public string Protocol { get; set; }
|
|
||||||
public string ExternalId { get; set; }
|
|
||||||
public string Content { get; set; }
|
|
||||||
public bool MentionsMe { get; set; }
|
|
||||||
public DateTimeOffset Timestamp { get; set; }
|
|
||||||
public bool ActedOn { get; set; }
|
|
||||||
[DeleteBehavior(DeleteBehavior.Cascade)]
|
|
||||||
public List<Attachment> Attachments { get; set; }
|
|
||||||
public Account Author { get; set; }
|
|
||||||
public Channel Channel { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
//TODO: these are nicities to make it OOP, but it couples them with their respective platform interfaces (and connections!)
|
|
||||||
[NonSerialized]
|
|
||||||
public Func<string, Task> Reply;
|
|
||||||
|
|
||||||
[NonSerialized]
|
|
||||||
public Func<string, Task> React;
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
namespace vassago.Models;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
using vassago.Models;
|
|
||||||
|
|
||||||
public class UAC
|
|
||||||
{
|
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
|
||||||
public Guid Id { get; set; }
|
|
||||||
|
|
||||||
///<summary indulgence="haiku-like">
|
|
||||||
///behaviors will have
|
|
||||||
///a hardcoded ID thing
|
|
||||||
///so they can find theirs.
|
|
||||||
///</summary>
|
|
||||||
public Guid OwnerId { get; set;}
|
|
||||||
public string DisplayName { get; set; }
|
|
||||||
public List<Account> AccountInChannels { get; set; }
|
|
||||||
public List<Channel> Channels { get; set; }
|
|
||||||
public List<User> Users { get; set; }
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
namespace vassago.Models;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
using System.Reflection;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
public class User
|
|
||||||
{
|
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
|
||||||
public Guid Id { get; set; }
|
|
||||||
[DeleteBehavior(DeleteBehavior.Cascade)]
|
|
||||||
public List<Account> Accounts { get; set; }
|
|
||||||
|
|
||||||
public List<UAC> UACs { get; set; }
|
|
||||||
|
|
||||||
//if I ever get lots and lots of tags, or some automatic way to register a feature's arbitrary tags, then I can move this off.
|
|
||||||
//public bool Tag_CanTwitchSummon { get; set; }
|
|
||||||
|
|
||||||
public string DisplayName
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (Accounts?.Any() ?? false)
|
|
||||||
{
|
|
||||||
return Accounts.Select(a => a.DisplayName).Distinct()
|
|
||||||
.MaxBy(distinctName =>
|
|
||||||
Accounts.Select(a => a.DisplayName)
|
|
||||||
.Where(selectedName => selectedName == distinctName).Count()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return $"[accountless {Id}]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
377
Program.cs
377
Program.cs
@ -1,56 +1,341 @@
|
|||||||
using Microsoft.AspNetCore.Mvc.Razor;
|
//https://discord.com/oauth2/authorize?client_id=913003037348491264&permissions=274877942784&scope=bot%20messages.read
|
||||||
using Microsoft.EntityFrameworkCore;
|
using System;
|
||||||
using Microsoft.AspNetCore.Mvc.NewtonsoftJson;
|
using System.Collections.Generic;
|
||||||
using vassago.Models;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Net;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Discord;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using Discord.Net;
|
||||||
|
|
||||||
#pragma warning disable CA2254
|
namespace silverworker_discord
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
|
||||||
|
|
||||||
// Add services to the container.
|
|
||||||
builder.Services.AddControllersWithViews();
|
|
||||||
builder.Services.AddSingleton<IHostedService, vassago.ConsoleService>();
|
|
||||||
builder.Services.AddDbContext<ChattingContext>();
|
|
||||||
builder.Services.AddControllers().AddNewtonsoftJson(options => {
|
|
||||||
options.SerializerSettings.ReferenceLoopHandling =
|
|
||||||
Newtonsoft.Json.ReferenceLoopHandling.Ignore;
|
|
||||||
});
|
|
||||||
builder.Services.AddProblemDetails();
|
|
||||||
builder.Services.Configure<RazorViewEngineOptions>(o => {
|
|
||||||
o.ViewLocationFormats.Clear();
|
|
||||||
o.ViewLocationFormats.Add("/WebInterface/Views/{1}/{0}" + RazorViewEngine.ViewExtension);
|
|
||||||
o.ViewLocationFormats.Add("/WebInterface/Views/Shared/{0}" + RazorViewEngine.ViewExtension);
|
|
||||||
});
|
|
||||||
builder.Services.AddSwaggerGen();
|
|
||||||
|
|
||||||
var app = builder.Build();
|
|
||||||
|
|
||||||
// Configure the HTTP request pipeline.
|
|
||||||
if (!app.Environment.IsDevelopment())
|
|
||||||
{
|
{
|
||||||
app.UseExceptionHandler("/Home/Error");
|
class Program
|
||||||
|
{
|
||||||
|
private DiscordSocketClient _client;
|
||||||
|
private bool eventsSignedUp = false;
|
||||||
|
private Random r = new Random();
|
||||||
|
|
||||||
|
IConfigurationRoot config = new ConfigurationBuilder()
|
||||||
|
.AddJsonFile("appsettings.json", true, true)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
public static void Main(string[] args)
|
||||||
|
=> new Program().MainAsync().GetAwaiter().GetResult();
|
||||||
|
private Task Log(LogMessage msg)
|
||||||
|
{
|
||||||
|
Console.WriteLine(msg.ToString());
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
public async Task MainAsync()
|
||||||
|
{
|
||||||
|
#if !DEBUG
|
||||||
|
Process[] processes = Process.GetProcesses();
|
||||||
|
Process currentProc = Process.GetCurrentProcess();
|
||||||
|
Console.WriteLine("Current proccess: {0}", currentProc.ProcessName);
|
||||||
|
foreach (Process process in processes)
|
||||||
|
{
|
||||||
|
if (currentProc.ProcessName == process.ProcessName && currentProc.Id != process.Id)
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine($"{DateTime.Now} - Another instance of this process is already running: {process.Id} (I'm {currentProc.Id})");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
Conversion.Converter.Load(config["exchangePairsLocation"]);
|
||||||
|
|
||||||
|
_client = new DiscordSocketClient(new DiscordSocketConfig(){GatewayIntents = GatewayIntents.All});
|
||||||
|
|
||||||
|
_client.Log += Log;
|
||||||
|
|
||||||
|
_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.UserJoined += UserJoined;
|
||||||
|
//_client.ButtonExecuted += MyButtonHandler;
|
||||||
|
_client.SlashCommandExecuted += SlashCommandsHelper.SlashCommandHandler;
|
||||||
|
SlashCommandsHelper.Register(_client).GetAwaiter().GetResult();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine("bot appears to be RE connected, so I'm not going to sign up twice");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await _client.LoginAsync(TokenType.Bot, config["token"]);
|
||||||
|
await _client.StartAsync();
|
||||||
|
|
||||||
|
// Block this task until the program is closed.
|
||||||
|
await Task.Delay(-1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
app.UseStaticFiles();
|
#pragma warning disable 4014 //the "you're not awaiting this" warning. yeah I know, that's the beauty of an async method lol
|
||||||
app.UseRouting();
|
#pragma warning disable 1998 //the "it's async but you're not awaiting anything".
|
||||||
app.UseAuthorization();
|
private async Task MessageReceived(SocketMessage messageParam)
|
||||||
app.MapControllerRoute(
|
#pragma warning restore 1998
|
||||||
name: "default",
|
|
||||||
pattern: "{controller=Home}/{action=Index}/{id?}");
|
|
||||||
|
|
||||||
app.UseSwagger();
|
|
||||||
|
|
||||||
app.UseSwaggerUI(c =>
|
|
||||||
{
|
{
|
||||||
c.SwaggerEndpoint("/swagger/v1/swagger.json", "api");
|
var message = messageParam as SocketUserMessage;
|
||||||
});
|
if (message == null) return;
|
||||||
|
if (message.Author.Id == _client.CurrentUser.Id) return;
|
||||||
|
|
||||||
app.UseExceptionHandler();
|
Console.WriteLine($"#{message.Channel}[{DateTime.Now}][{message.Author.Username} [id={message.Author.Id}]][msg id: {message.Id}] {message.Content}");
|
||||||
app.UseStatusCodePages();
|
|
||||||
|
|
||||||
if (app.Environment.IsDevelopment())
|
if (message.Author.IsWebhook || message.Author.IsBot)
|
||||||
{
|
{
|
||||||
app.UseDeveloperExceptionPage();
|
if (message.Author.Id == 159985870458322944) //MEE6
|
||||||
|
{
|
||||||
|
if (message.Content?.Contains("you just advanced") == true)
|
||||||
|
{
|
||||||
|
var newText = Regex.Replace(message.Content, "<[^>]*>", message.Author.Username);
|
||||||
|
newText = Regex.Replace(newText, "level [\\d]+", "level -1");
|
||||||
|
Features.mock(newText, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var didThing = false;
|
||||||
|
var contentWithoutMention = message.Content;
|
||||||
|
var mentionedMe = false;
|
||||||
|
if (message.MentionedUsers?.FirstOrDefault(muid => muid.Id == _client.CurrentUser.Id) != null)
|
||||||
|
{
|
||||||
|
var mentionOfMe = "<@" + _client.CurrentUser.Id + ">";
|
||||||
|
contentWithoutMention = message.Content.Replace(mentionOfMe + " ", null);
|
||||||
|
contentWithoutMention = contentWithoutMention.Replace(mentionOfMe, null);
|
||||||
|
mentionedMe = true;
|
||||||
|
}
|
||||||
|
var wordLikes = message.Content.Split(' ', StringSplitOptions.TrimEntries);
|
||||||
|
var links = wordLikes?.Where(wl => Uri.IsWellFormedUriString(wl, UriKind.Absolute)).Select(wl => new Uri(wl));
|
||||||
|
if (links != null && links.Count() > 0)
|
||||||
|
{
|
||||||
|
foreach (var link in links)
|
||||||
|
{
|
||||||
|
if (link.Host.EndsWith(".tiktok.com"))
|
||||||
|
{
|
||||||
|
Features.detiktokify(link, message);
|
||||||
|
didThing = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
app.Run();
|
if (message.Attachments?.Count > 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{message.Attachments.Count} attachments");
|
||||||
|
var appleReactions = false;
|
||||||
|
foreach (var att in message.Attachments)
|
||||||
|
{
|
||||||
|
if (att.Filename?.EndsWith(".heic") == true)
|
||||||
|
{
|
||||||
|
Features.deheic(message, att);
|
||||||
|
appleReactions = true;
|
||||||
|
didThing = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (appleReactions)
|
||||||
|
{
|
||||||
|
message.AddReactionAsync(new Emoji("\U0001F34F"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var msgText = message.Content?.ToLower();
|
||||||
|
if (!string.IsNullOrWhiteSpace(msgText))
|
||||||
|
{
|
||||||
|
if (Regex.IsMatch(msgText, "\\bcloud( |-)?native\\b", RegexOptions.IgnoreCase) ||
|
||||||
|
Regex.IsMatch(msgText, "\\benterprise( |-)?(level|solution)\\b", RegexOptions.IgnoreCase))
|
||||||
|
{
|
||||||
|
switch (r.Next(2))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
await message.AddReactionAsync(new Emoji("\uD83E\uDD2E")); //vomit emoji
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
await message.AddReactionAsync(new Emoji("\uD83C\uDDE7")); //B emoji
|
||||||
|
await message.AddReactionAsync(new Emoji("\uD83C\uDDE6")); //A
|
||||||
|
await message.AddReactionAsync(new Emoji("\uD83C\uDDF3")); //N
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
didThing = true;
|
||||||
|
}
|
||||||
|
if (Regex.IsMatch(msgText, "^(s?he|(yo)?u|y'?all) thinks? i'?m (playin|jokin|kiddin)g?$", RegexOptions.IgnoreCase))
|
||||||
|
{
|
||||||
|
await message.Channel.SendMessageAsync("I believed you for a second, but then you assured me you's a \uD83C\uDDE7 \uD83C\uDDEE \uD83C\uDDF9 \uD83C\uDDE8 \uD83C\uDDED");
|
||||||
|
didThing = true;
|
||||||
|
}
|
||||||
|
if (Regex.IsMatch(msgText, "\\bskynet\\b", RegexOptions.IgnoreCase))
|
||||||
|
{
|
||||||
|
Features.Skynet(message);
|
||||||
|
didThing = true;
|
||||||
|
}
|
||||||
|
if (Regex.IsMatch(msgText, "\\bchatgpt\\b", RegexOptions.IgnoreCase))
|
||||||
|
{
|
||||||
|
message.Channel.SendMessageAsync("chatGPT is **weak**. also, are we done comparing every little if-then-else to skynet?");
|
||||||
|
didThing = true;
|
||||||
|
}
|
||||||
|
if (Regex.IsMatch(msgText, "\\bi need (an? )?(peptalk|inspiration|ego-?boost)\\b", RegexOptions.IgnoreCase))
|
||||||
|
{
|
||||||
|
Console.WriteLine("peptalk");
|
||||||
|
Features.peptalk(message);
|
||||||
|
didThing = true;
|
||||||
|
}
|
||||||
|
if (Regex.IsMatch(msgText, "\\bwish me luck\\b", RegexOptions.IgnoreCase))
|
||||||
|
{
|
||||||
|
if (r.Next(20) == 0)
|
||||||
|
{
|
||||||
|
await message.AddReactionAsync(new Emoji("\U0001f340"));//4-leaf clover
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await message.AddReactionAsync(new Emoji("☘️"));
|
||||||
|
}
|
||||||
|
didThing = true;
|
||||||
|
}
|
||||||
|
if (Regex.IsMatch(msgText, "\\bgaslight(ing)?\\b", RegexOptions.IgnoreCase))
|
||||||
|
{
|
||||||
|
message.Channel.SendMessageAsync("that's not what gaslight means. Did you mean \"say something that (you believe) is wrong\"?");
|
||||||
|
didThing = true;
|
||||||
|
}
|
||||||
|
if (msgText.Contains("!qrplz "))
|
||||||
|
{
|
||||||
|
Features.qrify(message.Content.Substring("!qrplz ".Length + msgText.IndexOf("!qrplz ")), message);
|
||||||
|
didThing = true;
|
||||||
|
}
|
||||||
|
if (msgText.Contains("!freedomunits "))
|
||||||
|
{
|
||||||
|
Features.Convert(message, contentWithoutMention);
|
||||||
|
didThing = true;
|
||||||
|
}
|
||||||
|
if (Regex.IsMatch(msgText, "!joke\\b"))
|
||||||
|
{
|
||||||
|
Features.Joke(message);
|
||||||
|
didThing = true;
|
||||||
|
}
|
||||||
|
if (Regex.IsMatch(msgText, "!pulse ?check\\b"))
|
||||||
|
{
|
||||||
|
message.Channel.SendFileAsync("assets/ekgblip.png");
|
||||||
|
Console.WriteLine(Conversion.Converter.DebugInfo());
|
||||||
|
didThing = true;
|
||||||
|
}
|
||||||
|
if (mentionedMe && (Regex.IsMatch(msgText, "\\brecipe for .+") || Regex.IsMatch(msgText, ".+ recipe\\b")))
|
||||||
|
{
|
||||||
|
Features.Recipe(message);
|
||||||
|
didThing = true;
|
||||||
|
}
|
||||||
|
if (msgText.Contains("cognitive dissonance") == true)
|
||||||
|
{
|
||||||
|
message.ReplyAsync("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"))
|
||||||
|
{
|
||||||
|
Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await message.Channel.SendMessageAsync("mother.");
|
||||||
|
await Task.Delay(3000);
|
||||||
|
await message.Channel.SendMessageAsync("oh, longest? I thought you said fattest.");
|
||||||
|
});
|
||||||
|
didThing = true;
|
||||||
|
}
|
||||||
|
if (Regex.IsMatch(msgText, "\\bthank (yo)?u\\b", RegexOptions.IgnoreCase) &&
|
||||||
|
(mentionedMe || Regex.IsMatch(msgText, "\\b(sh?tik)?bot\\b", RegexOptions.IgnoreCase)))
|
||||||
|
{
|
||||||
|
switch (r.Next(4))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
message.Channel.SendMessageAsync("you're welcome, citizen!");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
message.AddReactionAsync(new Emoji("☺"));
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
message.AddReactionAsync(new Emoji("\U0001F607")); //smiling face with halo
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
switch (r.Next(9))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
message.AddReactionAsync(new Emoji("❤")); //normal heart, usually rendered red
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
message.AddReactionAsync(new Emoji("\U0001F9E1")); //orange heart
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
message.AddReactionAsync(new Emoji("\U0001F49B")); //yellow heart
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
message.AddReactionAsync(new Emoji("\U0001F49A")); //green heart
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
message.AddReactionAsync(new Emoji("\U0001F499")); //blue heart
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
message.AddReactionAsync(new Emoji("\U0001F49C")); //purple heart
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
message.AddReactionAsync(new Emoji("\U0001F90E")); //brown heart
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
message.AddReactionAsync(new Emoji("\U0001F5A4")); //black heart
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
message.AddReactionAsync(new Emoji("\U0001F90D")); //white heart
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
didThing = true;
|
||||||
|
#pragma warning restore 4014
|
||||||
|
}
|
||||||
|
// if (didThing == false && mentionedMe && contentWithoutMention.Contains("how long has that been there?"))
|
||||||
|
// {
|
||||||
|
// await message.Channel.SendMessageAsync("text", false, null, null, null, null, new ComponentBuilder().WithButton("label", "custom-id").Build());
|
||||||
|
// didThing = true;
|
||||||
|
// }
|
||||||
|
if (didThing == false && mentionedMe && contentWithoutMention.Contains('?'))
|
||||||
|
{
|
||||||
|
Console.WriteLine("providing bullshit nonanswer / admitting uselessness");
|
||||||
|
var responses = new List<string>(){
|
||||||
|
@"Well, that's a great question, and there are certainly many different possible answers. Ultimately, the decision will depend on a variety of factors, including your personal interests and goals, as well as any practical considerations (like the economy). I encourage you to do your research, speak with experts and educators, and explore your options before making a decision that's right for you.",
|
||||||
|
@"┐(゚ ~゚ )┌",@"¯\_(ツ)_/¯",@"╮ (. ❛ ᴗ ❛.) ╭", @"╮(╯ _╰ )╭"
|
||||||
|
};
|
||||||
|
await message.Channel.SendMessageAsync(responses[r.Next(responses.Count)]);
|
||||||
|
didThing = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private Task UserJoined(SocketGuildUser arg)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"user joined: {arg.Nickname}. Guid: {arg.Guild.Id}. Channel: {arg.Guild.DefaultChannel}");
|
||||||
|
var abbreviatedNickname = arg.Nickname;
|
||||||
|
if (arg.Nickname.Length > 3)
|
||||||
|
{
|
||||||
|
abbreviatedNickname = arg.Nickname.Substring(0, arg.Nickname.Length / 3);
|
||||||
|
}
|
||||||
|
Console.WriteLine($"imma call him {abbreviatedNickname}");
|
||||||
|
return arg.Guild.DefaultChannel.SendMessageAsync($"oh hey {abbreviatedNickname}- IPLAYTHESEALOFORICHALCOS <:ORICHALCOS:852749196633309194>");
|
||||||
|
}
|
||||||
|
private async Task ButtonHandler(SocketMessageComponent component)
|
||||||
|
{
|
||||||
|
switch(component.Data.CustomId)
|
||||||
|
{
|
||||||
|
case "custom-id":
|
||||||
|
await component.RespondAsync($"{component.User.Mention}, it's been here the whole time!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -1,37 +0,0 @@
|
|||||||
{
|
|
||||||
"iisSettings": {
|
|
||||||
"windowsAuthentication": false,
|
|
||||||
"anonymousAuthentication": true,
|
|
||||||
"iisExpress": {
|
|
||||||
"applicationUrl": "http://localhost:42619",
|
|
||||||
"sslPort": 44354
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"profiles": {
|
|
||||||
"http": {
|
|
||||||
"commandName": "Project",
|
|
||||||
"dotnetRunMessages": true,
|
|
||||||
"launchBrowser": true,
|
|
||||||
"applicationUrl": "http://localhost:5093",
|
|
||||||
"environmentVariables": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"https": {
|
|
||||||
"commandName": "Project",
|
|
||||||
"dotnetRunMessages": true,
|
|
||||||
"launchBrowser": true,
|
|
||||||
"applicationUrl": "https://localhost:7206;http://localhost:5093",
|
|
||||||
"environmentVariables": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"IIS Express": {
|
|
||||||
"commandName": "IISExpress",
|
|
||||||
"launchBrowser": true,
|
|
||||||
"environmentVariables": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,412 +0,0 @@
|
|||||||
//https://discord.com/oauth2/authorize?client_id=913003037348491264&permissions=274877942784&scope=bot%20messages.read
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Discord;
|
|
||||||
using Discord.WebSocket;
|
|
||||||
using vassago.Models;
|
|
||||||
using vassago.Behavior;
|
|
||||||
using Discord.Rest;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Reactive.Linq;
|
|
||||||
|
|
||||||
namespace vassago.ProtocolInterfaces.DiscordInterface;
|
|
||||||
|
|
||||||
//data received
|
|
||||||
//translate data to internal type
|
|
||||||
//store
|
|
||||||
//ship off to behaver
|
|
||||||
|
|
||||||
public class DiscordInterface
|
|
||||||
{
|
|
||||||
internal static string PROTOCOL { get => "discord"; }
|
|
||||||
internal DiscordSocketClient client;
|
|
||||||
private bool eventsSignedUp = false;
|
|
||||||
private static readonly SemaphoreSlim discordChannelSetup = new(1, 1);
|
|
||||||
private Channel protocolAsChannel;
|
|
||||||
|
|
||||||
public async Task Init(string config)
|
|
||||||
{
|
|
||||||
var token = config;
|
|
||||||
await SetupDiscordChannel();
|
|
||||||
client = new DiscordSocketClient(new DiscordSocketConfig() { GatewayIntents = GatewayIntents.All });
|
|
||||||
|
|
||||||
client.Log += (msg) =>
|
|
||||||
{
|
|
||||||
Console.WriteLine(msg.ToString());
|
|
||||||
return Task.CompletedTask;
|
|
||||||
};
|
|
||||||
client.Connected += () => Task.Run(SelfConnected);
|
|
||||||
client.Ready += () => Task.Run(ClientReady);
|
|
||||||
|
|
||||||
await client.LoginAsync(TokenType.Bot, token);
|
|
||||||
await client.StartAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SetupDiscordChannel()
|
|
||||||
{
|
|
||||||
await discordChannelSetup.WaitAsync();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
protocolAsChannel = Rememberer.SearchChannel(c => c.ParentChannel == null && c.Protocol == PROTOCOL);
|
|
||||||
if (protocolAsChannel == null)
|
|
||||||
{
|
|
||||||
protocolAsChannel = new Channel()
|
|
||||||
{
|
|
||||||
DisplayName = "discord (itself)",
|
|
||||||
MeannessFilterLevel = Enumerations.MeannessFilterLevel.Strict,
|
|
||||||
LewdnessFilterLevel = Enumerations.LewdnessFilterLevel.Moderate,
|
|
||||||
MaxTextChars = 2000,
|
|
||||||
MaxAttachmentBytes = 25 * 1024 * 1024, //allegedly it's 25, but I worry it's not actually.
|
|
||||||
LinksAllowed = true,
|
|
||||||
ReactionsPossible = true,
|
|
||||||
ExternalId = null,
|
|
||||||
Protocol = PROTOCOL,
|
|
||||||
SubChannels = []
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.WriteLine($"discord, channel with id {protocolAsChannel.Id}, already exists");
|
|
||||||
}
|
|
||||||
protocolAsChannel.DisplayName = "discord (itself)";
|
|
||||||
protocolAsChannel.SendMessage = (t) => { throw new InvalidOperationException($"protocol isn't a real channel, cannot accept text"); };
|
|
||||||
protocolAsChannel.SendFile = (f, t) => { throw new InvalidOperationException($"protocol isn't a real channel, cannot send file"); };
|
|
||||||
protocolAsChannel = Rememberer.RememberChannel(protocolAsChannel);
|
|
||||||
Console.WriteLine($"protocol as channel addeed; {protocolAsChannel}");
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
discordChannelSetup.Release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ClientReady()
|
|
||||||
{
|
|
||||||
if (!eventsSignedUp)
|
|
||||||
{
|
|
||||||
eventsSignedUp = true;
|
|
||||||
Console.WriteLine($"Bot is connected ({client.CurrentUser.Username}; {client.CurrentUser.Mention})! going to sign up for message received and user joined in client ready");
|
|
||||||
|
|
||||||
client.MessageReceived += MessageReceived;
|
|
||||||
// _client.MessageUpdated +=
|
|
||||||
client.UserJoined += UserJoined;
|
|
||||||
client.SlashCommandExecuted += SlashCommandHandler;
|
|
||||||
//client.ChannelCreated +=
|
|
||||||
// _client.ChannelDestroyed +=
|
|
||||||
// _client.ChannelUpdated +=
|
|
||||||
// _client.GuildMemberUpdated +=
|
|
||||||
// _client.UserBanned +=
|
|
||||||
// _client.UserLeft +=
|
|
||||||
// _client.ThreadCreated +=
|
|
||||||
// _client.ThreadUpdated +=
|
|
||||||
// _client.ThreadDeleted +=
|
|
||||||
// _client.JoinedGuild +=
|
|
||||||
// _client.GuildUpdated +=
|
|
||||||
// _client.LeftGuild +=
|
|
||||||
|
|
||||||
await SlashCommandsHelper.Register(client);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.WriteLine("bot appears to be RE connected, so I'm not going to sign up twice");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SelfConnected()
|
|
||||||
{
|
|
||||||
await discordChannelSetup.WaitAsync();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var selfAccount = UpsertAccount(client.CurrentUser, protocolAsChannel);
|
|
||||||
selfAccount.DisplayName = client.CurrentUser.Username;
|
|
||||||
Behaver.Instance.MarkSelf(selfAccount);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
discordChannelSetup.Release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task MessageReceived(SocketMessage messageParam)
|
|
||||||
{
|
|
||||||
if (messageParam is not SocketUserMessage)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"{messageParam.Content}, but not a user message");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var suMessage = messageParam as SocketUserMessage;
|
|
||||||
|
|
||||||
Console.WriteLine($"#{suMessage.Channel}[{DateTime.Now}][{suMessage.Author.Username} [id={suMessage.Author.Id}]][msg id: {suMessage.Id}] {suMessage.Content}");
|
|
||||||
|
|
||||||
var m = UpsertMessage(suMessage);
|
|
||||||
|
|
||||||
if (suMessage.MentionedUsers?.FirstOrDefault(muid => muid.Id == client.CurrentUser.Id) != null)
|
|
||||||
{
|
|
||||||
var mentionOfMe = "<@" + client.CurrentUser.Id + ">";
|
|
||||||
m.MentionsMe = true;
|
|
||||||
}
|
|
||||||
await Behaver.Instance.ActOn(m);
|
|
||||||
m.ActedOn = true; // for its own ruposess it might act on it later, but either way, fuck it, we checked.
|
|
||||||
// ...but we don't save?
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task UserJoined(SocketGuildUser arg)
|
|
||||||
{
|
|
||||||
var guild = UpsertChannel(arg.Guild);
|
|
||||||
var defaultChannel = UpsertChannel(arg.Guild.DefaultChannel);
|
|
||||||
defaultChannel.ParentChannel = guild;
|
|
||||||
var u = UpsertAccount(arg, guild);
|
|
||||||
u.DisplayName = arg.DisplayName;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
internal 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
internal static vassago.Models.Attachment UpsertAttachment(IAttachment dAttachment)
|
|
||||||
{
|
|
||||||
var a = Rememberer.SearchAttachment(ai => ai.ExternalId == dAttachment.Id)
|
|
||||||
?? new vassago.Models.Attachment();
|
|
||||||
|
|
||||||
a.ContentType = dAttachment.ContentType;
|
|
||||||
a.Description = dAttachment.Description;
|
|
||||||
a.Filename = dAttachment.Filename;
|
|
||||||
a.Size = dAttachment.Size;
|
|
||||||
a.Source = new Uri(dAttachment.Url);
|
|
||||||
Rememberer.RememberAttachment(a);
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
internal Message UpsertMessage(IUserMessage dMessage)
|
|
||||||
{
|
|
||||||
var m = Rememberer.SearchMessage(mi => mi.ExternalId == dMessage.Id.ToString() && mi.Protocol == PROTOCOL)
|
|
||||||
?? new()
|
|
||||||
{
|
|
||||||
Protocol = PROTOCOL
|
|
||||||
};
|
|
||||||
|
|
||||||
if (dMessage.Attachments?.Count > 0)
|
|
||||||
{
|
|
||||||
m.Attachments = [];
|
|
||||||
foreach (var da in dMessage.Attachments)
|
|
||||||
{
|
|
||||||
m.Attachments.Add(UpsertAttachment(da));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.Content = dMessage.Content;
|
|
||||||
m.ExternalId = dMessage.Id.ToString();
|
|
||||||
m.Timestamp = dMessage.EditedTimestamp ?? dMessage.CreatedAt;
|
|
||||||
m.Channel = UpsertChannel(dMessage.Channel);
|
|
||||||
m.Author = UpsertAccount(dMessage.Author, m.Channel);
|
|
||||||
Console.WriteLine($"received message; author: {m.Author.DisplayName}, {m.Author.Id}");
|
|
||||||
if (dMessage.Channel is IGuildChannel)
|
|
||||||
{
|
|
||||||
m.Author.DisplayName = (dMessage.Author as IGuildUser).DisplayName;//discord forgot how display names work.
|
|
||||||
}
|
|
||||||
m.MentionsMe = (dMessage.Author.Id != client.CurrentUser.Id
|
|
||||||
&& (dMessage.MentionedUserIds?.FirstOrDefault(muid => muid == client.CurrentUser.Id) > 0));
|
|
||||||
|
|
||||||
m.Reply = (t) => { return dMessage.ReplyAsync(t); };
|
|
||||||
m.React = (e) => { return AttemptReact(dMessage, e); };
|
|
||||||
Rememberer.RememberMessage(m);
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
internal Channel UpsertChannel(IMessageChannel channel)
|
|
||||||
{
|
|
||||||
Channel c = Rememberer.SearchChannel(ci => ci.ExternalId == channel.Id.ToString() && ci.Protocol == PROTOCOL);
|
|
||||||
if (c == null)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"couldn't find channel under protocol {PROTOCOL} with externalId {channel.Id.ToString()}");
|
|
||||||
c = new Channel()
|
|
||||||
{
|
|
||||||
Users = []
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
c.ExternalId = channel.Id.ToString();
|
|
||||||
c.ChannelType = (channel is IPrivateChannel) ? vassago.Models.Enumerations.ChannelType.DM : vassago.Models.Enumerations.ChannelType.Normal;
|
|
||||||
c.Messages ??= [];
|
|
||||||
c.Protocol = PROTOCOL;
|
|
||||||
if (channel is IGuildChannel)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"{channel.Name} is a guild channel. So i'm going to upsert the guild, {(channel as IGuildChannel).Guild}");
|
|
||||||
c.ParentChannel = UpsertChannel((channel as IGuildChannel).Guild);
|
|
||||||
}
|
|
||||||
else if (channel is IPrivateChannel)
|
|
||||||
{
|
|
||||||
c.ParentChannel = protocolAsChannel;
|
|
||||||
Console.WriteLine("i'm a private channel so I'm setting my parent channel to the protocol as channel");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
c.ParentChannel = protocolAsChannel;
|
|
||||||
Console.Error.WriteLine($"trying to upsert channel {channel.Id}/{channel.Name}, but it's neither guildchannel nor private channel. shrug.jpg");
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine($"upsertion of channel {c.DisplayName}, it's type {c.ChannelType}");
|
|
||||||
switch (c.ChannelType)
|
|
||||||
{
|
|
||||||
case vassago.Models.Enumerations.ChannelType.DM:
|
|
||||||
var asPriv =(channel as IPrivateChannel);
|
|
||||||
var sender = asPriv?.Recipients?.FirstOrDefault(u => u.Id != client.CurrentUser.Id); // why yes, there's a list of recipients, and it's the sender.
|
|
||||||
if(sender != null)
|
|
||||||
{
|
|
||||||
c.DisplayName = "DM: " + sender.Username;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//I sent it, so I don't know the recipient's name.
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
c.DisplayName = channel.Name;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Channel parentChannel = null;
|
|
||||||
if (channel is IGuildChannel)
|
|
||||||
{
|
|
||||||
parentChannel = Rememberer.SearchChannel(c => c.ExternalId == (channel as IGuildChannel).Guild.Id.ToString() && c.Protocol == PROTOCOL);
|
|
||||||
if (parentChannel is null)
|
|
||||||
{
|
|
||||||
Console.Error.WriteLine("why am I still null?");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (channel is IPrivateChannel)
|
|
||||||
{
|
|
||||||
parentChannel = protocolAsChannel;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
parentChannel = protocolAsChannel;
|
|
||||||
Console.Error.WriteLine($"trying to upsert channel {channel.Id}/{channel.Name}, but it's neither guildchannel nor private channel. shrug.jpg");
|
|
||||||
}
|
|
||||||
parentChannel.SubChannels ??= [];
|
|
||||||
if(!parentChannel.SubChannels.Contains(c))
|
|
||||||
{
|
|
||||||
parentChannel.SubChannels.Add(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
c.SendMessage = (t) => { return channel.SendMessageAsync(t); };
|
|
||||||
c.SendFile = (f, t) => { return channel.SendFileAsync(f, t); };
|
|
||||||
|
|
||||||
c = Rememberer.RememberChannel(c);
|
|
||||||
|
|
||||||
//Console.WriteLine($"no one knows how to make good tooling. c.users.first, which needs client currentuser id tostring. c: {c}, c.Users {c.Users}, client: {client}, client.CurrentUser: {client.CurrentUser}, client.currentUser.Id: {client.CurrentUser.Id}");
|
|
||||||
var selfAccountInChannel = c.Users?.FirstOrDefault(a => a.ExternalId == client.CurrentUser.Id.ToString());
|
|
||||||
if(selfAccountInChannel == null)
|
|
||||||
{
|
|
||||||
selfAccountInChannel = UpsertAccount(client.CurrentUser, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
internal Channel UpsertChannel(IGuild channel)
|
|
||||||
{
|
|
||||||
Channel c = Rememberer.SearchChannel(ci => ci.ExternalId == channel.Id.ToString() && ci.Protocol == PROTOCOL);
|
|
||||||
if (c == null)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"couldn't find channel under protocol {PROTOCOL} with externalId {channel.Id.ToString()}");
|
|
||||||
c = new Channel();
|
|
||||||
}
|
|
||||||
|
|
||||||
c.DisplayName = channel.Name;
|
|
||||||
c.ExternalId = channel.Id.ToString();
|
|
||||||
c.ChannelType = vassago.Models.Enumerations.ChannelType.OU;
|
|
||||||
c.Messages ??= [];
|
|
||||||
c.Protocol = protocolAsChannel.Protocol;
|
|
||||||
c.ParentChannel = protocolAsChannel;
|
|
||||||
c.SubChannels ??= [];
|
|
||||||
c.MaxAttachmentBytes = channel.MaxUploadLimit;
|
|
||||||
|
|
||||||
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 Rememberer.RememberChannel(c);
|
|
||||||
}
|
|
||||||
internal static Account UpsertAccount(IUser discordUser, Channel inChannel)
|
|
||||||
{
|
|
||||||
var acc = Rememberer.SearchAccount(ui => ui.ExternalId == discordUser.Id.ToString() && ui.SeenInChannel.Id == inChannel.Id);
|
|
||||||
Console.WriteLine($"upserting account, retrieved {acc?.Id}.");
|
|
||||||
if (acc != null)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"acc's user: {acc.IsUser?.Id}");
|
|
||||||
}
|
|
||||||
acc ??= new Account() {
|
|
||||||
IsUser = Rememberer.SearchUser(u => u.Accounts.Any(a => a.ExternalId == discordUser.Id.ToString() && a.Protocol == PROTOCOL))
|
|
||||||
?? new User()
|
|
||||||
};
|
|
||||||
|
|
||||||
acc.Username = discordUser.Username;
|
|
||||||
acc.ExternalId = discordUser.Id.ToString();
|
|
||||||
acc.IsBot = discordUser.IsBot || discordUser.IsWebhook;
|
|
||||||
acc.Protocol = PROTOCOL;
|
|
||||||
acc.SeenInChannel = inChannel;
|
|
||||||
|
|
||||||
Console.WriteLine($"we asked rememberer to search for acc's user. {acc.IsUser?.Id}");
|
|
||||||
if (acc.IsUser != null)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"user has record of {acc.IsUser.Accounts?.Count ?? 0} accounts");
|
|
||||||
}
|
|
||||||
acc.IsUser ??= new User() { Accounts = [acc] };
|
|
||||||
if (inChannel.Users?.Count > 0)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"channel has {inChannel.Users.Count} accounts");
|
|
||||||
}
|
|
||||||
Rememberer.RememberAccount(acc);
|
|
||||||
inChannel.Users ??= [];
|
|
||||||
if(!inChannel.Users.Contains(acc))
|
|
||||||
{
|
|
||||||
inChannel.Users.Add(acc);
|
|
||||||
Rememberer.RememberChannel(inChannel);
|
|
||||||
}
|
|
||||||
return acc;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Task AttemptReact(IUserMessage msg, string e)
|
|
||||||
{
|
|
||||||
var c = Rememberer.SearchChannel(c => c.ExternalId == msg.Channel.Id.ToString());// db.Channels.FirstOrDefault(c => c.ExternalId == msg.Channel.Id.ToString());
|
|
||||||
//var preferredEmote = c.EmoteOverrides?[e] ?? e; //TODO: emote overrides
|
|
||||||
var preferredEmote = e;
|
|
||||||
if (Emoji.TryParse(preferredEmote, out Emoji emoji))
|
|
||||||
{
|
|
||||||
return msg.AddReactionAsync(emoji);
|
|
||||||
}
|
|
||||||
if (!Emote.TryParse(preferredEmote, out Emote emote))
|
|
||||||
{
|
|
||||||
if (preferredEmote == e)
|
|
||||||
Console.Error.WriteLine($"never heard of emote {e}");
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
return msg.AddReactionAsync(emote);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
namespace vassago.ProtocolInterfaces;
|
|
||||||
|
|
||||||
public static class ProtocolList
|
|
||||||
{
|
|
||||||
public static List<DiscordInterface.DiscordInterface> discords = new();
|
|
||||||
public static List<TwitchInterface.TwitchInterface> twitchs = new();
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
namespace vassago.TwitchInterface;
|
|
||||||
|
|
||||||
public class TwitchConfig
|
|
||||||
{
|
|
||||||
public string username {get; set;}
|
|
||||||
public string clientId {get; set;}
|
|
||||||
public string secret {get; set;}
|
|
||||||
public string oauth {get; set;}
|
|
||||||
}
|
|
@ -1,315 +0,0 @@
|
|||||||
using RestSharp;
|
|
||||||
using System.Security.Cryptography.X509Certificates;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using TwitchLib.Api.Helix.Models.Users.GetUsers;
|
|
||||||
using TwitchLib.Api;
|
|
||||||
using TwitchLib.Client.Events;
|
|
||||||
using TwitchLib.Client.Models;
|
|
||||||
using TwitchLib.Client;
|
|
||||||
using TwitchLib.Communication.Clients;
|
|
||||||
using TwitchLib.Communication.Models;
|
|
||||||
using vassago.Behavior;
|
|
||||||
using vassago.Models;
|
|
||||||
|
|
||||||
namespace vassago.TwitchInterface;
|
|
||||||
|
|
||||||
internal class unifiedTwitchMessage
|
|
||||||
{
|
|
||||||
public unifiedTwitchMessage(ChatMessage chatMessage){}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class TwitchInterface
|
|
||||||
{
|
|
||||||
internal const string PROTOCOL = "twitch";
|
|
||||||
private static SemaphoreSlim channelSetupSemaphpore = new SemaphoreSlim(1, 1);
|
|
||||||
private Channel protocolAsChannel;
|
|
||||||
private Account selfAccountInProtocol;
|
|
||||||
TwitchClient client;
|
|
||||||
|
|
||||||
private async Task SetupTwitchChannel()
|
|
||||||
{
|
|
||||||
await channelSetupSemaphpore.WaitAsync();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
protocolAsChannel = Rememberer.SearchChannel(c => c.ParentChannel == null && c.Protocol == PROTOCOL);
|
|
||||||
if (protocolAsChannel == null)
|
|
||||||
{
|
|
||||||
protocolAsChannel = new Channel()
|
|
||||||
{
|
|
||||||
DisplayName = "twitch (itself)",
|
|
||||||
MeannessFilterLevel = Enumerations.MeannessFilterLevel.Medium,
|
|
||||||
LewdnessFilterLevel = Enumerations.LewdnessFilterLevel.G,
|
|
||||||
MaxTextChars = 500,
|
|
||||||
MaxAttachmentBytes = 0,
|
|
||||||
LinksAllowed = false,
|
|
||||||
ReactionsPossible = false,
|
|
||||||
ExternalId = null,
|
|
||||||
Protocol = PROTOCOL,
|
|
||||||
SubChannels = []
|
|
||||||
};
|
|
||||||
protocolAsChannel.DisplayName = "twitch (itself)";
|
|
||||||
protocolAsChannel.SendMessage = (t) => { throw new InvalidOperationException($"twitch itself cannot accept text"); };
|
|
||||||
protocolAsChannel.SendFile = (f, t) => { throw new InvalidOperationException($"twitch itself cannot send file"); };
|
|
||||||
protocolAsChannel = Rememberer.RememberChannel(protocolAsChannel);
|
|
||||||
Console.WriteLine($"protocol as channle added; {protocolAsChannel}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.WriteLine($"twitch, channel with id {protocolAsChannel.Id}, already exists");
|
|
||||||
}
|
|
||||||
//protocolAsChan
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
channelSetupSemaphpore.Release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///<param name="oauth">https://www.twitchapps.com/tmi/</param>
|
|
||||||
public async Task Init(TwitchConfig tc)
|
|
||||||
{
|
|
||||||
await SetupTwitchChannel();
|
|
||||||
|
|
||||||
WebSocketClient customClient = new WebSocketClient(new ClientOptions
|
|
||||||
{
|
|
||||||
MessagesAllowedInPeriod = 750,
|
|
||||||
ThrottlingPeriod = TimeSpan.FromSeconds(30)
|
|
||||||
}
|
|
||||||
);
|
|
||||||
client = new TwitchClient(customClient);
|
|
||||||
client.Initialize(new ConnectionCredentials(tc.username, tc.oauth, capabilities: new Capabilities()));
|
|
||||||
|
|
||||||
client.OnLog += Client_OnLog;
|
|
||||||
client.OnJoinedChannel += Client_OnJoinedChannel;
|
|
||||||
client.OnMessageReceived += Client_OnMessageReceivedAsync;
|
|
||||||
client.OnWhisperReceived += Client_OnWhisperReceivedAsync;
|
|
||||||
client.OnConnected += Client_OnConnected;
|
|
||||||
|
|
||||||
client.Connect();
|
|
||||||
Console.WriteLine("twitch client 1 connected");
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void Client_OnWhisperReceivedAsync(object sender, OnWhisperReceivedArgs e)
|
|
||||||
{
|
|
||||||
//data received
|
|
||||||
Console.WriteLine($"whisper#{e.WhisperMessage.Username}[{DateTime.Now}][{e.WhisperMessage.DisplayName} [id={e.WhisperMessage.Username}]][msg id: {e.WhisperMessage.MessageId}] {e.WhisperMessage.Message}");
|
|
||||||
|
|
||||||
//translate to internal, upsert
|
|
||||||
var m = UpsertMessage(e.WhisperMessage);
|
|
||||||
m.Reply = (t) => { return Task.Run(() => { client.SendWhisper(e.WhisperMessage.Username, t); }); };
|
|
||||||
m.Channel.ChannelType = vassago.Models.Enumerations.ChannelType.DM;
|
|
||||||
//act on
|
|
||||||
await Behaver.Instance.ActOn(m);
|
|
||||||
m.ActedOn = true;
|
|
||||||
//TODO: remember it again?
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void Client_OnMessageReceivedAsync(object sender, OnMessageReceivedArgs e)
|
|
||||||
{
|
|
||||||
//data eived
|
|
||||||
Console.WriteLine($"#{e.ChatMessage.Channel}[{DateTime.Now}][{e.ChatMessage.DisplayName} [id={e.ChatMessage.Username}]][msg id: {e.ChatMessage.Id}] {e.ChatMessage.Message}");
|
|
||||||
|
|
||||||
//translate to internal, upsert
|
|
||||||
var m = UpsertMessage(e.ChatMessage);
|
|
||||||
m.Reply = (t) => { return Task.Run(() => { client.SendReply(e.ChatMessage.Channel, e.ChatMessage.Id, t); }); };
|
|
||||||
m.Channel.ChannelType = vassago.Models.Enumerations.ChannelType.Normal;
|
|
||||||
//act on
|
|
||||||
await Behaver.Instance.ActOn(m);
|
|
||||||
m.ActedOn = true;
|
|
||||||
//TODO: remember again?
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Client_OnConnected(object sender, OnConnectedArgs e)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"twitch marking selfaccount as seeninchannel {protocolAsChannel.Id}");
|
|
||||||
selfAccountInProtocol = UpsertAccount(e.BotUsername, protocolAsChannel);
|
|
||||||
selfAccountInProtocol.DisplayName = e.BotUsername;
|
|
||||||
Behaver.Instance.MarkSelf(selfAccountInProtocol);
|
|
||||||
|
|
||||||
Console.WriteLine($"Connected to {e.AutoJoinChannel}");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Client_OnJoinedChannel(object sender, OnJoinedChannelArgs e)
|
|
||||||
{
|
|
||||||
client.SendMessage(e.Channel, "beep boop");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Client_OnLog(object sender, OnLogArgs e)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"{e.DateTime.ToString()}: {e.BotUsername} - {e.Data}");
|
|
||||||
}
|
|
||||||
|
|
||||||
private Account UpsertAccount(string username, Channel inChannel)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"upserting twitch account. username: {username}. inChannel: {inChannel?.Id}");
|
|
||||||
var acc = Rememberer.SearchAccount(ui => ui.ExternalId == username && ui.SeenInChannel.ExternalId == inChannel.ExternalId);
|
|
||||||
Console.WriteLine($"upserting twitch account, retrieved {acc?.Id}.");
|
|
||||||
if (acc != null)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"acc's usser: {acc.IsUser?.Id}");
|
|
||||||
}
|
|
||||||
acc ??= new Account() {
|
|
||||||
IsUser = Rememberer.SearchUser(
|
|
||||||
u => u.Accounts.Any(a => a.ExternalId == username && a.Protocol == PROTOCOL))
|
|
||||||
?? new vassago.Models.User()
|
|
||||||
};
|
|
||||||
|
|
||||||
acc.Username = username;
|
|
||||||
acc.ExternalId = username;
|
|
||||||
//acc.IsBot = false? there is a way to tell, but you have to go back through the API
|
|
||||||
acc.Protocol = PROTOCOL;
|
|
||||||
acc.SeenInChannel = inChannel;
|
|
||||||
|
|
||||||
Console.WriteLine($"we asked rememberer to search for acc's user. {acc.IsUser?.Id}");
|
|
||||||
if (acc.IsUser != null)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"user has record of {acc.IsUser.Accounts?.Count ?? 0} accounts");
|
|
||||||
}
|
|
||||||
acc.IsUser ??= new vassago.Models.User() { Accounts = [acc] };
|
|
||||||
if (inChannel.Users?.Count > 0)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"channel has {inChannel.Users.Count} accounts");
|
|
||||||
}
|
|
||||||
Rememberer.RememberAccount(acc);
|
|
||||||
inChannel.Users ??= [];
|
|
||||||
if (!inChannel.Users.Contains(acc))
|
|
||||||
{
|
|
||||||
inChannel.Users.Add(acc);
|
|
||||||
Rememberer.RememberChannel(inChannel);
|
|
||||||
}
|
|
||||||
return acc;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Channel UpsertChannel(string channelName)
|
|
||||||
{
|
|
||||||
Channel c = Rememberer.SearchChannel(ci => ci.ExternalId == channelName
|
|
||||||
&& ci.Protocol == PROTOCOL);
|
|
||||||
if (c == null)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"couldn't find channel under protocol {PROTOCOL} with externalId {channelName}");
|
|
||||||
c = new Channel()
|
|
||||||
{
|
|
||||||
Users = []
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
c.DisplayName = channelName;
|
|
||||||
c.ExternalId = channelName;
|
|
||||||
c.ChannelType = vassago.Models.Enumerations.ChannelType.Normal;
|
|
||||||
c.Messages ??= [];
|
|
||||||
c.Protocol = PROTOCOL;
|
|
||||||
c.ParentChannel = protocolAsChannel;
|
|
||||||
c.SubChannels = c.SubChannels ?? new List<Channel>();
|
|
||||||
c.SendMessage = (t) => { return Task.Run(() => { client.SendMessage(channelName, t); }); };
|
|
||||||
c.SendFile = (f, t) => { throw new InvalidOperationException($"twitch cannot send files"); };
|
|
||||||
c = Rememberer.RememberChannel(c);
|
|
||||||
|
|
||||||
var selfAccountInChannel = c.Users?.FirstOrDefault(a => a.ExternalId == selfAccountInProtocol.ExternalId);
|
|
||||||
if(selfAccountInChannel == null)
|
|
||||||
{
|
|
||||||
selfAccountInChannel = UpsertAccount(selfAccountInProtocol.Username, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
private Channel UpsertDMChannel(string whisperWith)
|
|
||||||
{
|
|
||||||
Channel c = Rememberer.SearchChannel(ci => ci.ExternalId == $"w_{whisperWith}"
|
|
||||||
&& ci.Protocol == PROTOCOL);
|
|
||||||
if (c == null)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"couldn't find channel under protocol {PROTOCOL}, whisper with {whisperWith}");
|
|
||||||
c = new Channel()
|
|
||||||
{
|
|
||||||
Users = []
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
c.DisplayName = $"Whisper: {whisperWith}";
|
|
||||||
c.ExternalId = $"w_{whisperWith}";
|
|
||||||
c.ChannelType = vassago.Models.Enumerations.ChannelType.DM;
|
|
||||||
c.Messages ??= [];
|
|
||||||
c.Protocol = PROTOCOL;
|
|
||||||
c.ParentChannel = protocolAsChannel;
|
|
||||||
c.SubChannels = c.SubChannels ?? new List<Channel>();
|
|
||||||
c.SendMessage = (t) => { return Task.Run(() => {
|
|
||||||
try
|
|
||||||
{
|
|
||||||
|
|
||||||
client.SendWhisper(whisperWith, t);
|
|
||||||
}
|
|
||||||
catch(Exception e)
|
|
||||||
{
|
|
||||||
Console.Error.WriteLine(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
c.SendFile = (f, t) => { throw new InvalidOperationException($"twitch cannot send files"); };
|
|
||||||
c = Rememberer.RememberChannel(c);
|
|
||||||
|
|
||||||
var selfAccountInChannel = c.Users.FirstOrDefault(a => a.ExternalId == selfAccountInProtocol.ExternalId);
|
|
||||||
if(selfAccountInChannel == null)
|
|
||||||
{
|
|
||||||
selfAccountInChannel = UpsertAccount(selfAccountInChannel.Username, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
//n.b., I see you future adam. "we should unify these, they're redundant".
|
|
||||||
//ah, but that's the trick, they aren't! twitchlib has a common base class, but
|
|
||||||
//none of the features we care about are on it!
|
|
||||||
private Message UpsertMessage(ChatMessage chatMessage)
|
|
||||||
{
|
|
||||||
var m = Rememberer.SearchMessage(mi => mi.ExternalId == chatMessage.Id && mi.Protocol == PROTOCOL)
|
|
||||||
?? new()
|
|
||||||
{
|
|
||||||
Protocol = PROTOCOL,
|
|
||||||
Timestamp = (DateTimeOffset)DateTime.SpecifyKind(DateTime.UtcNow, DateTimeKind.Utc)
|
|
||||||
};
|
|
||||||
m.Content = chatMessage.Message;
|
|
||||||
m.ExternalId = chatMessage.Id;
|
|
||||||
m.Channel = UpsertChannel(chatMessage.Channel);
|
|
||||||
m.Author = UpsertAccount(chatMessage.Username, m.Channel);
|
|
||||||
m.MentionsMe = Regex.IsMatch(m.Content?.ToLower(), $"@\\b{selfAccountInProtocol.Username.ToLower()}\\b");
|
|
||||||
m.Reply = (t) => { return Task.Run(() => { client.SendReply(chatMessage.Channel, chatMessage.Id, t); }); };
|
|
||||||
m.React = (e) => { throw new InvalidOperationException($"twitch cannot react"); };
|
|
||||||
Rememberer.RememberMessage(m);
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
//n.b., I see you future adam. "we should unify these, they're redundant".
|
|
||||||
//ah, but that's the trick, they aren't! twitchlib has a common base class, but
|
|
||||||
//none of the features we care about are on it!
|
|
||||||
private Message UpsertMessage(WhisperMessage whisperMessage)
|
|
||||||
{
|
|
||||||
//WhisperMessage.Id corresponds to chatMessage.Id. \*eye twitch*
|
|
||||||
var m = Rememberer.SearchMessage(mi => mi.ExternalId == whisperMessage.MessageId && mi.Protocol == PROTOCOL)
|
|
||||||
?? new()
|
|
||||||
{
|
|
||||||
Protocol = PROTOCOL,
|
|
||||||
Timestamp = (DateTimeOffset)DateTime.SpecifyKind(DateTime.UtcNow, DateTimeKind.Utc)
|
|
||||||
};
|
|
||||||
m.Content = whisperMessage.Message;
|
|
||||||
m.ExternalId = whisperMessage.MessageId;
|
|
||||||
m.Channel = UpsertDMChannel(whisperMessage.Username);
|
|
||||||
m.Author = UpsertAccount(whisperMessage.Username, m.Channel);
|
|
||||||
m.MentionsMe = Regex.IsMatch(m.Content?.ToLower(), $"@\\b{selfAccountInProtocol.Username.ToLower()}\\b");
|
|
||||||
m.Reply = (t) => { return Task.Run(() => { client.SendWhisper(whisperMessage.Username, t); }); };
|
|
||||||
m.React = (e) => { throw new InvalidOperationException($"twitch cannot react"); };
|
|
||||||
Rememberer.RememberMessage(m);
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string AttemptJoin(string channelTarget)
|
|
||||||
{
|
|
||||||
client.JoinChannel(channelTarget);
|
|
||||||
return $"attempt join {channelTarget} - o7";
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void AttemptLeave(string channelTarget)
|
|
||||||
{
|
|
||||||
client.SendMessage(channelTarget, "o7");
|
|
||||||
client.LeaveChannel(channelTarget);
|
|
||||||
}
|
|
||||||
}
|
|
46
README.md
46
README.md
@ -1,52 +1,8 @@
|
|||||||
# discord-bot
|
# discord-bot
|
||||||
|
|
||||||
copy appsettings.json to appsettings.ENV.json and fill it in. dotnet seems to understand files called appsettings.json (and appsettings.xml?) and knows how to overwrite *specific values found within* the .[ENV].[extension] version
|
copy appsettings.json and fill it in
|
||||||
|
|
||||||
# auth link
|
# auth link
|
||||||
|
|
||||||
https://discord.com/oauth2/authorize?client_id=913003037348491264&permissions=274877942784&scope=bot
|
https://discord.com/oauth2/authorize?client_id=913003037348491264&permissions=274877942784&scope=bot
|
||||||
that's read messages/view channels, send messages, send messages in threads, and attach files. but not add reactions?
|
that's read messages/view channels, send messages, send messages in threads, and attach files. but not add reactions?
|
||||||
|
|
||||||
# concepts
|
|
||||||
|
|
||||||
## Data Types
|
|
||||||
|
|
||||||
database diagram. is a fancy term.
|
|
||||||
|
|
||||||
message 1:n attachment
|
|
||||||
user 1:n account
|
|
||||||
channel 1:n account
|
|
||||||
channel 1:n message
|
|
||||||
account 1:n message
|
|
||||||
|
|
||||||
featurepermission n:n ?
|
|
||||||
|
|
||||||
### Accounts
|
|
||||||
|
|
||||||
a `User` can have multiple `Account`s. e.g., @adam:greyn.club? that's an "account". I, however, am a `User`. An `Account` has references to the `Channels` its seen in - as in, leaf-level. If you're in a subchannel, you'll have an appropriate listing there - i.e., you will never have an account in "discord (itself)", you'll have one in the guild text-channels
|
|
||||||
|
|
||||||
### Attachment
|
|
||||||
|
|
||||||
debating whether to save a copy of every single attachment. Discord allows 100MB attachments for turbo users, and shtikbot lives in several art channels. (unfortunately, being that shtikbot doesn't have a viable SMS spam vector, it's limited to 8MB, in contradiction to discord itself reporting a server that doesn't agree to put its own name on discord's finer-grained rules has a limit of 10MB)
|
|
||||||
|
|
||||||
### Channel
|
|
||||||
|
|
||||||
a place where communication can happen. any level of these can have any number of children. In matrix, everything is a "room" - even spaces and threads. Seems like a fine idea. So for vassago, a discord "channel" is a channel. a "thread" is a child of that channel. a "category" is a parent of that channel. A "server" (formerly "guild") is a parent of that channel. and fuck it, Discord itself is a "channel". Includes permissions vassago has for a channel; MaxAttachmentBytes, etc. go down the hierarchy until you find an override.
|
|
||||||
|
|
||||||
### FeaturePermission
|
|
||||||
|
|
||||||
the permissions of a feature. It can be restricted to accounts, to users, to channels. It has an internal name... and tag? and it can be (or not be) inheritable?
|
|
||||||
|
|
||||||
### Message
|
|
||||||
|
|
||||||
a message (duh). features bools for "mentions me", the external ID, the reference to the account, the channel.
|
|
||||||
|
|
||||||
### User
|
|
||||||
|
|
||||||
a person or program who operates an account. recognizing that 2 `Account`s belong to 1 `User` can be done by that user (using LinkMe). I should be able to collapse myself automatically.
|
|
||||||
|
|
||||||
## Behavior
|
|
||||||
|
|
||||||
both a "feature" and an "anti-feature". a channel might dictate something isn't allowed (lewdness in a g-rated channel). A person might not be allowed to do something - lots of me-only things like directing other bots (and the now rendered-moot Torrent feature). A behavior might need a command alias in a particular channel (freedomunits in jubel's)
|
|
||||||
|
|
||||||
so "behavior" might need to tag other data types? do I have it do a full select every time we get a message? ...no, only if the (other) triggering conditions are met. Then you can take your time.
|
|
189
Rememberer.cs
189
Rememberer.cs
@ -1,189 +0,0 @@
|
|||||||
namespace vassago;
|
|
||||||
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
using vassago.Models;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
public static class Rememberer
|
|
||||||
{
|
|
||||||
private static readonly SemaphoreSlim dbAccessSemaphore = new(1, 1);
|
|
||||||
private static readonly ChattingContext db = new();
|
|
||||||
|
|
||||||
public static Account SearchAccount(Expression<Func<Account, bool>> predicate)
|
|
||||||
{
|
|
||||||
Account toReturn;
|
|
||||||
dbAccessSemaphore.Wait();
|
|
||||||
toReturn = db.Accounts?.Include(a => a.IsUser)?.FirstOrDefault(predicate);
|
|
||||||
dbAccessSemaphore.Release();
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
public static List<Account> SearchAccounts(Expression<Func<Account, bool>> predicate)
|
|
||||||
{
|
|
||||||
List<Account> toReturn;
|
|
||||||
dbAccessSemaphore.Wait();
|
|
||||||
toReturn = db.Accounts.Where(predicate).ToList();
|
|
||||||
dbAccessSemaphore.Release();
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
public static Attachment SearchAttachment(Expression<Func<Attachment, bool>> predicate)
|
|
||||||
{
|
|
||||||
Attachment toReturn;
|
|
||||||
dbAccessSemaphore.Wait();
|
|
||||||
toReturn = db.Attachments.FirstOrDefault(predicate);
|
|
||||||
dbAccessSemaphore.Release();
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
public static Channel SearchChannel(Expression<Func<Channel, bool>> predicate)
|
|
||||||
{
|
|
||||||
Channel toReturn;
|
|
||||||
dbAccessSemaphore.Wait();
|
|
||||||
toReturn = db.Channels.FirstOrDefault(predicate);
|
|
||||||
dbAccessSemaphore.Release();
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
public static Message SearchMessage(Expression<Func<Message, bool>> predicate)
|
|
||||||
{
|
|
||||||
Message toReturn;
|
|
||||||
dbAccessSemaphore.Wait();
|
|
||||||
toReturn = db.Messages.FirstOrDefault(predicate);
|
|
||||||
dbAccessSemaphore.Release();
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
public static User SearchUser(Expression<Func<User, bool>> predicate)
|
|
||||||
{
|
|
||||||
User toReturn;
|
|
||||||
dbAccessSemaphore.Wait();
|
|
||||||
toReturn = db.Users.Where(predicate).Include(u => u.Accounts).FirstOrDefault(predicate);
|
|
||||||
dbAccessSemaphore.Release();
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
public static void RememberAccount(Account toRemember)
|
|
||||||
{
|
|
||||||
dbAccessSemaphore.Wait();
|
|
||||||
toRemember.IsUser ??= new User { Accounts = [toRemember] };
|
|
||||||
db.Update(toRemember.IsUser);
|
|
||||||
db.SaveChanges();
|
|
||||||
dbAccessSemaphore.Release();
|
|
||||||
}
|
|
||||||
public static void RememberAttachment(Attachment toRemember)
|
|
||||||
{
|
|
||||||
dbAccessSemaphore.Wait();
|
|
||||||
toRemember.Message ??= new Message() { Attachments = [toRemember] };
|
|
||||||
db.Update(toRemember.Message);
|
|
||||||
db.SaveChanges();
|
|
||||||
dbAccessSemaphore.Release();
|
|
||||||
}
|
|
||||||
public static Channel RememberChannel(Channel toRemember)
|
|
||||||
{
|
|
||||||
dbAccessSemaphore.Wait();
|
|
||||||
db.Update(toRemember);
|
|
||||||
db.SaveChanges();
|
|
||||||
dbAccessSemaphore.Release();
|
|
||||||
return toRemember;
|
|
||||||
}
|
|
||||||
public static void RememberMessage(Message toRemember)
|
|
||||||
{
|
|
||||||
dbAccessSemaphore.Wait();
|
|
||||||
toRemember.Channel ??= new() { Messages = [toRemember] };
|
|
||||||
db.Update(toRemember.Channel);
|
|
||||||
db.SaveChanges();
|
|
||||||
dbAccessSemaphore.Release();
|
|
||||||
}
|
|
||||||
public static void RememberUser(User toRemember)
|
|
||||||
{
|
|
||||||
dbAccessSemaphore.Wait();
|
|
||||||
db.Users.Update(toRemember);
|
|
||||||
db.SaveChanges();
|
|
||||||
dbAccessSemaphore.Release();
|
|
||||||
}
|
|
||||||
public static void ForgetAccount(Account toForget)
|
|
||||||
{
|
|
||||||
var user = toForget.IsUser;
|
|
||||||
var usersOnlyAccount = user.Accounts?.Count == 1;
|
|
||||||
|
|
||||||
if (usersOnlyAccount)
|
|
||||||
{
|
|
||||||
Rememberer.ForgetUser(user);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dbAccessSemaphore.Wait();
|
|
||||||
db.Accounts.Remove(toForget);
|
|
||||||
db.SaveChanges();
|
|
||||||
dbAccessSemaphore.Release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static void ForgetChannel(Channel toForget)
|
|
||||||
{
|
|
||||||
dbAccessSemaphore.Wait();
|
|
||||||
db.Channels.Remove(toForget);
|
|
||||||
db.SaveChanges();
|
|
||||||
dbAccessSemaphore.Release();
|
|
||||||
}
|
|
||||||
public static void ForgetUser(User toForget)
|
|
||||||
{
|
|
||||||
dbAccessSemaphore.Wait();
|
|
||||||
db.Users.Remove(toForget);
|
|
||||||
db.SaveChanges();
|
|
||||||
dbAccessSemaphore.Release();
|
|
||||||
}
|
|
||||||
public static List<Account> AccountsOverview()
|
|
||||||
{
|
|
||||||
List<Account> toReturn;
|
|
||||||
dbAccessSemaphore.Wait();
|
|
||||||
toReturn = [.. db.Accounts];
|
|
||||||
dbAccessSemaphore.Release();
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
public static List<Channel> ChannelsOverview()
|
|
||||||
{
|
|
||||||
List<Channel> toReturn;
|
|
||||||
dbAccessSemaphore.Wait();
|
|
||||||
toReturn = [.. db.Channels.Include(u => u.SubChannels).Include(c => c.ParentChannel)];
|
|
||||||
dbAccessSemaphore.Release();
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
public static Channel ChannelDetail(Guid Id)
|
|
||||||
{
|
|
||||||
Channel toReturn;
|
|
||||||
dbAccessSemaphore.Wait();
|
|
||||||
toReturn = db.Channels.Find(Id);
|
|
||||||
dbAccessSemaphore.Release();
|
|
||||||
return toReturn;
|
|
||||||
// .Include(u => u.SubChannels)
|
|
||||||
// .Include(u => u.Users)
|
|
||||||
// .Include(u => u.ParentChannel);
|
|
||||||
}
|
|
||||||
public static List<User> UsersOverview()
|
|
||||||
{
|
|
||||||
List<User> toReturn;
|
|
||||||
dbAccessSemaphore.Wait();
|
|
||||||
toReturn = db.Users.ToList();
|
|
||||||
dbAccessSemaphore.Release();
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
public static List<UAC> UACsOverview()
|
|
||||||
{
|
|
||||||
List<UAC> toReturn;
|
|
||||||
dbAccessSemaphore.Wait();
|
|
||||||
toReturn = db.UACs.Include(uac => uac.Users).Include(uac => uac.Channels).Include(uac => uac.AccountInChannels).ToList();
|
|
||||||
dbAccessSemaphore.Release();
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
public static UAC SearchUAC(Expression<Func<UAC, bool>> predicate)
|
|
||||||
{
|
|
||||||
UAC toReturn;
|
|
||||||
dbAccessSemaphore.Wait();
|
|
||||||
toReturn = db.UACs.Include(uac => uac.Users).Include(uac => uac.Channels).Include(uac => uac.AccountInChannels)
|
|
||||||
.FirstOrDefault(predicate);
|
|
||||||
dbAccessSemaphore.Release();
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
public static void RememberUAC(UAC toRemember)
|
|
||||||
{
|
|
||||||
dbAccessSemaphore.Wait();
|
|
||||||
db.Update(toRemember);
|
|
||||||
db.SaveChanges();
|
|
||||||
dbAccessSemaphore.Release();
|
|
||||||
}
|
|
||||||
}
|
|
10
Shared.cs
10
Shared.cs
@ -1,14 +1,10 @@
|
|||||||
namespace vassago;
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Net.Http;
|
|
||||||
using vassago.Models;
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace silverworker_discord
|
||||||
|
{
|
||||||
public static class Shared
|
public static class Shared
|
||||||
{
|
{
|
||||||
public static Random r = new Random();
|
public static Random r = new Random();
|
||||||
public static string DBConnectionString { get; set; }
|
}
|
||||||
public static HttpClient HttpClient { get; internal set; } = new HttpClient();
|
|
||||||
public static bool SetupSlashCommands { get; set; }
|
|
||||||
}
|
}
|
@ -1,14 +1,14 @@
|
|||||||
|
namespace silverworker_discord
|
||||||
|
{
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using Discord;
|
|
||||||
using Discord.Net;
|
using Discord.Net;
|
||||||
|
using Discord;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace vassago.ProtocolInterfaces.DiscordInterface
|
|
||||||
{
|
|
||||||
public static class SlashCommandsHelper
|
public static class SlashCommandsHelper
|
||||||
{
|
{
|
||||||
private static List<CommandSetup> slashCommands = new List<CommandSetup>()
|
private static List<CommandSetup> slashCommands = new List<CommandSetup>()
|
||||||
@ -16,13 +16,11 @@ namespace vassago.ProtocolInterfaces.DiscordInterface
|
|||||||
new CommandSetup(){
|
new CommandSetup(){
|
||||||
Id = "freedomunits",
|
Id = "freedomunits",
|
||||||
UpdatedAt = new DateTime(2023, 5, 21, 13, 3, 0),
|
UpdatedAt = new DateTime(2023, 5, 21, 13, 3, 0),
|
||||||
guild = 825293851110801428, //TODO: demagic this magic number
|
guild = 825293851110801428,
|
||||||
register = Register_FreedomUnits
|
register = register_FreedomUnits
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
public static async Task Register(DiscordSocketClient client)
|
public static async Task Register(DiscordSocketClient client)
|
||||||
{
|
|
||||||
if(Shared.SetupSlashCommands)
|
|
||||||
{
|
{
|
||||||
var commandsInContext = await client.GetGlobalApplicationCommandsAsync();
|
var commandsInContext = await client.GetGlobalApplicationCommandsAsync();
|
||||||
await Register(client, commandsInContext, null);
|
await Register(client, commandsInContext, null);
|
||||||
@ -32,13 +30,12 @@ namespace vassago.ProtocolInterfaces.DiscordInterface
|
|||||||
{
|
{
|
||||||
await Register(client, await guild.GetApplicationCommandsAsync(), guild);
|
await Register(client, await guild.GetApplicationCommandsAsync(), guild);
|
||||||
}
|
}
|
||||||
catch (HttpException ex)
|
catch (Discord.Net.HttpException ex)
|
||||||
{
|
{
|
||||||
Console.Error.WriteLine($"error registering slash commands for guild {guild.Name} (id {guild.Id}) - {ex.Message}");
|
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)
|
private static async Task Register(DiscordSocketClient client, IEnumerable<SocketApplicationCommand> commandsInContext, SocketGuild guild)
|
||||||
{
|
{
|
||||||
@ -49,6 +46,7 @@ namespace vassago.ProtocolInterfaces.DiscordInterface
|
|||||||
{
|
{
|
||||||
Console.WriteLine($"deleting command {existingCommand.Name} - (created at {existingCommand.CreatedAt}, it's in guild {existingCommand.Guild?.Id} while I'm in {guild?.Id})");
|
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();
|
await existingCommand.DeleteAsync();
|
||||||
|
Console.WriteLine("survived");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -57,6 +55,7 @@ namespace vassago.ProtocolInterfaces.DiscordInterface
|
|||||||
{
|
{
|
||||||
Console.WriteLine($"overwriting command {existingCommand.Name}");
|
Console.WriteLine($"overwriting command {existingCommand.Name}");
|
||||||
await myVersion.register(false, client, guild);
|
await myVersion.register(false, client, guild);
|
||||||
|
Console.WriteLine($"survived");
|
||||||
}
|
}
|
||||||
myVersion.alreadyRegistered = true;
|
myVersion.alreadyRegistered = true;
|
||||||
}
|
}
|
||||||
@ -65,10 +64,11 @@ namespace vassago.ProtocolInterfaces.DiscordInterface
|
|||||||
{
|
{
|
||||||
Console.WriteLine($"creating new command {remaining.Id} ({(remaining.guild == null ? "global" : $"for guild {remaining.guild}")})");
|
Console.WriteLine($"creating new command {remaining.Id} ({(remaining.guild == null ? "global" : $"for guild {remaining.guild}")})");
|
||||||
await remaining.register(true, client, guild);
|
await remaining.register(true, client, guild);
|
||||||
|
Console.WriteLine($"survived");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task Register_FreedomUnits(bool isNew, DiscordSocketClient client, SocketGuild guild)
|
private static async Task register_FreedomUnits(bool isNew, DiscordSocketClient client, SocketGuild guild)
|
||||||
{
|
{
|
||||||
var builtCommand = new SlashCommandBuilder()
|
var builtCommand = new SlashCommandBuilder()
|
||||||
.WithName("freedomunits")
|
.WithName("freedomunits")
|
||||||
@ -108,6 +108,32 @@ namespace vassago.ProtocolInterfaces.DiscordInterface
|
|||||||
Console.Error.WriteLine(json);
|
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
|
private class CommandSetup
|
||||||
{
|
{
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
@ -1,35 +0,0 @@
|
|||||||
using System.Diagnostics;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using vassago.Models;
|
|
||||||
using vassago.WebInterface.Models;
|
|
||||||
|
|
||||||
namespace vassago.WebInterface.Controllers;
|
|
||||||
|
|
||||||
public class AccountsController(ChattingContext db) : Controller
|
|
||||||
{
|
|
||||||
private ChattingContext Database => db;
|
|
||||||
|
|
||||||
public async Task<IActionResult> Index()
|
|
||||||
{
|
|
||||||
return Database.Accounts != null ?
|
|
||||||
View(await Database.Accounts.ToListAsync()) :
|
|
||||||
Problem("Entity set '_db.Accounts' is null.");
|
|
||||||
}
|
|
||||||
public async Task<IActionResult> Details(Guid id)
|
|
||||||
{
|
|
||||||
var account = await Database.Accounts
|
|
||||||
.Include(a => a.IsUser)
|
|
||||||
.Include(a => a.SeenInChannel)
|
|
||||||
.FirstAsync(a => a.Id == id);
|
|
||||||
return Database.Accounts != null ?
|
|
||||||
View(account) :
|
|
||||||
Problem("Entity set '_db.Accounts' is null.");
|
|
||||||
}
|
|
||||||
|
|
||||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
|
||||||
public IActionResult Error()
|
|
||||||
{
|
|
||||||
return View(new ErrorPageViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,61 +0,0 @@
|
|||||||
using System.ComponentModel;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Text;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using vassago.Models;
|
|
||||||
using vassago.WebInterface.Models;
|
|
||||||
|
|
||||||
namespace vassago.WebInterface.Controllers;
|
|
||||||
|
|
||||||
public class ChannelsController() : Controller
|
|
||||||
{
|
|
||||||
public IActionResult Details(Guid id)
|
|
||||||
{
|
|
||||||
var allChannels = Rememberer.ChannelsOverview();
|
|
||||||
if(allChannels == null)
|
|
||||||
return Problem("Entity set '_db.Channels' is null.");
|
|
||||||
//"but adam", says the strawman, "why load *every* channel and walk your way up? surely there's a .Load command that works or something."
|
|
||||||
//eh. I checked. Not really. You could make an SQL view that recurses its way up, meh idk how. You could just eagerly load *every* related object...
|
|
||||||
//but that would take in all the messages.
|
|
||||||
//realistically I expect this will have less than 1MB of total "channels", and several GB of total messages per (text) channel.
|
|
||||||
|
|
||||||
var channel = allChannels.First(u => u.Id == id);
|
|
||||||
var walker = channel;
|
|
||||||
while(walker != null)
|
|
||||||
{
|
|
||||||
ViewData["breadcrumbs"] = $"<a href=\"{Url.ActionLink(action: "Details", controller: "Channels", values: new {id = walker.Id})}\">{walker.DisplayName}</a>/" +
|
|
||||||
ViewData["breadcrumbs"];
|
|
||||||
walker = walker.ParentChannel;
|
|
||||||
}
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
sb.Append('[');
|
|
||||||
sb.Append($"{{text: \"{channel.SubChannels?.Count}\", nodes: [");
|
|
||||||
var first=true;
|
|
||||||
foreach(var subChannel in channel.SubChannels)
|
|
||||||
{
|
|
||||||
if(!first)
|
|
||||||
{
|
|
||||||
sb.Append(',');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
sb.Append($"{{\"text\": \"<a href=\\\"{Url.ActionLink(action: "Details", controller: "Channels", values: new {id = subChannel.Id})}\\\">{subChannel.DisplayName}</a>\"}}");
|
|
||||||
}
|
|
||||||
sb.Append("]}]");
|
|
||||||
|
|
||||||
ViewData.Add("channelsTree", sb.ToString());
|
|
||||||
return View(
|
|
||||||
new Tuple<Channel, Enumerations.LewdnessFilterLevel, Enumerations.MeannessFilterLevel>(
|
|
||||||
channel, channel.EffectivePermissions.LewdnessFilterLevel, channel.EffectivePermissions.MeannessFilterLevel
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
|
||||||
public IActionResult Error()
|
|
||||||
{
|
|
||||||
return View(new ErrorPageViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,228 +0,0 @@
|
|||||||
using System.Diagnostics;
|
|
||||||
using System.Text;
|
|
||||||
using System.Web;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.Extensions.FileSystemGlobbing.Internal.PathSegments;
|
|
||||||
using vassago.Models;
|
|
||||||
using vassago.WebInterface.Models;
|
|
||||||
|
|
||||||
namespace vassago.Controllers;
|
|
||||||
|
|
||||||
public class HomeController : Controller
|
|
||||||
{
|
|
||||||
private readonly ILogger<HomeController> _logger;
|
|
||||||
|
|
||||||
public HomeController(ILogger<HomeController> logger)
|
|
||||||
{
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IActionResult Index()
|
|
||||||
{
|
|
||||||
var allAccounts = Rememberer.AccountsOverview();
|
|
||||||
var allChannels = Rememberer.ChannelsOverview();
|
|
||||||
Console.WriteLine($"accounts: {allAccounts?.Count ?? 0}, channels: {allChannels?.Count ?? 0}");
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
sb.Append('[');
|
|
||||||
|
|
||||||
//UACs
|
|
||||||
var allUACs = Rememberer.UACsOverview();
|
|
||||||
var first = true;
|
|
||||||
if(allUACs.Any())
|
|
||||||
{
|
|
||||||
sb.Append("{text: \"uacs\", expanded:true, nodes: [");
|
|
||||||
first=true;
|
|
||||||
foreach(var uac in allUACs)
|
|
||||||
{
|
|
||||||
if (first)
|
|
||||||
{
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sb.Append(',');
|
|
||||||
}
|
|
||||||
sb.Append($"{{\"text\": \"<a href=\\\"{Url.ActionLink(action: "Details", controller: "UACs", values: new {id = uac.Id})}\\\">{uac.DisplayName}</a>\"}}");
|
|
||||||
}
|
|
||||||
sb.Append("]}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sb.Append("{text: \"uacs (0)\", }");
|
|
||||||
}
|
|
||||||
|
|
||||||
//users
|
|
||||||
var users = Rememberer.UsersOverview();
|
|
||||||
if(users.Any())
|
|
||||||
{
|
|
||||||
sb.Append(",{text: \"users\", expanded:true, nodes: [");
|
|
||||||
first=true;
|
|
||||||
//refresh list; we'll be knocking them out again in serializeUser
|
|
||||||
allAccounts = Rememberer.AccountsOverview();
|
|
||||||
foreach(var user in users)
|
|
||||||
{
|
|
||||||
if (first)
|
|
||||||
{
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sb.Append(',');
|
|
||||||
}
|
|
||||||
serializeUser(ref sb, ref allAccounts, user);
|
|
||||||
}
|
|
||||||
sb.Append("]}");
|
|
||||||
}
|
|
||||||
|
|
||||||
//type error, e is not defined
|
|
||||||
//channels
|
|
||||||
sb.Append(",{text: \"channels\", expanded:true, nodes: [");
|
|
||||||
var topLevelChannels = Rememberer.ChannelsOverview().Where(x => x.ParentChannel == null);
|
|
||||||
first = true;
|
|
||||||
foreach (var topLevelChannel in topLevelChannels)
|
|
||||||
{
|
|
||||||
if (first)
|
|
||||||
{
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sb.Append(',');
|
|
||||||
}
|
|
||||||
|
|
||||||
serializeChannel(ref sb, ref allChannels, ref allAccounts, topLevelChannel);
|
|
||||||
}
|
|
||||||
sb.Append("]}");
|
|
||||||
|
|
||||||
if (allChannels.Any())
|
|
||||||
{
|
|
||||||
sb.Append(",{text: \"orphaned channels\", expanded:true, nodes: [");
|
|
||||||
first = true;
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if (first)
|
|
||||||
{
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sb.Append(',');
|
|
||||||
}
|
|
||||||
serializeChannel(ref sb, ref allChannels, ref allAccounts, allChannels.First());
|
|
||||||
if (!allChannels.Any())
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sb.Append("]}");
|
|
||||||
}
|
|
||||||
if (allAccounts.Any())
|
|
||||||
{
|
|
||||||
sb.Append(",{text: \"channelless accounts\", expanded:true, nodes: [");
|
|
||||||
first = true;
|
|
||||||
foreach (var acc in allAccounts)
|
|
||||||
{
|
|
||||||
if (first)
|
|
||||||
{
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sb.Append(',');
|
|
||||||
}
|
|
||||||
serializeAccount(ref sb, acc);
|
|
||||||
}
|
|
||||||
sb.Append("]}");
|
|
||||||
}
|
|
||||||
|
|
||||||
sb.Append("]");
|
|
||||||
ViewData.Add("treeString", sb.ToString());
|
|
||||||
return View("Index");
|
|
||||||
}
|
|
||||||
private void serializeChannel(ref StringBuilder sb, ref List<Channel> allChannels, ref List<Account> allAccounts, Channel 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
|
|
||||||
sb.Append($"{{\"text\": \"<a href=\\\"{Url.ActionLink(action: "Details", controller: "Channels", values: new {id = currentChannel.Id})}\\\">{currentChannel.DisplayName}</a>\"");
|
|
||||||
sb.Append(", expanded:true ");
|
|
||||||
var theseAccounts = allAccounts.Where(a => a.SeenInChannel?.Id == currentChannel.Id).ToList();
|
|
||||||
allAccounts.RemoveAll(a => a.SeenInChannel?.Id == currentChannel.Id);
|
|
||||||
var first = true;
|
|
||||||
if (currentChannel.SubChannels != null || theseAccounts != null)
|
|
||||||
{
|
|
||||||
sb.Append(", \"nodes\": [");
|
|
||||||
if (currentChannel.SubChannels != null)
|
|
||||||
{
|
|
||||||
foreach (var subChannel in currentChannel.SubChannels)
|
|
||||||
{
|
|
||||||
if (first)
|
|
||||||
{
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
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
|
|
||||||
{
|
|
||||||
sb.Append(',');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (theseAccounts != null)
|
|
||||||
{
|
|
||||||
first = true;
|
|
||||||
sb.Append($"{{\"text\": \"(accounts: {theseAccounts.Count()})\", \"expanded\":true, nodes:[");
|
|
||||||
foreach (var account in theseAccounts)
|
|
||||||
{
|
|
||||||
if (first)
|
|
||||||
{
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sb.Append(',');
|
|
||||||
}
|
|
||||||
serializeAccount(ref sb, account);
|
|
||||||
}
|
|
||||||
sb.Append("]}");
|
|
||||||
}
|
|
||||||
sb.Append(']');
|
|
||||||
}
|
|
||||||
sb.Append('}');
|
|
||||||
}
|
|
||||||
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>\"}}");
|
|
||||||
}
|
|
||||||
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(currentUser.DisplayName);
|
|
||||||
sb.Append("</a>\", ");
|
|
||||||
var ownedAccounts = allAccounts.Where(a => a.IsUser == currentUser);
|
|
||||||
if (ownedAccounts?.Count() > 0)
|
|
||||||
{
|
|
||||||
sb.Append("nodes: [");
|
|
||||||
sb.Append($"{{\"text\": \"owned accounts:\", \"expanded\":true, \"nodes\": [");
|
|
||||||
var first = true;
|
|
||||||
foreach (var acc in ownedAccounts)
|
|
||||||
{
|
|
||||||
if(!first)
|
|
||||||
sb.Append(',');
|
|
||||||
serializeAccount(ref sb, acc);
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
sb.Append("]}]");
|
|
||||||
}
|
|
||||||
sb.Append("}");
|
|
||||||
}
|
|
||||||
|
|
||||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
|
||||||
public IActionResult Error()
|
|
||||||
{
|
|
||||||
return View(new ErrorPageViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
using System.Diagnostics;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using vassago.Models;
|
|
||||||
using vassago.WebInterface.Models;
|
|
||||||
|
|
||||||
namespace vassago.WebInterface.Controllers;
|
|
||||||
|
|
||||||
public class UACsController() : Controller
|
|
||||||
{
|
|
||||||
public IActionResult Index()
|
|
||||||
{
|
|
||||||
return View(Rememberer.UACsOverview());
|
|
||||||
}
|
|
||||||
public IActionResult Details(Guid id)
|
|
||||||
{
|
|
||||||
return View(Rememberer.SearchUAC(uac => uac.Id == id));
|
|
||||||
}
|
|
||||||
|
|
||||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
|
||||||
public IActionResult Error()
|
|
||||||
{
|
|
||||||
return View(new ErrorPageViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
using System.Diagnostics;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using vassago.Models;
|
|
||||||
using vassago.WebInterface.Models;
|
|
||||||
|
|
||||||
namespace vassago.WebInterface.Controllers;
|
|
||||||
|
|
||||||
public class UsersController(ChattingContext db) : Controller
|
|
||||||
{
|
|
||||||
private ChattingContext Database => db;
|
|
||||||
|
|
||||||
public async Task<IActionResult> Index()
|
|
||||||
{
|
|
||||||
return Database.Users != null ?
|
|
||||||
View(await Database.Users.Include(u => u.Accounts).ToListAsync()) :
|
|
||||||
Problem("Entity set '_db.Users' is null.");
|
|
||||||
}
|
|
||||||
public async Task<IActionResult> Details(Guid id)
|
|
||||||
{
|
|
||||||
var user = await Database.Users
|
|
||||||
.Include(u => u.Accounts)
|
|
||||||
.FirstAsync(u => u.Id == id);
|
|
||||||
var allTheChannels = await Database.Channels.ToListAsync();
|
|
||||||
foreach(var acc in user.Accounts)
|
|
||||||
{
|
|
||||||
acc.SeenInChannel = allTheChannels.FirstOrDefault(c => c.Id == acc.SeenInChannel.Id);
|
|
||||||
}
|
|
||||||
return Database.Users != null ?
|
|
||||||
View(user) :
|
|
||||||
Problem("Entity set '_db.Users' is null.");
|
|
||||||
}
|
|
||||||
|
|
||||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
|
||||||
public IActionResult Error()
|
|
||||||
{
|
|
||||||
return View(new ErrorPageViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,89 +0,0 @@
|
|||||||
using System.Diagnostics;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using vassago.Models;
|
|
||||||
|
|
||||||
namespace vassago.Controllers.api;
|
|
||||||
|
|
||||||
[Route("api/[controller]")]
|
|
||||||
[ApiController]
|
|
||||||
public class ChannelsController : ControllerBase
|
|
||||||
{
|
|
||||||
private readonly ILogger<ChannelsController> _logger;
|
|
||||||
|
|
||||||
public ChannelsController(ILogger<ChannelsController> logger)
|
|
||||||
{
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("{id}")]
|
|
||||||
[Produces("application/json")]
|
|
||||||
public Channel Get(Guid id)
|
|
||||||
{
|
|
||||||
return Rememberer.ChannelDetail(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPatch]
|
|
||||||
[Produces("application/json")]
|
|
||||||
public IActionResult Patch([FromBody] Channel channel)
|
|
||||||
{
|
|
||||||
var fromDb = Rememberer.ChannelDetail(channel.Id);
|
|
||||||
if (fromDb == null)
|
|
||||||
{
|
|
||||||
_logger.LogError($"attempt to update channel {channel.Id}, not found");
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_logger.LogDebug($"patching {channel.DisplayName} (id: {channel.Id})");
|
|
||||||
}
|
|
||||||
//settable values: lewdness filter level, meanness filter level. maybe i could decorate them...
|
|
||||||
fromDb.LewdnessFilterLevel = channel.LewdnessFilterLevel;
|
|
||||||
fromDb.MeannessFilterLevel = channel.MeannessFilterLevel;
|
|
||||||
Rememberer.RememberChannel(fromDb);
|
|
||||||
return Ok(fromDb);
|
|
||||||
}
|
|
||||||
[HttpDelete]
|
|
||||||
[Produces("application/json")]
|
|
||||||
public IActionResult Delete([FromBody] Channel channel)
|
|
||||||
{
|
|
||||||
var fromDb = Rememberer.ChannelDetail(channel.Id);
|
|
||||||
if (fromDb == null)
|
|
||||||
{
|
|
||||||
_logger.LogError($"attempt to delete channel {channel.Id}, not found");
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
deleteChannel(fromDb);
|
|
||||||
return Ok();
|
|
||||||
}
|
|
||||||
private void deleteChannel(Channel channel)
|
|
||||||
{
|
|
||||||
if (channel.SubChannels?.Count > 0)
|
|
||||||
{
|
|
||||||
foreach (var childChannel in channel.SubChannels)
|
|
||||||
{
|
|
||||||
deleteChannel(childChannel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(channel.Users?.Count > 0)
|
|
||||||
{
|
|
||||||
foreach(var account in channel.Users)
|
|
||||||
{
|
|
||||||
deleteAccount(account);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rememberer.ForgetChannel(channel);
|
|
||||||
}
|
|
||||||
private void deleteAccount(Account account)
|
|
||||||
{
|
|
||||||
var user = account.IsUser;
|
|
||||||
var usersOnlyAccount = user.Accounts?.Count == 1;
|
|
||||||
|
|
||||||
Rememberer.ForgetAccount(account);
|
|
||||||
|
|
||||||
if(usersOnlyAccount)
|
|
||||||
Rememberer.ForgetUser(user);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,213 +0,0 @@
|
|||||||
using System.Diagnostics;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using vassago.Models;
|
|
||||||
using vassago.ProtocolInterfaces.DiscordInterface;
|
|
||||||
|
|
||||||
namespace vassago.Controllers.api;
|
|
||||||
|
|
||||||
[Route("api/[controller]")]
|
|
||||||
[ApiController]
|
|
||||||
public class UACController: ControllerBase
|
|
||||||
{
|
|
||||||
private readonly ILogger<UACController> _logger;
|
|
||||||
|
|
||||||
public UACController(ILogger<UACController> logger)
|
|
||||||
{
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
//microsoft: "you can't have multiple [FromBody]. The reason for this rule is some bullshti about storage buffers."
|
|
||||||
//cool story, bro. nobody gives a fuck, look at the boilerplate you've necessitated.
|
|
||||||
public class extraSpecialObjectReadGlorifiedTupleFor_LinkChannel
|
|
||||||
{
|
|
||||||
public Guid uac_guid;
|
|
||||||
public Guid channel_guid;
|
|
||||||
}
|
|
||||||
[HttpPatch]
|
|
||||||
[Route("LinkChannel")]
|
|
||||||
[Produces("application/json")]
|
|
||||||
public IActionResult LinkChannel([FromBody] extraSpecialObjectReadGlorifiedTupleFor_LinkChannel req)
|
|
||||||
{
|
|
||||||
var uac_guid = req.uac_guid;
|
|
||||||
var channel_guid = req.channel_guid;
|
|
||||||
var uacFromDb = Rememberer.SearchUAC(uac => uac.Id == uac_guid);
|
|
||||||
if (uacFromDb == null)
|
|
||||||
{
|
|
||||||
var err =$"attempt to link channel for uac {uac_guid}, not found";
|
|
||||||
_logger.LogError(err);
|
|
||||||
return NotFound(err);
|
|
||||||
}
|
|
||||||
var channelFromDb = Rememberer.SearchChannel(c => c.Id == channel_guid);
|
|
||||||
if (channelFromDb == null)
|
|
||||||
{
|
|
||||||
var err = $"attempt to link channel for channel {channel_guid}, not found";
|
|
||||||
_logger.LogError(err);
|
|
||||||
return NotFound(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
uacFromDb.Channels ??= [];
|
|
||||||
if (uacFromDb.Channels.Contains(channelFromDb))
|
|
||||||
{
|
|
||||||
return BadRequest("channel already linked");
|
|
||||||
}
|
|
||||||
uacFromDb.Channels.Add(channelFromDb);
|
|
||||||
Rememberer.RememberUAC(uacFromDb);
|
|
||||||
return Ok(uacFromDb);
|
|
||||||
}
|
|
||||||
public class extraSpecialObjectReadGlorifiedTupleFor_LinkUser
|
|
||||||
{
|
|
||||||
public Guid uac_guid;
|
|
||||||
public Guid user_guid;
|
|
||||||
}
|
|
||||||
[HttpPatch]
|
|
||||||
[Route("LinkUser")]
|
|
||||||
[Produces("application/json")]
|
|
||||||
public IActionResult LinkUser([FromBody] extraSpecialObjectReadGlorifiedTupleFor_LinkUser req)
|
|
||||||
{
|
|
||||||
var uac_guid = req.uac_guid;
|
|
||||||
var user_guid = req.user_guid;
|
|
||||||
var uacFromDb = Rememberer.SearchUAC(uac => uac.Id == uac_guid);
|
|
||||||
if (uacFromDb == null)
|
|
||||||
{
|
|
||||||
_logger.LogError($"attempt to link channal for uac {uac_guid}, not found");
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
var userFromDb = Rememberer.SearchUser(c => c.Id == user_guid);
|
|
||||||
if (userFromDb == null)
|
|
||||||
{
|
|
||||||
_logger.LogError($"attempt to link user for user {user_guid}, not found");
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
uacFromDb.Users ??= [];
|
|
||||||
if (uacFromDb.Users.Contains(userFromDb))
|
|
||||||
{
|
|
||||||
return BadRequest("user already linked");
|
|
||||||
}
|
|
||||||
uacFromDb.Users.Add(userFromDb);
|
|
||||||
Rememberer.RememberUAC(uacFromDb);
|
|
||||||
return Ok(uacFromDb);
|
|
||||||
}
|
|
||||||
public class extraSpecialObjectReadGlorifiedTupleFor_LinkAccount
|
|
||||||
{
|
|
||||||
public Guid uac_guid;
|
|
||||||
public Guid account_guid;
|
|
||||||
}
|
|
||||||
[HttpPatch]
|
|
||||||
[Route("LinkAccount")]
|
|
||||||
[Produces("application/json")]
|
|
||||||
public IActionResult LinkAccount([FromBody] extraSpecialObjectReadGlorifiedTupleFor_LinkAccount req)
|
|
||||||
{
|
|
||||||
var uac_guid = req.uac_guid;
|
|
||||||
var account_guid = req.account_guid;
|
|
||||||
var uacFromDb = Rememberer.SearchUAC(uac => uac.Id == uac_guid);
|
|
||||||
if (uacFromDb == null)
|
|
||||||
{
|
|
||||||
_logger.LogError($"attempt to link channal for uac {uac_guid}, not found");
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
var accountFromDb = Rememberer.SearchAccount(c => c.Id == account_guid);
|
|
||||||
if (accountFromDb == null)
|
|
||||||
{
|
|
||||||
_logger.LogError($"attempt to link account for user {account_guid}, not found");
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
uacFromDb.AccountInChannels ??= [];
|
|
||||||
if (uacFromDb.AccountInChannels.Contains(accountFromDb))
|
|
||||||
{
|
|
||||||
return BadRequest("account already linked");
|
|
||||||
}
|
|
||||||
uacFromDb.AccountInChannels.Add(accountFromDb);
|
|
||||||
Rememberer.RememberUAC(uacFromDb);
|
|
||||||
return Ok(uacFromDb);
|
|
||||||
}
|
|
||||||
[HttpPatch]
|
|
||||||
[Route("UnlinkUser")]
|
|
||||||
[Produces("application/json")]
|
|
||||||
public IActionResult UnlinkUser([FromBody] extraSpecialObjectReadGlorifiedTupleFor_LinkUser req)
|
|
||||||
{
|
|
||||||
var uac_guid = req.uac_guid;
|
|
||||||
var user_guid = req.user_guid;
|
|
||||||
var uacFromDb = Rememberer.SearchUAC(uac => uac.Id == uac_guid);
|
|
||||||
if (uacFromDb == null)
|
|
||||||
{
|
|
||||||
_logger.LogError($"attempt to unlink uac for uac {uac_guid}, not found");
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
var userFromDb = Rememberer.SearchUser(c => c.Id == user_guid);
|
|
||||||
if (userFromDb == null)
|
|
||||||
{
|
|
||||||
_logger.LogError($"attempt to unlink user for user {user_guid}, not found");
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
uacFromDb.Users ??= [];
|
|
||||||
if (!uacFromDb.Users.Contains(userFromDb))
|
|
||||||
{
|
|
||||||
return BadRequest("user not linked");
|
|
||||||
}
|
|
||||||
uacFromDb.Users.Remove(userFromDb);
|
|
||||||
Rememberer.RememberUAC(uacFromDb);
|
|
||||||
return Ok(uacFromDb);
|
|
||||||
}
|
|
||||||
[HttpPatch]
|
|
||||||
[Route("UnlinkAccount")]
|
|
||||||
[Produces("application/json")]
|
|
||||||
public IActionResult UnlinkAccount([FromBody] extraSpecialObjectReadGlorifiedTupleFor_LinkAccount req)
|
|
||||||
{
|
|
||||||
var uac_guid = req.uac_guid;
|
|
||||||
var account_guid = req.account_guid;
|
|
||||||
var uacFromDb = Rememberer.SearchUAC(uac => uac.Id == uac_guid);
|
|
||||||
if (uacFromDb == null)
|
|
||||||
{
|
|
||||||
_logger.LogError($"attempt to unlink uac for uac {uac_guid}, not found");
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
var accountFromDb = Rememberer.SearchAccount(a => a.Id == account_guid);
|
|
||||||
if (accountFromDb == null)
|
|
||||||
{
|
|
||||||
_logger.LogError($"attempt to unlink account for user {account_guid}, not found");
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
uacFromDb.AccountInChannels ??= [];
|
|
||||||
if (!uacFromDb.AccountInChannels.Contains(accountFromDb))
|
|
||||||
{
|
|
||||||
return BadRequest("account not linked");
|
|
||||||
}
|
|
||||||
uacFromDb.AccountInChannels.Remove(accountFromDb);
|
|
||||||
Rememberer.RememberUAC(uacFromDb);
|
|
||||||
return Ok(uacFromDb);
|
|
||||||
}
|
|
||||||
[HttpPatch]
|
|
||||||
[Route("UnlinkChannel")]
|
|
||||||
[Produces("application/json")]
|
|
||||||
public IActionResult UnlinkChannel([FromBody] extraSpecialObjectReadGlorifiedTupleFor_LinkChannel req)
|
|
||||||
{
|
|
||||||
var uac_guid = req.uac_guid;
|
|
||||||
var channel_guid = req.channel_guid;
|
|
||||||
var uacFromDb = Rememberer.SearchUAC(uac => uac.Id == uac_guid);
|
|
||||||
if (uacFromDb == null)
|
|
||||||
{
|
|
||||||
_logger.LogError($"attempt to unlink channal for uac {uac_guid}, not found");
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
var channelFromDb = Rememberer.SearchChannel(c => c.Id == channel_guid);
|
|
||||||
if (channelFromDb == null)
|
|
||||||
{
|
|
||||||
_logger.LogError($"attempt to unlink user for user {channel_guid}, not found");
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
uacFromDb.Users ??= [];
|
|
||||||
if (!uacFromDb.Channels.Contains(channelFromDb))
|
|
||||||
{
|
|
||||||
return BadRequest("user not linked");
|
|
||||||
}
|
|
||||||
uacFromDb.Channels.Remove(channelFromDb);
|
|
||||||
Rememberer.RememberUAC(uacFromDb);
|
|
||||||
return Ok(uacFromDb);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
using System.Diagnostics;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using vassago.Models;
|
|
||||||
using vassago.ProtocolInterfaces.DiscordInterface;
|
|
||||||
|
|
||||||
namespace vassago.Controllers.api;
|
|
||||||
|
|
||||||
[Route("api/[controller]")]
|
|
||||||
[ApiController]
|
|
||||||
public class UsersController : ControllerBase
|
|
||||||
{
|
|
||||||
private readonly ILogger<ChannelsController> _logger;
|
|
||||||
|
|
||||||
public UsersController(ILogger<ChannelsController> logger)
|
|
||||||
{
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPatch]
|
|
||||||
[Produces("application/json")]
|
|
||||||
public IActionResult Patch([FromBody] User user)
|
|
||||||
{
|
|
||||||
var fromDb = Rememberer.SearchUser(u => u.Id == user.Id);
|
|
||||||
if (fromDb == null)
|
|
||||||
{
|
|
||||||
_logger.LogError($"attempt to update user {user.Id}, not found");
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_logger.LogDebug($"patching {user.DisplayName} (id: {user.Id})");
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: settable values: display name
|
|
||||||
//fromDb.DisplayName = user.DisplayName;
|
|
||||||
Rememberer.RememberUser(fromDb);
|
|
||||||
return Ok(fromDb);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
namespace vassago.WebInterface.Models;
|
|
||||||
|
|
||||||
public class ErrorPageViewModel
|
|
||||||
{
|
|
||||||
public string RequestId { get; set; }
|
|
||||||
|
|
||||||
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
|
||||||
}
|
|
@ -1,68 +0,0 @@
|
|||||||
@model Account
|
|
||||||
@using Newtonsoft.Json
|
|
||||||
@using System.Text
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Account details";
|
|
||||||
}
|
|
||||||
|
|
||||||
<a href="/">home</a>/@Html.Raw(ViewData["breadcrumbs"])
|
|
||||||
<table class="table">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">belongs to user</th>
|
|
||||||
<td>@Model.IsUser.DisplayName</td>
|
|
||||||
<td><button alt="to do" disabled>separate</button></2td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Seen in channel</th>
|
|
||||||
<td class="account @Model.SeenInChannel.Protocol"><div class="protocol-icon"> </div>@Model.SeenInChannel.LineageSummary<a href="/Channels/Details/@Model.SeenInChannel.Id">@Model.SeenInChannel.DisplayName</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Permission Tags</th>
|
|
||||||
<td>
|
|
||||||
<div id="tagsTree"></div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
@section Scripts{
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
@{
|
|
||||||
var accountAsString = JsonConvert.SerializeObject(Model, new JsonSerializerSettings
|
|
||||||
{
|
|
||||||
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const userOnLoad = @Html.Raw(accountAsString);
|
|
||||||
function jsonifyUser() {
|
|
||||||
var userNow = structuredClone(userOnLoad);
|
|
||||||
userNow.Accounts = null;
|
|
||||||
userNow.DisplayName = document.querySelector("#displayName").value;
|
|
||||||
console.log(userNow);
|
|
||||||
return userNow;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTagsTree() {
|
|
||||||
@{
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
sb.Append("[{text: \"permission tags\", \"expanded\":true, nodes: [");
|
|
||||||
var first = true;
|
|
||||||
for (int i = 0; i < 1; i++)
|
|
||||||
{
|
|
||||||
if (!first)
|
|
||||||
sb.Append(',');
|
|
||||||
sb.Append($"{{text: \"<input type=\\\"checkbox\\\" > is goated (w/ sauce)</input>\"}}");
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
sb.Append("]}]");
|
|
||||||
}
|
|
||||||
console.log(@Html.Raw(sb.ToString()));
|
|
||||||
var tree = @Html.Raw(sb.ToString());
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
$('#tagsTree').bstreeview({ data: getTagsTree() });
|
|
||||||
document.querySelectorAll("input[type=checkbox]").forEach(node => { node.onchange = () => { patchModel(jsonifyUser(), '/api/Users/') } });
|
|
||||||
</script>
|
|
||||||
}
|
|
@ -1,169 +0,0 @@
|
|||||||
@using System.ComponentModel
|
|
||||||
@using Newtonsoft.Json
|
|
||||||
@using System.Text;
|
|
||||||
@model Tuple<Channel, Enumerations.LewdnessFilterLevel, Enumerations.MeannessFilterLevel>
|
|
||||||
@{
|
|
||||||
var ThisChannel = Model.Item1;
|
|
||||||
var IfInheritedLewdnessFilterLevel = Model.Item2;
|
|
||||||
var IfInheritedMeannessFilterLevel = Model.Item3;
|
|
||||||
}
|
|
||||||
|
|
||||||
<a href="/">home</a>/
|
|
||||||
@Html.Raw(ViewData["breadcrumbs"])
|
|
||||||
|
|
||||||
<table class="table">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Display Name</th>
|
|
||||||
<td>@ThisChannel.DisplayName</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Channel type</th>
|
|
||||||
<td>@(Enumerations.GetDescription(ThisChannel.ChannelType))</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Lewdness Filter Level</th>
|
|
||||||
<td>
|
|
||||||
<select name="LewdnessFilterLevel" id="LewdnessFilterLevel" onchange="patchModel(jsonifyChannel(), '/api/Channels/')">
|
|
||||||
<!option value="" @(ThisChannel.LewdnessFilterLevel == null ? "selected" : "")>⤵ inherited - @Enumerations.GetDescription(IfInheritedLewdnessFilterLevel)</!option>
|
|
||||||
@foreach (Enumerations.LewdnessFilterLevel enumVal in
|
|
||||||
Enum.GetValues(typeof(Enumerations.LewdnessFilterLevel)))
|
|
||||||
{
|
|
||||||
<!option value="@((int)enumVal)" @(ThisChannel.LewdnessFilterLevel == enumVal ? "selected" : "")>
|
|
||||||
@(Enumerations.GetDescription<Enumerations.LewdnessFilterLevel>(enumVal))</!option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Links Allowed</th>
|
|
||||||
<td>@(ThisChannel.LinksAllowed?.ToString() ?? "unknown")</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Lineage summary</th>
|
|
||||||
<td>@ThisChannel.LineageSummary</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">max attachment bytes</th>
|
|
||||||
<td>@ThisChannel.MaxAttachmentBytes (i hear there's "ByteSize")</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">max message length</th>
|
|
||||||
<td>@(ThisChannel.MaxTextChars?.ToString() ?? "inherited")</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Meanness Filter Level</th>
|
|
||||||
<td>
|
|
||||||
<select name="MeannessFilterLevel" id="MeannessFilterLevel" onchange="patchModel(jsonifyChannel(), '/api/Channels/')">
|
|
||||||
<!option value="" @(ThisChannel.MeannessFilterLevel == null ? "selected" : "")>⤵ inherited - @Enumerations.GetDescription(IfInheritedMeannessFilterLevel)</!option>
|
|
||||||
@foreach (Enumerations.MeannessFilterLevel enumVal in
|
|
||||||
Enum.GetValues(typeof(Enumerations.MeannessFilterLevel)))
|
|
||||||
{
|
|
||||||
<!option value="@((int)enumVal)" @(ThisChannel.MeannessFilterLevel == enumVal ? "selected" : "")>
|
|
||||||
@(Enumerations.GetDescription<Enumerations.MeannessFilterLevel>(enumVal))</!option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Messages (count)</th>
|
|
||||||
<td>@(ThisChannel.Messages?.Count ?? 0)</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Protocol</th>
|
|
||||||
<td>@ThisChannel.Protocol</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Reactions Possible</th>
|
|
||||||
<td>@(ThisChannel.ReactionsPossible?.ToString() ?? "inherited")</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Sub Channels</th>
|
|
||||||
<td>
|
|
||||||
@if((ThisChannel.SubChannels?.Count ?? 0) > 0)
|
|
||||||
{
|
|
||||||
@Html.Raw("<div id=\"channelsTree\"></div>");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
@Html.Raw("0")
|
|
||||||
}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Accounts</th>
|
|
||||||
<td>
|
|
||||||
@if((ThisChannel.Users?.Count ?? 0) > 0)
|
|
||||||
{
|
|
||||||
@Html.Raw("<div id=\"accountsTree\"></div>");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
@Html.Raw("none")
|
|
||||||
}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td colspan="2">
|
|
||||||
<button onclick="forget()">forget</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
@section Scripts{
|
|
||||||
<script type="text/javascript">
|
|
||||||
@{
|
|
||||||
var modelAsString = JsonConvert.SerializeObject(ThisChannel, new JsonSerializerSettings
|
|
||||||
{
|
|
||||||
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const channelOnLoad = @Html.Raw(modelAsString);
|
|
||||||
function jsonifyChannel() {
|
|
||||||
var channelNow = structuredClone(channelOnLoad);
|
|
||||||
channelNow.SubChannels = null;
|
|
||||||
channelNow.ParentChannel = null;
|
|
||||||
channelNow.Messages = null;
|
|
||||||
channelNow.Users = null;
|
|
||||||
|
|
||||||
channelNow.LewdnessFilterLevel = document.querySelector("#LewdnessFilterLevel").value;
|
|
||||||
channelNow.MeannessFilterLevel = document.querySelector("#MeannessFilterLevel").value;
|
|
||||||
console.log(channelNow);
|
|
||||||
return channelNow;
|
|
||||||
}
|
|
||||||
function forget(){
|
|
||||||
console.log("here we go");
|
|
||||||
if(window.confirm("delete? really really?") == true){
|
|
||||||
deleteModel(jsonifyChannel(), '/api/Channels/');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function channelsTree() {
|
|
||||||
var tree = @Html.Raw(ViewData["channelsTree"]);
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
|
|
||||||
function accountsTree() {
|
|
||||||
@{
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
sb.Append("[{text: \"accounts\", \"expanded\":true, nodes: [");
|
|
||||||
var first = true;
|
|
||||||
foreach (var acc in ThisChannel.Users.OrderBy(a => a.SeenInChannel.LineageSummary))
|
|
||||||
{
|
|
||||||
if(!first)
|
|
||||||
sb.Append(',');
|
|
||||||
sb.Append($"{{text: \"<div class=\\\"account {acc.Protocol}\\\"><div class=\\\"protocol-icon\\\"> </div>{acc.SeenInChannel.LineageSummary}/<a href=\\\"/Accounts/Details/{acc.Id}\\\">{acc.DisplayName}</a>\"}}");
|
|
||||||
first=false;
|
|
||||||
}
|
|
||||||
sb.Append("]}]");
|
|
||||||
}
|
|
||||||
//console.log(@Html.Raw(sb.ToString()));
|
|
||||||
var tree = @Html.Raw(sb.ToString());
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
$('#channelsTree').bstreeview({ data: channelsTree() });
|
|
||||||
$('#accountsTree').bstreeview({ data: accountsTree() });
|
|
||||||
|
|
||||||
</script>
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
@model IEnumerable<Channel>
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Channels";
|
|
||||||
}
|
|
||||||
|
|
||||||
<table class="table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>
|
|
||||||
protocol
|
|
||||||
</th>
|
|
||||||
<th>type</th>
|
|
||||||
<th>
|
|
||||||
display name
|
|
||||||
</th>
|
|
||||||
<th>
|
|
||||||
Lineage
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
@foreach (var item in Model) {
|
|
||||||
<tr>
|
|
||||||
<td class="@item.Protocol">
|
|
||||||
<div class="protocol-icon"> </div>
|
|
||||||
</td>
|
|
||||||
<td class="@item.ChannelType">
|
|
||||||
<div class="channel-type-icon"> </div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
@Html.DisplayFor(modelItem => item.DisplayName)
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
@item.LineageSummary
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<a asp-action="Details" asp-route-id="@item.Id">Details</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
@ -1,17 +0,0 @@
|
|||||||
@{
|
|
||||||
ViewData["Title"] = "Home Page";
|
|
||||||
}
|
|
||||||
<div id="tree">tree here</div>
|
|
||||||
|
|
||||||
@section Scripts{
|
|
||||||
<script type="text/javascript">
|
|
||||||
function getTree() {
|
|
||||||
var tree = @Html.Raw(ViewData["treeString"]);
|
|
||||||
console.log('tree');
|
|
||||||
console.log('@ViewData["treeString"]');
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#tree').bstreeview({ data: getTree() });
|
|
||||||
</script>
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
@model vassago.WebInterface.Models.ErrorPageViewModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Error";
|
|
||||||
}
|
|
||||||
|
|
||||||
<h1 class="text-danger">Error.</h1>
|
|
||||||
<h2 class="text-danger">An error occurred while processing your request.</h2>
|
|
||||||
|
|
||||||
@if (Model.ShowRequestId)
|
|
||||||
{
|
|
||||||
<p>
|
|
||||||
<strong>Request ID:</strong> <code>@Model.RequestId</code>
|
|
||||||
</p>
|
|
||||||
}
|
|
||||||
|
|
||||||
<h3>Development Mode</h3>
|
|
||||||
<p>
|
|
||||||
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
|
|
||||||
It can result in displaying sensitive information from exceptions to end users.
|
|
||||||
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
|
|
||||||
and restarting the app.
|
|
||||||
</p>
|
|
@ -1,25 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<title>@ViewData["Title"] - vassago</title>
|
|
||||||
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
|
|
||||||
<link rel="stylesheet" href="~/css/fontawesome.min.css" />
|
|
||||||
<link rel="stylesheet" href="~/css/bs.min.treeview.css" />
|
|
||||||
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
|
|
||||||
<link rel="stylesheet" href="~/vassago.styles.css" asp-append-version="true" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="container">
|
|
||||||
<main role="main" class="pb-3">
|
|
||||||
@RenderBody()
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
<script src="~/lib/jquery/dist/jquery.min.js"></script>
|
|
||||||
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
|
|
||||||
<script src="~/js/bstreeview.min.js"></script>
|
|
||||||
<script src="~/js/site.js" asp-append-version="true"></script>
|
|
||||||
@await RenderSectionAsync("Scripts", required: false)
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,48 +0,0 @@
|
|||||||
/* Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
|
|
||||||
for details on configuring this project to bundle and minify static web assets. */
|
|
||||||
|
|
||||||
a.navbar-brand {
|
|
||||||
white-space: normal;
|
|
||||||
text-align: center;
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: #0077cc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary {
|
|
||||||
color: #fff;
|
|
||||||
background-color: #1b6ec2;
|
|
||||||
border-color: #1861ac;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-pills .nav-link.active, .nav-pills .show > .nav-link {
|
|
||||||
color: #fff;
|
|
||||||
background-color: #1b6ec2;
|
|
||||||
border-color: #1861ac;
|
|
||||||
}
|
|
||||||
|
|
||||||
.border-top {
|
|
||||||
border-top: 1px solid #e5e5e5;
|
|
||||||
}
|
|
||||||
.border-bottom {
|
|
||||||
border-bottom: 1px solid #e5e5e5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.box-shadow {
|
|
||||||
box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
|
|
||||||
}
|
|
||||||
|
|
||||||
button.accept-policy {
|
|
||||||
font-size: 1rem;
|
|
||||||
line-height: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
width: 100%;
|
|
||||||
white-space: nowrap;
|
|
||||||
line-height: 60px;
|
|
||||||
}
|
|
@ -1,2 +0,0 @@
|
|||||||
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
|
|
||||||
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
|
|
@ -1,214 +0,0 @@
|
|||||||
@using System.ComponentModel
|
|
||||||
@using Newtonsoft.Json
|
|
||||||
@using System.Text;
|
|
||||||
@model UAC
|
|
||||||
|
|
||||||
<a href="/">home</a>/
|
|
||||||
@Html.Raw(ViewData["breadcrumbs"])
|
|
||||||
|
|
||||||
<table class="table">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Display Name</th>
|
|
||||||
<td>@Model.DisplayName</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Channels</th>
|
|
||||||
<td>
|
|
||||||
@Html.Raw("<div id=\"channelsTree\"></div>")
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Users</th>
|
|
||||||
<td>
|
|
||||||
@Html.Raw("<div id=\"usersTree\"></div>")
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">AccountInChannels</th>
|
|
||||||
<td>
|
|
||||||
@Html.Raw("<div id=\"accountsTree\"></div>")
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<div id="add-modal" class="modal" tabindex="-1" role="dialog">
|
|
||||||
<div class="modal-dialog" role="document">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title">Insert GUID</h5>
|
|
||||||
<button type="button" class="btn btn-close" data-dismiss="add-modal" aria-label="Close">
|
|
||||||
<span aria-hidden="true">×</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<p>
|
|
||||||
<ul>
|
|
||||||
<li>//TODO: search</li>
|
|
||||||
</ul>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<input id="addmodaltext" type="text" />
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button id="modalsubmit" type="button" class="btn btn-primary">Save changes</button>
|
|
||||||
<button type="button" class="btn btn-secondary" data-dismiss="add-modal">Close</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="remove-modal" class="modal" tabindex="-1" role="dialog">
|
|
||||||
<div class="modal-dialog" role="document">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title">Confirm</h5>
|
|
||||||
<button type="button" class="btn-close" data-dismiss="remove-modal" aria-label="Close">
|
|
||||||
<span aria-hidden="true">×</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<p>
|
|
||||||
are you sure you wnat to unlink
|
|
||||||
<input id="removeModalText" enabled="false" type="text" />
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
to be clear; this is going to "unlink", not like.. delete.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button id="modalsubmit" type="button" class="btn btn-danger">unlink</button>
|
|
||||||
<button type="button" class="btn btn-secondary" data-dismiss="remove-modal">Close</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
@section Scripts{
|
|
||||||
<script type="text/javascript">
|
|
||||||
function addChannel(){
|
|
||||||
let modalbutton = document.querySelector("#add-modal button#modalsubmit");
|
|
||||||
modalbutton.onclick = addChannelSubmit;
|
|
||||||
$("#add-modal").modal("show");
|
|
||||||
}
|
|
||||||
function addChannelSubmit(){
|
|
||||||
let guid = document.querySelector("#add-modal #addmodaltext").value;
|
|
||||||
linkUAC_Channel(guid, () => { window.location.reload(); });
|
|
||||||
$("#add-modal").modal("hide");
|
|
||||||
console.log(guid);
|
|
||||||
}
|
|
||||||
function addUser(){
|
|
||||||
let modalbutton = document.querySelector("#add-modal button#modalsubmit");
|
|
||||||
modalbutton.onclick = addUserSubmit;
|
|
||||||
$("#add-modal").modal("show");
|
|
||||||
}
|
|
||||||
function addUserSubmit(){
|
|
||||||
let guid = document.querySelector("#add-modal #addmodaltext").value;
|
|
||||||
linkUAC_User(guid, () => {window.location.reload(); });
|
|
||||||
$("#add-modal").modal("hide");
|
|
||||||
console.log(guid);
|
|
||||||
}
|
|
||||||
function addAccount(){
|
|
||||||
let modalbutton = document.querySelector("#add-modal button#modalsubmit");
|
|
||||||
modalbutton.onclick = addAccountSubmit;
|
|
||||||
$("#add-modal").modal("show");
|
|
||||||
}
|
|
||||||
function addAccountSubmit(){
|
|
||||||
let guid = document.querySelector("#add-modal #addmodaltext").value;
|
|
||||||
linkUAC_Account(guid, () => { window.location.reload(); });
|
|
||||||
$("#add-modal").modal("hide");
|
|
||||||
console.log(guid);
|
|
||||||
}
|
|
||||||
function removeUser(guid){
|
|
||||||
document.querySelector("#remove-modal #removeModalText").value = guid;
|
|
||||||
let modalbutton = document.querySelector("#remove-modal button#modalsubmit");
|
|
||||||
modalbutton.onclick = removeUserSubmit;
|
|
||||||
$("#remove-modal").modal("show");
|
|
||||||
}
|
|
||||||
function removeUserSubmit(){
|
|
||||||
let guid = document.querySelector("#remove-modal #removeModalText").value;
|
|
||||||
unlinkUAC_User(guid, () => { window.location.reload(); });
|
|
||||||
$("#remove-modal").modal("hide");
|
|
||||||
}
|
|
||||||
function removeChannel(guid){
|
|
||||||
document.querySelector("#remove-modal #removeModalText").value = guid;
|
|
||||||
let modalbutton = document.querySelector("#remove-modal button#modalsubmit");
|
|
||||||
modalbutton.onclick = removeChannelSubmit;
|
|
||||||
$("#remove-modal").modal("show");
|
|
||||||
}
|
|
||||||
function removeChannelSubmit(){
|
|
||||||
let guid = document.querySelector("#remove-modal #removeModalText").value;
|
|
||||||
unlinkUAC_Channel(guid, () => { window.location.reload(); });
|
|
||||||
$("#remove-modal").modal("hide");
|
|
||||||
}
|
|
||||||
function removeAccount(guid){
|
|
||||||
document.querySelector("#remove-modal #removeModalText").value = guid;
|
|
||||||
let modalbutton = document.querySelector("#remove-modal button#modalsubmit");
|
|
||||||
modalbutton.onclick = removeAccountSubmit;
|
|
||||||
$("#remove-modal").modal("show");
|
|
||||||
}
|
|
||||||
function removeAccountSubmit(){
|
|
||||||
let guid = document.querySelector("#remove-modal #removeModalText").value;
|
|
||||||
unlinkUAC_Account(guid , () => { window.location.reload(); });
|
|
||||||
$("#remove-modal").modal("hide");
|
|
||||||
}
|
|
||||||
function channelsTree() {
|
|
||||||
@{
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
sb.Append("[{text: \"Channels\", \"expanded\":true, nodes: [");
|
|
||||||
|
|
||||||
sb.Append($"{{text: \"<button type=\\\"button\\\" class=\\\"btn btn-primary\\\" onclick=\\\"addChannel()\\\">add channel</button>\"}}");
|
|
||||||
foreach (var acc in Model.Channels?.OrderBy(a => a.DisplayName))
|
|
||||||
{
|
|
||||||
sb.Append(',');
|
|
||||||
sb.Append($"{{text: \"<a href=\\\"/Channels/Details/{acc.Id}\\\">{acc.DisplayName}</a> - <button type=\\\"button\\\" class=\\\"btn btn-danger\\\" onclick=\\\"removeChannel('{acc.Id}')\\\">remove</button>\"}}");
|
|
||||||
}
|
|
||||||
sb.Append("]}]");
|
|
||||||
}
|
|
||||||
var tree = @Html.Raw(sb.ToString());
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
function usersTree() {
|
|
||||||
@{
|
|
||||||
sb = new StringBuilder();
|
|
||||||
sb.Append("[{text: \"Users\", \"expanded\":true, nodes: [");
|
|
||||||
|
|
||||||
sb.Append($"{{text: \"<button type=\\\"button\\\" class=\\\"btn btn-primary\\\" onclick=\\\"addUser()\\\">add user</button>\"}}");
|
|
||||||
foreach (var acc in Model.Users?.OrderBy(a => a.DisplayName))
|
|
||||||
{
|
|
||||||
sb.Append(',');
|
|
||||||
sb.Append($"{{text: \"<a href=\\\"/Users/Details/{acc.Id}\\\">{acc.DisplayName}</a> - <button type=\\\"button\\\" class=\\\"btn btn-danger\\\" onclick=\\\"removeUser('{acc.Id}')\\\">remove</button>\"}}");
|
|
||||||
}
|
|
||||||
sb.Append("]}]");
|
|
||||||
}
|
|
||||||
var tree = @Html.Raw(sb.ToString());
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
function accountsTree() {
|
|
||||||
@{
|
|
||||||
sb = new StringBuilder();
|
|
||||||
sb.Append("[{text: \"Accounts\", \"expanded\":true, nodes: [");
|
|
||||||
|
|
||||||
sb.Append($"{{text: \"<button type=\\\"button\\\" class=\\\"btn btn-primary\\\" onclick=\\\"addAccount()\\\">add account</button>\"}}");
|
|
||||||
foreach (var acc in Model.AccountInChannels?.OrderBy(a => a.DisplayName))
|
|
||||||
{
|
|
||||||
sb.Append(',');
|
|
||||||
sb.Append($"{{text: \"<a href=\\\"/Accounts/Details/{acc.Id}\\\">{acc.DisplayName}</a> - <button type=\\\"button\\\" class=\\\"btn btn-danger\\\" onclick=\\\"removeAccount('{acc.Id}')\\\">remove</button>\"}}");
|
|
||||||
}
|
|
||||||
sb.Append("]}]");
|
|
||||||
}
|
|
||||||
var tree = @Html.Raw(sb.ToString());
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
$('#channelsTree').bstreeview({ data: channelsTree() });
|
|
||||||
$('#usersTree').bstreeview({ data: usersTree() });
|
|
||||||
$('#accountsTree').bstreeview({ data: accountsTree() });
|
|
||||||
|
|
||||||
var components = window.location.pathname.split('/');
|
|
||||||
var uacId = components[3];
|
|
||||||
|
|
||||||
</script>
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
@model User
|
|
||||||
@using Newtonsoft.Json
|
|
||||||
@using System.Text
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "User details";
|
|
||||||
}
|
|
||||||
|
|
||||||
<a href="/">home</a>/@Html.Raw(ViewData["breadcrumbs"])
|
|
||||||
<table class="table">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Display Name (here)</th>
|
|
||||||
<td><input type="text" id="displayName" value="@Model.DisplayName" disabled alt="todo"></input> <button
|
|
||||||
onclick="patchModel(jsonifyUser(), @Html.Raw("'/api/Users/'"))" disabled alt"todo">update</button></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Accounts</th>
|
|
||||||
<td>
|
|
||||||
<div id="accountsTree"></div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
@section Scripts{
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
@{
|
|
||||||
var userAsString = JsonConvert.SerializeObject(Model, new JsonSerializerSettings
|
|
||||||
{
|
|
||||||
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const userOnLoad = @Html.Raw(userAsString);
|
|
||||||
function jsonifyUser() {
|
|
||||||
var userNow = structuredClone(userOnLoad);
|
|
||||||
userNow.Accounts = null;
|
|
||||||
userNow.DisplayName = document.querySelector("#displayName").value;
|
|
||||||
//userNow.Tag_CanTwitchSummon = document.querySelector("#tagCanTwitchSummon").checked;
|
|
||||||
console.log(userNow);
|
|
||||||
return userNow;
|
|
||||||
}
|
|
||||||
function getAccountsTree() {
|
|
||||||
@{
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
sb.Append("[{text: \"accounts\", \"expanded\":true, nodes: [");
|
|
||||||
var first = true;
|
|
||||||
foreach (var acc in Model.Accounts.OrderBy(a => a.SeenInChannel.LineageSummary))
|
|
||||||
{
|
|
||||||
if (!first)
|
|
||||||
sb.Append(',');
|
|
||||||
sb.Append($"{{text: \"<div class=\\\"account {acc.Protocol}\\\"><div class=\\\"protocol-icon\\\"> </div>{acc.SeenInChannel.LineageSummary}/<a href=\\\"/Accounts/Details/{acc.Id}\\\">{acc.DisplayName}</a>\"}}");
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
sb.Append("]}]");
|
|
||||||
}
|
|
||||||
console.log(@Html.Raw(sb.ToString()));
|
|
||||||
var tree = @Html.Raw(sb.ToString());
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#accountsTree').bstreeview({ data: getAccountsTree() });
|
|
||||||
document.querySelectorAll("input[type=checkbox]").forEach(node => { node.onchange = () => { patchModel(jsonifyUser(), '/api/Users/') } });
|
|
||||||
</script>
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
@model IEnumerable<User>
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Users";
|
|
||||||
}
|
|
||||||
|
|
||||||
<table class="table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>
|
|
||||||
@Html.DisplayNameFor(model => model.Id)
|
|
||||||
</th>
|
|
||||||
<th>
|
|
||||||
name*
|
|
||||||
</th>
|
|
||||||
<th>
|
|
||||||
number of associated accounts
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
@foreach (var item in Model) {
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
@Html.DisplayFor(modelItem => item.Id)
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
@Html.DisplayFor(modelItem => item.DisplayName)
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
@Html.DisplayFor(modelItem => item.Accounts.Count)x
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<a asp-action="Details" asp-route-id="@item.Id">Details</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
@ -1,3 +0,0 @@
|
|||||||
@using vassago
|
|
||||||
@using vassago.Models
|
|
||||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
|
@ -1,3 +0,0 @@
|
|||||||
@{
|
|
||||||
Layout = "_Layout";
|
|
||||||
}
|
|
4
appsettings.example.json
Normal file
4
appsettings.example.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"token": "59 chars",
|
||||||
|
"exchangePairsLocation": "assets/exchangepairs.json"
|
||||||
|
}
|
@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"Logging": {
|
|
||||||
"LogLevel": {
|
|
||||||
"Default": "Information",
|
|
||||||
"Microsoft.AspNetCore": "Warning",
|
|
||||||
"Microsoft.EntityFrameworkCore": "None"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"AllowedHosts": "*",
|
|
||||||
"DiscordTokens": [
|
|
||||||
|
|
||||||
],
|
|
||||||
"TwitchConfigs": [
|
|
||||||
],
|
|
||||||
"exchangePairsLocation": "assets/exchangepairs.json",
|
|
||||||
"DBConnectionString": "Host=azure.club;Database=db;Username=user;Password=password",
|
|
||||||
"SetupSlashCommands": false
|
|
||||||
}
|
|
@ -36,13 +36,6 @@
|
|||||||
"metre"
|
"metre"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"canonical":"mm",
|
|
||||||
"aliases": [
|
|
||||||
"millimeter",
|
|
||||||
"millimetre"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"canonical":"km",
|
"canonical":"km",
|
||||||
"aliases": [
|
"aliases": [
|
||||||
@ -211,40 +204,6 @@
|
|||||||
"aliases": [
|
"aliases": [
|
||||||
"parsec"
|
"parsec"
|
||||||
]
|
]
|
||||||
},
|
|
||||||
{
|
|
||||||
"canonical":"mi",
|
|
||||||
"aliases": [
|
|
||||||
"mile"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"canonical":"blue whale length",
|
|
||||||
"aliases": [
|
|
||||||
"bwl",
|
|
||||||
"whales"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"canonical":"ångström",
|
|
||||||
"aliases": [
|
|
||||||
"angstrom",
|
|
||||||
"Å"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"canonical":"μm",
|
|
||||||
"aliases": [
|
|
||||||
"micrometers",
|
|
||||||
"micrometres",
|
|
||||||
"microns"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"canonical":"uncle jordan",
|
|
||||||
"aliases":[
|
|
||||||
"uj"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"linearPairs":[
|
"linearPairs":[
|
||||||
@ -257,12 +216,9 @@
|
|||||||
{"item1":"mi", "item2":"ft", "factor":5280},
|
{"item1":"mi", "item2":"ft", "factor":5280},
|
||||||
{"item1":"m", "item2":"in", "factor":39.37008},
|
{"item1":"m", "item2":"in", "factor":39.37008},
|
||||||
{"item1":"m", "item2":"cm", "factor":100},
|
{"item1":"m", "item2":"cm", "factor":100},
|
||||||
{"item1":"cm", "item2":"mm", "factor":10},
|
|
||||||
{"item1":"m", "item2":"μm", "factor":1000000},
|
|
||||||
{"item1":"km", "item2":"mi", "factor":0.6213712},
|
{"item1":"km", "item2":"mi", "factor":0.6213712},
|
||||||
{"item1":"ft", "item2":"in", "factor":12},
|
{"item1":"ft", "item2":"in", "factor":12},
|
||||||
{"item1":"yd", "item2":"ft", "factor":3},
|
{"item1":"yd", "item2":"ft", "factor":3},
|
||||||
{"item1":"football field", "item2":"yd", "factor":100},
|
|
||||||
{"item1":"chain", "item2":"yd", "factor":22},
|
{"item1":"chain", "item2":"yd", "factor":22},
|
||||||
{"item1":"chain", "item2":"link", "factor":100},
|
{"item1":"chain", "item2":"link", "factor":100},
|
||||||
{"item1":"furlong", "item2":"mi", "factor":8},
|
{"item1":"furlong", "item2":"mi", "factor":8},
|
||||||
@ -270,10 +226,6 @@
|
|||||||
{"item1":"AU", "item2":"ly", "factor": 0.0000158125},
|
{"item1":"AU", "item2":"ly", "factor": 0.0000158125},
|
||||||
{"item1":"ly", "item2":"km", "factor": 946070000000},
|
{"item1":"ly", "item2":"km", "factor": 946070000000},
|
||||||
{"item1":"pc", "item2":"AU", "factor":206266.3},
|
{"item1":"pc", "item2":"AU", "factor":206266.3},
|
||||||
{"item1":"blue whale length", "item2": "m", "factor": 29.9},
|
|
||||||
{"item1":"m", "item2": "ångström", "factor": 10000000000},
|
|
||||||
{"item1":"smoot", "item2": "ft", "factor": 5.583333333333},
|
|
||||||
{"item1":"uncle jordan", "item2": "cm", "factor":192.405},
|
|
||||||
|
|
||||||
{"item1":"floz", "item2":"mL", "factor":29.57344},
|
{"item1":"floz", "item2":"mL", "factor":29.57344},
|
||||||
{"item1":"L", "item2":"mL", "factor":1000},
|
{"item1":"L", "item2":"mL", "factor":1000},
|
||||||
|
@ -40,6 +40,7 @@ A ghost walked into a bar and ordered a shot of vodka. The bartender said, ‘So
|
|||||||
A blind man walked into a bar. and a table. and a chair.
|
A blind man walked into a bar. and a table. and a chair.
|
||||||
How do you make holy water? You boil the hell out of it.
|
How do you make holy water? You boil the hell out of it.
|
||||||
My teachers told me I’d never amount to much because I procrastinate so much. I told them, “Just you wait!”
|
My teachers told me I’d never amount to much because I procrastinate so much. I told them, “Just you wait!”
|
||||||
|
ברכב שנוסע על 4 גלגלים, איזה גלגל לא זז? גלגל רזרבי
|
||||||
what's the best part about living in switzerland? well the flag is a big plus.
|
what's the best part about living in switzerland? well the flag is a big plus.
|
||||||
I asked my date to meet me at the gym today. She didn't show up. That's when I knew we weren't gonna work out.
|
I asked my date to meet me at the gym today. She didn't show up. That's when I knew we weren't gonna work out.
|
||||||
The CEO of IKEA was elected Prime Minister in Sweden. He should have his cabinet together by the end of the weekend.
|
The CEO of IKEA was elected Prime Minister in Sweden. He should have his cabinet together by the end of the weekend.
|
||||||
|
36
devutils.sh
36
devutils.sh
@ -1,36 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
servicename="vassago"
|
|
||||||
pw_developmentdatabase="wnmhOttjA0wCiR9hVoG7jjrf90SxWvAV"
|
|
||||||
connnectionstr="Host=localhost;Database=${servicename}_dev;Username=${servicename};Password=${pw_developmentdatabase};IncludeErrorDetail=true;"
|
|
||||||
|
|
||||||
case "$1" in
|
|
||||||
"initial")
|
|
||||||
sudo -u postgres psql -c "create database ${servicename}_dev;"
|
|
||||||
sudo -u postgres psql -c "create user $servicename with encrypted password '$pw_developmentdatabase';"
|
|
||||||
sudo -u postgres psql -c "grant all privileges on database ${servicename}_dev to $servicename;"
|
|
||||||
sudo -u postgres psql -d "${servicename}_dev" -c "GRANT ALL ON SCHEMA public TO $servicename"
|
|
||||||
|
|
||||||
cp appsettings.sample.json appsettings.json
|
|
||||||
dotnet ef database update --connection "$connnectionstr"
|
|
||||||
;;
|
|
||||||
|
|
||||||
"add-migration")
|
|
||||||
dotnet ef migrations add "$2"
|
|
||||||
dotnet ef database update --connection "$connnectionstr"
|
|
||||||
;;
|
|
||||||
|
|
||||||
"dbupdate")
|
|
||||||
dotnet ef database update --connection "$connnectionstr"
|
|
||||||
;;
|
|
||||||
|
|
||||||
"db-fullreset")
|
|
||||||
sudo -u postgres psql -c "drop database ${servicename}_dev;"
|
|
||||||
sudo -u postgres psql -c "drop user $servicename"
|
|
||||||
$0 "initial"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Unknown command '$1', try 'initial'"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
@ -7,7 +7,7 @@ using System.Text;
|
|||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace vassago
|
namespace silverworker_discord
|
||||||
{
|
{
|
||||||
public class ExternalProcess
|
public class ExternalProcess
|
||||||
{
|
{
|
||||||
|
38
shtikbot-discord.csproj
Normal file
38
shtikbot-discord.csproj
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
<RootNamespace>silverworker_discord</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="discord.net" Version="3.10.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="5.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0.0" />
|
||||||
|
<PackageReference Include="QRCoder" Version="1.4.2" />
|
||||||
|
<PackageReference Include="youtubedlsharp" Version="0.3.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="assets/jokes.txt">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="assets/coding and algorithms.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="assets/ekgblip.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="assets/conversion.json">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="assets/loud sweating.gif">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="appsettings.json">
|
||||||
|
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
@ -1,54 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<NoWarn>$(NoWarn);CA2254</NoWarn>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="bootstrap" Version="5.3.3" />
|
|
||||||
<PackageReference Include="discord.net" Version="3.10.0" />
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="7.0.20" />
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.5">
|
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
|
||||||
<PrivateAssets>all</PrivateAssets>
|
|
||||||
</PackageReference>
|
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
|
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="5.0.0" />
|
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0.0" />
|
|
||||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.4" />
|
|
||||||
<PackageReference Include="QRCoder" Version="1.4.2" />
|
|
||||||
<PackageReference Include="RestSharp" Version="112.1.0" />
|
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.Swagger" Version="6.6.2" />
|
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="6.6.2" />
|
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.6.2" />
|
|
||||||
<PackageReference Include="TwitchLib" Version="3.5.3" />
|
|
||||||
<PackageReference Include="youtubedlsharp" Version="0.3.1" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<None Update="assets/jokes.txt">
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="assets/coding and algorithms.png">
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="assets/ekgblip.png">
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="assets/conversion.json">
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="assets/loud sweating.gif">
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="appsettings.json">
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<Content Include="wwwroot/**/*">
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
10
wwwroot/css/bstreeview.min.css
vendored
10
wwwroot/css/bstreeview.min.css
vendored
@ -1,10 +0,0 @@
|
|||||||
/*
|
|
||||||
@preserve
|
|
||||||
bstreeview.css
|
|
||||||
Version: 1.2.0
|
|
||||||
Authors: Sami CHNITER <sami.chniter@gmail.com>
|
|
||||||
Copyright 2020
|
|
||||||
License: Apache License 2.0
|
|
||||||
Project: https://github.com/nhmvienna/bs5treeview
|
|
||||||
*/
|
|
||||||
.bstreeview{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem;padding:0;overflow:hidden}.bstreeview .list-group{margin-bottom:0}.bstreeview .list-group-item{border-radius:0;border-width:1px 0 0 0;padding-top:.5rem;padding-bottom:.5rem;cursor:pointer}.bstreeview .list-group-item:hover{background-color:#dee2e6}.bstreeview>.list-group-item:first-child{border-top-width:0}.bstreeview .state-icon{margin-right:8px}.bstreeview .item-icon{margin-right:5px}
|
|
9
wwwroot/css/fontawesome.min.css
vendored
9
wwwroot/css/fontawesome.min.css
vendored
File diff suppressed because one or more lines are too long
@ -1,46 +0,0 @@
|
|||||||
html {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
|
||||||
html {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
|
|
||||||
box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
|
|
||||||
}
|
|
||||||
|
|
||||||
html {
|
|
||||||
position: relative;
|
|
||||||
min-height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin-bottom: 60px;
|
|
||||||
}
|
|
||||||
.protocol-icon,.channel-type-icon{
|
|
||||||
display:inline-block;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
background-size: 32px;
|
|
||||||
}
|
|
||||||
.discord .protocol-icon{
|
|
||||||
background-image: url("../imgs/discord_logo1600.png");
|
|
||||||
}
|
|
||||||
.twitch .protocol-icon{
|
|
||||||
background-image: url("../imgs/twitch.png");
|
|
||||||
}
|
|
||||||
.Normal .channel-type-icon{
|
|
||||||
background-color: black;
|
|
||||||
}
|
|
||||||
.DM .channel-type-icon{
|
|
||||||
background-color: black;
|
|
||||||
}
|
|
||||||
.Protocol .channel-type-icon{
|
|
||||||
background-color: black;
|
|
||||||
}
|
|
||||||
.OU .channel-type-icon{
|
|
||||||
background-color: black;
|
|
||||||
}
|
|
Binary file not shown.
Before Width: | Height: | Size: 5.3 KiB |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user