Skip to content

Commit

Permalink
[Bot] Upgrade MemberConverter
Browse files Browse the repository at this point in the history
It now accepts alias and discord user mention
  • Loading branch information
Pythonic-Rainbow committed Sep 7, 2024
1 parent c362d7f commit 3dacdb6
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 23 deletions.
7 changes: 6 additions & 1 deletion .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
1. [Prerequisites](#prerequisites)
2. [Structure Overview](#overview)
3. [Coding Guidelines](#guidelines)
4. [Dev Notes](#devnotes)

<a name="prerequisites"></a>
# Prerequisites
Expand Down Expand Up @@ -93,4 +94,8 @@ private List<uint> FindFactors(uint number) { }
private async Task ReportToCIA() { }
public uint ComputeFactorial(uint number) { }
public async Task ProcessPayment() { }
```
```

<a name="devnotes"></a>
# Dev Notes
1. Use `Coc.GetMember` or `Coc.TryGetMember` if you want to check whether a player tag is currently in the clan.
2 changes: 2 additions & 0 deletions Bot/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Hyperstellar.db
Hyperstellar
hyperstellar-token.txt

.idea

# User-specific files
*.rsuser
*.suo
Expand Down
14 changes: 7 additions & 7 deletions Bot/Discord/Cmds.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace Hyperstellar.Discord;
public class Cmds : InteractionModuleBase
{
[RequireOwner]
[SlashCommand("shutdown", "Shuts down the bot")]
[SlashCommand("shutdown", "[Owner] Shuts down the bot")]
public async Task ShutdownAsync(bool commit = true)
{
await RespondAsync("Ok", ephemeral: true);
Expand All @@ -23,15 +23,15 @@ public async Task ShutdownAsync(bool commit = true)
}

[RequireOwner]
[SlashCommand("commit", "Commits db")]
[SlashCommand("commit", "[Owner] Commits db")]
public async Task CommitAsync()
{
Db.Commit();
await RespondAsync("Committed", ephemeral: true);
}

[RequireOwner]
[SlashCommand("admin", "Makes the Discord user an admin")] // Maybe rename to addadmin
[SlashCommand("admin", "[Owner] Makes the Discord user an admin")] // Maybe rename to addadmin
public async Task AdminAsync(SocketGuildUser user)
{
bool success = Db.AddAdmin(user.Id);
Expand All @@ -46,7 +46,7 @@ public async Task AdminAsync(SocketGuildUser user)
}

[RequireAdmin]
[SlashCommand("alt", "Links an alt to a main")]
[SlashCommand("alt", "[Admin] Links an alt to a main")]
public async Task AltAsync(Member alt, Member main)
{
if (alt.CocId == main.CocId)
Expand All @@ -72,8 +72,8 @@ public async Task AltAsync(Member alt, Member main)
}

[RequireAdmin]
[SlashCommand("link", "[Admin] Links a Discord account to a Main")]
public async Task LinkAsync(Member coc, IGuildUser discord)
[SlashCommand("discord", "[Admin] Links a Discord account to a Main")]
public async Task DiscordAsync(Member coc, IGuildUser discord)
{
Main? main = coc.TryToMain();
if (main == null)
Expand Down Expand Up @@ -131,7 +131,7 @@ public async Task InfoAsync(Member clanMember)
}

[RequireAdmin]
[SlashCommand("alias", "Sets an alias for a Coc member")]
[SlashCommand("alias", "[Admin] Sets an alias for a Coc member")]
public async Task AliasAsync(string alias, Member member)
{
bool success = Db.AddAlias(alias, member);
Expand Down
83 changes: 69 additions & 14 deletions Bot/Discord/MemberConverter.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using Discord;
using System.Text.RegularExpressions;
using ClashOfClans.Models;
using Discord;
using Discord.Interactions;
using Hyperstellar.Clash;
using Hyperstellar.Sql;
using Type = System.Type;

namespace Hyperstellar.Discord;

Expand All @@ -12,22 +15,74 @@ internal sealed class MemberConverter : TypeConverter
public override Task<TypeConverterResult> ReadAsync(IInteractionContext context, IApplicationCommandInteractionDataOption option, IServiceProvider services)
{
string input = (string)option.Value;
// Console.WriteLine($"\"{input}\"");
Member? member = Db.GetMember(input);
if (member == null)

// Check whether input matches a Discord user mention
Match dUserMentionMatch = Regexes.DiscordUserMention().Match(input);
if (dUserMentionMatch.Success)
{
string? id = Coc.GetMemberId(input);
if (id != null)
// Extract uid from mention
ReadOnlySpan<char> captured = dUserMentionMatch.ValueSpan; // <@123>
ulong uid = Convert.ToUInt64(captured[2..^1].ToString()); // 123

// Checks whether this Discord user is linked to a main
Main? main = Db.GetMainByDiscord(uid);
if (main == null)
{
member = Db.GetMember(id);
return TypeConverters.Error("This Discord user isn't linked to any CoC account.");
}

// REMOVE THIS AFTER DB REDESIGN - SKIPPING THE CHECK BELOW BECUZ FOR NOW, IN DB = MUST BE IN CLAN
Member sqlMember = Db.GetMember(main.MainId)!;
return TypeConverters.Success(sqlMember);

/*
// Check whether the main is still in the clan
string cocId = main.MainId;
ClanMember? member = Coc.TryGetMember(cocId);
return member == null
? TypeConverters.Error("The main of this Discord user isn't in the clan.")
: Task.FromResult(TypeConverterResult.FromSuccess(member));
*/
}

// Check whether input matches an alias
CocMemberAlias? dbAlias = Db.TryGetAlias(input);
if (dbAlias != null)
{
// Check whether the coc account of the alias is still in the clan
string aliasCocId = dbAlias.CocId;
ClanMember? aliasClanMember = Coc.TryGetMember(aliasCocId);
Member sqlMember = Db.GetMember(aliasCocId)!;

return aliasClanMember == null
? TypeConverters.Error("The player of this alias isn't in the clan.")
: TypeConverters.Success(sqlMember);
}
return member == null
? Task.FromResult(TypeConverterResult.FromError(
InteractionCommandError.ConvertFailed,
@$"Invalid `{option.Name}`. To specify a clan member:
* Enter his name (非速本主義Arkyo), alias (Arkyo) or ID with # (#28QL0CJV2)
* Mention his Discord (@Dim) __which will refer to his main__"))
: Task.FromResult(TypeConverterResult.FromSuccess(member));

// Check whether input is the name of a clan member
string? cocId = Coc.GetMemberId(input);
if (cocId != null)
{
Member sqlMember = Db.GetMember(cocId)!;
return TypeConverters.Success(sqlMember);
}

// Check whether input is the tag of a clan member
ClanMember? member = Coc.TryGetMember(input);
if (member != null)
{
Member sqlMember = Db.GetMember(input)!;
return TypeConverters.Success(sqlMember);
}

return TypeConverters.Error(
$"""
Invalid `{option.Name}`. To specify a clan member:
* Enter his name (非速本主義Arkyo), alias (arkyo) or ID with # (#28QL0CJV2)
* Mention his Discord (@Dim) __which will refer to his main__
""");
}


}
13 changes: 13 additions & 0 deletions Bot/Discord/TypeConverters.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Discord.Interactions;

namespace Hyperstellar.Discord;

// Util class for other type converters in this package
internal static class TypeConverters
{
// Shorthand for generating an error response
internal static Task<TypeConverterResult> Error(string reason) => Task.FromResult(TypeConverterResult.FromError(InteractionCommandError.ConvertFailed, reason));

// Shorthand for generating a successful conversion
internal static Task<TypeConverterResult> Success(object value) => Task.FromResult(TypeConverterResult.FromSuccess(value));
}
9 changes: 9 additions & 0 deletions Bot/Regexes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.Text.RegularExpressions;

namespace Hyperstellar;

internal static partial class Regexes
{
[GeneratedRegex("^<@\\d{1,20}>$")]
internal static partial Regex DiscordUserMention();
}
10 changes: 9 additions & 1 deletion Bot/Sql/Db.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ internal static bool AddMembers(string[] members)

internal static Main? GetMain(string id) => s_db.Table<Main>().FirstOrDefault(d => d.MainId == id);

internal static Main? GetMainByDiscord(ulong uid) => s_db.Table<Main>().FirstOrDefault(m => m.Discord == uid);

internal static IEnumerable<Main> GetDonations() => s_db.Table<Main>();

internal static bool UpdateMain(Main main) => s_db.Update(main) == 1;
Expand All @@ -41,11 +43,17 @@ internal static bool AddAdmin(ulong id)
return count == 1;
}

internal static CocMemberAlias? TryGetAlias(string alias)
{
alias = alias.ToLower();
return s_db.Table<CocMemberAlias>().FirstOrDefault(a => a.Alias == alias);
}

internal static IEnumerable<CocMemberAlias> GetAliases() => s_db.Table<CocMemberAlias>();

internal static bool AddAlias(string alias, Member member)
{
CocMemberAlias cocMemberAlias = new(alias, member.CocId);
CocMemberAlias cocMemberAlias = new(alias.ToLower(), member.CocId);
int count = s_db.Insert(cocMemberAlias);
return count == 1;
}
Expand Down

0 comments on commit 3dacdb6

Please sign in to comment.