Added support for channel creation / deletion and joining / leaving stages for Discord

This commit is contained in:
barelyprofessional
2024-08-23 12:27:31 +08:00
parent 61f54c6958
commit 840fe19430
7 changed files with 3634 additions and 1 deletions

View File

@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\KfChatDotNetBot\KfChatDotNetBot.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="NLog" Version="5.3.3" />
</ItemGroup>
<ItemGroup>
<Content Update="NLog.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
autoReload="true"
throwExceptions="false"
internalLogLevel="Off" internalLogFile="~/nlog-internal.log">
<targets>
<target xsi:type="ColoredConsole" name="console"/>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="console" />
</rules>
</nlog>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
// This new template sucks
using NLog;
var logger = LogManager.GetCurrentClassLogger();
logger.Info("Starting up");
var token = "authorization token!";
var proxy = "socks5://whatever:1080";
var discord = new KfChatDotNetBot.Services.DiscordService(token, proxy);
discord.StartWsClient().Wait();
logger.Info("Started");
var exitEvent = new ManualResetEvent(false);
exitEvent.WaitOne();

View File

@@ -14,6 +14,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThreeXplWsClient", "ThreeXp
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThreeXplCliClient", "ThreeXplCliClient\ThreeXplCliClient.csproj", "{D098E281-5535-4A07-9514-57AF78704B0C}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThreeXplCliClient", "ThreeXplCliClient\ThreeXplCliClient.csproj", "{D098E281-5535-4A07-9514-57AF78704B0C}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CliDiscordPacketDump", "CliDiscordPacketDump\CliDiscordPacketDump.csproj", "{792ECCCD-FAC3-4CE5-A760-988080960BB9}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@@ -48,5 +50,9 @@ Global
{D098E281-5535-4A07-9514-57AF78704B0C}.Debug|Any CPU.Build.0 = Debug|Any CPU {D098E281-5535-4A07-9514-57AF78704B0C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D098E281-5535-4A07-9514-57AF78704B0C}.Release|Any CPU.ActiveCfg = Release|Any CPU {D098E281-5535-4A07-9514-57AF78704B0C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D098E281-5535-4A07-9514-57AF78704B0C}.Release|Any CPU.Build.0 = Release|Any CPU {D098E281-5535-4A07-9514-57AF78704B0C}.Release|Any CPU.Build.0 = Release|Any CPU
{792ECCCD-FAC3-4CE5-A760-988080960BB9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{792ECCCD-FAC3-4CE5-A760-988080960BB9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{792ECCCD-FAC3-4CE5-A760-988080960BB9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{792ECCCD-FAC3-4CE5-A760-988080960BB9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View File

@@ -430,9 +430,31 @@ public class ChatBot
_discord.OnInvalidCredentials += DiscordOnInvalidCredentials; _discord.OnInvalidCredentials += DiscordOnInvalidCredentials;
_discord.OnMessageReceived += DiscordOnMessageReceived; _discord.OnMessageReceived += DiscordOnMessageReceived;
_discord.OnPresenceUpdated += DiscordOnPresenceUpdated; _discord.OnPresenceUpdated += DiscordOnPresenceUpdated;
_discord.OnChannelCreated += DiscordOnChannelCreated;
_discord.OnChannelDeleted += DiscordOnChannelDeleted;
_discord.StartWsClient().Wait(_cancellationToken); _discord.StartWsClient().Wait(_cancellationToken);
} }
private void DiscordOnChannelDeleted(object sender, DiscordChannelDeletionModel channel)
{
_logger.Info($"Received channel deletion event of type {channel.Type} with name {channel.Name}");
if (channel.Type != DiscordChannelType.GuildText && channel.Type != DiscordChannelType.GuildVoice &&
channel.Type != DiscordChannelType.GuildStageVoice) return;
var discordIcon = Helpers.GetValue(BuiltIn.Keys.DiscordIcon).Result;
var channelName = channel.Name ?? "Unknown name";
SendChatMessage($"[img]{discordIcon.Value}[/img] Discord {channel.Type.Humanize()} channel {channelName} was deleted", true);
}
private void DiscordOnChannelCreated(object sender, DiscordChannelCreationModel channel)
{
_logger.Info($"Received channel creation event of type {channel.Type} with name {channel.Name}");
if (channel.Type != DiscordChannelType.GuildText && channel.Type != DiscordChannelType.GuildVoice &&
channel.Type != DiscordChannelType.GuildStageVoice) return;
var discordIcon = Helpers.GetValue(BuiltIn.Keys.DiscordIcon).Result;
var channelName = channel.Name ?? "Unknown name";
SendChatMessage($"[img]{discordIcon.Value}[/img] New Discord {channel.Type.Humanize()} channel created: {channelName}", true);
}
private void BuildTwitchChat() private void BuildTwitchChat()
{ {
var settings = Helpers.GetMultipleValues([BuiltIn.Keys.TwitchBossmanJackUsername, BuiltIn.Keys.Proxy]).Result; var settings = Helpers.GetMultipleValues([BuiltIn.Keys.TwitchBossmanJackUsername, BuiltIn.Keys.Proxy]).Result;
@@ -485,6 +507,19 @@ public class ChatBot
{ {
return; return;
} }
if (message.Type == DiscordMessageType.StageStart)
{
SendChatMessage($"[img]{settings[BuiltIn.Keys.DiscordIcon].Value}[/img] BossmanJack just started a stage called {message.Content} 🚨🚨",
true);
return;
}
if (message.Type == DiscordMessageType.StageEnd)
{
SendChatMessage($"[img]{settings[BuiltIn.Keys.DiscordIcon].Value}[/img] BossmanJack just ended a stage called {message.Content} :lossmanjack:",
true);
return;
}
var result = $"[img]{settings[BuiltIn.Keys.DiscordIcon].Value}[/img] BossmanJack: {message.Content}"; var result = $"[img]{settings[BuiltIn.Keys.DiscordIcon].Value}[/img] BossmanJack: {message.Content}";
foreach (var attachment in message.Attachments ?? []) foreach (var attachment in message.Attachments ?? [])

View File

@@ -1,4 +1,5 @@
using System.Net; using System.ComponentModel;
using System.Net;
using System.Net.WebSockets; using System.Net.WebSockets;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
@@ -23,10 +24,15 @@ public class DiscordService : IDisposable
public delegate void PresenceUpdateEventHandler(object sender, DiscordPresenceUpdateModel presence); public delegate void PresenceUpdateEventHandler(object sender, DiscordPresenceUpdateModel presence);
public delegate void WsDisconnectionEventHandler(object sender, DisconnectionInfo e); public delegate void WsDisconnectionEventHandler(object sender, DisconnectionInfo e);
public delegate void InvalidCredentialsEventHandler(object sender, DiscordPacketReadModel packet); public delegate void InvalidCredentialsEventHandler(object sender, DiscordPacketReadModel packet);
public delegate void ChannelCreatedEventHandler(object sender, DiscordChannelCreationModel channel);
public delegate void ChannelDeletedEventHandler(object sender, DiscordChannelDeletionModel channel);
public event MessageReceivedEventHandler OnMessageReceived; public event MessageReceivedEventHandler OnMessageReceived;
public event PresenceUpdateEventHandler OnPresenceUpdated; public event PresenceUpdateEventHandler OnPresenceUpdated;
public event WsDisconnectionEventHandler OnWsDisconnection; public event WsDisconnectionEventHandler OnWsDisconnection;
public event InvalidCredentialsEventHandler OnInvalidCredentials; public event InvalidCredentialsEventHandler OnInvalidCredentials;
public event ChannelCreatedEventHandler OnChannelCreated;
public event ChannelDeletedEventHandler OnChannelDeleted;
private readonly CancellationToken _cancellationToken = CancellationToken.None; private readonly CancellationToken _cancellationToken = CancellationToken.None;
private readonly CancellationTokenSource _pingCts = new(); private readonly CancellationTokenSource _pingCts = new();
@@ -186,6 +192,16 @@ public class DiscordService : IDisposable
OnMessageReceived?.Invoke(this, OnMessageReceived?.Invoke(this,
packet.Data.Deserialize<DiscordMessageModel>() ?? throw new InvalidOperationException()); packet.Data.Deserialize<DiscordMessageModel>() ?? throw new InvalidOperationException());
return; return;
case "CHANNEL_CREATE":
OnChannelCreated?.Invoke(this,
packet.Data.Deserialize<DiscordChannelCreationModel>() ??
throw new InvalidOperationException());
return;
case "CHANNEL_DELETE":
OnChannelDeleted?.Invoke(this,
packet.Data.Deserialize<DiscordChannelDeletionModel>() ??
throw new InvalidOperationException());
return;
default: default:
_logger.Debug($"{packet.DispatchEvent} was unhandled. JSON follows"); _logger.Debug($"{packet.DispatchEvent} was unhandled. JSON follows");
_logger.Debug(message.Text); _logger.Debug(message.Text);
@@ -248,10 +264,51 @@ public class DiscordUserModel
public class DiscordMessageModel public class DiscordMessageModel
{ {
[JsonPropertyName("type")]
public required DiscordMessageType Type { get; set; }
[JsonPropertyName("content")] [JsonPropertyName("content")]
public string? Content { get; set; } public string? Content { get; set; }
[JsonPropertyName("author")] [JsonPropertyName("author")]
public required DiscordUserModel Author { get; set; } public required DiscordUserModel Author { get; set; }
[JsonPropertyName("attachments")] [JsonPropertyName("attachments")]
public JsonElement[]? Attachments { get; set; } public JsonElement[]? Attachments { get; set; }
}
public class DiscordChannelCreationModel
{
[JsonPropertyName("type")]
public required DiscordChannelType Type { get; set; }
[JsonPropertyName("name")]
public string? Name { get; set; }
[JsonPropertyName("guild_id")]
public required string GuildId { get; set; }
}
public class DiscordChannelDeletionModel
{
[JsonPropertyName("type")]
public required DiscordChannelType Type { get; set; }
[JsonPropertyName("name")]
public string? Name { get; set; }
}
// https://discord.com/developers/docs/resources/channel#channel-object-channel-types
// Ignored the ones nobody cares about
public enum DiscordChannelType
{
[Description("Text")]
GuildText = 0,
[Description("Voice")]
GuildVoice = 2,
[Description("Stage")]
GuildStageVoice = 13
}
public enum DiscordMessageType
{
Default = 0,
[Description("Stage start")]
StageStart = 27,
[Description("Stage end")]
StageEnd = 28
} }