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)
{