Exemplo n.º 1
0
        public static async Task <IReadOnlyDictionary <ulong, List <EmojiReaction> > > GetEmojiReactionsForAllGuildsAsync(this DBService db)
        {
            var ereactions = new Dictionary <ulong, List <EmojiReaction> >();

            await db.ExecuteCommandAsync(async (cmd) => {
                cmd.CommandText = "SELECT id, gid, trigger, reaction FROM gf.emoji_reactions;";

                using (var reader = await cmd.ExecuteReaderAsync().ConfigureAwait(false)) {
                    while (await reader.ReadAsync().ConfigureAwait(false))
                    {
                        ulong gid = (ulong)(long)reader["gid"];

                        if (ereactions.ContainsKey(gid))
                        {
                            if (ereactions[gid] == null)
                            {
                                ereactions[gid] = new List <EmojiReaction>();
                            }
                        }
                        else
                        {
                            ereactions.Add(gid, new List <EmojiReaction>());
                        }

                        int id         = (int)reader["id"];
                        string trigger = (string)reader["trigger"];
                        string emoji   = (string)reader["reaction"];

                        EmojiReaction conflict = ereactions[gid].FirstOrDefault(tr => tr.Response == emoji);
                        if (conflict != null)
                        {
                            conflict.AddTrigger(trigger, isRegex: true);
                        }
                        else
                        {
                            ereactions[gid].Add(new EmojiReaction(id, trigger, emoji, isRegex: true));
                        }
                    }
                }
            });

            return(new ReadOnlyDictionary <ulong, List <EmojiReaction> >(ereactions));
        }
Exemplo n.º 2
0
        private async Task AddEmojiReactionAsync(CommandContext ctx, DiscordEmoji emoji, bool regex, params string[] triggers)
        {
            if (triggers == null)
            {
                throw new InvalidCommandUsageException("Missing trigger words!");
            }

            var eb = new StringBuilder();

            foreach (string trigger in triggers.Select(t => t.ToLowerInvariant()))
            {
                if (trigger.Length > 120)
                {
                    eb.AppendLine($"Error: Trigger {Formatter.Bold(trigger)} is too long (120 chars max).");
                    continue;
                }

                if (!this.Shared.EmojiReactions.ContainsKey(ctx.Guild.Id))
                {
                    if (!this.Shared.EmojiReactions.TryAdd(ctx.Guild.Id, new ConcurrentHashSet <EmojiReaction>()))
                    {
                        throw new ConcurrentOperationException("Failed to create emoji reaction data structure");
                    }
                }

                if (regex && !trigger.IsValidRegex())
                {
                    eb.AppendLine($"Error: Trigger {Formatter.Bold(trigger)} is not a valid regular expression.");
                    continue;
                }

                string ename = emoji.GetDiscordName();

                if (this.Shared.EmojiReactions[ctx.Guild.Id].Where(er => er.ContainsTriggerPattern(trigger)).Any(er => er.Response == ename))
                {
                    eb.AppendLine($"Error: Trigger {Formatter.Bold(trigger)} already exists for this emoji.");
                    continue;
                }

                int id = 0;
                try {
                    id = await this.Database.AddEmojiReactionAsync(ctx.Guild.Id, trigger, ename, regex : regex);
                } catch (Exception e) {
                    this.Shared.LogProvider.LogException(LogLevel.Warning, e);
                    eb.AppendLine($"Warning: Failed to add trigger {Formatter.Bold(trigger)} to the database.");
                }

                EmojiReaction reaction = this.Shared.EmojiReactions[ctx.Guild.Id].FirstOrDefault(tr => tr.Response == ename);
                if (reaction != null)
                {
                    if (!reaction.AddTrigger(trigger, isRegex: regex))
                    {
                        throw new CommandFailedException($"Failed to add trigger {Formatter.Bold(trigger)}.");
                    }
                }
                else
                {
                    if (!this.Shared.EmojiReactions[ctx.Guild.Id].Add(new EmojiReaction(id, trigger, ename, isRegex: regex)))
                    {
                        throw new CommandFailedException($"Failed to add trigger {Formatter.Bold(trigger)}.");
                    }
                }
            }

            DiscordChannel logchn = this.Shared.GetLogChannelForGuild((DiscordClientImpl)ctx.Client, ctx.Guild);

            if (logchn != null)
            {
                var emb = new DiscordEmbedBuilder()
                {
                    Title = "New emoji reactions added",
                    Color = this.ModuleColor
                };
                emb.AddField("User responsible", ctx.User.Mention, inline: true);
                emb.AddField("Invoked in", ctx.Channel.Mention, inline: true);
                emb.AddField("Reaction", emoji, inline: true);
                emb.AddField("Triggers", string.Join("\n", triggers));
                if (eb.Length > 0)
                {
                    emb.AddField("With errors", eb.ToString());
                }
                await logchn.SendMessageAsync(embed : emb.Build());
            }

            if (eb.Length > 0)
            {
                await this.InformFailureAsync(ctx, $"Action finished with following warnings/errors:\n\n{eb.ToString()}");
            }
            else
            {
                await this.InformAsync(ctx, "Successfully added all given emoji reactions.", important : false);
            }
        }
Exemplo n.º 3
0
        private async Task AddEmojiReactionAsync(CommandContext ctx, DiscordEmoji emoji, bool regex, params string[] triggers)
        {
            if (emoji is DiscordGuildEmoji && !ctx.Guild.Emojis.Values.Contains(emoji))
            {
                throw new CommandFailedException("The reaction has to be an emoji from this guild.");
            }

            if (triggers is null || !triggers.Any())
            {
                throw new InvalidCommandUsageException("Missing trigger words!");
            }

            if (!this.Shared.EmojiReactions.ContainsKey(ctx.Guild.Id))
            {
                if (!this.Shared.EmojiReactions.TryAdd(ctx.Guild.Id, new ConcurrentHashSet <EmojiReaction>()))
                {
                    throw new ConcurrentOperationException("Failed to create emoji reaction data structure");
                }
            }

            int id;

            using (DatabaseContext db = this.Database.CreateContext()) {
                DatabaseEmojiReaction dber = db.EmojiReactions.FirstOrDefault(er => er.GuildId == ctx.Guild.Id && er.Reaction == emoji.GetDiscordName());
                if (dber is null)
                {
                    dber = new DatabaseEmojiReaction {
                        GuildId  = ctx.Guild.Id,
                        Reaction = emoji.GetDiscordName()
                    };
                    db.EmojiReactions.Add(dber);
                    await db.SaveChangesAsync();
                }

                foreach (string trigger in triggers)
                {
                    dber.DbTriggers.Add(new DatabaseEmojiReactionTrigger {
                        ReactionId = dber.Id, Trigger = regex ? trigger : Regex.Escape(trigger)
                    });
                }

                await db.SaveChangesAsync();

                id = dber.Id;
            }

            var eb = new StringBuilder();

            foreach (string trigger in triggers.Select(t => t.ToLowerInvariant()))
            {
                if (trigger.Length > 120)
                {
                    eb.AppendLine($"Error: Trigger {Formatter.Bold(trigger)} is too long (120 chars max).");
                    continue;
                }

                if (regex && !trigger.IsValidRegex())
                {
                    eb.AppendLine($"Error: Trigger {Formatter.Bold(trigger)} is not a valid regular expression.");
                    continue;
                }

                ConcurrentHashSet <EmojiReaction> ereactions = this.Shared.EmojiReactions[ctx.Guild.Id];

                string ename = emoji.GetDiscordName();
                if (ereactions.Where(er => er.ContainsTriggerPattern(trigger)).Any(er => er.Response == ename))
                {
                    eb.AppendLine($"Error: Trigger {Formatter.Bold(trigger)} already exists for this emoji.");
                    continue;
                }

                EmojiReaction reaction = ereactions.FirstOrDefault(tr => tr.Response == ename);
                if (reaction is null)
                {
                    if (!ereactions.Add(new EmojiReaction(id, trigger, ename, isRegex: regex)))
                    {
                        throw new CommandFailedException($"Failed to add trigger {Formatter.Bold(trigger)}.");
                    }
                }
                else
                {
                    if (!reaction.AddTrigger(trigger, isRegex: regex))
                    {
                        throw new CommandFailedException($"Failed to add trigger {Formatter.Bold(trigger)}.");
                    }
                }
            }

            DiscordChannel logchn = this.Shared.GetLogChannelForGuild(ctx.Client, ctx.Guild);

            if (!(logchn is null))
            {
                var emb = new DiscordEmbedBuilder {
                    Title = "New emoji reactions added",
                    Color = this.ModuleColor
                };
                emb.AddField("User responsible", ctx.User.Mention, inline: true);
                emb.AddField("Invoked in", ctx.Channel.Mention, inline: true);
                emb.AddField("Reaction", emoji, inline: true);
                emb.AddField("Triggers", string.Join("\n", triggers));
                if (eb.Length > 0)
                {
                    emb.AddField("With errors", eb.ToString());
                }
                await logchn.SendMessageAsync(embed : emb.Build());
            }

            if (eb.Length > 0)
            {
                await this.InformFailureAsync(ctx, $"Action finished with following warnings/errors:\n\n{eb.ToString()}");
            }
            else
            {
                await this.InformAsync(ctx, "Successfully added all given emoji reactions.", important : false);
            }
        }