From 9f92fc8e27f501b3549976bd1ecdc0a56f72bff1 Mon Sep 17 00:00:00 2001
From: barelyprofessional
<150058423+barelyprofessional@users.noreply.github.com>
Date: Mon, 25 Mar 2024 20:11:49 +0800
Subject: [PATCH] Initial commit
---
.gitignore | 34 +
.idea/.idea.KfChatDotNet/.idea/.gitignore | 13 +
.idea/.idea.KfChatDotNet/.idea/avalonia.xml | 14 +
.idea/.idea.KfChatDotNet/.idea/encodings.xml | 4 +
.../.idea.KfChatDotNet/.idea/indexLayout.xml | 8 +
.../.idea.KfChatDotNet/.idea/sqldialects.xml | 6 +
.idea/.idea.KfChatDotNet/.idea/vcs.xml | 6 +
KfChatDotNet.sln | 40 +
KfChatDotNetCli/ChatCliMain.cs | 85 +
KfChatDotNetCli/KfChatDotNetCli.csproj | 28 +
KfChatDotNetCli/NLog.config | 15 +
KfChatDotNetCli/NLog.xsd | 3483 +++++++++++++++++
KfChatDotNetCli/Program.cs | 40 +
KfChatDotNetGui/.gitignore | 454 +++
KfChatDotNetGui/App.axaml | 13 +
KfChatDotNetGui/App.axaml.cs | 71 +
KfChatDotNetGui/Assets/avalonia-logo.ico | Bin 0 -> 176111 bytes
KfChatDotNetGui/Helpers/ForumIdentity.cs | 42 +
KfChatDotNetGui/KfChatDotNetGui.csproj | 43 +
KfChatDotNetGui/Models/ForumIdentityModel.cs | 20 +
KfChatDotNetGui/Models/RoomSettingsModel.cs | 14 +
KfChatDotNetGui/Models/SettingsModel.cs | 12 +
KfChatDotNetGui/NLog.config | 15 +
KfChatDotNetGui/NLog.xsd | 3483 +++++++++++++++++
KfChatDotNetGui/Program.cs | 23 +
KfChatDotNetGui/ViewLocator.cs | 28 +
.../IdentitySettingsWindowViewModel.cs | 47 +
.../ViewModels/MainWindowViewModel.cs | 126 +
.../ViewModels/RoomSettingsWindowViewModel.cs | 20 +
KfChatDotNetGui/ViewModels/ViewModelBase.cs | 8 +
.../Views/IdentitySettingsWindow.axaml | 32 +
.../Views/IdentitySettingsWindow.axaml.cs | 116 +
KfChatDotNetGui/Views/MainWindow.axaml | 107 +
KfChatDotNetGui/Views/MainWindow.axaml.cs | 499 +++
.../Views/RoomSettingsWindow.axaml | 28 +
.../Views/RoomSettingsWindow.axaml.cs | 174 +
KfChatDotNetKickBot/Helpers.cs | 36 +
.../KfChatDotNetKickBot.csproj | 32 +
KfChatDotNetKickBot/KickBot.cs | 164 +
KfChatDotNetKickBot/Models.cs | 24 +
KfChatDotNetKickBot/NLog.config | 15 +
KfChatDotNetKickBot/NLog.xsd | 3483 +++++++++++++++++
KfChatDotNetKickBot/Program.cs | 15 +
KfChatDotNetKickBot/config.json | 6 +
KfChatDotNetWsClient/ChatClient.cs | 285 ++
.../KfChatDotNetWsClient.csproj | 23 +
.../Models/ChatClientConfigModel.cs | 12 +
.../Models/Events/EventHandlers.cs | 28 +
.../Models/Events/MessageModel.cs | 12 +
.../Models/Events/UserModel.cs | 10 +
.../Models/Json/DeleteMessagesJsonModel.cs | 9 +
.../Models/Json/EditMessageJsonModel.cs | 12 +
.../Models/Json/MessagesJsonModel.cs | 59 +
.../Models/Json/UsersJsonModel.cs | 32 +
KfChatDotNetWsClient/NLog.config | 15 +
KfChatDotNetWsClient/NLog.xsd | 3483 +++++++++++++++++
KickWsClient/KickWsClient.cs | 267 ++
KickWsClient/KickWsClient.csproj | 15 +
KickWsClient/Models/EventHandlers.cs | 41 +
KickWsClient/Models/KickModels.cs | 519 +++
KickWsClient/Models/PusherModels.cs | 76 +
global.json | 7 +
62 files changed, 17831 insertions(+)
create mode 100644 .gitignore
create mode 100644 .idea/.idea.KfChatDotNet/.idea/.gitignore
create mode 100644 .idea/.idea.KfChatDotNet/.idea/avalonia.xml
create mode 100644 .idea/.idea.KfChatDotNet/.idea/encodings.xml
create mode 100644 .idea/.idea.KfChatDotNet/.idea/indexLayout.xml
create mode 100644 .idea/.idea.KfChatDotNet/.idea/sqldialects.xml
create mode 100644 .idea/.idea.KfChatDotNet/.idea/vcs.xml
create mode 100644 KfChatDotNet.sln
create mode 100644 KfChatDotNetCli/ChatCliMain.cs
create mode 100644 KfChatDotNetCli/KfChatDotNetCli.csproj
create mode 100644 KfChatDotNetCli/NLog.config
create mode 100644 KfChatDotNetCli/NLog.xsd
create mode 100644 KfChatDotNetCli/Program.cs
create mode 100644 KfChatDotNetGui/.gitignore
create mode 100644 KfChatDotNetGui/App.axaml
create mode 100644 KfChatDotNetGui/App.axaml.cs
create mode 100644 KfChatDotNetGui/Assets/avalonia-logo.ico
create mode 100644 KfChatDotNetGui/Helpers/ForumIdentity.cs
create mode 100644 KfChatDotNetGui/KfChatDotNetGui.csproj
create mode 100644 KfChatDotNetGui/Models/ForumIdentityModel.cs
create mode 100644 KfChatDotNetGui/Models/RoomSettingsModel.cs
create mode 100644 KfChatDotNetGui/Models/SettingsModel.cs
create mode 100644 KfChatDotNetGui/NLog.config
create mode 100644 KfChatDotNetGui/NLog.xsd
create mode 100644 KfChatDotNetGui/Program.cs
create mode 100644 KfChatDotNetGui/ViewLocator.cs
create mode 100644 KfChatDotNetGui/ViewModels/IdentitySettingsWindowViewModel.cs
create mode 100644 KfChatDotNetGui/ViewModels/MainWindowViewModel.cs
create mode 100644 KfChatDotNetGui/ViewModels/RoomSettingsWindowViewModel.cs
create mode 100644 KfChatDotNetGui/ViewModels/ViewModelBase.cs
create mode 100644 KfChatDotNetGui/Views/IdentitySettingsWindow.axaml
create mode 100644 KfChatDotNetGui/Views/IdentitySettingsWindow.axaml.cs
create mode 100644 KfChatDotNetGui/Views/MainWindow.axaml
create mode 100644 KfChatDotNetGui/Views/MainWindow.axaml.cs
create mode 100644 KfChatDotNetGui/Views/RoomSettingsWindow.axaml
create mode 100644 KfChatDotNetGui/Views/RoomSettingsWindow.axaml.cs
create mode 100644 KfChatDotNetKickBot/Helpers.cs
create mode 100644 KfChatDotNetKickBot/KfChatDotNetKickBot.csproj
create mode 100644 KfChatDotNetKickBot/KickBot.cs
create mode 100644 KfChatDotNetKickBot/Models.cs
create mode 100644 KfChatDotNetKickBot/NLog.config
create mode 100644 KfChatDotNetKickBot/NLog.xsd
create mode 100644 KfChatDotNetKickBot/Program.cs
create mode 100644 KfChatDotNetKickBot/config.json
create mode 100644 KfChatDotNetWsClient/ChatClient.cs
create mode 100644 KfChatDotNetWsClient/KfChatDotNetWsClient.csproj
create mode 100644 KfChatDotNetWsClient/Models/ChatClientConfigModel.cs
create mode 100644 KfChatDotNetWsClient/Models/Events/EventHandlers.cs
create mode 100644 KfChatDotNetWsClient/Models/Events/MessageModel.cs
create mode 100644 KfChatDotNetWsClient/Models/Events/UserModel.cs
create mode 100644 KfChatDotNetWsClient/Models/Json/DeleteMessagesJsonModel.cs
create mode 100644 KfChatDotNetWsClient/Models/Json/EditMessageJsonModel.cs
create mode 100644 KfChatDotNetWsClient/Models/Json/MessagesJsonModel.cs
create mode 100644 KfChatDotNetWsClient/Models/Json/UsersJsonModel.cs
create mode 100644 KfChatDotNetWsClient/NLog.config
create mode 100644 KfChatDotNetWsClient/NLog.xsd
create mode 100644 KickWsClient/KickWsClient.cs
create mode 100644 KickWsClient/KickWsClient.csproj
create mode 100644 KickWsClient/Models/EventHandlers.cs
create mode 100644 KickWsClient/Models/KickModels.cs
create mode 100644 KickWsClient/Models/PusherModels.cs
create mode 100644 global.json
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9998c3d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,34 @@
+# Common IntelliJ Platform excludes
+
+# User specific
+**/.idea/**/workspace.xml
+**/.idea/**/tasks.xml
+**/.idea/shelf/*
+**/.idea/dictionaries
+**/.idea/httpRequests/
+
+# Sensitive or high-churn files
+**/.idea/**/dataSources/
+**/.idea/**/dataSources.ids
+**/.idea/**/dataSources.xml
+**/.idea/**/dataSources.local.xml
+**/.idea/**/sqlDataSources.xml
+**/.idea/**/dynamic.xml
+
+# Rider
+# Rider auto-generates .iml files, and contentModel.xml
+**/.idea/**/*.iml
+**/.idea/**/contentModel.xml
+**/.idea/**/modules.xml
+
+*.suo
+*.user
+.vs/
+[Bb]in/
+[Oo]bj/
+_UpgradeReport_Files/
+[Pp]ackages/
+
+Thumbs.db
+Desktop.ini
+.DS_Store
diff --git a/.idea/.idea.KfChatDotNet/.idea/.gitignore b/.idea/.idea.KfChatDotNet/.idea/.gitignore
new file mode 100644
index 0000000..fb77034
--- /dev/null
+++ b/.idea/.idea.KfChatDotNet/.idea/.gitignore
@@ -0,0 +1,13 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Rider ignored files
+/.idea.KfChatDotNet.iml
+/modules.xml
+/contentModel.xml
+/projectSettingsUpdater.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/.idea.KfChatDotNet/.idea/avalonia.xml b/.idea/.idea.KfChatDotNet/.idea/avalonia.xml
new file mode 100644
index 0000000..d13e3a0
--- /dev/null
+++ b/.idea/.idea.KfChatDotNet/.idea/avalonia.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/.idea.KfChatDotNet/.idea/encodings.xml b/.idea/.idea.KfChatDotNet/.idea/encodings.xml
new file mode 100644
index 0000000..df87cf9
--- /dev/null
+++ b/.idea/.idea.KfChatDotNet/.idea/encodings.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/.idea.KfChatDotNet/.idea/indexLayout.xml b/.idea/.idea.KfChatDotNet/.idea/indexLayout.xml
new file mode 100644
index 0000000..7b08163
--- /dev/null
+++ b/.idea/.idea.KfChatDotNet/.idea/indexLayout.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/.idea.KfChatDotNet/.idea/sqldialects.xml b/.idea/.idea.KfChatDotNet/.idea/sqldialects.xml
new file mode 100644
index 0000000..80f40a6
--- /dev/null
+++ b/.idea/.idea.KfChatDotNet/.idea/sqldialects.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/.idea.KfChatDotNet/.idea/vcs.xml b/.idea/.idea.KfChatDotNet/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/.idea.KfChatDotNet/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/KfChatDotNet.sln b/KfChatDotNet.sln
new file mode 100644
index 0000000..ee16e3e
--- /dev/null
+++ b/KfChatDotNet.sln
@@ -0,0 +1,40 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KfChatDotNetWsClient", "KfChatDotNetWsClient\KfChatDotNetWsClient.csproj", "{B3BC806A-7FFC-47BD-9C18-45CD2B99F9F8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KfChatDotNetCli", "KfChatDotNetCli\KfChatDotNetCli.csproj", "{A4D19F8E-5A1F-4A66-BC42-214DB9D5429B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KfChatDotNetGui", "KfChatDotNetGui\KfChatDotNetGui.csproj", "{B2A5D4EE-5EB6-4F0B-BB5E-2B87AAFBFB5B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KickWsClient", "KickWsClient\KickWsClient.csproj", "{DECBB95C-2C9F-44C2-AFA3-3741986FBA38}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KfChatDotNetKickBot", "KfChatDotNetKickBot\KfChatDotNetKickBot.csproj", "{4734E0A4-150E-4915-B905-928BB4BE3FF6}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B3BC806A-7FFC-47BD-9C18-45CD2B99F9F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B3BC806A-7FFC-47BD-9C18-45CD2B99F9F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B3BC806A-7FFC-47BD-9C18-45CD2B99F9F8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B3BC806A-7FFC-47BD-9C18-45CD2B99F9F8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A4D19F8E-5A1F-4A66-BC42-214DB9D5429B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A4D19F8E-5A1F-4A66-BC42-214DB9D5429B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A4D19F8E-5A1F-4A66-BC42-214DB9D5429B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A4D19F8E-5A1F-4A66-BC42-214DB9D5429B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B2A5D4EE-5EB6-4F0B-BB5E-2B87AAFBFB5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B2A5D4EE-5EB6-4F0B-BB5E-2B87AAFBFB5B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B2A5D4EE-5EB6-4F0B-BB5E-2B87AAFBFB5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B2A5D4EE-5EB6-4F0B-BB5E-2B87AAFBFB5B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DECBB95C-2C9F-44C2-AFA3-3741986FBA38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DECBB95C-2C9F-44C2-AFA3-3741986FBA38}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DECBB95C-2C9F-44C2-AFA3-3741986FBA38}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DECBB95C-2C9F-44C2-AFA3-3741986FBA38}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4734E0A4-150E-4915-B905-928BB4BE3FF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4734E0A4-150E-4915-B905-928BB4BE3FF6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4734E0A4-150E-4915-B905-928BB4BE3FF6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4734E0A4-150E-4915-B905-928BB4BE3FF6}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/KfChatDotNetCli/ChatCliMain.cs b/KfChatDotNetCli/ChatCliMain.cs
new file mode 100644
index 0000000..e24feb9
--- /dev/null
+++ b/KfChatDotNetCli/ChatCliMain.cs
@@ -0,0 +1,85 @@
+using KfChatDotNetWsClient;
+using KfChatDotNetWsClient.Models;
+using KfChatDotNetWsClient.Models.Events;
+using KfChatDotNetWsClient.Models.Json;
+using NLog;
+using Spectre.Console;
+using Websocket.Client;
+
+namespace KfChatDotNetCli;
+
+public class ChatCliMain
+{
+ private ChatClient _client;
+ private Logger _logger = LogManager.GetCurrentClassLogger();
+ private int _roomId;
+
+ public ChatCliMain(string xfSessionToken, int roomId)
+ {
+ _roomId = roomId;
+ _client = new ChatClient(new ChatClientConfigModel
+ {
+ WsUri = new Uri("wss://kiwifarms.st/chat.ws"),
+ XfSessionToken = xfSessionToken
+ });
+
+ _client.OnMessages += OnMessages;
+ _client.OnDeleteMessages += OnDeleteMessages;
+ _client.OnUsersJoined += OnUsersJoined;
+ _client.OnUsersParted += OnUsersParted;
+ _client.OnWsReconnect += OnWsReconnected;
+
+ _client.StartWsClient().Wait();
+ _client.JoinRoom(_roomId);
+
+ while (true)
+ {
+ var input = AnsiConsole.Prompt(new TextPrompt("Enter Message:"));
+ _client.SendMessage(input);
+ }
+ // ReSharper disable once FunctionNeverReturns
+ }
+
+ private void OnMessages(object sender, List messages, MessagesJsonModel jsonPayload)
+ {
+ _logger.Debug($"Received {messages.Count} message(s)");
+ foreach (var message in messages)
+ {
+ AnsiConsole.MarkupLine($"<{message.Author.Username}> {message.Message.EscapeMarkup()} ({message.MessageDate.LocalDateTime.ToShortTimeString()})");
+ }
+ }
+
+ private void OnDeleteMessages(object sender, List messageIds)
+ {
+ _logger.Debug($"Received delete event for {messageIds}");
+ foreach (var id in messageIds)
+ {
+ AnsiConsole.MarkupLine($"[red]{id} message deleted![/]");
+ }
+ }
+
+ private void OnUsersJoined(object sender, List users, UsersJsonModel jsonPayload)
+ {
+ _logger.Debug($"Received {users.Count} user join events");
+ foreach (var user in users)
+ {
+ AnsiConsole.MarkupLine($"[green]{user.Username.EscapeMarkup()} joined![/]");
+ }
+ }
+
+ private void OnUsersParted(object sender, List userIds)
+ {
+ _logger.Debug($"Received {userIds.Count} user part events");
+ foreach (var id in userIds)
+ {
+ AnsiConsole.MarkupLine($"[red]{id} left the chat...[/]");
+ }
+ }
+
+ private void OnWsReconnected(object sender, ReconnectionInfo reconnectionInfo)
+ {
+ AnsiConsole.MarkupLine($"[red]Reconnected due to {reconnectionInfo.Type}[/]");
+ AnsiConsole.MarkupLine($"[green]Rejoining {_roomId}[/]");
+ _client.JoinRoom(_roomId);
+ }
+}
\ No newline at end of file
diff --git a/KfChatDotNetCli/KfChatDotNetCli.csproj b/KfChatDotNetCli/KfChatDotNetCli.csproj
new file mode 100644
index 0000000..13801b6
--- /dev/null
+++ b/KfChatDotNetCli/KfChatDotNetCli.csproj
@@ -0,0 +1,28 @@
+
+
+
+ Exe
+ net8.0
+ enable
+ enable
+ default
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Always
+
+
+
+
diff --git a/KfChatDotNetCli/NLog.config b/KfChatDotNetCli/NLog.config
new file mode 100644
index 0000000..e255848
--- /dev/null
+++ b/KfChatDotNetCli/NLog.config
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/KfChatDotNetCli/NLog.xsd b/KfChatDotNetCli/NLog.xsd
new file mode 100644
index 0000000..e2b7858
--- /dev/null
+++ b/KfChatDotNetCli/NLog.xsd
@@ -0,0 +1,3483 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Watch config file for changes and reload automatically.
+
+
+
+
+ Print internal NLog messages to the console. Default value is: false
+
+
+
+
+ Print internal NLog messages to the console error output. Default value is: false
+
+
+
+
+ Write internal NLog messages to the specified file.
+
+
+
+
+ Log level threshold for internal log messages. Default value is: Info.
+
+
+
+
+ Global log level threshold for application log messages. Messages below this level won't be logged.
+
+
+
+
+ Throw an exception when there is an internal error. Default value is: false. Not recommend to set to true in production!
+
+
+
+
+ Throw an exception when there is a configuration error. If not set, determined by throwExceptions.
+
+
+
+
+ Gets or sets a value indicating whether Variables should be kept on configuration reload. Default value is: false.
+
+
+
+
+ Write internal NLog messages to the System.Diagnostics.Trace. Default value is: false.
+
+
+
+
+ Write timestamps for internal NLog messages. Default value is: true.
+
+
+
+
+ Use InvariantCulture as default culture instead of CurrentCulture. Default value is: false.
+
+
+
+
+ Perform message template parsing and formatting of LogEvent messages (true = Always, false = Never, empty = Auto Detect). Default value is: empty.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Make all targets within this section asynchronous (creates additional threads but the calling thread isn't blocked by any target writes).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Prefix for targets/layout renderers/filters/conditions loaded from this assembly.
+
+
+
+
+ Load NLog extensions from the specified file (*.dll)
+
+
+
+
+ Load NLog extensions from the specified assembly. Assembly name should be fully qualified.
+
+
+
+
+
+
+
+
+
+ Filter on the name of the logger. May include wildcard characters ('*' or '?').
+
+
+
+
+ Comma separated list of levels that this rule matches.
+
+
+
+
+ Minimum level that this rule matches.
+
+
+
+
+ Maximum level that this rule matches.
+
+
+
+
+ Level that this rule matches.
+
+
+
+
+ Comma separated list of target names.
+
+
+
+
+ Ignore further rules if this one matches.
+
+
+
+
+ Enable this rule. Note: disabled rules aren't available from the API.
+
+
+
+
+ Rule identifier to allow rule lookup with Configuration.FindRuleByName and Configuration.RemoveRuleByName.
+
+
+
+
+ Loggers matching will be restricted to specified minimum level for following rules.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Default action if none of the filters match.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the file to be included. You could use * wildcard. The name is relative to the name of the current config file.
+
+
+
+
+ Ignore any errors in the include file.
+
+
+
+
+
+
+
+ Variable value. Note, the 'value' attribute has precedence over this one.
+
+
+
+
+
+ Variable name.
+
+
+
+
+ Variable value.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+ Action to be taken when the lazy writer thread request queue count exceeds the set limit.
+
+
+
+
+ Limit on the number of requests in the lazy writer thread request queue.
+
+
+
+
+ Number of log events that should be processed in a batch by the lazy writer thread.
+
+
+
+
+ Whether to use the locking queue, instead of a lock-free concurrent queue
+
+
+
+
+ Number of batches of P:NLog.Targets.Wrappers.AsyncTargetWrapper.BatchSize to write before yielding into P:NLog.Targets.Wrappers.AsyncTargetWrapper.TimeToSleepBetweenBatches
+
+
+
+
+ Time in milliseconds to sleep between batches. (1 or less means trigger on new activity)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+ Delay the flush until the LogEvent has been confirmed as written
+
+
+
+
+ Condition expression. Log events who meet this condition will cause a flush on the wrapped target.
+
+
+
+
+ Only flush when LogEvent matches condition. Ignore explicit-flush, config-reload-flush and shutdown-flush
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+ Number of log events to be buffered.
+
+
+
+
+ Action to take if the buffer overflows.
+
+
+
+
+ Timeout (in milliseconds) after which the contents of buffer will be flushed if there's no write in the specified period of time. Use -1 to disable timed flushes.
+
+
+
+
+ Indicates whether to use sliding timeout.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+ Separator for T:NLog.ScopeContext operation-states-stack.
+
+
+
+
+ Stack separator for log4j:NDC in output from T:NLog.ScopeContext nested context.
+
+
+
+
+ Renderer for log4j:event logger-xml-attribute (Default ${logger})
+
+
+
+
+ Whether to include the contents of the T:NLog.ScopeContext properties-dictionary.
+
+
+
+
+ Whether to include log4j:NDC in output from T:NLog.ScopeContext nested context.
+
+
+
+
+ Indicates whether to include source info (file name and line number) in the information sent over the network.
+
+
+
+
+ Whether to include log4j:NDC in output from T:NLog.ScopeContext nested context.
+
+
+
+
+ Option to include all properties from the log events
+
+
+
+
+ Indicates whether to include call site (class and method name) in the information sent over the network.
+
+
+
+
+ AppInfo field. By default it's the friendly name of the current AppDomain.
+
+
+
+
+ Instance of T:NLog.Layouts.Log4JXmlEventLayout that is used to format log messages.
+
+
+
+
+ Indicates whether to include NLog-specific extensions to log4j schema.
+
+
+
+
+ Action that should be taken, when more connections than P:NLog.Targets.NetworkTarget.MaxConnections.
+
+
+
+
+ SSL/TLS protocols. Default no SSL/TLS is used. Currently only implemented for TCP.
+
+
+
+
+ Action that should be taken, when more pending messages than P:NLog.Targets.NetworkTarget.MaxQueueSize.
+
+
+
+
+ Action that should be taken if the message is larger than P:NLog.Targets.NetworkTarget.MaxMessageSize
+
+
+
+
+ Maximum queue size for a single connection. Requires P:NLog.Targets.NetworkTarget.KeepConnection = true
+
+
+
+
+ Network address.
+
+
+
+
+ Indicates whether to keep connection open whenever possible.
+
+
+
+
+ The number of seconds a connection will remain idle before the first keep-alive probe is sent
+
+
+
+
+ Size of the connection cache (number of connections which are kept alive). Requires P:NLog.Targets.NetworkTarget.KeepConnection = true
+
+
+
+
+ Maximum simultaneous connections. Requires P:NLog.Targets.NetworkTarget.KeepConnection = false
+
+
+
+
+ Type of compression for protocol payload. Useful for UDP where datagram max-size is 8192 bytes.
+
+
+
+
+ Skip compression when protocol payload is below limit to reduce overhead in cpu-usage and additional headers
+
+
+
+
+ Maximum message size in bytes. On limit breach then P:NLog.Targets.NetworkTarget.OnOverflow action is activated.
+
+
+
+
+ Encoding to be used.
+
+
+
+
+ End of line value if a newline is appended at the end of log message P:NLog.Targets.NetworkTarget.NewLine.
+
+
+
+
+ Indicates whether to append newline at the end of log message.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Viewer parameter name.
+
+
+
+
+ Layout that should be use to calculate the value for the parameter.
+
+
+
+
+ Whether an attribute with empty value should be included in the output
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+ Text to be rendered.
+
+
+
+
+ Header.
+
+
+
+
+ Footer.
+
+
+
+
+ Indicates whether to auto-check if the console is available. - Disables console writing if Environment.UserInteractive = False (Windows Service) - Disables console writing if Console Standard Input is not available (Non-Console-App)
+
+
+
+
+ Enables output using ANSI Color Codes
+
+
+
+
+ The encoding for writing messages to the T:System.Console.
+
+
+
+
+ Indicates whether to send the log messages to the standard error instead of the standard output.
+
+
+
+
+ Indicates whether to auto-flush after M:System.Console.WriteLine
+
+
+
+
+ Indicates whether to auto-check if the console has been redirected to file - Disables coloring logic when System.Console.IsOutputRedirected = true
+
+
+
+
+ Indicates whether to use default row highlighting rules.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Background color.
+
+
+
+
+ Condition that must be met in order to set the specified foreground and background color.
+
+
+
+
+ Foreground color.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Background color.
+
+
+
+
+ Compile the P:NLog.Targets.ConsoleWordHighlightingRule.Regex? This can improve the performance, but at the costs of more memory usage. If false, the Regex Cache is used.
+
+
+
+
+ Condition that must be met before scanning the row for highlight of words
+
+
+
+
+ Foreground color.
+
+
+
+
+ Indicates whether to ignore case when comparing texts.
+
+
+
+
+ Regular expression to be matched. You must specify either text or regex.
+
+
+
+
+ Text to be matched. You must specify either text or regex.
+
+
+
+
+ Indicates whether to match whole words only.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+ Text to be rendered.
+
+
+
+
+ Header.
+
+
+
+
+ Footer.
+
+
+
+
+ Indicates whether to auto-flush after M:System.Console.WriteLine
+
+
+
+
+ Indicates whether to auto-check if the console is available - Disables console writing if Environment.UserInteractive = False (Windows Service) - Disables console writing if Console Standard Input is not available (Non-Console-App)
+
+
+
+
+ The encoding for writing messages to the T:System.Console.
+
+
+
+
+ Indicates whether to send the log messages to the standard error instead of the standard output.
+
+
+
+
+ Whether to activate internal buffering to allow batch writing, instead of using M:System.Console.WriteLine
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+ Database user name. If the ConnectionString is not provided this value will be used to construct the "User ID=" part of the connection string.
+
+
+
+
+ Database password. If the ConnectionString is not provided this value will be used to construct the "Password=" part of the connection string.
+
+
+
+
+ Database name. If the ConnectionString is not provided this value will be used to construct the "Database=" part of the connection string.
+
+
+
+
+ Name of the connection string (as specified in <connectionStrings> configuration section.
+
+
+
+
+ Database host name. If the ConnectionString is not provided this value will be used to construct the "Server=" part of the connection string.
+
+
+
+
+ Indicates whether to keep the database connection open between the log events.
+
+
+
+
+ Name of the database provider.
+
+
+
+
+ Connection string. When provided, it overrides the values specified in DBHost, DBUserName, DBPassword, DBDatabase.
+
+
+
+
+ Connection string using for installation and uninstallation. If not provided, regular ConnectionString is being used.
+
+
+
+
+ Configures isolated transaction batch writing. If supported by the database, then it will improve insert performance.
+
+
+
+
+ Text of the SQL command to be run on each log level.
+
+
+
+
+ Type of the SQL command to be run on each log level.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Convert format of the property value
+
+
+
+
+ Culture used for parsing property string-value for type-conversion
+
+
+
+
+ Value to assign on the object-property
+
+
+
+
+ Name for the object-property
+
+
+
+
+ Type of the object-property
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Type of the command.
+
+
+
+
+ Connection string to run the command against. If not provided, connection string from the target is used.
+
+
+
+
+ Indicates whether to ignore failures.
+
+
+
+
+ Command text.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Database parameter name.
+
+
+
+
+ Layout that should be use to calculate the value for the parameter.
+
+
+
+
+ Database parameter DbType.
+
+
+
+
+ Database parameter size.
+
+
+
+
+ Database parameter precision.
+
+
+
+
+ Database parameter scale.
+
+
+
+
+ Type of the parameter.
+
+
+
+
+ Fallback value when result value is not available
+
+
+
+
+ Convert format of the database parameter value.
+
+
+
+
+ Culture used for parsing parameter string-value for type-conversion
+
+
+
+
+ Whether empty value should translate into DbNull. Requires database column to allow NULL values.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+ Text to be rendered.
+
+
+
+
+ Header.
+
+
+
+
+ Footer.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+ Text to be rendered.
+
+
+
+
+ Header.
+
+
+
+
+ Footer.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+ Layout used to format log messages.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+ Layout used to format log messages.
+
+
+
+
+ Layout that renders event Category.
+
+
+
+
+ Optional entry type. When not set, or when not convertible to T:System.Diagnostics.EventLogEntryType then determined by T:NLog.LogLevel
+
+
+
+
+ Layout that renders event ID.
+
+
+
+
+ Name of the Event Log to write to. This can be System, Application or any user-defined name.
+
+
+
+
+ Name of the machine on which Event Log service is running.
+
+
+
+
+ Maximum Event log size in kilobytes.
+
+
+
+
+ Message length limit to write to the Event Log.
+
+
+
+
+ Value to be used as the event Source.
+
+
+
+
+ Action to take if the message is larger than the P:NLog.Targets.EventLogTarget.MaxMessageLength option.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+ Indicates whether to return to the first target after any successful write.
+
+
+
+
+ Whether to enable batching, but fallback will be handled individually
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+ Name of the file to write to.
+
+
+
+
+ Text to be rendered.
+
+
+
+
+ Header.
+
+
+
+
+ Footer.
+
+
+
+
+ Indicates whether the footer should be written only when the file is archived.
+
+
+
+
+ Maximum number of archive files that should be kept.
+
+
+
+
+ Maximum days of archive files that should be kept.
+
+
+
+
+ Value of the file size threshold to archive old log file on startup.
+
+
+
+
+ Indicates whether to archive old log file on startup.
+
+
+
+
+ Indicates whether to compress archive files into the zip archive format.
+
+
+
+
+ Name of the file to be used for an archive.
+
+
+
+
+ Is the P:NLog.Targets.FileTarget.ArchiveFileName an absolute or relative path?
+
+
+
+
+ Indicates whether to automatically archive log files every time the specified time passes.
+
+
+
+
+ Value specifying the date format to use when archiving files.
+
+
+
+
+ Size in bytes above which log files will be automatically archived.
+
+
+
+
+ Way file archives are numbered.
+
+
+
+
+ Indicates whether to create directories if they do not exist.
+
+
+
+
+ Indicates whether file creation calls should be synchronized by a system global mutex.
+
+
+
+
+ Gets or set a value indicating whether a managed file stream is forced, instead of using the native implementation.
+
+
+
+
+ Is the P:NLog.Targets.FileTarget.FileName an absolute or relative path?
+
+
+
+
+ File attributes (Windows only).
+
+
+
+
+ Cleanup invalid values in a filename, e.g. slashes in a filename. If set to true, this can impact the performance of massive writes. If set to false, nothing gets written when the filename is wrong.
+
+
+
+
+ Indicates whether to write BOM (byte order mark) in created files. Defaults to true for UTF-16 and UTF-32
+
+
+
+
+ Indicates whether to enable log file(s) to be deleted.
+
+
+
+
+ Indicates whether to delete old log file on startup.
+
+
+
+
+ File encoding.
+
+
+
+
+ Indicates whether to replace file contents on each write instead of appending log message at the end.
+
+
+
+
+ Line ending mode.
+
+
+
+
+ Number of times the write is appended on the file before NLog discards the log message.
+
+
+
+
+ Delay in milliseconds to wait before attempting to write to the file again.
+
+
+
+
+ Maximum number of seconds before open files are flushed. Zero or negative means disabled.
+
+
+
+
+ Maximum number of seconds that files are kept open. Zero or negative means disabled.
+
+
+
+
+ Indicates whether concurrent writes to the log file by multiple processes on different network hosts.
+
+
+
+
+ Log file buffer size in bytes.
+
+
+
+
+ Indicates whether to automatically flush the file buffers after each log message.
+
+
+
+
+ Indicates whether to keep log file open instead of opening and closing it on each logging event.
+
+
+
+
+ Indicates whether concurrent writes to the log file by multiple processes on the same host.
+
+
+
+
+ Whether or not this target should just discard all data that its asked to write. Mostly used for when testing NLog Stack except final write
+
+
+
+
+ Number of files to be kept open. Setting this to a higher value may improve performance in a situation where a single File target is writing to many files (such as splitting by level or by logger).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+ Condition expression. Log events who meet this condition will be forwarded to the wrapped target.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+ Identifier to perform group-by
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+ Windows domain name to change context to.
+
+
+
+
+ Required impersonation level.
+
+
+
+
+ Type of the logon provider.
+
+
+
+
+ Logon Type.
+
+
+
+
+ User account password.
+
+
+
+
+ Indicates whether to revert to the credentials of the process instead of impersonating another user.
+
+
+
+
+ Username to change context to.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+ Interval in which messages will be written up to the P:NLog.Targets.Wrappers.LimitingTargetWrapper.MessageLimit number of messages.
+
+
+
+
+ Maximum allowed number of messages written per P:NLog.Targets.Wrappers.LimitingTargetWrapper.Interval.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+ Text to be rendered.
+
+
+
+
+ Header.
+
+
+
+
+ Footer.
+
+
+
+
+ Indicates whether NewLine characters in the body should be replaced with tags.
+
+
+
+
+ Priority used for sending mails.
+
+
+
+
+ Encoding to be used for sending e-mail.
+
+
+
+
+ BCC email addresses separated by semicolons (e.g. john@domain.com;jane@domain.com).
+
+
+
+
+ CC email addresses separated by semicolons (e.g. john@domain.com;jane@domain.com).
+
+
+
+
+ Indicates whether to add new lines between log entries.
+
+
+
+
+ Indicates whether to send message as HTML instead of plain text.
+
+
+
+
+ Sender's email address (e.g. joe@domain.com).
+
+
+
+
+ Mail message body (repeated for each log message send in one mail).
+
+
+
+
+ Mail subject.
+
+
+
+
+ Recipients' email addresses separated by semicolons (e.g. john@domain.com;jane@domain.com).
+
+
+
+
+ Specifies how outgoing email messages will be handled.
+
+
+
+
+ SMTP Server to be used for sending.
+
+
+
+
+ SMTP Authentication mode.
+
+
+
+
+ Username used to connect to SMTP server (used when SmtpAuthentication is set to "basic").
+
+
+
+
+ Password used to authenticate against SMTP server (used when SmtpAuthentication is set to "basic").
+
+
+
+
+ Indicates whether SSL (secure sockets layer) should be used when communicating with SMTP server.
+
+
+
+
+ Port number that SMTP Server is listening on.
+
+
+
+
+ Indicates whether the default Settings from System.Net.MailSettings should be used.
+
+
+
+
+ Folder where applications save mail messages to be processed by the local SMTP server.
+
+
+
+
+ Indicates the SMTP client timeout.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+ Text to be rendered.
+
+
+
+
+ Header.
+
+
+
+
+ Footer.
+
+
+
+
+ Max number of items to have in memory
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+ Class name.
+
+
+
+
+ Method name. The method must be public and static. Use the AssemblyQualifiedName , https://msdn.microsoft.com/en-us/library/system.type.assemblyqualifiedname(v=vs.110).aspx e.g.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the parameter.
+
+
+
+
+ Layout that should be use to calculate the value for the parameter.
+
+
+
+
+ Fallback value when result value is not available
+
+
+
+
+ Type of the parameter.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+ Layout used to format log messages.
+
+
+
+
+ SSL/TLS protocols. Default no SSL/TLS is used. Currently only implemented for TCP.
+
+
+
+
+ Action that should be taken, when more pending messages than P:NLog.Targets.NetworkTarget.MaxQueueSize.
+
+
+
+
+ Action that should be taken if the message is larger than P:NLog.Targets.NetworkTarget.MaxMessageSize
+
+
+
+
+ Maximum queue size for a single connection. Requires P:NLog.Targets.NetworkTarget.KeepConnection = true
+
+
+
+
+ Action that should be taken, when more connections than P:NLog.Targets.NetworkTarget.MaxConnections.
+
+
+
+
+ Indicates whether to keep connection open whenever possible.
+
+
+
+
+ The number of seconds a connection will remain idle before the first keep-alive probe is sent
+
+
+
+
+ Size of the connection cache (number of connections which are kept alive). Requires P:NLog.Targets.NetworkTarget.KeepConnection = true
+
+
+
+
+ Network address.
+
+
+
+
+ Maximum simultaneous connections. Requires P:NLog.Targets.NetworkTarget.KeepConnection = false
+
+
+
+
+ Type of compression for protocol payload. Useful for UDP where datagram max-size is 8192 bytes.
+
+
+
+
+ Skip compression when protocol payload is below limit to reduce overhead in cpu-usage and additional headers
+
+
+
+
+ Maximum message size in bytes. On limit breach then P:NLog.Targets.NetworkTarget.OnOverflow action is activated.
+
+
+
+
+ Encoding to be used.
+
+
+
+
+ End of line value if a newline is appended at the end of log message P:NLog.Targets.NetworkTarget.NewLine.
+
+
+
+
+ Indicates whether to append newline at the end of log message.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+ Separator for T:NLog.ScopeContext operation-states-stack.
+
+
+
+
+ Stack separator for log4j:NDC in output from T:NLog.ScopeContext nested context.
+
+
+
+
+ Renderer for log4j:event logger-xml-attribute (Default ${logger})
+
+
+
+
+ Whether to include the contents of the T:NLog.ScopeContext properties-dictionary.
+
+
+
+
+ Whether to include log4j:NDC in output from T:NLog.ScopeContext nested context.
+
+
+
+
+ Indicates whether to include source info (file name and line number) in the information sent over the network.
+
+
+
+
+ Whether to include log4j:NDC in output from T:NLog.ScopeContext nested context.
+
+
+
+
+ Option to include all properties from the log events
+
+
+
+
+ Indicates whether to include call site (class and method name) in the information sent over the network.
+
+
+
+
+ AppInfo field. By default it's the friendly name of the current AppDomain.
+
+
+
+
+ Instance of T:NLog.Layouts.Log4JXmlEventLayout that is used to format log messages.
+
+
+
+
+ Indicates whether to include NLog-specific extensions to log4j schema.
+
+
+
+
+ Action that should be taken, when more connections than P:NLog.Targets.NetworkTarget.MaxConnections.
+
+
+
+
+ SSL/TLS protocols. Default no SSL/TLS is used. Currently only implemented for TCP.
+
+
+
+
+ Action that should be taken, when more pending messages than P:NLog.Targets.NetworkTarget.MaxQueueSize.
+
+
+
+
+ Action that should be taken if the message is larger than P:NLog.Targets.NetworkTarget.MaxMessageSize
+
+
+
+
+ Maximum queue size for a single connection. Requires P:NLog.Targets.NetworkTarget.KeepConnection = true
+
+
+
+
+ Network address.
+
+
+
+
+ Indicates whether to keep connection open whenever possible.
+
+
+
+
+ The number of seconds a connection will remain idle before the first keep-alive probe is sent
+
+
+
+
+ Size of the connection cache (number of connections which are kept alive). Requires P:NLog.Targets.NetworkTarget.KeepConnection = true
+
+
+
+
+ Maximum simultaneous connections. Requires P:NLog.Targets.NetworkTarget.KeepConnection = false
+
+
+
+
+ Type of compression for protocol payload. Useful for UDP where datagram max-size is 8192 bytes.
+
+
+
+
+ Skip compression when protocol payload is below limit to reduce overhead in cpu-usage and additional headers
+
+
+
+
+ Maximum message size in bytes. On limit breach then P:NLog.Targets.NetworkTarget.OnOverflow action is activated.
+
+
+
+
+ Encoding to be used.
+
+
+
+
+ End of line value if a newline is appended at the end of log message P:NLog.Targets.NetworkTarget.NewLine.
+
+
+
+
+ Indicates whether to append newline at the end of log message.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+ Layout used to format log messages.
+
+
+
+
+ Indicates whether to perform layout calculation.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+ Default filter to be applied when no specific rule matches.
+
+
+
+
+
+
+
+
+
+
+
+
+ Condition to be tested.
+
+
+
+
+ Resulting filter to be applied when the condition matches.
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+ Number of times to repeat each log message.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+ Whether to enable batching, and only apply single delay when a whole batch fails
+
+
+
+
+ Number of retries that should be attempted on the wrapped target in case of a failure.
+
+
+
+
+ Time to wait between retries in milliseconds.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+ Text to be rendered.
+
+
+
+
+ Header.
+
+
+
+
+ Footer.
+
+
+
+
+ Forward F:NLog.LogLevel.Fatal to M:System.Diagnostics.Trace.Fail(System.String) (Instead of M:System.Diagnostics.Trace.TraceError(System.String))
+
+
+
+
+ Force use M:System.Diagnostics.Trace.WriteLine(System.String) independent of T:NLog.LogLevel
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the target.
+
+
+
+
+ Indicates whether to pre-authenticate the HttpWebRequest (Requires 'Authorization' in P:NLog.Targets.WebServiceTarget.Headers parameters)
+
+
+
+
+ Value whether escaping be done according to Rfc3986 (Supports Internationalized Resource Identifiers - IRIs)
+
+
+
+
+ Value whether escaping be done according to the old NLog style (Very non-standard)
+
+
+
+
+ Value of the User-agent HTTP header.
+
+
+
+
+ Web service URL.
+
+
+
+
+ Proxy configuration when calling web service
+
+
+
+
+ Custom proxy address, include port separated by a colon
+
+
+
+
+ Protocol to be used when calling web service.
+
+
+
+
+ Web service namespace. Only used with Soap.
+
+
+
+
+ Web service method name. Only used with Soap.
+
+
+
+
+ Should we include the BOM (Byte-order-mark) for UTF? Influences the P:NLog.Targets.WebServiceTarget.Encoding property. This will only work for UTF-8.
+
+
+
+
+ Encoding.
+
+
+
+
+ Name of the root XML element, if POST of XML document chosen. If so, this property must not be null. (see P:NLog.Targets.WebServiceTarget.Protocol and F:NLog.Targets.WebServiceProtocol.XmlPost).
+
+
+
+
+ (optional) root namespace of the XML document, if POST of XML document chosen. (see P:NLog.Targets.WebServiceTarget.Protocol and F:NLog.Targets.WebServiceProtocol.XmlPost).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Custom column delimiter value (valid when ColumnDelimiter is set to 'Custom').
+
+
+
+
+ Column delimiter.
+
+
+
+
+ Footer layout.
+
+
+
+
+ Header layout.
+
+
+
+
+ Body layout (can be repeated multiple times).
+
+
+
+
+ Quote Character.
+
+
+
+
+ Quoting mode.
+
+
+
+
+ Indicates whether CVS should include header.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the column.
+
+
+
+
+ Layout of the column.
+
+
+
+
+ Override of Quoting mode
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Option to render the empty object value {}
+
+
+
+
+ Option to suppress the extra spaces in the output json
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Option to include all properties from the log event (as JSON)
+
+
+
+
+ Indicates whether to include contents of the T:NLog.GlobalDiagnosticsContext dictionary.
+
+
+
+
+ Whether to include the contents of the T:NLog.ScopeContext dictionary.
+
+
+
+
+ Should forward slashes be escaped? If true, / will be converted to \/
+
+
+
+
+ Option to exclude null/empty properties from the log event (as JSON)
+
+
+
+
+ List of property names to exclude when P:NLog.Layouts.JsonLayout.IncludeAllProperties is true
+
+
+
+
+ How far should the JSON serializer follow object references before backing off
+
+
+
+
+ Option to render the empty object value {}
+
+
+
+
+ Option to suppress the extra spaces in the output json
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the attribute.
+
+
+
+
+ Layout that will be rendered as the attribute's value.
+
+
+
+
+ Fallback value when result value is not available
+
+
+
+
+ Determines whether or not this attribute will be Json encoded.
+
+
+
+
+ Should forward slashes be escaped? If true, / will be converted to \/
+
+
+
+
+ Indicates whether to escape non-ascii characters
+
+
+
+
+ Whether an attribute with empty value should be included in the output
+
+
+
+
+ Result value type, for conversion of layout rendering output
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Footer layout.
+
+
+
+
+ Header layout.
+
+
+
+
+ Body layout (can be repeated multiple times).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Option to include all properties from the log events
+
+
+
+
+ Whether to include log4j:NDC in output from T:NLog.ScopeContext nested context.
+
+
+
+
+ Whether to include log4j:NDC in output from T:NLog.ScopeContext nested context.
+
+
+
+
+ Whether to include the contents of the T:NLog.ScopeContext properties-dictionary.
+
+
+
+
+ AppInfo field. By default it's the friendly name of the current AppDomain.
+
+
+
+
+ Indicates whether to include call site (class and method name) in the information sent over the network.
+
+
+
+
+ Indicates whether to include source info (file name and line number) in the information sent over the network.
+
+
+
+
+ Log4j:event logger-xml-attribute (Default ${logger})
+
+
+
+
+ Whether the log4j:throwable xml-element should be written as CDATA
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Layout text.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the root XML element
+
+
+
+
+ Value inside the root XML element
+
+
+
+
+ Whether to include the contents of the T:NLog.ScopeContext dictionary.
+
+
+
+
+ Determines whether or not this attribute will be Xml encoded.
+
+
+
+
+ List of property names to exclude when P:NLog.Layouts.XmlElementBase.IncludeAllProperties is true
+
+
+
+
+ Whether a ElementValue with empty value should be included in the output
+
+
+
+
+ Auto indent and create new lines
+
+
+
+
+ How far should the XML serializer follow object references before backing off
+
+
+
+
+ XML element name to use for rendering IList-collections items
+
+
+
+
+ XML attribute name to use when rendering property-key When null (or empty) then key-attribute is not included
+
+
+
+
+ XML element name to use when rendering properties
+
+
+
+
+ XML attribute name to use when rendering property-value When null (or empty) then value-attribute is not included and value is formatted as XML-element-value
+
+
+
+
+ Option to include all properties from the log event (as XML)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the attribute.
+
+
+
+
+ Layout that will be rendered as the attribute's value.
+
+
+
+
+ Fallback value when result value is not available
+
+
+
+
+ Determines whether or not this attribute will be Xml encoded.
+
+
+
+
+ Whether an attribute with empty value should be included in the output
+
+
+
+
+ Result value type, for conversion of layout rendering output
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the element
+
+
+
+
+ Whether to include the contents of the T:NLog.ScopeContext dictionary.
+
+
+
+
+ Value inside the element
+
+
+
+
+ Determines whether or not this attribute will be Xml encoded.
+
+
+
+
+ List of property names to exclude when P:NLog.Layouts.XmlElementBase.IncludeAllProperties is true
+
+
+
+
+ Whether a ElementValue with empty value should be included in the output
+
+
+
+
+ Auto indent and create new lines
+
+
+
+
+ How far should the XML serializer follow object references before backing off
+
+
+
+
+ XML element name to use for rendering IList-collections items
+
+
+
+
+ XML attribute name to use when rendering property-key When null (or empty) then key-attribute is not included
+
+
+
+
+ XML element name to use when rendering properties
+
+
+
+
+ XML attribute name to use when rendering property-value When null (or empty) then value-attribute is not included and value is formatted as XML-element-value
+
+
+
+
+ Option to include all properties from the log event (as XML)
+
+
+
+
+
+
+
+
+
+
+
+
+ Action to be taken when filter matches.
+
+
+
+
+ Condition expression.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Action to be taken when filter matches.
+
+
+
+
+ Indicates whether to ignore case when comparing strings.
+
+
+
+
+ Layout to be used to filter log messages.
+
+
+
+
+ Substring to be matched.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Action to be taken when filter matches.
+
+
+
+
+ String to compare the layout to.
+
+
+
+
+ Indicates whether to ignore case when comparing strings.
+
+
+
+
+ Layout to be used to filter log messages.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Action to be taken when filter matches.
+
+
+
+
+ Indicates whether to ignore case when comparing strings.
+
+
+
+
+ Layout to be used to filter log messages.
+
+
+
+
+ Substring to be matched.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Action to be taken when filter matches.
+
+
+
+
+ String to compare the layout to.
+
+
+
+
+ Indicates whether to ignore case when comparing strings.
+
+
+
+
+ Layout to be used to filter log messages.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Action to be taken when filter matches.
+
+
+
+
+ Append FilterCount to the P:NLog.LogEventInfo.Message when an event is no longer filtered
+
+
+
+
+ Insert FilterCount value into P:NLog.LogEventInfo.Properties when an event is no longer filtered
+
+
+
+
+ Applies the configured action to the initial logevent that starts the timeout period. Used to configure that it should ignore all events until timeout.
+
+
+
+
+ Layout to be used to filter log messages.
+
+
+
+
+ Max length of filter values, will truncate if above limit
+
+
+
+
+ How long before a filter expires, and logging is accepted again
+
+
+
+
+ Default number of unique filter values to expect, will automatically increase if needed
+
+
+
+
+ Max number of unique filter values to expect simultaneously
+
+
+
+
+ Default buffer size for the internal buffers
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/KfChatDotNetCli/Program.cs b/KfChatDotNetCli/Program.cs
new file mode 100644
index 0000000..f6bb823
--- /dev/null
+++ b/KfChatDotNetCli/Program.cs
@@ -0,0 +1,40 @@
+using System.Net;
+using System.Text;
+using CommandLine;
+using NLog;
+
+namespace KfChatDotNetCli
+{
+ public class Program
+ {
+ public class Options
+ {
+ [Option('t', "token", Required = false, Default = null, HelpText = "XF session token from the 'xf_session' cookie")]
+ public string XfSessionToken { get; set; } = null!;
+
+ [Option("debug", Required = false, Default = false, HelpText = "Enable debug logging")]
+ public bool Debug { get; set; }
+ [Option('r', "room", Required = true, HelpText = "Room ID to join on start")]
+ public int RoomId { get; set; }
+ }
+ static void Main(string[] args)
+ {
+ Console.OutputEncoding = Encoding.UTF8;
+ Parser.Default.ParseArguments(args).WithParsed(CliOptions);
+ }
+
+ static void CliOptions(Options options)
+ {
+ ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls13;
+ if (options.Debug)
+ {
+ foreach (var rule in LogManager.Configuration.LoggingRules)
+ {
+ rule.EnableLoggingForLevel(LogLevel.Debug);
+ }
+ }
+
+ new ChatCliMain(options.XfSessionToken, options.RoomId);
+ }
+ }
+}
diff --git a/KfChatDotNetGui/.gitignore b/KfChatDotNetGui/.gitignore
new file mode 100644
index 0000000..8afdcb6
--- /dev/null
+++ b/KfChatDotNetGui/.gitignore
@@ -0,0 +1,454 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# Tye
+.tye/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+##
+## Visual studio for Mac
+##
+
+
+# globs
+Makefile.in
+*.userprefs
+*.usertasks
+config.make
+config.status
+aclocal.m4
+install-sh
+autom4te.cache/
+*.tar.gz
+tarballs/
+test-results/
+
+# Mac bundle stuff
+*.dmg
+*.app
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
+# Windows thumbnail cache files
+Thumbs.db
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+##
+## Visual Studio Code
+##
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
diff --git a/KfChatDotNetGui/App.axaml b/KfChatDotNetGui/App.axaml
new file mode 100644
index 0000000..17b4d69
--- /dev/null
+++ b/KfChatDotNetGui/App.axaml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/KfChatDotNetGui/App.axaml.cs b/KfChatDotNetGui/App.axaml.cs
new file mode 100644
index 0000000..6f32462
--- /dev/null
+++ b/KfChatDotNetGui/App.axaml.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Collections.ObjectModel;
+using System.IO;
+using Avalonia;
+using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Markup.Xaml;
+using KfChatDotNetGui.Models;
+using KfChatDotNetGui.ViewModels;
+using KfChatDotNetGui.Views;
+using Newtonsoft.Json;
+using NLog;
+
+namespace KfChatDotNetGui
+{
+ public partial class App : Application
+ {
+ public override void Initialize()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+
+ public override void OnFrameworkInitializationCompleted()
+ {
+ var logger = LogManager.GetCurrentClassLogger();
+ if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+ {
+ var dataContext = new MainWindowViewModel();
+ if (File.Exists("rooms.json"))
+ {
+ var rooms = JsonConvert.DeserializeObject(File.ReadAllText("rooms.json"));
+ dataContext.RoomList = rooms!.Rooms;
+
+ }
+ dataContext.Messages.Add(new MainWindowViewModel.MessageViewModel
+ {
+ Author = "SneedChat",
+ Messages = new ObservableCollection{
+ new(){
+ Message = "Welcome to my shitty chat client.",
+ MessageId = 0,
+ OwnMessage = false
+ },
+ new()
+ {
+ Message = "Click on Settings -> Identity to configure your XenForo token so you may connect to SneedChat",
+ MessageId = 0,
+ OwnMessage = false
+ }
+ },
+ PostedAt = DateTimeOffset.Now,
+ AuthorId = -1
+ });
+ if (dataContext.RoomList.Count == 0)
+ {
+ dataContext.Messages[0].Messages.Add(new MainWindowViewModel.InnerMessageViewModel
+ {
+ Message = "Also it looks like you have no rooms configured. Click on Settings -> Rooms to configure the room list",
+ MessageId = 0,
+ OwnMessage = false
+ });
+ }
+ desktop.MainWindow = new MainWindow
+ {
+ DataContext = dataContext
+ };
+ }
+
+ base.OnFrameworkInitializationCompleted();
+ }
+ }
+}
\ No newline at end of file
diff --git a/KfChatDotNetGui/Assets/avalonia-logo.ico b/KfChatDotNetGui/Assets/avalonia-logo.ico
new file mode 100644
index 0000000000000000000000000000000000000000..da8d49ff9b94e52778f5324a1b87dd443a698b57
GIT binary patch
literal 176111
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