Add remaining project files
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
using DeluxeBackend.Models;
|
||||
using DeluxeBackend.Services;
|
||||
using Discord;
|
||||
using Discord.Interactions;
|
||||
using Discord.WebSocket;
|
||||
using System.Security.Cryptography;
|
||||
using static DeluxeBackend.Enums;
|
||||
|
||||
namespace DeluxeBackend.Discord.Commands
|
||||
{
|
||||
public class LinkCode : InteractionModuleBase<SocketInteractionContext>
|
||||
{
|
||||
private readonly ILiteDbService _db;
|
||||
private readonly INotificationService _ws;
|
||||
|
||||
private static readonly HashSet<ulong> GameRoles = new()
|
||||
{
|
||||
1502718783700078767, 1495587327593021490, 1495580320525844581,
|
||||
1495580213529280563, 1495909230643908729, 1500323661251477635,
|
||||
1495580027453046804, 1501711512996282369, 1495580006712213674,
|
||||
1495580717134905457
|
||||
};
|
||||
|
||||
public LinkCode(ILiteDbService db, INotificationService ws)
|
||||
{
|
||||
_db = db;
|
||||
_ws = ws;
|
||||
}
|
||||
|
||||
[SlashCommand("ping", "Check bot latency")]
|
||||
public async Task Ping() => await RespondAsync($"{Context.Client.Latency}ms");
|
||||
|
||||
[SlashCommand("link", "Generate a unique code to link your Deluxe account")]
|
||||
public async Task LinkAccount()
|
||||
{
|
||||
await DeferAsync(ephemeral: true);
|
||||
|
||||
if (Context.User is not SocketGuildUser guildUser)
|
||||
{
|
||||
await FollowupAsync("This command must be used within a server.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!guildUser.Roles.Any(r => GameRoles.Contains(r.Id)))
|
||||
{
|
||||
await FollowupAsync("You do not have the required permissions.", ephemeral: true);
|
||||
return;
|
||||
}
|
||||
Account? account = _db.Accounts.FindOne(x => x.DiscordId == guildUser.Id);
|
||||
if (account != null)
|
||||
{
|
||||
var linkedEmbed = new EmbedBuilder()
|
||||
.WithDescription("Your Discord profile is **already linked** to a Deluxe account.")
|
||||
.WithColor(Color.LighterGrey)
|
||||
.Build();
|
||||
|
||||
await FollowupAsync(embed: linkedEmbed, ephemeral: true);
|
||||
return;
|
||||
}
|
||||
|
||||
var pendingLink = _db.ActionLinks.FindOne(x =>
|
||||
x.ExtraData!.DiscordUserId == guildUser.Id &&
|
||||
x.ExpiresAt > DateTime.UtcNow &&
|
||||
x.Uses < x.MaxUses);
|
||||
|
||||
if (pendingLink != null)
|
||||
{
|
||||
long unixTime = ((DateTimeOffset)pendingLink.ExpiresAt).ToUnixTimeSeconds();
|
||||
var existingEmbed = new EmbedBuilder()
|
||||
.WithDescription($"You already have an active code:\n\n**`{pendingLink.Code}`**\n\nIt expires **<t:{unixTime}:R>** (<t:{unixTime}:f>).")
|
||||
.WithColor(Color.LighterGrey)
|
||||
.Build();
|
||||
|
||||
await FollowupAsync(embed: existingEmbed, ephemeral: true);
|
||||
return;
|
||||
}
|
||||
|
||||
string code;
|
||||
while (true)
|
||||
{
|
||||
code = GenerateSecureCode(8);
|
||||
var existing = _db.ActionLinks.FindOne(x => x.Code == code);
|
||||
|
||||
if (existing == null) break;
|
||||
|
||||
if (!existing.IsValid)
|
||||
{
|
||||
_db.ActionLinks.Delete(existing.Id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DateTime expiry = DateTime.UtcNow.AddMinutes(10);
|
||||
long expiryUnix = ((DateTimeOffset)expiry).ToUnixTimeSeconds();
|
||||
|
||||
var actionLink = new ActionLink
|
||||
{
|
||||
Code = code,
|
||||
CreatorPlayerId = 1,
|
||||
Description = $"Discord Link: {guildUser.Username}",
|
||||
ExpiresAt = expiry,
|
||||
Type = ActionLinkType.DiscordLink,
|
||||
ExtraData = new ActionLinkExtraData { DiscordUserId = guildUser.Id },
|
||||
MaxUses = 1
|
||||
};
|
||||
|
||||
_db.ActionLinks.Insert(actionLink);
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
.WithDescription($"Use the code below to link your account:\n\n**`{code}`**\n\nExpires **<t:{expiryUnix}:R>**.")
|
||||
.WithColor(Color.LighterGrey)
|
||||
.Build();
|
||||
|
||||
await FollowupAsync(embed: embed, ephemeral: true);
|
||||
}
|
||||
|
||||
private static string GenerateSecureCode(int length)
|
||||
{
|
||||
const string chars = "abcdefghijklmnopqrstuvwxyz0123456789";
|
||||
return string.Create(length, chars, (buffer, symbols) =>
|
||||
{
|
||||
for (int i = 0; i < buffer.Length; i++)
|
||||
{
|
||||
buffer[i] = symbols[RandomNumberGenerator.GetInt32(symbols.Length)];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user