Example #1
0
            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);
            }
Example #2
0
            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));
            }
        }
Example #4
0
            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));
            }
        }