Port rank for slash commands
This commit is contained in:
parent
772557978b
commit
e20faa43e1
5 changed files with 225 additions and 86 deletions
|
@ -1,7 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Geekbot.Core;
|
using Geekbot.Core;
|
||||||
|
@ -9,10 +6,8 @@ using Geekbot.Core.CommandPreconditions;
|
||||||
using Geekbot.Core.Converters;
|
using Geekbot.Core.Converters;
|
||||||
using Geekbot.Core.Database;
|
using Geekbot.Core.Database;
|
||||||
using Geekbot.Core.ErrorHandling;
|
using Geekbot.Core.ErrorHandling;
|
||||||
using Geekbot.Core.Extensions;
|
|
||||||
using Geekbot.Core.GuildSettingsManager;
|
using Geekbot.Core.GuildSettingsManager;
|
||||||
using Geekbot.Core.Highscores;
|
using Geekbot.Core.Highscores;
|
||||||
using Localization = Geekbot.Core.Localization;
|
|
||||||
|
|
||||||
namespace Geekbot.Bot.Commands.User.Ranking
|
namespace Geekbot.Bot.Commands.User.Ranking
|
||||||
{
|
{
|
||||||
|
@ -40,85 +35,9 @@ namespace Geekbot.Bot.Commands.User.Ranking
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
HighscoreTypes type;
|
var res = new Geekbot.Commands.Rank(_database, _emojiConverter, _highscoreManager)
|
||||||
try
|
.Run(typeUnformated, amount, season, Context.Guild.Id, Context.Guild.Name);
|
||||||
{
|
await ReplyAsync(res);
|
||||||
type = Enum.Parse<HighscoreTypes>(typeUnformated, true);
|
|
||||||
if (!Enum.IsDefined(typeof(HighscoreTypes), type)) throw new Exception();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
await ReplyAsync(Localization.Rank.InvalidType);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var replyBuilder = new StringBuilder();
|
|
||||||
if (amount > 20)
|
|
||||||
{
|
|
||||||
await ReplyAsync(Localization.Rank.LimitingTo20Warning);
|
|
||||||
amount = 20;
|
|
||||||
}
|
|
||||||
|
|
||||||
var guildId = Context.Guild.Id;
|
|
||||||
Dictionary<HighscoreUserDto, int> highscoreUsers;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
highscoreUsers = _highscoreManager.GetHighscoresWithUserData(type, guildId, amount, season);
|
|
||||||
}
|
|
||||||
catch (HighscoreListEmptyException)
|
|
||||||
{
|
|
||||||
await ReplyAsync(string.Format(Localization.Rank.NoTypeFoundForServer, type));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var guildMessages = 0;
|
|
||||||
if (type == HighscoreTypes.messages)
|
|
||||||
{
|
|
||||||
guildMessages = _database.Messages
|
|
||||||
.Where(e => e.GuildId.Equals(Context.Guild.Id.AsLong()))
|
|
||||||
.Select(e => e.MessageCount)
|
|
||||||
.Sum();
|
|
||||||
}
|
|
||||||
|
|
||||||
var failedToRetrieveUser = highscoreUsers.Any(e => string.IsNullOrEmpty(e.Key.Username));
|
|
||||||
|
|
||||||
if (failedToRetrieveUser) replyBuilder.AppendLine(Localization.Rank.FailedToResolveAllUsernames).AppendLine();
|
|
||||||
|
|
||||||
if (type == HighscoreTypes.seasons)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(season))
|
|
||||||
{
|
|
||||||
season = SeasonsUtils.GetCurrentSeason();
|
|
||||||
}
|
|
||||||
replyBuilder.AppendLine(string.Format(Localization.Rank.HighscoresFor, $"{type.ToString().CapitalizeFirst()} ({season})", Context.Guild.Name));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
replyBuilder.AppendLine(string.Format(Localization.Rank.HighscoresFor, type.ToString().CapitalizeFirst(), Context.Guild.Name));
|
|
||||||
}
|
|
||||||
|
|
||||||
var highscorePlace = 1;
|
|
||||||
foreach (var (user, value) in highscoreUsers)
|
|
||||||
{
|
|
||||||
replyBuilder.Append(highscorePlace < 11
|
|
||||||
? $"{_emojiConverter.NumberToEmoji(highscorePlace)} "
|
|
||||||
: $"`{highscorePlace}.` ");
|
|
||||||
|
|
||||||
replyBuilder.Append(user.Username != null
|
|
||||||
? $"**{user.Username}#{user.Discriminator}**"
|
|
||||||
: $"**{user.Id}**");
|
|
||||||
|
|
||||||
replyBuilder.Append(type switch
|
|
||||||
{
|
|
||||||
HighscoreTypes.messages => $" - {value} {HighscoreTypes.messages} - {Math.Round((double) (100 * value) / guildMessages, 2)}%\n",
|
|
||||||
HighscoreTypes.seasons => $" - {value} {HighscoreTypes.messages}\n",
|
|
||||||
_ => $" - {value} {type}\n"
|
|
||||||
});
|
|
||||||
|
|
||||||
highscorePlace++;
|
|
||||||
}
|
|
||||||
|
|
||||||
await ReplyAsync(replyBuilder.ToString());
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
107
src/Commands/Rank.cs
Normal file
107
src/Commands/Rank.cs
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Geekbot.Core.Converters;
|
||||||
|
using Geekbot.Core.Database;
|
||||||
|
using Geekbot.Core.Extensions;
|
||||||
|
using Geekbot.Core.Highscores;
|
||||||
|
using Localization = Geekbot.Core.Localization;
|
||||||
|
|
||||||
|
namespace Geekbot.Commands
|
||||||
|
{
|
||||||
|
public class Rank
|
||||||
|
{
|
||||||
|
private readonly DatabaseContext _database;
|
||||||
|
private readonly IEmojiConverter _emojiConverter;
|
||||||
|
private readonly IHighscoreManager _highscoreManager;
|
||||||
|
|
||||||
|
public Rank(DatabaseContext database, IEmojiConverter emojiConverter, IHighscoreManager highscoreManager)
|
||||||
|
{
|
||||||
|
_database = database;
|
||||||
|
_emojiConverter = emojiConverter;
|
||||||
|
_highscoreManager = highscoreManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Run(string typeUnformated, int amount, string season, ulong guildId, string guildName)
|
||||||
|
{
|
||||||
|
HighscoreTypes type;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
type = Enum.Parse<HighscoreTypes>(typeUnformated, true);
|
||||||
|
if (!Enum.IsDefined(typeof(HighscoreTypes), type)) throw new Exception();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return Localization.Rank.InvalidType;
|
||||||
|
}
|
||||||
|
|
||||||
|
var replyBuilder = new StringBuilder();
|
||||||
|
if (amount > 20)
|
||||||
|
{
|
||||||
|
replyBuilder.AppendLine(Localization.Rank.LimitingTo20Warning);
|
||||||
|
amount = 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary<HighscoreUserDto, int> highscoreUsers;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
highscoreUsers = _highscoreManager.GetHighscoresWithUserData(type, guildId, amount, season);
|
||||||
|
}
|
||||||
|
catch (HighscoreListEmptyException)
|
||||||
|
{
|
||||||
|
return string.Format(Core.Localization.Rank.NoTypeFoundForServer, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
var guildMessages = 0;
|
||||||
|
if (type == HighscoreTypes.messages)
|
||||||
|
{
|
||||||
|
guildMessages = _database.Messages
|
||||||
|
.Where(e => e.GuildId.Equals(guildId.AsLong()))
|
||||||
|
.Select(e => e.MessageCount)
|
||||||
|
.Sum();
|
||||||
|
}
|
||||||
|
|
||||||
|
var failedToRetrieveUser = highscoreUsers.Any(e => string.IsNullOrEmpty(e.Key.Username));
|
||||||
|
|
||||||
|
if (failedToRetrieveUser) replyBuilder.AppendLine(Core.Localization.Rank.FailedToResolveAllUsernames).AppendLine();
|
||||||
|
|
||||||
|
if (type == HighscoreTypes.seasons)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(season))
|
||||||
|
{
|
||||||
|
season = SeasonsUtils.GetCurrentSeason();
|
||||||
|
}
|
||||||
|
|
||||||
|
replyBuilder.AppendLine(string.Format(Core.Localization.Rank.HighscoresFor, $"{type.ToString().CapitalizeFirst()} ({season})", guildName));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
replyBuilder.AppendLine(string.Format(Core.Localization.Rank.HighscoresFor, type.ToString().CapitalizeFirst(), guildName));
|
||||||
|
}
|
||||||
|
|
||||||
|
var highscorePlace = 1;
|
||||||
|
foreach (var (user, value) in highscoreUsers)
|
||||||
|
{
|
||||||
|
replyBuilder.Append(highscorePlace < 11
|
||||||
|
? $"{_emojiConverter.NumberToEmoji(highscorePlace)} "
|
||||||
|
: $"`{highscorePlace}.` ");
|
||||||
|
|
||||||
|
replyBuilder.Append(user.Username != null
|
||||||
|
? $"**{user.Username}#{user.Discriminator}**"
|
||||||
|
: $"**{user.Id}**");
|
||||||
|
|
||||||
|
replyBuilder.Append(type switch
|
||||||
|
{
|
||||||
|
HighscoreTypes.messages => $" - {value} {HighscoreTypes.messages} - {Math.Round((double)(100 * value) / guildMessages, 2)}%\n",
|
||||||
|
HighscoreTypes.seasons => $" - {value} {HighscoreTypes.messages}\n",
|
||||||
|
_ => $" - {value} {type}\n"
|
||||||
|
});
|
||||||
|
|
||||||
|
highscorePlace++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return replyBuilder.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,5 +13,11 @@ namespace Geekbot.Core.Interactions.ApplicationCommand
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonPropertyName("name")]
|
[JsonPropertyName("name")]
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// value of the choice, up to 100 characters if string
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("value")]
|
||||||
|
public string Value { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
102
src/Web/Commands/Rank.cs
Normal file
102
src/Web/Commands/Rank.cs
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Geekbot.Core.Converters;
|
||||||
|
using Geekbot.Core.Database;
|
||||||
|
using Geekbot.Core.Highscores;
|
||||||
|
using Geekbot.Core.Interactions;
|
||||||
|
using Geekbot.Core.Interactions.ApplicationCommand;
|
||||||
|
using Geekbot.Core.Interactions.Request;
|
||||||
|
using Geekbot.Core.Interactions.Response;
|
||||||
|
|
||||||
|
namespace Geekbot.Web.Commands
|
||||||
|
{
|
||||||
|
public class Rank : InteractionBase
|
||||||
|
{
|
||||||
|
private readonly DatabaseContext _database;
|
||||||
|
private readonly IEmojiConverter _emojiConverter;
|
||||||
|
private readonly IHighscoreManager _highscoreManager;
|
||||||
|
|
||||||
|
public Rank(DatabaseContext database, IEmojiConverter emojiConverter, IHighscoreManager highscoreManager)
|
||||||
|
{
|
||||||
|
_database = database;
|
||||||
|
_emojiConverter = emojiConverter;
|
||||||
|
_highscoreManager = highscoreManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum Options
|
||||||
|
{
|
||||||
|
Counter,
|
||||||
|
Amount,
|
||||||
|
Season
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Command GetCommandInfo()
|
||||||
|
{
|
||||||
|
return new Command()
|
||||||
|
{
|
||||||
|
Name = "rank",
|
||||||
|
Description = "BETA: Highscores for various counters",
|
||||||
|
Type = CommandType.ChatInput,
|
||||||
|
Options = new List<Option>()
|
||||||
|
{
|
||||||
|
new ()
|
||||||
|
{
|
||||||
|
Name = Options.Counter.ToString().ToLower(),
|
||||||
|
Description = "The counter to show",
|
||||||
|
Required = true,
|
||||||
|
Type = OptionType.String,
|
||||||
|
Choices = Enumerable.Select(
|
||||||
|
Enum.GetNames<HighscoreTypes>(),
|
||||||
|
highscoreType => new OptionChoice()
|
||||||
|
{
|
||||||
|
Name = highscoreType,
|
||||||
|
Value = highscoreType
|
||||||
|
}).ToList()
|
||||||
|
},
|
||||||
|
new ()
|
||||||
|
{
|
||||||
|
Name = Options.Amount.ToString().ToLower(),
|
||||||
|
Description = "Amount of positions to show in the list",
|
||||||
|
Required = false,
|
||||||
|
Type = OptionType.Integer
|
||||||
|
},
|
||||||
|
new ()
|
||||||
|
{
|
||||||
|
Name = Options.Season.ToString().ToLower(),
|
||||||
|
Description = "Select the season, only applies for the seasons counter",
|
||||||
|
Required = false,
|
||||||
|
Type = OptionType.String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task<InteractionResponse> Exec(Interaction interaction)
|
||||||
|
{
|
||||||
|
var counterTypeOption = interaction.Data.Options.Find(o => o.Name == Options.Counter.ToString().ToLower());
|
||||||
|
var amountOption = interaction.Data.Options.Find(o => o.Name == Options.Amount.ToString().ToLower());
|
||||||
|
var seasonOption = interaction.Data.Options.Find(o => o.Name == Options.Season.ToString().ToLower());
|
||||||
|
|
||||||
|
var res = new Geekbot.Commands.Rank(_database, _emojiConverter, _highscoreManager)
|
||||||
|
.Run(
|
||||||
|
counterTypeOption?.Value.GetString() ?? HighscoreTypes.messages.ToString(),
|
||||||
|
amountOption?.Value.GetInt32() ?? 10,
|
||||||
|
seasonOption?.Value.GetString() ?? string.Empty,
|
||||||
|
ulong.Parse(interaction.GuildId),
|
||||||
|
"...");
|
||||||
|
|
||||||
|
var interactionResponse = new InteractionResponse()
|
||||||
|
{
|
||||||
|
Type = InteractionResponseType.ChannelMessageWithSource,
|
||||||
|
Data = new InteractionResponseData()
|
||||||
|
{
|
||||||
|
Content = res
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return Task.FromResult(interactionResponse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,6 +22,11 @@ namespace Geekbot.Web.Commands
|
||||||
_randomNumberGenerator = randomNumberGenerator;
|
_randomNumberGenerator = randomNumberGenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private enum Options
|
||||||
|
{
|
||||||
|
Guess
|
||||||
|
}
|
||||||
|
|
||||||
public override Command GetCommandInfo()
|
public override Command GetCommandInfo()
|
||||||
{
|
{
|
||||||
return new Command()
|
return new Command()
|
||||||
|
@ -33,7 +38,7 @@ namespace Geekbot.Web.Commands
|
||||||
{
|
{
|
||||||
new Option()
|
new Option()
|
||||||
{
|
{
|
||||||
Name = "guess",
|
Name = Options.Guess.ToString().ToLower(),
|
||||||
Description = "A number between 1 and 100 (inclusive)",
|
Description = "A number between 1 and 100 (inclusive)",
|
||||||
Required = true,
|
Required = true,
|
||||||
Type = OptionType.Integer
|
Type = OptionType.Integer
|
||||||
|
@ -44,7 +49,7 @@ namespace Geekbot.Web.Commands
|
||||||
|
|
||||||
public override async Task<InteractionResponse> Exec(Interaction interaction)
|
public override async Task<InteractionResponse> Exec(Interaction interaction)
|
||||||
{
|
{
|
||||||
var guessOption = interaction.Data.Options.Find(o => o.Name == "guess");
|
var guessOption = interaction.Data.Options.Find(o => o.Name == Options.Guess.ToString().ToLower());
|
||||||
var guess = guessOption.Value.GetInt32();
|
var guess = guessOption.Value.GetInt32();
|
||||||
|
|
||||||
var res = await new Geekbot.Commands.Roll.Roll(_kvInMemoryStore, _database, _randomNumberGenerator)
|
var res = await new Geekbot.Commands.Roll.Roll(_kvInMemoryStore, _database, _randomNumberGenerator)
|
||||||
|
|
Loading…
Reference in a new issue