Пример #1
0
        Task HandleReactionAsync(IMessageChannel channel,
                                 SocketReaction reaction,
                                 ReactionEvent eventType)
        {
            if (reaction.UserId != _discord.CurrentUser.Id)
            {
                _ = Task.Run(async() =>
                {
                    // retrieve message
                    if (!(await channel.GetMessageAsync(reaction.MessageId) is IUserMessage message))
                    {
                        return;
                    }

                    // retrieve user
                    if (!(await channel.GetUserAsync(reaction.UserId) is IUser user))
                    {
                        return;
                    }

                    // create context
                    var context = new ReactionContext
                    {
                        Client        = _discord,
                        Message       = message,
                        User          = user,
                        GuildSettings = _guildSettingsCache[message.Channel],
                        Reaction      = reaction,
                        Event         = eventType
                    };

                    try
                    {
                        foreach (var handler in _reactionHandlers)
                        {
                            if (await handler.TryHandleAsync(context))
                            {
                                HandledReactions.Increment();
                                break;
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        await _errorReporter.ReportAsync(e, context, false);
                    }
                    finally
                    {
                        ReceivedReactions.Increment();
                    }
                });
            }

            return(Task.CompletedTask);
        }
Пример #2
0
        public async Task <bool> IsBotPrivateChannel(IMessageChannel contextChannel)
        {
            try
            {
                return(contextChannel.GetType() == typeof(SocketDMChannel) && await contextChannel.GetUserAsync(Client.CurrentUser.Id) != null);
            }
            catch (Exception ex)
            {
                await LogHelper.LogEx(nameof(IsBotPrivateChannel), ex, LogCat.Discord);

                return(false);
            }
        }
Пример #3
0
 private void TimerTimeout_Elapsed(object sender, ElapsedEventArgs e)
 {
     if (CheckTimeoutVote())
     {
         var user = channelTimeout.GetUserAsync(timeoutUser).Result;
         channelTimeout.SendMessageAsync($"{user.Username} sent to timeout for being bad!");
         (user as IGuildUser).ModifyAsync(x =>
         {
             x.Channel = new Optional <IVoiceChannel>(afkChannel);
         });
     }
     ClearTimeout();
 }
Пример #4
0
 private async Task PurgeUserMessages(SocketUser user)
 {
     foreach (SocketChannel c in Context.Guild.Channels)
     {
         IMessageChannel channel = c as IMessageChannel;
         if (channel == null)
         {
             continue;
         }
         if (await channel.GetUserAsync(user.Id) == null)
         {
             continue;
         }
         await PurgeUserMessages(user, channel, -1);
     }
 }
Пример #5
0
        public async Task LevelAsync(string UserId, int GuildMsgs)
        {
            try
            {
                IMessageChannel message = (IMessageChannel)Context.Channel.GetMessagesAsync(GuildMsgs);
                var             msg     = await message.GetUserAsync(ulong.Parse(UserId));

                var e = new EmbedBuilder();
                e.WithDescription($"**Your Hug Level is {msg}**");
                e.WithColor(4360181);

                await ReplyAsync(embed : e.Build());
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
            {
            }
        }
Пример #6
0
        private void CheckReactionUsers(IUserMessage gameMessage, Dictionary <string, string> newPlayersNickNameLookup)
        {
            int eventReactionsCount  = newPlayersNickNameLookup.Count;
            int badGetReactions      = 0;
            int addedGetReactions    = 0;
            int existingGetReactions = 0;
            int getReactionsCount    = 0;
            var result = gameMessage.GetReactionUsersAsync(ReactionToUse, DiscordConfig.MaxUsersPerBatch).GetAwaiter().GetResult();

            if (result != null)
            {
                Dictionary <string, string> playersUserNameLookup = new Dictionary <string, string>();
                foreach (KeyValuePair <string, string> keyValuePair in newPlayersNickNameLookup)
                {
                    playersUserNameLookup[keyValuePair.Value] = keyValuePair.Key;
                }

                getReactionsCount = result.Count;
                foreach (IUser user in result)
                {
                    if (playersUserNameLookup.ContainsKey(user.Username) == false)
                    {
                        SocketGuildUser userLookup = _channel.GetUserAsync(user.Id).GetAwaiter().GetResult() as SocketGuildUser;
                        if (userLookup != null)
                        {
                            newPlayersNickNameLookup[userLookup.Nickname ?? userLookup.Username] = userLookup.Username;
                            addedGetReactions++;
                        }
                        else
                        {
                            badGetReactions++;
                        }
                    }
                    else
                    {
                        existingGetReactions++;
                    }
                }
            }
            Logger.Log($"RunGame - GetReactionsReturned: {getReactionsCount} EventReactions: {eventReactionsCount} BadUsers: {badGetReactions} AddedUsers: {addedGetReactions} ExistingUsers: {existingGetReactions} TotalPlayers: {newPlayersNickNameLookup.Count}");
        }
Пример #7
0
        internal static ImmutableArray <IUser> GetUserMentions(string text, IMessageChannel channel, IReadOnlyCollection <IUser> mentionedUsers)
        {
            var matches = _userRegex.Matches(text);
            var builder = ImmutableArray.CreateBuilder <IUser>(matches.Count);

            foreach (var match in matches.OfType <Match>())
            {
                ulong id;
                if (ulong.TryParse(match.Groups[1].Value, NumberStyles.None, CultureInfo.InvariantCulture, out id))
                {
                    IUser user = null;

                    //Verify this user was actually mentioned
                    foreach (var userMention in mentionedUsers)
                    {
                        if (userMention.Id == id)
                        {
                            if (channel.IsAttached) //Waiting this sync is safe because it's using a cache
                            {
                                user = channel.GetUserAsync(id).GetAwaiter().GetResult() as IUser;
                            }
                            if (user == null) //User not found, fallback to basic mention info
                            {
                                user = userMention;
                            }
                            break;
                        }
                    }

                    if (user != null)
                    {
                        builder.Add(user);
                    }
                }
            }
            return(builder.ToImmutable());
        }
Пример #8
0
        protected AGame(IGuild guild, IMessageChannel chan, List <string> dictionnary, Config config, ulong playerId, bool ignoreDictionnarycheck = false)
        {
            _http = new HttpClient();

            _guild = guild;
            _chan  = chan;
            if (!ignoreDictionnarycheck && (dictionnary == null || dictionnary.Count < 100)) // Dictionnary failed to load
            {
                throw new NoDictionnaryException();
            }
            _dictionnary           = dictionnary != null ? new List <string>(dictionnary) : null; // We create a new one to be sure to not modify the common one
            _contributors          = new List <ulong>();
            _saveName              = config.gameName + (config.difficulty == Difficulty.Easy ? "-easy" : "") + (config.isFull ? "-full" : "") + (config.isCropped ? "-cropped" : "") + (config.isShaded != APreload.Shadow.None ? "-shaded" : "");
            _gameName              = new CultureInfo("en-US").TextInfo.ToTitleCase(config.gameName);
            _score                 = 0;
            _postImage             = false;
            _checkingAnswer        = false;
            _gameState             = GameState.WaitingForPlayers;
            _startTime             = DateTime.Now;
            _timer                 = config.refTime * (int)config.difficulty;
            _lobby                 = (config.isMultiplayer == APreload.Multiplayer.MultiOnly ? new MultiplayerLobby(playerId) : null);
            _isFound               = false;
            _isCropped             = config.isCropped;
            _isShaded              = config.isShaded;
            _multiType             = config.multiplayerType;
            _bestOfScore           = new Dictionary <string, int>();
            _bestOfTries           = new Dictionary <string, int>();
            _bestOfRemainingRounds = nbQuestions;

            _audioFilePath = null;
            _process       = null;
            _audioStream   = null;
            if (GetPostType() == PostType.Audio)
            {
                if (!File.Exists("ffmpeg.exe"))
                {
                    throw new FileNotFoundException("ffmpeg.exe was not found. Please put it near the bot executable.");
                }
                // TODO: Check is Sanara isn't already in a vocal channel and if we are not in PM
                var user = chan.GetUserAsync(playerId).GetAwaiter().GetResult() as IGuildUser;
                if (user == null)
                {
                    throw new ArgumentException("Can't convert user to IGuildUser");
                }
                var chanRadio = user.VoiceChannel;
                if (chanRadio == null)
                {
                    throw new NoAudioChannel();
                }
                try
                {
                    _voiceSession = chanRadio.ConnectAsync().GetAwaiter().GetResult();
                } catch (TaskCanceledException e)
                {
                    LooseAsync("An error occured while connecting to vocal channel.").GetAwaiter().GetResult();
                    Program.p.LogError(new LogMessage(LogSeverity.Error, e.Source, e.Message, e));
                }
            }
            else
            {
                _voiceSession = null;
            }

            Init();
        }
Пример #9
0
        public static ImmutableArray <ITag> ParseTags(string text, IMessageChannel channel, IGuild guild, IReadOnlyCollection <IUser> userMentions)
        {
            var tags = ImmutableArray.CreateBuilder <ITag>();

            int index = 0;

            while (true)
            {
                index = text.IndexOf('<', index);
                if (index == -1)
                {
                    break;
                }
                int endIndex = text.IndexOf('>', index + 1);
                if (endIndex == -1)
                {
                    break;
                }
                string content = text.Substring(index, endIndex - index + 1);

                if (MentionUtils.TryParseUser(content, out ulong id))
                {
                    IUser mentionedUser = null;
                    foreach (var mention in userMentions)
                    {
                        if (mention.Id == id)
                        {
                            mentionedUser = channel?.GetUserAsync(id, CacheMode.CacheOnly).GetAwaiter().GetResult();
                            if (mentionedUser == null)
                            {
                                mentionedUser = mention;
                            }
                            break;
                        }
                    }
                    tags.Add(new Tag <IUser>(TagType.UserMention, index, content.Length, id, mentionedUser));
                }
                else if (MentionUtils.TryParseChannel(content, out id))
                {
                    IChannel mentionedChannel = null;
                    if (guild != null)
                    {
                        mentionedChannel = guild.GetChannelAsync(id, CacheMode.CacheOnly).GetAwaiter().GetResult();
                    }
                    tags.Add(new Tag <IChannel>(TagType.ChannelMention, index, content.Length, id, mentionedChannel));
                }
                else if (MentionUtils.TryParseRole(content, out id))
                {
                    IRole mentionedRole = null;
                    if (guild != null)
                    {
                        mentionedRole = guild.GetRole(id);
                    }
                    tags.Add(new Tag <IRole>(TagType.RoleMention, index, content.Length, id, mentionedRole));
                }
                else if (Emote.TryParse(content, out var emoji))
                {
                    tags.Add(new Tag <Emote>(TagType.Emoji, index, content.Length, emoji.Id, emoji));
                }
                else //Bad Tag
                {
                    index = index + 1;
                    continue;
                }
                index = endIndex + 1;
            }

            index = 0;
            while (true)
            {
                index = text.IndexOf("@everyone", index);
                if (index == -1)
                {
                    break;
                }

                var tagIndex = FindIndex(tags, index);
                if (tagIndex.HasValue)
                {
                    tags.Insert(tagIndex.Value, new Tag <object>(TagType.EveryoneMention, index, "@everyone".Length, 0, null));
                }
                index++;
            }

            index = 0;
            while (true)
            {
                index = text.IndexOf("@here", index);
                if (index == -1)
                {
                    break;
                }

                var tagIndex = FindIndex(tags, index);
                if (tagIndex.HasValue)
                {
                    tags.Insert(tagIndex.Value, new Tag <object>(TagType.HereMention, index, "@here".Length, 0, null));
                }
                index++;
            }

            return(tags.ToImmutable());
        }
Пример #10
0
        public static ImmutableArray <ITag> ParseTags(string text, IMessageChannel channel, IGuild guild, IReadOnlyCollection <IUser> userMentions)
        {
            var tags      = ImmutableArray.CreateBuilder <ITag>();
            int index     = 0;
            var codeIndex = 0;

            // checks if the tag being parsed is wrapped in code blocks
            bool CheckWrappedCode()
            {
                // util to check if the index of a tag is within the bounds of the codeblock
                bool EnclosedInBlock(Match m)
                => m.Groups[1].Index < index && index < m.Groups[2].Index;

                // loop through all code blocks that are before the start of the tag
                while (codeIndex < index)
                {
                    var blockMatch = BlockCodeRegex.Match(text, codeIndex);
                    if (blockMatch.Success)
                    {
                        if (EnclosedInBlock(blockMatch))
                        {
                            return(true);
                        }
                        // continue if the end of the current code was before the start of the tag
                        codeIndex += blockMatch.Groups[2].Index + blockMatch.Groups[2].Length;
                        if (codeIndex < index)
                        {
                            continue;
                        }
                        return(false);
                    }
                    var inlineMatch = InlineCodeRegex.Match(text, codeIndex);
                    if (inlineMatch.Success)
                    {
                        if (EnclosedInBlock(inlineMatch))
                        {
                            return(true);
                        }
                        // continue if the end of the current code was before the start of the tag
                        codeIndex += inlineMatch.Groups[2].Index + inlineMatch.Groups[2].Length;
                        if (codeIndex < index)
                        {
                            continue;
                        }
                        return(false);
                    }
                    return(false);
                }
                return(false);
            }

            while (true)
            {
                index = text.IndexOf('<', index);
                if (index == -1)
                {
                    break;
                }
                int endIndex = text.IndexOf('>', index + 1);
                if (endIndex == -1)
                {
                    break;
                }
                if (CheckWrappedCode())
                {
                    break;
                }
                string content = text.Substring(index, endIndex - index + 1);

                if (MentionUtils.TryParseUser(content, out ulong id))
                {
                    IUser mentionedUser = null;
                    foreach (var mention in userMentions)
                    {
                        if (mention.Id == id)
                        {
                            mentionedUser = channel?.GetUserAsync(id, CacheMode.CacheOnly).GetAwaiter().GetResult();
                            if (mentionedUser == null)
                            {
                                mentionedUser = mention;
                            }
                            break;
                        }
                    }
                    tags.Add(new Tag <IUser>(TagType.UserMention, index, content.Length, id, mentionedUser));
                }
                else if (MentionUtils.TryParseChannel(content, out id))
                {
                    IChannel mentionedChannel = null;
                    if (guild != null)
                    {
                        mentionedChannel = guild.GetChannelAsync(id, CacheMode.CacheOnly).GetAwaiter().GetResult();
                    }
                    tags.Add(new Tag <IChannel>(TagType.ChannelMention, index, content.Length, id, mentionedChannel));
                }
                else if (MentionUtils.TryParseRole(content, out id))
                {
                    IRole mentionedRole = null;
                    if (guild != null)
                    {
                        mentionedRole = guild.GetRole(id);
                    }
                    tags.Add(new Tag <IRole>(TagType.RoleMention, index, content.Length, id, mentionedRole));
                }
                else if (Emote.TryParse(content, out var emoji))
                {
                    tags.Add(new Tag <Emote>(TagType.Emoji, index, content.Length, emoji.Id, emoji));
                }
                else //Bad Tag
                {
                    index++;
                    continue;
                }
                index = endIndex + 1;
            }

            index     = 0;
            codeIndex = 0;
            while (true)
            {
                index = text.IndexOf("@everyone", index);
                if (index == -1)
                {
                    break;
                }
                if (CheckWrappedCode())
                {
                    break;
                }
                var tagIndex = FindIndex(tags, index);
                if (tagIndex.HasValue)
                {
                    tags.Insert(tagIndex.Value, new Tag <IRole>(TagType.EveryoneMention, index, "@everyone".Length, 0, guild?.EveryoneRole));
                }
                index++;
            }

            index     = 0;
            codeIndex = 0;
            while (true)
            {
                index = text.IndexOf("@here", index);
                if (index == -1)
                {
                    break;
                }
                if (CheckWrappedCode())
                {
                    break;
                }
                var tagIndex = FindIndex(tags, index);
                if (tagIndex.HasValue)
                {
                    tags.Insert(tagIndex.Value, new Tag <IRole>(TagType.HereMention, index, "@here".Length, 0, guild?.EveryoneRole));
                }
                index++;
            }

            return(tags.ToImmutable());
        }
Пример #11
0
        internal static void AddCommands(Commands.CommandGroupBuilder group)
        {
            group.CreateCommand("ping")
            .Description("I'll reply with 'Pong!'")
            .Do(e => e.Channel.SendMessageAsync($"{e.User.Mention}, Pong!{DoPing(e.Message)}"));

            group.CreateCommand("pong")
            .Hide()     // More of an easter egg, don't show in help.
            .Description("I'll reply with 'Ping?'")
            .Do(e => e.Channel.SendMessageAsync($"{e.User.Mention}, Ping?{DoPing(e.Message)}"));

            group.CreateCommand("uptime")
            .Description("I'll tell you how long I've been awake~")
            .Do(e => e.Channel.SendMessageAsync(Format.Code(Helpers.Uptime().ToString())));

            EmbedFieldBuilder role_info(SocketRole r)
            {
                string ret = $"ID is {r.Id}, has {r.Members.Count()} members, color is {r.Color}, perms are {r.Permissions.RawValue}, and position is {r.Position}";

                if (r.IsManaged)
                {
                    ret += "; it is managed by the server";
                }
                ret += $"\nIt was created on {r.CreatedAt}";
                return(new EmbedFieldBuilder().WithName(r.Name).WithValue(ret));
            }

            group.CreateCommand("whois")
            .Alias("getinfo")
            .Parameter("[@User1] [@User2] [...]", Commands.ParameterType.Unparsed)
            .Description("I'll give you information about the mentioned user(s).")
            .Do(async e =>
            {
                if (e.Args[0].Length == 0 || (!e.Message.MentionedUserIds.Any() && !e.Message.MentionedRoleIds.Any()))
                {
                    return;
                }
                bool oniicheck = e.User.Id == 63299786798796800;
                var embed      = Helpers.EmbedDesc("WhoIs Response");
                async Task <IUserMessage> send() => await e.Channel.SendMessageAsync(embed: embed.Build());
                foreach (var t in e.Message.Tags)
                {
                    if (embed.Fields.Count == EmbedBuilder.MaxFieldCount)
                    {
                        await send();
                        embed.Fields.Clear();
                    }
                    switch (t.Type)
                    {
                    case TagType.RoleMention:
                        embed.AddField(role_info(t.Value as SocketRole));
                        break;

                    case TagType.UserMention:
                        var u             = t.Value as IGuildUser;
                        bool onii         = oniicheck && u.Id == 63296013791666176;
                        string possessive = onii ? "His" : "Their";
                        string pronoun    = onii ? "He" : "They";
                        var field         = new EmbedFieldBuilder();
                        string reply      = string.Empty;
                        if (onii)
                        {
                            reply += "is your onii-chan <3\n";
                        }
                        if (!string.IsNullOrEmpty(u.Nickname))
                        {
                            reply += $"Nick: {u.Nickname}\n";
                        }
                        reply += $"ID: {u.Id}\n{possessive} discriminator is {u.Discriminator}. {possessive} permission level is {Helpers.GetPermissions(u, e.Channel)}.";
                        reply += $"\n{pronoun} joined Discord on {u.CreatedAt}.\n{pronoun} joined this server on {u.JoinedAt}.\n";
                        if (u.IsBot)
                        {
                            reply += $" {pronoun} are also a bot!";
                        }
                        reply += $" {possessive} status is {u.Status}.\n";
                        if (u.Activity != null)
                        {
                            reply += $"\n{pronoun} {(onii ? "is" : "are")} {u.Activity.Type} {u.Activity.Name}.";
                        }
                        if (u.VoiceChannel != null)
                        {
                            reply += $"Current voice channel: {u.VoiceChannel.Name}";
                        }
                        embed.AddField(u.Username, reply);
                        break;
                    }
                }
                if (embed.Fields.Count != 0)
                {
                    await send();
                }
            });

            group.CreateCommand("whois role")
            .Alias("getinfo role")
            .Parameter("role(s)", Commands.ParameterType.Unparsed)
            .Description("I'll give you info on particular roles by name (comma separated)")
            .Do(e =>
            {
                string reply = "";
                if (e.Args[0].Length == 0)
                {
                    reply = "You need to provide at least one role name!";
                }
                else
                {
                    Helpers.CommaSeparateRoleNames(e, (roles, str) =>
                    {
                        foreach (var r in roles)
                        {
                            reply += role_info(r);
                        }
                    });
                }
                e.Channel.SendMessageAsync(reply);
            });

            Music.AddCommands(group);

            Image.AddCommands(group);

            Func <Commands.CommandEventArgs, Task <bool> > lookup_nothing = async e =>
            {
                var args = e.Args[0];
                if (args.Length == 0)
                {
                    await Helpers.SendEmbed(e, Helpers.EmbedDesc("I cannot lookup nothing, silly!"));

                    return(true);
                }
                return(false);
            };

            group.CreateCommand("urban")
            .Alias("urbandictionary")
            .Alias("ud")
            .Parameter("phrase", Commands.ParameterType.Unparsed)
            .Description("I'll give you the urban dictionary definition of a phrase.")
            .Do(async e =>
            {
                if (await lookup_nothing(e))
                {
                    return;
                }
                var req = new RestRequest("define", Method.GET);
                req.AddQueryParameter("term", e.Args[0]);
                var json = JObject.Parse(Helpers.GetRestClient("http://api.urbandictionary.com/v0").Execute(req).Content);
                var list = json["list"];
                if (!list.HasValues)
                {
                    await Helpers.SendEmbed(e, Helpers.EmbedDesc("No results found."));
                    return;
                }
                var resp  = list[0];
                var embed = Helpers.EmbedDesc(resp["definition"].ToString())
                            .WithTitle(resp["word"].ToString())
                            .WithUrl(resp["permalink"].ToString())
                            .WithFooter($"⬆{resp["thumbs_up"]} ⬇{resp["thumbs_down"]}")
                            .WithTimestamp(DateTime.Parse(resp["written_on"].ToString(), null, System.Globalization.DateTimeStyles.RoundtripKind))
                            .AddField("Example", resp["example"]);
                var sounds = resp["sound_urls"];
                if (sounds.HasValues)
                {
                    embed.AddField(sounds.Count() > 1 ? "Sounds" : "Sound", string.Join("\n", sounds));     // I wish we could embed just one of these and have an audio player, but this works too.
                }
                await Helpers.SendEmbed(e, embed);
            });

            if (Helpers.FieldExists("WolframAlpha", "appid"))
            {
                group.CreateCommand("wolfram")
                .Parameter("input", Commands.ParameterType.Unparsed)
                .Description("I'll look something up for you on WolframAlpha")
                .Do(async e =>
                {
                    if (await lookup_nothing(e))
                    {
                        return;
                    }
                    var rc = Helpers.GetRestClient("http://api.wolframalpha.com/v2/");     // TODO: Do we want this static?
                    rc.AddDefaultParameter("appid", Program.config["WolframAlpha"]["appid"]);
                    var req = new RestRequest("query", Method.GET);
                    req.AddQueryParameter("input", e.Args[0]);
                    var json = Helpers.XmlToJson(rc.Execute(req).Content)["queryresult"];
                    if (!json["@success"].ToObject <bool>())
                    {
                        const string didyoumeans = "didyoumeans";
                        if (Helpers.FieldExists(json, didyoumeans))
                        {
                            var embed  = Helpers.EmbedBuilder.WithTitle("Perhaps you meant");
                            json       = json[didyoumeans];
                            int count  = json["@count"].ToObject <int>();
                            string ret = "";
                            Func <JToken, string> format_suggestion = suggestion => $" `{suggestion["#text"]}`";
                            json = json["didyoumean"];
                            if (count == 1)
                            {
                                ret += format_suggestion(json);
                            }
                            else
                            {
                                for (int i = 0; i < count; ++i)
                                {
                                    ret += (i == 0 ? "" : i == count - 1 ? ", or " : ",") + format_suggestion(json[i]);
                                }
                            }
                            ret += '?';
                            await Helpers.SendEmbed(e, embed.WithDescription(ret.TrimStart()));
                        }
                        await Helpers.SendEmbed(e, Helpers.EmbedDesc("Sorry, I couldn't find anything for your input."));
                    }
                    else
                    {
                        int show   = 4;   // Show the first four results
                        json       = json["pod"];
                        string ret = "";
                        //var embed = Helpers.EmbedBuilder.WithTitle($"Results for {e.Args}");
                        for (int i = 0, count = json.Count(); show != 0 && i < count; ++i)
                        {
                            var pod        = json[i];
                            int numsubpods = pod["@numsubpods"].ToObject <int>();
                            if (numsubpods == 1)
                            {
                                ret += $"{pod["subpod"]["img"]["@src"]}\n";
                                --show;
                            }
                            else
                            {
                                for (int j = 0; show != 0 && j < numsubpods; ++j, --show)
                                {
                                    ret += $"{pod["subpod"][j]["img"]["@src"]}\n";
                                }
                            }
                        }
                        await e.Channel.SendMessageAsync(ret);
                        //await Helpers.SendEmbed(e, embed.WithDescription(ret)); // I don't know how this would look good, at this point.
                    }
                });
            }

            var quote_site = "http://bacon.mlgdoor.uk/";

            group.CreateCommand("quote")
            .Description($"I'll give you a random quote from {quote_site}quotes")
            .Do(async e =>
            {
                var result = JObject.Parse(Helpers.GetRestClient(quote_site).Execute <JObject>(new RestRequest("api/v1/quotes/random", Method.GET)).Content)["quotes"][0];
                await e.Channel.SendMessageAsync($"\"{result["quote"]}\" - {result["author"]} {result["year"]}");
            });

            Func <string, string, string, string> add_quote = (quote, author, year) =>
            {
                var result = JObject.Parse(Helpers.GetRestClient(quote_site)
                                           .Execute <JObject>(new RestRequest("api/v1/quotes", Method.POST)
                                                              .AddParameter("quote", quote)
                                                              .AddParameter("author", author)
                                                              .AddParameter("year", year))
                                           .Content);
                return(result["success"].ToObject <bool>() ? "Quote added." : $"Adding quote failed: {result["data"]}");
            };

            group.CreateCommand("addquote")
            .Parameter("<quote>|<author>[|year]", Commands.ParameterType.MultipleUnparsed)
            .Description($"I'll add a quote to {quote_site}quotes, mentions will be garbage text in this.")
            .Do(async e =>
            {
                // TODO: Resolve mentions?
                var args = string.Join(" ", e.Args).Split('|');
                if (args.Length < 2)
                {
                    await e.Channel.SendMessageAsync("I need a quote and its author, silly!");
                    return;
                }
                await e.Channel.SendMessageAsync(add_quote(args[0], args[1], args.Length == 2 ? DateTime.Now.Year.ToString() : args[2]));
            });
            group.CreateCommand("quotemessage")
            .Parameter("messageid", Commands.ParameterType.Required)
            .Description($"I'll add a message from this channel as a quote on {quote_site}quotes, mentions will be resolved.")
            .Do(async e =>
            {
                IMessage message = await e.Channel.GetMessageAsync(Convert.ToUInt64(e.Args[0]));
                if (message == null)     // It's missing, report failure.
                {
                    await e.Channel.SendMessageAsync("Sorry, I couldn't find that message!");
                    return;
                }
                await e.Channel.SendMessageAsync(add_quote(Helpers.ResolveTags(message), Helpers.Nickname(message.Author as SocketGuildUser), message.Timestamp.Date.ToShortDateString()));
            });

            Google.AddCommands(group);

            group.CreateCommand("8ball")
            .Parameter("question", Commands.ParameterType.Optional)
            .Parameter("?", Commands.ParameterType.Multiple)
            .Description("The magic eightball can answer any question!")
            .Do(async e =>
            {
                // TODO: Decide if we want to load this will all the other response commands, if so this check could be bypassed
                // Note: We'd also need to put all responses in asterisks.
                if (!string.Join(" ", e.Args).EndsWith("?"))
                {
                    await e.Channel.SendMessageAsync("You must ask a proper question!");
                    return;
                }
                string[] eightball =
                {
                    "It is certain.",             "It is decidedly so.",   "Without a doubt.",
                    "Yes, definitely.",           "You may rely on it.",   "As I see it, yes.",           "Most likely.",          "Outlook good.",
                    "Yes.",                       "Signs point to yes.",   "Reply hazy try again...",     "Ask again later...",
                    "Better not tell you now...", "Cannot predict now...", "Concentrate and ask again...",
                    "Don't count on it.",         "My reply is no.",       "My sources say no.",          "Outlook not so good.",
                    "Very doubtful.",             "Nyas.",                 "Why not?",                    "zzzzz...",              "No."
                };
                await e.Channel.SendMessageAsync($"*{Helpers.Pick(eightball)}*");
            });

            AddResponseCommands(group, "response_commands.json");
            AddResponseCommands(group, "custom_response_commands.json");

            group.CreateCommand("say")
            .Alias("forward")
            .Alias("echo")
            .Parameter("[#channel or @User (or user/channel id in PMs)] text...", Commands.ParameterType.Unparsed)
            .Description("I'll repeat what you said. (To a given user or channel)")
            .Do(async e =>
            {
                IMessageChannel channel = e.Channel;
                string message          = e.Args[0];
                if (message.Length == 0)
                {
                    return;                          // Unparsed can be empty
                }

                /* Liru Note: I don't think we have to do this anymore.
                 * message = e.Message.MentionedChannels.Aggregate(
                 *  e.Message.MentionedUsers.Aggregate(message, (m, u) => m.Replace($"@{u.Name}", u.Mention)),
                 *  (m, c) => m.Replace($"#{c.Name}", c.Mention));
                 */

                if (message.StartsWith("<@") || message.StartsWith("<#"))
                {
                    bool selfmention = e.Message.MentionedUserIds.Contains(Program.Self.Id);
                    var tag          = e.Message.Tags.Skip(selfmention ? 1 : 0).FirstOrDefault();
                    var usermention  = tag.Type == TagType.UserMention;
                    if (tag != null && (usermention || tag.Type == TagType.ChannelMention))
                    {
                        // FIXME: This will fail in some cases, like mentioning a channel way later... we should check the mention is directly after, aside from spacing
                        int index = message.IndexOf('>', selfmention ? message.IndexOf('>') : 0);
                        if (index + 2 < message.Length)
                        {
                            ulong mentionid = tag.Key;
                            if (mentionid != Program.client.CurrentUser.Id)
                            {
                                channel = usermention ? await(tag.Value as IUser).GetOrCreateDMChannelAsync() : tag.Value as IMessageChannel;
                                if (Helpers.CanSay(ref channel, await channel.GetUserAsync(e.User.Id), e.Channel))
                                {
                                    message = message.Substring(index + 2);
                                }
                            }
                        }
                    }
                }
                else if (channel is IPrivateChannel)
                {
                    try
                    {
                        var index = message.IndexOf(' ');
                        if (index != -1 && index + 2 < message.Length)
                        {
                            channel = await Program.GetChannel(Convert.ToUInt64(message.Substring(0, index)));
                            if (Helpers.CanSay(ref channel, (IGuildUser)channel.GetUserAsync(e.User.Id), e.Channel))
                            {
                                message = message.Substring(index + 1);
                            }
                        }
                    } catch { }
                }
                if (message.TrimEnd() != "")
                {
                    await channel.SendMessageAsync(message);
                }
            });

            group.CreateCommand("reverse")
            .Alias("backward")
            .Alias("flip")
            .Parameter("text...", Commands.ParameterType.Unparsed)
            .Description("I'll repeat what you said, in reverse!")
            .Do(async e =>
            {
                var text = e.Args[0];
                if (text.Length != 0)
                {
                    await e.Channel.SendMessageAsync(string.Join("", Helpers.GraphemeClusters(text).Reverse().ToArray()));
                }
            });

            group.CreateCommand("whereami")
            .Alias("channelinfo")
            .Alias("channel")
            .Alias("location")
            .Alias("where")
            .Description("I'll tell you information about the channel and server you're asking me this from.")
            .Do(async e =>
            {
                if (e.Channel is IPrivateChannel)
                {
                    await e.Channel.SendMessageAsync("You're in a private message with me, baka.");
                }
                else
                {
                    var owner      = await e.Server.GetOwnerAsync();
                    var chan       = e.Channel as ITextChannel;
                    string message = $@"You are currently in {e.Channel.Name} (id: {e.Channel.Id})
on server **{e.Server.Name}** (id: {e.Server.Id}) (region: {Program.client.GetVoiceRegion(e.Server.VoiceRegionId).Name} (id: {e.Server.VoiceRegionId}))
owned by {owner.Nickname ?? owner.Username} (id: {e.Server.OwnerId}).";
                    if (!string.IsNullOrEmpty(chan.Topic))
                    {
                        message = message + $@"
The current topic is: {chan.Topic}";
                    }
                    await e.Channel.SendMessageAsync(message);
                }
            });

            group.CreateCommand("avatar")
            .Parameter("[@User1] [@User2] [...]", Commands.ParameterType.Unparsed)
            .Description("I'll give you the avatars of every mentioned users.")
            .Do(async e =>
            {
                if (e.Args[0].Length == 0)
                {
                    return;
                }
                foreach (var t in e.Message.Tags)
                {
                    if (t.Type == TagType.UserMention)
                    {
                        var u   = t.Value as IUser;
                        var url = u.GetAvatarUrl();
                        await e.Channel.SendMessageAsync(u.Mention + (url == null ? " has no avatar." : $"'s avatar is: {url.Substring(0, url.LastIndexOf('?'))}"));
                    }
                }
            });

            group.CreateCommand("lastlog")
            .Parameter("few (default 4)", Commands.ParameterType.Optional)
            .Parameter("string to search for (case-sensitive)", Commands.ParameterType.Unparsed)
            .Description("I'll search for and return the last `few` messages in this channel with your search string in them (This may take a while, depending on history size and `few`)")
            .Do(async e =>
            {
                var args = e.Args;
                if (!Helpers.HasArg(args))
                {
                    await e.Channel.SendMessageAsync("Just read the last messages yourself, baka!");
                }
                else
                {
                    int few = 4;
                    if (Helpers.HasArg(args, 1))
                    {
                        if (int.TryParse(args[0], out few))
                        {
                            if (few <= 0)
                            {
                                await e.Channel.SendMessageAsync("You're silly!");
                                return;
                            }
                            args = args.Skip(1).ToArray();
                        }
                        else
                        {
                            few = 4;
                        }
                    }

                    var search = string.Join(" ", args).TrimEnd();
                    var found  = new List <IMessage>();
                    await Helpers.DoToMessages((e.Channel as SocketTextChannel), few, (msgs, has_cmd_msg) =>
                    {
                        Func <IMessage, bool> find = s => Helpers.ResolveTags(s).Contains(search);
                        found.AddRange(has_cmd_msg ? msgs.Where(s => s.Id != e.Message.Id && find(s)) : msgs.Where(find));
                        return(found.Count());
                    });

                    if ((few = Math.Min(found.Count(), few)) == 0)
                    {
                        await e.Channel.SendMessageAsync("None found...");
                    }
                    else
                    {
                        foreach (var msg in found.Take(few))
                        {
                            var extradata = $"[[{msg.Timestamp}]({msg.GetJumpUrl()})]{msg.Author.Username}:";
                            //if (msg.Content.Length > EmbedBuilder.MaxDescriptionLength) // This should never happen, unless we decide to start searching embeds.
                            {
                                var builder = Helpers.EmbedBuilder;
                                builder.WithTimestamp(msg.Timestamp).WithDescription(msg.Content);
                                builder.WithTitle($"{msg.Author.ToString()}'s message").WithUrl(msg.GetJumpUrl());
                                await e.Channel.SendMessageAsync(embed: builder.Build());
                            }
                            //else await e.Channel.SendMessageAsync($"Content too long to show, message here: <{msg.GetJumpUrl()}>");
                        }
                    }
                }
            });

            RPG.AddCommands(group);

            group.CreateCommand("lotto")
            .Description("I'll give you a set of 6 lucky numbers!")
            .Do(async e =>
            {
                List <int> lotto = new List <int>();
                Random rnd       = new Random();
                for (var i = 0; i != 6; ++i)
                {
                    var number = rnd.Next(1, 60);
                    if (!lotto.Contains(number))
                    {
                        lotto.Add(number);
                    }
                }
                await e.Channel.SendMessageAsync($"Your lucky numbers are **{lotto[0]}, {lotto[1]}, {lotto[2]}, {lotto[3]}, {lotto[4]}, {lotto[5]}**.");
            });

            // TODO: Decide if PerformAction commands should be moved to their own json file like response_commands.json
            group.CreateCommand("pet")
            .Alias("pets")
            .Parameter("[@User1] [@User2] [...]", Commands.ParameterType.Unparsed)
            .Description("Everyone loves being pet, right!?! Pets each *@user*. Leave empty (or mention me too) to pet me!")
            .Do(e => Helpers.PerformAction(e, "pet", "*purrs*", false));

            group.CreateCommand("hug")
            .Alias("hugs")
            .Parameter("[@User1] [@User2] [...]", Commands.ParameterType.Unparsed)
            .Description("Hug someone! Hugs each *@user*. Leave empty to get a hug!")
            .Do(e => Helpers.PerformAction(e, "hug", "<3", true));
        }
Пример #12
0
 public async Task <bool> IsBotPrivateChannel(IMessageChannel contextChannel)
 {
     return(contextChannel.GetType() == typeof(SocketDMChannel) && await contextChannel.GetUserAsync(Client.CurrentUser.Id) != null);
 }
Пример #13
0
    private async Task EloDecayAsync(IMessageChannel thisChannel, string region, int gameMode)
    {
        DateTime nowTime = DateTime.Now;

        List <ulong> decayWarning = new List <ulong>(30);
        List <ulong> decayIDs     = new List <ulong>(30);
        List <int>   decayDays    = new List <int>(30);
        string       query        = $"SELECT decaytimer, decayed, id FROM leaderboard{region}{gameMode};";
        await Globals.conn.OpenAsync();

        try
        {
            MySqlCommand    cmd    = new MySqlCommand(query, Globals.conn);
            MySqlDataReader reader = cmd.ExecuteReader();

            while (reader.Read())
            {
                DateTime oldTime       = new DateTime(reader.GetInt64(0));
                TimeSpan timeDifBinary = nowTime - oldTime;
                int      timeDif       = (int)timeDifBinary.TotalDays;
                int      decayed       = reader.GetInt16(1);
                ulong    id            = reader.GetUInt64(2);
                if (timeDif == 2 && decayed == -1)
                {
                    decayWarning.Add(id);
                }

                if (timeDif - decayed == 3 && decayed > -1)
                {
                    decayIDs.Add(id);
                    decayDays.Add((int)timeDif);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
            await Globals.conn.CloseAsync();

            throw;
        }
        await Globals.conn.CloseAsync();

        foreach (var id in decayWarning)
        {
            await Task.Delay(5000);

            await Globals.conn.OpenAsync();

            query = $"UPDATE leaderboard{region}{gameMode} SET decayed = 0 WHERE id = {id};";
            try
            {
                MySqlCommand cmd = new MySqlCommand(query, Globals.conn);
                cmd.ExecuteNonQuery();
                await thisChannel.SendMessageAsync($"Hey <@{id}> your elo decay will be starting tomorrow. Play a {gameMode}v{gameMode} game in the next 24 hours to prevent this from happening.");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                await Globals.conn.CloseAsync();

                throw;
            }
            await Globals.conn.CloseAsync();
        }

        for (int i = 0; i < decayIDs.Count; i++)
        {
            query = $"UPDATE leaderboard{region}{gameMode} SET elo = elo - {decayDays[i] + 2} WHERE id = {decayIDs[i]};";
            await Globals.conn.OpenAsync();

            try
            {
                MySqlCommand cmd = new MySqlCommand(query, Globals.conn);
                cmd.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                await Globals.conn.CloseAsync();

                throw;
            }
            await Globals.conn.CloseAsync();

            var user = await thisChannel.GetUserAsync(decayIDs[i]);

            Console.WriteLine($"{user.Username} has lost {decayDays[i] + 2} {gameMode}v{gameMode} elo to decay in {region}");

            query = $"UPDATE leaderboard{region}{gameMode} SET decayed = decayed + 1 WHERE id = {decayIDs[i]};";
            await Globals.conn.OpenAsync();

            try
            {
                MySqlCommand cmd = new MySqlCommand(query, Globals.conn);
                cmd.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                await Globals.conn.CloseAsync();

                throw;
            }
            await Globals.conn.CloseAsync();
        }
    }