public async Task MissBeatmap(InteractionContext ctx, [Option("Beatmap", "osu! beatmap link or id")] string beatmap, [Option("Index", "Index of play to analyze (default: 1)")] long index = 1) { await Logger.WriteLine("processing user call"); Logger.Log(Logging.UserCalls); ServerReplayLoader replayLoader = new ServerReplayLoader { Source = Source.USER, PlayIndex = (int)index - 1, }; var bmMatch = beatmapRegex.Match(beatmap); if (bmMatch.Success) { replayLoader.BeatmapId = bmMatch.Groups[1].Value; } else { replayLoader.ErrorMessage = "Invalid beatmap link"; } await HandleMissCommand(ctx, replayLoader); }
public async Task HandleMissCommand(InteractionContext ctx, ServerReplayLoader replayLoader) { await ctx.CreateResponseAsync(InteractionResponseType.DeferredChannelMessageWithSource); var guildSettings = context.Settings.GetGuild(ctx.Channel); _ = Task.Run(() => context.CreateResponse(ctx.Client, new InteractionResponse(context, guildSettings, ctx), replayLoader)); }
public async Task HandleMessage(DiscordClient discord, MessageCreateEventArgs e) { Logger.Log(Logging.EventsHandled); if (Settings.Test && e.Guild?.Id != Settings.TestGuild) { return; } var guildSettings = Settings.GetGuild(e.Channel); // if (IsHelpRequest(e, guildSettings)) // { // await e.Message.RespondAsync("MissAnalyzer now uses slash commands! Type /help for help."); // } ServerReplayLoader replayLoader = new ServerReplayLoader(); //attachment foreach (var attachment in e.Message.Attachments) { if (attachment.FileName.EndsWith(".osr")) { await Logger.WriteLine("processing attachment"); Logger.Log(Logging.AttachmentCalls); string dest = Path.Combine(Settings.ServerDir, "replays", attachment.FileName); using (var stream = await webClient.GetStreamAsync(attachment.Url)) using (var file = File.OpenWrite(dest)) { await stream.CopyToAsync(file); } replayLoader.ReplayFile = dest; replayLoader.Source = Source.ATTACHMENT; } } //bot if (guildSettings.AutoResponses && botIds.ContainsKey(e.Author.Id) && rsFunc[e.Author.Id](replayLoader, guildSettings, e)) { await Logger.WriteLine($"processing {botIds[e.Author.Id]} message"); Logger.Log(Logging.BotCalls); replayLoader.UserScores = "recent"; replayLoader.FailedScores = true; replayLoader.PlayIndex = 0; replayLoader.Source = Source.BOT; } if (replayLoader.Source != null) { Response r = (replayLoader.Source == Source.BOT && guildSettings.Compact) ? new CompactResponse(this, guildSettings, e) : new MessageResponse(this, guildSettings, e); _ = Task.Run(() => CreateResponse(discord, r, replayLoader)); } }
public async Task MissUser(InteractionContext ctx, [Option("Username", "osu! username")] string username, [Option("PlayType", "Select from user's top or recent plays")] UserOptions type, [Option("Index", "Index of play to analyze (default: 1)")] long index = 1) { await Logger.WriteLine("processing user call"); Logger.Log(Logging.UserCalls); ServerReplayLoader replayLoader = new ServerReplayLoader { Source = Source.USER, Username = username, UserScores = type.ToString(), PlayIndex = (int)index - 1, }; await HandleMissCommand(ctx, replayLoader); }
public async Task CreateResponse(DiscordClient discord, Response res, ServerReplayLoader replayLoader) { try { replayLoader.ErrorMessage ??= await replayLoader.Load(res.GuildSettings, Api, ReplayDb, BeatmapDb); if (replayLoader.Loaded) { MissAnalyzer missAnalyzer = new MissAnalyzer(replayLoader); res.Miss = new SavedMiss(discord, missAnalyzer); if (missAnalyzer.MissCount == 0) { replayLoader.ErrorMessage = "No misses found."; } else { UpdateCache(res, await res.CreateResponse()); } } } catch (ArgumentException ex) { replayLoader.ErrorMessage = ex.Message; } catch (Exception exc) { await Logger.LogException(exc, Logger.LogLevel.NORMAL); } if (replayLoader.ErrorMessage != null && (replayLoader.Source == Source.USER || replayLoader.Source == Source.ATTACHMENT)) { Logger.Log(Logging.MessageCreated); Logger.Log(Logging.ErrorHandled); await Logger.WriteLine($"Error handled: {replayLoader.ErrorMessage}"); await res.CreateErrorResponse(replayLoader.ErrorMessage); } }
public async Task ProcessMessage(MessageCreateEventArgs e, GuildSettings guildSettings, ServerReplayLoader replayLoader) { try { replayLoader.ErrorMessage ??= await replayLoader.Load(Api, ReplayDb, BeatmapDb); if (replayLoader.Loaded) { DiscordMessage message = null; MissAnalyzer missAnalyzer = new MissAnalyzer(replayLoader); if (missAnalyzer.MissCount == 0) { replayLoader.ErrorMessage = "No misses found."; } else if (replayLoader.Source == Source.BOT && guildSettings.Compact) { message = e.Message; await SendReactions(message, missAnalyzer.MissCount); } else if (missAnalyzer.MissCount == 1) { string miss = await SendMissMessage(missAnalyzer, 0); Logger.Log(Logging.MessageCreated); await e.Message.RespondAsync(miss); } else if (missAnalyzer.MissCount > 1) { Logger.Log(Logging.MessageCreated); message = await e.Message.RespondAsync($"Found **{missAnalyzer.MissCount}** misses"); await SendReactions(message, missAnalyzer.MissCount); } if (message != null) { CachedMisses[message] = new SavedMiss(missAnalyzer); Logger.LogAbsolute(Logging.CachedMessages, CachedMisses.Count); } } } catch (ArgumentException ex) { replayLoader.ErrorMessage = ex.Message; } if (replayLoader.ErrorMessage != null && (replayLoader.Source == Source.USER || replayLoader.Source == Source.ATTACHMENT)) { Logger.Log(Logging.MessageCreated); Logger.Log(Logging.ErrorHandled); Logger.WriteLine($"Error handled: {replayLoader.ErrorMessage}"); await e.Message.RespondAsync(replayLoader.ErrorMessage); } }
public async Task HandleMessage(DiscordClient discord, MessageCreateEventArgs e) { Logger.Log(Logging.EventsHandled); if (Settings.Test && e.Guild?.Id != Settings.TestChannel) { return; } var guildSettings = Settings.GetGuild(e.Channel); if (IsHelpRequest(e, guildSettings)) { await e.Message.RespondAsync(HelpMessage.Replace("$", guildSettings.GetCommand(""))); Logger.Log(Logging.HelpMessageCreated); return; } ServerReplayLoader replayLoader = new ServerReplayLoader(); //attachment foreach (var attachment in e.Message.Attachments) { if (attachment.FileName.EndsWith(".osr")) { await Logger.WriteLine("processing attachment"); Logger.Log(Logging.AttachmentCalls); string dest = Path.Combine(Settings.ServerDir, "replays", attachment.FileName); using (WebClient w = new WebClient()) { w.DownloadFile(attachment.Url, dest); } replayLoader.ReplayFile = dest; replayLoader.Source = Source.ATTACHMENT; } } //bot if (botIds.ContainsKey(e.Author.Id) && rsFunc[e.Author.Id](replayLoader, e)) { await Logger.WriteLine($"processing {botIds[e.Author.Id]} message"); Logger.Log(Logging.BotCalls); replayLoader.UserScores = "recent"; replayLoader.FailedScores = true; replayLoader.PlayIndex = 0; replayLoader.Source = Source.BOT; } //user-triggered string prefix = guildSettings.GetCommand(""); if (e.Message.Content.StartsWith(prefix)) { Match messageMatch = messageRegex.Match(e.Message.Content.Substring(prefix.Length)); if (messageMatch.Success) { await Logger.WriteLine("processing user call"); Logger.Log(Logging.UserCalls); replayLoader.Source = Source.USER; replayLoader.PlayIndex = 0; if (messageMatch.Groups.Count == 4 && messageMatch.Groups[3].Success) { replayLoader.PlayIndex = int.Parse(messageMatch.Groups[3].Value) - 1; } switch (messageMatch.Groups[1].Value) { case "user-recent": case "user-top": replayLoader.Username = messageMatch.Groups[2].Value; replayLoader.UserScores = messageMatch.Groups[1].Value == "user-recent" ? "recent" : "best"; break; case "beatmap": var bmMatch = beatmapRegex.Match(messageMatch.Groups[2].Value); if (bmMatch.Success) { replayLoader.BeatmapId = bmMatch.Groups[1].Value; } else { replayLoader.ErrorMessage = "Invalid beatmap link"; } break; } } //settings Match settingsMatch = settingsRegex.Match(e.Message.Content.Substring(prefix.Length)); if (settingsMatch.Success) { ulong?guildId = settingsMatch.Groups[1].Success? (ulong?)ulong.Parse(settingsMatch.Groups[1].Value) : null; guildId ??= (!e.Channel.IsPrivate)? (ulong?)e.Channel.GuildId : null; string response = null; if (guildId != null) { var user = await(await Discord.GetGuildAsync(guildId.Value)).GetMemberAsync(e.Author.Id); if (user.IsOwner || user.PermissionsIn(e.Channel).HasPermission(Permissions.Administrator)) { var guild = Settings.GetGuild(guildId.Value); if (!settingsMatch.Groups[2].Success || settingsMatch.Groups[2].Value.StartsWith("get")) { response = string.Join("\n", guild.GetSettings() .Select(s => $"{s.Key}: {s.Value}")); } else { string setting = settingsMatch.Groups[3].Value, value = settingsMatch.Groups[4].Value; try { response = guild.SetSetting(setting, value)? "Set successfully" : $"Setting {setting} does not exist"; } catch (TargetInvocationException ex) when(ex.InnerException is FormatException) { response = $"{value} not valid for setting {setting}"; } } } } else { response = "Please specify for which guild"; } if (response != null) { await e.Message.RespondAsync(response); } } } if (replayLoader.Source != null) { Task.Run(() => ProcessMessage(e, guildSettings, replayLoader)); } }