mirror of
https://github.com/oliverbooth/VPLink
synced 2024-11-09 23:45:40 +00:00
feat: replace !who with /who slash command
This commit is contained in:
parent
a1086a834c
commit
bb03b68c17
73
VpBridge/Commands/WhoCommand.cs
Normal file
73
VpBridge/Commands/WhoCommand.cs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
using Cysharp.Text;
|
||||||
|
using Discord;
|
||||||
|
using Discord.Interactions;
|
||||||
|
using VpSharp;
|
||||||
|
using VpSharp.Entities;
|
||||||
|
|
||||||
|
namespace VpBridge.Commands;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a class which implements the <c>who</c> command.
|
||||||
|
/// </summary>
|
||||||
|
internal sealed class WhoCommand : InteractionModuleBase<SocketInteractionContext>
|
||||||
|
{
|
||||||
|
private readonly VirtualParadiseClient _virtualParadiseClient;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="WhoCommand" /> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="virtualParadiseClient">The Virtual Paradise client.</param>
|
||||||
|
public WhoCommand(VirtualParadiseClient virtualParadiseClient)
|
||||||
|
{
|
||||||
|
_virtualParadiseClient = virtualParadiseClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
[SlashCommand("who", "Displays a list of active users in Virtual Paradise.")]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task HandleAsync()
|
||||||
|
{
|
||||||
|
var embed = new EmbedBuilder();
|
||||||
|
embed.WithColor(0x1E88E5);
|
||||||
|
embed.WithAuthor($"🌎 {_virtualParadiseClient.CurrentWorld?.Name}");
|
||||||
|
embed.WithTitle("Active Users");
|
||||||
|
embed.WithTimestamp(DateTimeOffset.UtcNow);
|
||||||
|
|
||||||
|
using Utf8ValueStringBuilder userBuilder = ZString.CreateUtf8StringBuilder();
|
||||||
|
using Utf8ValueStringBuilder botsBuilder = ZString.CreateUtf8StringBuilder();
|
||||||
|
var userCount = 0;
|
||||||
|
var botCount = 0;
|
||||||
|
|
||||||
|
foreach (VirtualParadiseAvatar avatar in _virtualParadiseClient.Avatars)
|
||||||
|
{
|
||||||
|
if (avatar.IsBot)
|
||||||
|
{
|
||||||
|
botsBuilder.AppendLine($"* {avatar.Name} ({avatar.Session})");
|
||||||
|
botCount++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
userBuilder.AppendLine($"* {avatar.Name} ({avatar.Session})");
|
||||||
|
userCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string userTitle = userCount switch
|
||||||
|
{
|
||||||
|
0 => "Users",
|
||||||
|
1 => "1 User",
|
||||||
|
_ => $"{userCount} Users"
|
||||||
|
};
|
||||||
|
|
||||||
|
string botTitle = botCount switch
|
||||||
|
{
|
||||||
|
0 => "Bots",
|
||||||
|
1 => "1 Bot",
|
||||||
|
_ => $"{botCount} Bots"
|
||||||
|
};
|
||||||
|
|
||||||
|
embed.AddField($"👤 {userTitle}", userCount > 0 ? userBuilder.ToString() : "*None*", true);
|
||||||
|
embed.AddField($"🤖 {botTitle}", botCount > 0 ? botsBuilder.ToString() : "*None*", true);
|
||||||
|
|
||||||
|
await RespondAsync(embed: embed.Build());
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
|
using Discord.Interactions;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
@ -24,10 +25,13 @@ builder.Logging.ClearProviders();
|
|||||||
builder.Logging.AddSerilog();
|
builder.Logging.AddSerilog();
|
||||||
|
|
||||||
builder.Services.AddSingleton<VirtualParadiseClient>();
|
builder.Services.AddSingleton<VirtualParadiseClient>();
|
||||||
builder.Services.AddSingleton(new DiscordSocketClient(new DiscordSocketConfig
|
|
||||||
|
builder.Services.AddSingleton<InteractionService>();
|
||||||
|
builder.Services.AddSingleton<DiscordSocketClient>();
|
||||||
|
builder.Services.AddSingleton(new DiscordSocketConfig
|
||||||
{
|
{
|
||||||
GatewayIntents = GatewayIntents.AllUnprivileged | GatewayIntents.MessageContent
|
GatewayIntents = GatewayIntents.AllUnprivileged | GatewayIntents.MessageContent
|
||||||
}));
|
});
|
||||||
|
|
||||||
builder.Services.AddHostedSingleton<IVirtualParadiseService, VirtualParadiseService>();
|
builder.Services.AddHostedSingleton<IVirtualParadiseService, VirtualParadiseService>();
|
||||||
builder.Services.AddHostedSingleton<IDiscordService, DiscordService>();
|
builder.Services.AddHostedSingleton<IDiscordService, DiscordService>();
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
using System.Reactive.Linq;
|
using System.Reactive.Linq;
|
||||||
using System.Reactive.Subjects;
|
using System.Reactive.Subjects;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using Discord;
|
using Discord;
|
||||||
|
using Discord.Interactions;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using VpBridge.Commands;
|
||||||
using VpSharp;
|
using VpSharp;
|
||||||
using VpSharp.Entities;
|
using VpSharp.Entities;
|
||||||
|
|
||||||
@ -19,7 +21,9 @@ internal sealed partial class DiscordService : BackgroundService, IDiscordServic
|
|||||||
private static readonly Regex EscapeRegex = GetEscapeRegex();
|
private static readonly Regex EscapeRegex = GetEscapeRegex();
|
||||||
|
|
||||||
private readonly ILogger<DiscordService> _logger;
|
private readonly ILogger<DiscordService> _logger;
|
||||||
|
private readonly IServiceProvider _serviceProvider;
|
||||||
private readonly IConfiguration _configuration;
|
private readonly IConfiguration _configuration;
|
||||||
|
private readonly InteractionService _interactionService;
|
||||||
private readonly DiscordSocketClient _discordClient;
|
private readonly DiscordSocketClient _discordClient;
|
||||||
private readonly VirtualParadiseClient _virtualParadiseClient;
|
private readonly VirtualParadiseClient _virtualParadiseClient;
|
||||||
private readonly Subject<IUserMessage> _messageReceived = new();
|
private readonly Subject<IUserMessage> _messageReceived = new();
|
||||||
@ -28,16 +32,22 @@ internal sealed partial class DiscordService : BackgroundService, IDiscordServic
|
|||||||
/// Initializes a new instance of the <see cref="DiscordService" /> class.
|
/// Initializes a new instance of the <see cref="DiscordService" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="logger">The logger.</param>
|
/// <param name="logger">The logger.</param>
|
||||||
|
/// <param name="serviceProvider">The service provider.</param>
|
||||||
/// <param name="configuration">The configuration.</param>
|
/// <param name="configuration">The configuration.</param>
|
||||||
|
/// <param name="interactionService">The interaction service.</param>
|
||||||
/// <param name="discordClient">The Discord client.</param>
|
/// <param name="discordClient">The Discord client.</param>
|
||||||
/// <param name="virtualParadiseClient">The Virtual Paradise client.</param>
|
/// <param name="virtualParadiseClient">The Virtual Paradise client.</param>
|
||||||
public DiscordService(ILogger<DiscordService> logger,
|
public DiscordService(ILogger<DiscordService> logger,
|
||||||
|
IServiceProvider serviceProvider,
|
||||||
IConfiguration configuration,
|
IConfiguration configuration,
|
||||||
|
InteractionService interactionService,
|
||||||
DiscordSocketClient discordClient,
|
DiscordSocketClient discordClient,
|
||||||
VirtualParadiseClient virtualParadiseClient)
|
VirtualParadiseClient virtualParadiseClient)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
_serviceProvider = serviceProvider;
|
||||||
_configuration = configuration;
|
_configuration = configuration;
|
||||||
|
_interactionService = interactionService;
|
||||||
_discordClient = discordClient;
|
_discordClient = discordClient;
|
||||||
_virtualParadiseClient = virtualParadiseClient;
|
_virtualParadiseClient = virtualParadiseClient;
|
||||||
}
|
}
|
||||||
@ -49,40 +59,13 @@ internal sealed partial class DiscordService : BackgroundService, IDiscordServic
|
|||||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Establishing relay");
|
_logger.LogInformation("Establishing relay");
|
||||||
_discordClient.MessageReceived += arg =>
|
|
||||||
{
|
|
||||||
if (arg is not IUserMessage message)
|
|
||||||
return Task.CompletedTask;
|
|
||||||
|
|
||||||
if (message.Channel.Id != _configuration.GetSection("Discord:ChannelId").Get<ulong>())
|
_logger.LogInformation("Adding command modules");
|
||||||
return Task.CompletedTask;
|
await _interactionService.AddModuleAsync<WhoCommand>(_serviceProvider).ConfigureAwait(false);
|
||||||
|
|
||||||
if (message.Content.Equals("!who"))
|
_discordClient.Ready += OnReady;
|
||||||
{
|
_discordClient.InteractionCreated += OnInteractionCreated;
|
||||||
VirtualParadiseAvatar[] avatars = _virtualParadiseClient.Avatars.Where(a => !a.IsBot).ToArray();
|
_discordClient.MessageReceived += OnDiscordMessageReceived;
|
||||||
int count = avatars.Length;
|
|
||||||
|
|
||||||
if (count > 0)
|
|
||||||
{
|
|
||||||
var builder = new StringBuilder();
|
|
||||||
builder.AppendLine("**Users In World 🌎**");
|
|
||||||
foreach (VirtualParadiseAvatar avatar in _virtualParadiseClient.Avatars)
|
|
||||||
{
|
|
||||||
if (avatar.IsBot || avatar == _virtualParadiseClient.CurrentAvatar)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
builder.AppendLine($"• {avatar.Name}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return message.ReplyAsync(builder.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
return message.ReplyAsync("**No Users In World 🚫**");
|
|
||||||
}
|
|
||||||
|
|
||||||
_messageReceived.OnNext(message);
|
|
||||||
return Task.CompletedTask;
|
|
||||||
};
|
|
||||||
|
|
||||||
string token = _configuration.GetSection("Discord:Token").Value ??
|
string token = _configuration.GetSection("Discord:Token").Value ??
|
||||||
throw new InvalidOperationException("Token is not set.");
|
throw new InvalidOperationException("Token is not set.");
|
||||||
@ -92,6 +75,45 @@ internal sealed partial class DiscordService : BackgroundService, IDiscordServic
|
|||||||
await _discordClient.StartAsync();
|
await _discordClient.StartAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Task OnDiscordMessageReceived(SocketMessage arg)
|
||||||
|
{
|
||||||
|
if (arg is not IUserMessage message)
|
||||||
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
if (message.Channel.Id != _configuration.GetSection("Discord:ChannelId").Get<ulong>())
|
||||||
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
_messageReceived.OnNext(message);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnInteractionCreated(SocketInteraction interaction)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var context = new SocketInteractionContext(_discordClient, interaction);
|
||||||
|
IResult result = await _interactionService.ExecuteCommandAsync(context, _serviceProvider);
|
||||||
|
|
||||||
|
if (!result.IsSuccess)
|
||||||
|
switch (result.Error)
|
||||||
|
{
|
||||||
|
case InteractionCommandError.UnmetPrecondition:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
if (interaction.Type is InteractionType.ApplicationCommand)
|
||||||
|
await interaction.GetOriginalResponseAsync().ContinueWith(async msg => await msg.Result.DeleteAsync());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task OnReady()
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Discord client ready");
|
||||||
|
return _interactionService.RegisterCommandsGloballyAsync();
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task SendMessageAsync(VirtualParadiseMessage message)
|
public Task SendMessageAsync(VirtualParadiseMessage message)
|
||||||
{
|
{
|
||||||
|
@ -52,6 +52,7 @@
|
|||||||
<PackageReference Include="VpSharp" Version="0.1.0-nightly.43"/>
|
<PackageReference Include="VpSharp" Version="0.1.0-nightly.43"/>
|
||||||
<PackageReference Include="X10D" Version="3.3.1"/>
|
<PackageReference Include="X10D" Version="3.3.1"/>
|
||||||
<PackageReference Include="X10D.Hosting" Version="3.3.1"/>
|
<PackageReference Include="X10D.Hosting" Version="3.3.1"/>
|
||||||
|
<PackageReference Include="ZString" Version="2.5.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
Loading…
Reference in New Issue
Block a user