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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Discord.Commands;
|
||||
using Geekbot.Core;
|
||||
|
@ -9,10 +6,8 @@ using Geekbot.Core.CommandPreconditions;
|
|||
using Geekbot.Core.Converters;
|
||||
using Geekbot.Core.Database;
|
||||
using Geekbot.Core.ErrorHandling;
|
||||
using Geekbot.Core.Extensions;
|
||||
using Geekbot.Core.GuildSettingsManager;
|
||||
using Geekbot.Core.Highscores;
|
||||
using Localization = Geekbot.Core.Localization;
|
||||
|
||||
namespace Geekbot.Bot.Commands.User.Ranking
|
||||
{
|
||||
|
@ -40,85 +35,9 @@ namespace Geekbot.Bot.Commands.User.Ranking
|
|||
{
|
||||
try
|
||||
{
|
||||
HighscoreTypes type;
|
||||
try
|
||||
{
|
||||
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());
|
||||
var res = new Geekbot.Commands.Rank(_database, _emojiConverter, _highscoreManager)
|
||||
.Run(typeUnformated, amount, season, Context.Guild.Id, Context.Guild.Name);
|
||||
await ReplyAsync(res);
|
||||
}
|
||||
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>
|
||||
[JsonPropertyName("name")]
|
||||
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;
|
||||
}
|
||||
|
||||
private enum Options
|
||||
{
|
||||
Guess
|
||||
}
|
||||
|
||||
public override Command GetCommandInfo()
|
||||
{
|
||||
return new Command()
|
||||
|
@ -33,7 +38,7 @@ namespace Geekbot.Web.Commands
|
|||
{
|
||||
new Option()
|
||||
{
|
||||
Name = "guess",
|
||||
Name = Options.Guess.ToString().ToLower(),
|
||||
Description = "A number between 1 and 100 (inclusive)",
|
||||
Required = true,
|
||||
Type = OptionType.Integer
|
||||
|
@ -44,7 +49,7 @@ namespace Geekbot.Web.Commands
|
|||
|
||||
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 res = await new Geekbot.Commands.Roll.Roll(_kvInMemoryStore, _database, _randomNumberGenerator)
|
||||
|
|
Loading…
Reference in a new issue