From 2d917bd3af75aa3e71678239af62532f3615f7b1 Mon Sep 17 00:00:00 2001 From: Oliver Booth Date: Sat, 26 Aug 2023 14:11:43 +0100 Subject: [PATCH] refactor: separate connection services and message services This change also fixes long messages from Discord breaking the bot in VP, and allows customisation of console message style. --- VPLink/Configuration/ChatConfiguration.cs | 21 +++ .../VirtualParadiseConfiguration.cs | 6 + VPLink/Data/RelayedMessage.cs | 30 ++++ VPLink/Program.cs | 7 +- VPLink/Services/DiscordMessageService.cs | 162 ++++++++++++++++++ VPLink/Services/DiscordService.cs | 112 +----------- ...rdService.cs => IDiscordMessageService.cs} | 21 +-- VPLink/Services/IRelayTarget.cs | 16 ++ .../IVirtualParadiseMessageService.cs | 17 ++ VPLink/Services/IVirtualParadiseService.cs | 25 --- VPLink/Services/RelayService.cs | 29 +--- .../Services/VirtualParadiseMessageService.cs | 69 ++++++++ VPLink/Services/VirtualParadiseService.cs | 28 +-- 13 files changed, 342 insertions(+), 201 deletions(-) create mode 100644 VPLink/Configuration/ChatConfiguration.cs create mode 100644 VPLink/Data/RelayedMessage.cs create mode 100644 VPLink/Services/DiscordMessageService.cs rename VPLink/Services/{IDiscordService.cs => IDiscordMessageService.cs} (50%) create mode 100644 VPLink/Services/IRelayTarget.cs create mode 100644 VPLink/Services/IVirtualParadiseMessageService.cs delete mode 100644 VPLink/Services/IVirtualParadiseService.cs create mode 100644 VPLink/Services/VirtualParadiseMessageService.cs diff --git a/VPLink/Configuration/ChatConfiguration.cs b/VPLink/Configuration/ChatConfiguration.cs new file mode 100644 index 0000000..dd99157 --- /dev/null +++ b/VPLink/Configuration/ChatConfiguration.cs @@ -0,0 +1,21 @@ +using VpSharp; + +namespace VPLink.Configuration; + +/// +/// Represents the chat configuration. +/// +public sealed class ChatConfiguration +{ + /// + /// Gets or sets the color of the message. + /// + /// The message color. + public uint Color { get; set; } = 0x191970; + + /// + /// Gets or sets the font style of the message. + /// + /// The font style. + public FontStyle Style { get; set; } = FontStyle.Regular; +} diff --git a/VPLink/Configuration/VirtualParadiseConfiguration.cs b/VPLink/Configuration/VirtualParadiseConfiguration.cs index e806157..c402a73 100644 --- a/VPLink/Configuration/VirtualParadiseConfiguration.cs +++ b/VPLink/Configuration/VirtualParadiseConfiguration.cs @@ -11,6 +11,12 @@ public sealed class VirtualParadiseConfiguration /// The display name. public string BotName { get; set; } = "VPLink"; + /// + /// Gets or sets the chat configuration. + /// + /// The chat configuration. + public ChatConfiguration ChatConfiguration { get; } = new(); + /// /// Gets or sets the password with which to log in to Virtual Paradise. /// diff --git a/VPLink/Data/RelayedMessage.cs b/VPLink/Data/RelayedMessage.cs new file mode 100644 index 0000000..07b1469 --- /dev/null +++ b/VPLink/Data/RelayedMessage.cs @@ -0,0 +1,30 @@ +namespace VPLink.Data; + +/// +/// Represents a message that is relayed between Discord and Virtual Paradise. +/// +public readonly struct RelayedMessage +{ + /// + /// Initializes a new instance of the struct. + /// + /// The author. + /// The content. + public RelayedMessage(string author, string content) + { + Author = author; + Content = content; + } + + /// + /// Gets the message content. + /// + /// The message content. + public string Content { get; } + + /// + /// Gets the user that sent the message. + /// + /// The user that sent the message. + public string Author { get; } +} diff --git a/VPLink/Program.cs b/VPLink/Program.cs index fce6fae..48613e0 100644 --- a/VPLink/Program.cs +++ b/VPLink/Program.cs @@ -35,8 +35,11 @@ builder.Services.AddSingleton(new DiscordSocketConfig }); builder.Services.AddHostedSingleton(); -builder.Services.AddHostedSingleton(); -builder.Services.AddHostedSingleton(); +builder.Services.AddHostedSingleton(); +builder.Services.AddHostedSingleton(); + +builder.Services.AddHostedSingleton(); +builder.Services.AddHostedSingleton(); builder.Services.AddHostedSingleton(); await builder.Build().RunAsync(); diff --git a/VPLink/Services/DiscordMessageService.cs b/VPLink/Services/DiscordMessageService.cs new file mode 100644 index 0000000..11c78bb --- /dev/null +++ b/VPLink/Services/DiscordMessageService.cs @@ -0,0 +1,162 @@ +using System.Diagnostics.CodeAnalysis; +using System.Reactive.Linq; +using System.Reactive.Subjects; +using System.Text; +using System.Text.RegularExpressions; +using Cysharp.Text; +using Discord; +using Discord.WebSocket; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using VPLink.Configuration; +using VPLink.Data; +using VpSharp.Entities; + +namespace VPLink.Services; + +/// +internal sealed partial class DiscordMessageService : BackgroundService, IDiscordMessageService +{ + private static readonly Encoding Utf8Encoding = new UTF8Encoding(false, false); + private static readonly Regex UnescapeRegex = GetUnescapeRegex(); + private static readonly Regex EscapeRegex = GetEscapeRegex(); + + private readonly ILogger _logger; + private readonly IConfigurationService _configurationService; + private readonly DiscordSocketClient _discordClient; + private readonly Subject _messageReceived = new(); + + /// + /// Initializes a new instance of the class. + /// + /// The logger. + /// The configuration service. + /// The Discord client. + public DiscordMessageService(ILogger logger, + IConfigurationService configurationService, + DiscordSocketClient discordClient) + { + _logger = logger; + _configurationService = configurationService; + _discordClient = discordClient; + } + + /// + public IObservable OnMessageReceived => _messageReceived.AsObservable(); + + /// + public Task AnnounceArrival(VirtualParadiseAvatar avatar) + { + if (avatar is null) throw new ArgumentNullException(nameof(avatar)); + if (!TryGetRelayChannel(out ITextChannel? channel)) return Task.CompletedTask; + + var embed = new EmbedBuilder(); + embed.WithColor(0x00FF00); + embed.WithTitle("📥 Avatar Joined"); + embed.WithDescription(avatar.Name); + embed.WithTimestamp(DateTimeOffset.UtcNow); + embed.WithFooter($"Session {avatar.Session}"); + + return channel.SendMessageAsync(embed: embed.Build()); + } + + /// + public Task AnnounceDeparture(VirtualParadiseAvatar avatar) + { + if (avatar is null) throw new ArgumentNullException(nameof(avatar)); + if (!TryGetRelayChannel(out ITextChannel? channel)) return Task.CompletedTask; + + var embed = new EmbedBuilder(); + embed.WithColor(0xFF0000); + embed.WithTitle("📤 Avatar Left"); + embed.WithDescription(avatar.Name); + embed.WithTimestamp(DateTimeOffset.UtcNow); + embed.WithFooter($"Session {avatar.Session}"); + + return channel.SendMessageAsync(embed: embed.Build()); + } + + /// + public Task SendMessageAsync(RelayedMessage message) + { + if (!TryGetRelayChannel(out ITextChannel? channel)) return Task.CompletedTask; + return channel.SendMessageAsync($"**{message.Author}**: {message.Content}"); + } + + /// + protected override Task ExecuteAsync(CancellationToken stoppingToken) + { + _discordClient.MessageReceived += OnDiscordMessageReceived; + return Task.CompletedTask; + } + + private Task OnDiscordMessageReceived(SocketMessage arg) + { + if (arg is not IUserMessage message) + return Task.CompletedTask; + + IUser author = message.Author; + if (author.Id == _discordClient.CurrentUser.Id) + return Task.CompletedTask; + + if (author.IsBot && !_configurationService.BotConfiguration.RelayBotMessages) + return Task.CompletedTask; + + string displayName = author.GlobalName ?? author.Username; + string unescaped = UnescapeRegex.Replace(message.Content, "$1"); + string content = EscapeRegex.Replace(unescaped, "\\$1"); + + IReadOnlyCollection attachments = message.Attachments; + if (attachments.Count > 0) + { + using Utf8ValueStringBuilder builder = ZString.CreateUtf8StringBuilder(); + for (var index = 0; index < attachments.Count; index++) + { + builder.AppendLine(attachments.ElementAt(index).Url); + } + + // += allocates more than necessary, just interpolate + content = $"{content}\n{builder}"; + } + + _logger.LogInformation("Message by {Author}: {Content}", author, content); + + Span buffer = stackalloc byte[255]; // VP message length limit + var messages = new List(); + int byteCount = Utf8Encoding.GetByteCount(content); + + var offset = 0; + while (offset < byteCount) + { + int length = Math.Min(byteCount - offset, 255); + Utf8Encoding.GetBytes(content.AsSpan(offset, length), buffer); + messages.Add(new RelayedMessage(displayName, Utf8Encoding.GetString(buffer))); + offset += length; + } + + messages.ForEach(_messageReceived.OnNext); + return Task.CompletedTask; + } + + private bool TryGetRelayChannel([NotNullWhen(true)] out ITextChannel? channel) + { + DiscordConfiguration configuration = _configurationService.DiscordConfiguration; + ulong channelId = configuration.ChannelId; + + if (_discordClient.GetChannel(channelId) is ITextChannel textChannel) + { + channel = textChannel; + return true; + } + + _logger.LogError("Channel {ChannelId} does not exist", channelId); + channel = null; + return false; + } + + [GeneratedRegex(@"\\(\*|_|`|~|\\)", RegexOptions.Compiled)] + private static partial Regex GetUnescapeRegex(); + + [GeneratedRegex(@"(\*|_|`|~|\\)", RegexOptions.Compiled)] + private static partial Regex GetEscapeRegex(); +} diff --git a/VPLink/Services/DiscordService.cs b/VPLink/Services/DiscordService.cs index 071bdc5..e01f909 100644 --- a/VPLink/Services/DiscordService.cs +++ b/VPLink/Services/DiscordService.cs @@ -1,7 +1,3 @@ -using System.Diagnostics.CodeAnalysis; -using System.Reactive.Linq; -using System.Reactive.Subjects; -using System.Text.RegularExpressions; using Discord; using Discord.Interactions; using Discord.WebSocket; @@ -9,22 +5,16 @@ using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using VPLink.Commands; using VPLink.Configuration; -using VpSharp.Entities; namespace VPLink.Services; -/// -internal sealed partial class DiscordService : BackgroundService, IDiscordService +internal sealed class DiscordService : BackgroundService { - private static readonly Regex UnescapeRegex = GetUnescapeRegex(); - private static readonly Regex EscapeRegex = GetEscapeRegex(); - private readonly ILogger _logger; private readonly IServiceProvider _serviceProvider; private readonly IConfigurationService _configurationService; private readonly InteractionService _interactionService; private readonly DiscordSocketClient _discordClient; - private readonly Subject _messageReceived = new(); /// /// Initializes a new instance of the class. @@ -47,9 +37,6 @@ internal sealed partial class DiscordService : BackgroundService, IDiscordServic _discordClient = discordClient; } - /// - public IObservable OnMessageReceived => _messageReceived.AsObservable(); - /// protected override async Task ExecuteAsync(CancellationToken stoppingToken) { @@ -60,7 +47,6 @@ internal sealed partial class DiscordService : BackgroundService, IDiscordServic _discordClient.Ready += OnReady; _discordClient.InteractionCreated += OnInteractionCreated; - _discordClient.MessageReceived += OnDiscordMessageReceived; DiscordConfiguration configuration = _configurationService.DiscordConfiguration; string token = configuration.Token ?? throw new InvalidOperationException("Token is not set."); @@ -70,19 +56,6 @@ internal sealed partial class DiscordService : BackgroundService, IDiscordServic await _discordClient.StartAsync(); } - private Task OnDiscordMessageReceived(SocketMessage arg) - { - if (arg is not IUserMessage message) - return Task.CompletedTask; - - DiscordConfiguration configuration = _configurationService.DiscordConfiguration; - if (message.Channel.Id != configuration.ChannelId) - return Task.CompletedTask; - - _messageReceived.OnNext(message); - return Task.CompletedTask; - } - private async Task OnInteractionCreated(SocketInteraction interaction) { try @@ -109,87 +82,4 @@ internal sealed partial class DiscordService : BackgroundService, IDiscordServic _logger.LogInformation("Discord client ready"); return _interactionService.RegisterCommandsGloballyAsync(); } - - /// - public Task AnnounceArrival(VirtualParadiseAvatar avatar) - { - if (avatar is null) throw new ArgumentNullException(nameof(avatar)); - if (!TryGetRelayChannel(out ITextChannel? channel)) return Task.CompletedTask; - - var embed = new EmbedBuilder(); - embed.WithColor(0x00FF00); - embed.WithTitle("📥 Avatar Joined"); - embed.WithDescription(avatar.Name); - embed.WithTimestamp(DateTimeOffset.UtcNow); - embed.WithFooter($"Session {avatar.Session}"); - - return channel.SendMessageAsync(embed: embed.Build()); - } - - /// - public Task AnnounceDeparture(VirtualParadiseAvatar avatar) - { - if (avatar is null) throw new ArgumentNullException(nameof(avatar)); - if (!TryGetRelayChannel(out ITextChannel? channel)) return Task.CompletedTask; - - var embed = new EmbedBuilder(); - embed.WithColor(0xFF0000); - embed.WithTitle("📤 Avatar Left"); - embed.WithDescription(avatar.Name); - embed.WithTimestamp(DateTimeOffset.UtcNow); - embed.WithFooter($"Session {avatar.Session}"); - - return channel.SendMessageAsync(embed: embed.Build()); - } - - /// - public Task SendMessageAsync(VirtualParadiseMessage message) - { - if (message is null) throw new ArgumentNullException(nameof(message)); - if (string.IsNullOrWhiteSpace(message.Content)) return Task.CompletedTask; - - if (message.Author is not { } author) - { - _logger.LogWarning("Received message without author, ignoring message"); - return Task.CompletedTask; - } - - if (author.IsBot && !_configurationService.BotConfiguration.RelayBotMessages) - { - _logger.LogDebug("Bot messages are disabled, ignoring message"); - return Task.CompletedTask; - } - - _logger.LogInformation("Message by {Author}: {Content}", author, message.Content); - - if (!TryGetRelayChannel(out ITextChannel? channel)) return Task.CompletedTask; - - string unescaped = UnescapeRegex.Replace(message.Content, "$1"); - string escaped = EscapeRegex.Replace(unescaped, "\\$1"); - - string displayName = author.Name; - return channel.SendMessageAsync($"**{displayName}**: {escaped}"); - } - - private bool TryGetRelayChannel([NotNullWhen(true)] out ITextChannel? channel) - { - DiscordConfiguration configuration = _configurationService.DiscordConfiguration; - ulong channelId = configuration.ChannelId; - - if (_discordClient.GetChannel(channelId) is ITextChannel textChannel) - { - channel = textChannel; - return true; - } - - _logger.LogError("Channel {ChannelId} does not exist", channelId); - channel = null; - return false; - } - - [GeneratedRegex(@"\\(\*|_|`|~|\\)", RegexOptions.Compiled)] - private static partial Regex GetUnescapeRegex(); - - [GeneratedRegex(@"(\*|_|`|~|\\)", RegexOptions.Compiled)] - private static partial Regex GetEscapeRegex(); } diff --git a/VPLink/Services/IDiscordService.cs b/VPLink/Services/IDiscordMessageService.cs similarity index 50% rename from VPLink/Services/IDiscordService.cs rename to VPLink/Services/IDiscordMessageService.cs index f442d1f..b338686 100644 --- a/VPLink/Services/IDiscordService.cs +++ b/VPLink/Services/IDiscordMessageService.cs @@ -1,18 +1,20 @@ -using Discord; +using VPLink.Data; using VpSharp.Entities; namespace VPLink.Services; /// -/// Represents a service that sends messages to the Discord channel. +/// Represents a service that listens for messages from the Discord bridge channel. /// -public interface IDiscordService +public interface IDiscordMessageService : IRelayTarget { /// - /// Gets an observable that is triggered when a message is received from the Discord channel. + /// Gets an observable that is triggered when a valid message is received from the Discord bridge channel. /// - /// An observable that is triggered when a message is received from the Discord channel. - IObservable OnMessageReceived { get; } + /// + /// An observable that is triggered when a valid message is received from the Discord bridge channel. + /// + IObservable OnMessageReceived { get; } /// /// Announces the arrival of an avatar. @@ -27,11 +29,4 @@ public interface IDiscordService /// The avatar. /// A representing the asynchronous operation. Task AnnounceDeparture(VirtualParadiseAvatar avatar); - - /// - /// Sends a message to the Discord channel. - /// - /// The message to send. - /// A representing the asynchronous operation. - Task SendMessageAsync(VirtualParadiseMessage message); } diff --git a/VPLink/Services/IRelayTarget.cs b/VPLink/Services/IRelayTarget.cs new file mode 100644 index 0000000..e5a6cd6 --- /dev/null +++ b/VPLink/Services/IRelayTarget.cs @@ -0,0 +1,16 @@ +using VPLink.Data; + +namespace VPLink.Services; + +/// +/// Represents an object that can be used as a relay target. +/// +public interface IRelayTarget +{ + /// + /// Sends a message to the relay target. + /// + /// The message to send. + /// A representing the asynchronous operation. + Task SendMessageAsync(RelayedMessage message); +} diff --git a/VPLink/Services/IVirtualParadiseMessageService.cs b/VPLink/Services/IVirtualParadiseMessageService.cs new file mode 100644 index 0000000..a08ed6a --- /dev/null +++ b/VPLink/Services/IVirtualParadiseMessageService.cs @@ -0,0 +1,17 @@ +using VPLink.Data; + +namespace VPLink.Services; + +/// +/// Represents a service that listens for messages from the Virtual Paradise world. +/// +public interface IVirtualParadiseMessageService : IRelayTarget +{ + /// + /// Gets an observable that is triggered when a valid message is received from the Virtual Paradise world. + /// + /// + /// An observable that is triggered when a valid message is received from the Virtual Paradise world. + /// + IObservable OnMessageReceived { get; } +} \ No newline at end of file diff --git a/VPLink/Services/IVirtualParadiseService.cs b/VPLink/Services/IVirtualParadiseService.cs deleted file mode 100644 index 1668fd6..0000000 --- a/VPLink/Services/IVirtualParadiseService.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Discord; -using VpSharp.Entities; - -namespace VPLink.Services; - -/// -/// Represents a service that sends messages to the Virtual Paradise world server. -/// -public interface IVirtualParadiseService -{ - /// - /// Gets an observable that is triggered when a message is received from the Virtual Paradise world server. - /// - /// - /// An observable that is triggered when a message is received from the Virtual Paradise world server. - /// - IObservable OnMessageReceived { get; } - - /// - /// Sends a message to the Virtual Paradise world server. - /// - /// The Discord message to send. - /// A representing the asynchronous operation. - Task SendMessageAsync(IUserMessage message); -} diff --git a/VPLink/Services/RelayService.cs b/VPLink/Services/RelayService.cs index dd23d7f..791e640 100644 --- a/VPLink/Services/RelayService.cs +++ b/VPLink/Services/RelayService.cs @@ -1,8 +1,5 @@ -using System.Reactive.Linq; -using Discord.WebSocket; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -using VpSharp; using VpSharp.Extensions; namespace VPLink.Services; @@ -10,11 +7,9 @@ namespace VPLink.Services; internal sealed class RelayService : BackgroundService { private readonly ILogger _logger; - private readonly IDiscordService _discordService; private readonly IAvatarService _avatarService; - private readonly IVirtualParadiseService _virtualParadiseService; - private readonly DiscordSocketClient _discordClient; - private readonly VirtualParadiseClient _virtualParadiseClient; + private readonly IDiscordMessageService _discordService; + private readonly IVirtualParadiseMessageService _virtualParadiseService; /// /// Initializes a new instance of the class. @@ -23,21 +18,15 @@ internal sealed class RelayService : BackgroundService /// The Discord service. /// The avatar service. /// The Virtual Paradise service. - /// The Discord client. - /// The Virtual Paradise client. public RelayService(ILogger logger, - IDiscordService discordService, IAvatarService avatarService, - IVirtualParadiseService virtualParadiseService, - DiscordSocketClient discordClient, - VirtualParadiseClient virtualParadiseClient) + IDiscordMessageService discordService, + IVirtualParadiseMessageService virtualParadiseService) { _logger = logger; _discordService = discordService; _avatarService = avatarService; _virtualParadiseService = virtualParadiseService; - _discordClient = discordClient; - _virtualParadiseClient = virtualParadiseClient; } /// @@ -45,16 +34,10 @@ internal sealed class RelayService : BackgroundService { _logger.LogInformation("Establishing relay"); - _discordService.OnMessageReceived - .Where(m => m.Author != _discordClient.CurrentUser) - .SubscribeAsync(_virtualParadiseService.SendMessageAsync); - _avatarService.OnAvatarJoined.SubscribeAsync(_discordService.AnnounceArrival); _avatarService.OnAvatarLeft.SubscribeAsync(_discordService.AnnounceDeparture); - - _virtualParadiseService.OnMessageReceived - .Where(m => m.Author != _virtualParadiseClient.CurrentAvatar) - .SubscribeAsync(_discordService.SendMessageAsync); + _discordService.OnMessageReceived.SubscribeAsync(_virtualParadiseService.SendMessageAsync); + _virtualParadiseService.OnMessageReceived.SubscribeAsync(_discordService.SendMessageAsync); return Task.CompletedTask; } diff --git a/VPLink/Services/VirtualParadiseMessageService.cs b/VPLink/Services/VirtualParadiseMessageService.cs new file mode 100644 index 0000000..3dd4243 --- /dev/null +++ b/VPLink/Services/VirtualParadiseMessageService.cs @@ -0,0 +1,69 @@ +using System.Drawing; +using System.Reactive.Linq; +using System.Reactive.Subjects; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using VPLink.Configuration; +using VPLink.Data; +using VpSharp; +using VpSharp.Entities; +using FontStyle = VpSharp.FontStyle; + +namespace VPLink.Services; + +/// +internal sealed class VirtualParadiseMessageService : BackgroundService, IVirtualParadiseMessageService +{ + private readonly ILogger _logger; + private readonly IConfigurationService _configurationService; + private readonly VirtualParadiseClient _virtualParadiseClient; + private readonly Subject _messageReceived = new(); + + /// + /// Initializes a new instance of the class. + /// + /// The logger. + /// The configuration service. + /// The Virtual Paradise client. + public VirtualParadiseMessageService(ILogger logger, + IConfigurationService configurationService, + VirtualParadiseClient virtualParadiseClient) + { + _logger = logger; + _configurationService = configurationService; + _virtualParadiseClient = virtualParadiseClient; + } + + /// + public IObservable OnMessageReceived => _messageReceived.AsObservable(); + + /// + public Task SendMessageAsync(RelayedMessage message) + { + ChatConfiguration configuration = _configurationService.VirtualParadiseConfiguration.ChatConfiguration; + + Color color = Color.FromArgb((int)configuration.Color); + FontStyle style = configuration.Style; + return _virtualParadiseClient.SendMessageAsync(message.Author, message.Content, style, color); + } + + /// + protected override Task ExecuteAsync(CancellationToken stoppingToken) + { + _virtualParadiseClient.MessageReceived.Subscribe(OnVPMessageReceived); + return Task.CompletedTask; + } + + private void OnVPMessageReceived(VirtualParadiseMessage message) + { + if (message is null) throw new ArgumentNullException(nameof(message)); + if (message.Type != MessageType.ChatMessage) return; + if (message.Author == _virtualParadiseClient.CurrentAvatar) return; + if (message.Author.IsBot && !_configurationService.BotConfiguration.RelayBotMessages) return; + + _logger.LogInformation("Message by {Author}: {Content}", message.Author, message.Content); + + var relayedMessage = new RelayedMessage(message.Author.Name, message.Content); + _messageReceived.OnNext(relayedMessage); + } +} diff --git a/VPLink/Services/VirtualParadiseService.cs b/VPLink/Services/VirtualParadiseService.cs index bc3365f..dc15115 100644 --- a/VPLink/Services/VirtualParadiseService.cs +++ b/VPLink/Services/VirtualParadiseService.cs @@ -1,17 +1,13 @@ -using System.Reactive.Linq; using System.Reactive.Subjects; -using Discord; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using VpSharp; using VpSharp.Entities; -using Color = System.Drawing.Color; using VirtualParadiseConfiguration = VPLink.Configuration.VirtualParadiseConfiguration; namespace VPLink.Services; -/// -internal sealed class VirtualParadiseService : BackgroundService, IVirtualParadiseService +internal sealed class VirtualParadiseService : BackgroundService { private readonly ILogger _logger; private readonly IConfigurationService _configurationService; @@ -33,28 +29,6 @@ internal sealed class VirtualParadiseService : BackgroundService, IVirtualParadi _virtualParadiseClient = virtualParadiseClient; } - /// - public IObservable OnMessageReceived => _messageReceived.AsObservable(); - - /// - public Task SendMessageAsync(IUserMessage message) - { - if (message is null) throw new ArgumentNullException(nameof(message)); - if (string.IsNullOrWhiteSpace(message.Content)) return Task.CompletedTask; - - if (message.Author.IsBot && !_configurationService.BotConfiguration.RelayBotMessages) - { - _logger.LogDebug("Bot messages are disabled, ignoring message"); - return Task.CompletedTask; - } - - _logger.LogInformation("Message by {Author}: {Content}", message.Author, message.Content); - - string displayName = message.Author.GlobalName ?? message.Author.Username; - return _virtualParadiseClient.SendMessageAsync(displayName, message.Content, FontStyle.Bold, - Color.MidnightBlue); - } - /// protected override async Task ExecuteAsync(CancellationToken stoppingToken) {