282 lines
No EOL
9.2 KiB
C#
282 lines
No EOL
9.2 KiB
C#
using System.Net;
|
|
using System.Text;
|
|
using EllieBot.Modules.Games.Common.Trivia;
|
|
using EllieBot.Modules.Games.Services;
|
|
|
|
namespace EllieBot.Modules.Games;
|
|
|
|
public partial class Games
|
|
{
|
|
[Group]
|
|
public partial class TriviaCommands : EllieModule<TriviaGamesService>
|
|
{
|
|
private readonly ILocalDataCache _cache;
|
|
private readonly ICurrencyService _cs;
|
|
private readonly GamesConfigService _gamesConfig;
|
|
private readonly DiscordSocketClient _client;
|
|
|
|
public TriviaCommands(
|
|
DiscordSocketClient client,
|
|
ILocalDataCache cache,
|
|
ICurrencyService cs,
|
|
GamesConfigService gamesConfig)
|
|
{
|
|
_cache = cache;
|
|
_cs = cs;
|
|
_gamesConfig = gamesConfig;
|
|
_client = client;
|
|
}
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[Priority(0)]
|
|
[EllieOptions<TriviaOptions>]
|
|
public async Task Trivia(params string[] args)
|
|
{
|
|
var (opts, _) = OptionsParser.ParseFrom(new TriviaOptions(), args);
|
|
|
|
var config = _gamesConfig.Data;
|
|
if (opts.WinRequirement != 0
|
|
&& config.Trivia.MinimumWinReq > 0
|
|
&& config.Trivia.MinimumWinReq > opts.WinRequirement)
|
|
return;
|
|
|
|
var trivia = new TriviaGame(opts, _cache);
|
|
if (_service.RunningTrivias.TryAdd(ctx.Guild.Id, trivia))
|
|
{
|
|
RegisterEvents(trivia);
|
|
await trivia.RunAsync();
|
|
return;
|
|
}
|
|
|
|
if (_service.RunningTrivias.TryGetValue(ctx.Guild.Id, out var tg))
|
|
{
|
|
await Response().Error(strs.trivia_already_running).SendAsync();
|
|
await tg.TriggerQuestionAsync();
|
|
}
|
|
}
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
public async Task Tl()
|
|
{
|
|
if (_service.RunningTrivias.TryGetValue(ctx.Guild.Id, out var trivia))
|
|
{
|
|
await trivia.TriggerStatsAsync();
|
|
return;
|
|
}
|
|
|
|
await Response().Error(strs.trivia_none).SendAsync();
|
|
}
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
public async Task Tq()
|
|
{
|
|
var channel = (ITextChannel)ctx.Channel;
|
|
|
|
if (_service.RunningTrivias.TryGetValue(channel.Guild.Id, out var trivia))
|
|
{
|
|
if (trivia.Stop())
|
|
{
|
|
try
|
|
{
|
|
await Response()
|
|
.Confirm(GetText(strs.trivia_game), GetText(strs.trivia_stopping))
|
|
.SendAsync();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Warning(ex, "Error sending trivia stopping message");
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
await Response().Error(strs.trivia_none).SendAsync();
|
|
}
|
|
|
|
private string GetLeaderboardString(TriviaGame tg)
|
|
{
|
|
var sb = new StringBuilder();
|
|
|
|
foreach (var (id, pts) in tg.GetLeaderboard())
|
|
sb.AppendLine(GetText(strs.trivia_points(Format.Bold($"<@{id}>"), pts)));
|
|
|
|
return sb.ToString();
|
|
}
|
|
|
|
private EmbedBuilder? questionEmbed;
|
|
private IUserMessage? questionMessage;
|
|
private bool showHowToQuit;
|
|
|
|
private void RegisterEvents(TriviaGame trivia)
|
|
{
|
|
trivia.OnQuestion += OnTriviaQuestion;
|
|
trivia.OnHint += OnTriviaHint;
|
|
trivia.OnGuess += OnTriviaGuess;
|
|
trivia.OnEnded += OnTriviaEnded;
|
|
trivia.OnStats += OnTriviaStats;
|
|
trivia.OnTimeout += OnTriviaTimeout;
|
|
}
|
|
|
|
private void UnregisterEvents(TriviaGame trivia)
|
|
{
|
|
trivia.OnQuestion -= OnTriviaQuestion;
|
|
trivia.OnHint -= OnTriviaHint;
|
|
trivia.OnGuess -= OnTriviaGuess;
|
|
trivia.OnEnded -= OnTriviaEnded;
|
|
trivia.OnStats -= OnTriviaStats;
|
|
trivia.OnTimeout -= OnTriviaTimeout;
|
|
}
|
|
|
|
private async Task OnTriviaHint(TriviaGame game, TriviaQuestion question)
|
|
{
|
|
try
|
|
{
|
|
if (questionMessage is null)
|
|
{
|
|
game.Stop();
|
|
return;
|
|
}
|
|
|
|
if (questionEmbed is not null)
|
|
await questionMessage.ModifyAsync(m
|
|
=> m.Embed = questionEmbed.WithFooter(question.GetHint()).Build());
|
|
}
|
|
catch (HttpException ex) when (ex.HttpCode is HttpStatusCode.NotFound or HttpStatusCode.Forbidden)
|
|
{
|
|
Log.Warning("Unable to edit message to show hint. Stopping trivia");
|
|
game.Stop();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Warning(ex, "Error editing trivia message");
|
|
}
|
|
}
|
|
|
|
private async Task OnTriviaQuestion(TriviaGame game, TriviaQuestion question)
|
|
{
|
|
try
|
|
{
|
|
questionEmbed = _sender.CreateEmbed()
|
|
.WithOkColor()
|
|
.WithTitle(GetText(strs.trivia_game))
|
|
.AddField(GetText(strs.category), question.Category)
|
|
.AddField(GetText(strs.question), question.Question);
|
|
|
|
showHowToQuit = !showHowToQuit;
|
|
if (showHowToQuit)
|
|
questionEmbed.WithFooter(GetText(strs.trivia_quit($"{prefix}tq")));
|
|
|
|
if (Uri.IsWellFormedUriString(question.ImageUrl, UriKind.Absolute))
|
|
questionEmbed.WithImageUrl(question.ImageUrl);
|
|
|
|
questionMessage = await Response().Embed(questionEmbed).SendAsync();
|
|
}
|
|
catch (HttpException ex) when (ex.HttpCode is HttpStatusCode.NotFound
|
|
or HttpStatusCode.Forbidden
|
|
or HttpStatusCode.BadRequest)
|
|
{
|
|
Log.Warning("Unable to send trivia questions. Stopping immediately");
|
|
game.Stop();
|
|
throw;
|
|
}
|
|
}
|
|
|
|
private async Task OnTriviaTimeout(TriviaGame _, TriviaQuestion question)
|
|
{
|
|
try
|
|
{
|
|
var embed = _sender.CreateEmbed()
|
|
.WithErrorColor()
|
|
.WithTitle(GetText(strs.trivia_game))
|
|
.WithDescription(GetText(strs.trivia_times_up(Format.Bold(question.Answer))));
|
|
|
|
if (Uri.IsWellFormedUriString(question.AnswerImageUrl, UriKind.Absolute))
|
|
embed.WithImageUrl(question.AnswerImageUrl);
|
|
|
|
await Response().Embed(embed).SendAsync();
|
|
}
|
|
catch
|
|
{
|
|
// ignored
|
|
}
|
|
}
|
|
|
|
private async Task OnTriviaStats(TriviaGame game)
|
|
{
|
|
try
|
|
{
|
|
await Response().Confirm(GetText(strs.leaderboard), GetLeaderboardString(game)).SendAsync();
|
|
}
|
|
catch
|
|
{
|
|
// ignored
|
|
}
|
|
}
|
|
|
|
private async Task OnTriviaEnded(TriviaGame game)
|
|
{
|
|
try
|
|
{
|
|
await Response().Embed(_sender.CreateEmbed()
|
|
.WithOkColor()
|
|
.WithAuthor(GetText(strs.trivia_ended))
|
|
.WithTitle(GetText(strs.leaderboard))
|
|
.WithDescription(GetLeaderboardString(game))).SendAsync();
|
|
}
|
|
catch
|
|
{
|
|
// ignored
|
|
}
|
|
finally
|
|
{
|
|
_service.RunningTrivias.TryRemove(ctx.Guild.Id, out _);
|
|
}
|
|
|
|
UnregisterEvents(game);
|
|
}
|
|
|
|
private async Task OnTriviaGuess(
|
|
TriviaGame _,
|
|
TriviaUser user,
|
|
TriviaQuestion question,
|
|
bool isWin)
|
|
{
|
|
try
|
|
{
|
|
var embed = _sender.CreateEmbed()
|
|
.WithOkColor()
|
|
.WithTitle(GetText(strs.trivia_game))
|
|
.WithDescription(GetText(strs.trivia_win(user.Name,
|
|
Format.Bold(question.Answer))));
|
|
|
|
if (Uri.IsWellFormedUriString(question.AnswerImageUrl, UriKind.Absolute))
|
|
embed.WithImageUrl(question.AnswerImageUrl);
|
|
|
|
|
|
if (isWin)
|
|
{
|
|
await Response().Embed(embed).SendAsync();
|
|
|
|
var reward = _gamesConfig.Data.Trivia.CurrencyReward;
|
|
if (reward > 0)
|
|
await _cs.AddAsync(user.Id, reward, new("trivia", "win"));
|
|
|
|
return;
|
|
}
|
|
|
|
embed.WithDescription(GetText(strs.trivia_guess(user.Name,
|
|
Format.Bold(question.Answer))));
|
|
|
|
await Response().Embed(embed).SendAsync();
|
|
}
|
|
catch
|
|
{
|
|
// ignored
|
|
}
|
|
}
|
|
}
|
|
} |