Пример #1
0
        private async Task VerifyCurrentUserRolesAsync()
        {
            var members = (await _textChannel.Guild.GetAllMembersAsync()).ToList();

            var usersWithMentionRoles =
                members.Where(x => _config.MentionRoles.Intersect(x.Roles.Select(y => y.Id)).Any()).ToList();

            // Check users who have reacted to the embed
            foreach (var(roleId, messageId) in _existingRoleEmbeds)
            {
                var message = await _textChannel.GetMessageAsync(messageId);

                var role = _textChannel.Guild.GetRole(roleId);

                if (!message.Author.IsSelf(_discordClient))
                {
                    continue;
                }

                // Get all users who have reacted to the embed
                var reactionUsers =
                    (await message.GetReactionsAsync(_config.MentionRoleEmoji, _textChannel.Guild.MemberCount))
                    .ToList();

                foreach (var user in reactionUsers.Where(user => !user.IsSelf(_discordClient) &&
                                                         !usersWithMentionRoles.Any(x =>
                                                                                    x.Roles.Any(y => y.Id == roleId) &&
                                                                                    x.Id == user.Id)))
                {
                    var member = members.FirstOrDefault(x => x.Id == user.Id);

                    if (member == null)
                    {
                        // User doesn't exist in the guild lets delete their reaction
                        continue;
                    }

                    // Make sure the user is not null, in case they have been banned/left the server
                    await member.GrantRoleAsync(role);
                }

                var userWithRole = usersWithMentionRoles.Where(x => x.Roles.Any(x => x.Id == roleId));
                foreach (var member in userWithRole)
                {
                    if (reactionUsers.Any(x => x.Id == member.Id) && !member.IsSelf(_discordClient))
                    {
                        continue;
                    }

                    // User has not reacted, remove the role
                    var guildUser = await _textChannel.Guild.GetMemberAsync(member.Id);

                    await guildUser.RevokeRoleAsync(role);
                }
            }
        }
Пример #2
0
        private static async Task CheckMessageAsync(DiscordClient client, DiscordChannel channel, DiscordUser user, DiscordMessage message, DiscordEmoji emoji, bool isBacklog)
        {
            try
            {
                if (user.IsBotSafeCheck() || channel.IsPrivate)
                {
                    return;
                }

                // in case it's not in cache and doesn't contain any info, including Author
                message = await channel.GetMessageAsync(message.Id).ConfigureAwait(false);

                if (emoji == Config.Reactions.Starbucks)
                {
                    await CheckMediaTalkAsync(client, channel, message, emoji).ConfigureAwait(false);
                }
                if (emoji == Config.Reactions.Shutup && !isBacklog)
                {
                    await ShutupAsync(client, user, message).ConfigureAwait(false);
                }
                if (emoji == Config.Reactions.BadUpdate && !isBacklog)
                {
                    await BadUpdateAsync(client, user, message, emoji).ConfigureAwait(false);
                }

                await CheckGameFansAsync(client, channel, message).ConfigureAwait(false);
            }
            catch (Exception e)
            {
                Config.Log.Error(e);
            }
        }
Пример #3
0
        public async Task RemoveServerAsync(IPEndPoint endPoint, ulong guildID)
        {
            GameServer serverToRemove = (await _dbContext.GameServers.AsQueryable().ToListAsync()).FirstOrDefault(x => x.ServerIP.Address.ToString() == endPoint.Address.ToString() && x.ServerIP.Port == endPoint.Port && x.GuildID == guildID);

            if (serverToRemove == null)
            {
                throw new ArgumentException("The specified server does not exist");
            }
            if (serverToRemove.MessageID != null)
            {
                try
                {
                    if (!_discordClient.Guilds.TryGetValue(serverToRemove.GuildID, out DiscordGuild guild))
                    {
                        return;
                    }
                    DiscordChannel channel = guild?.GetChannel(serverToRemove.ChannelID);
                    DiscordMessage msg     = await(channel?.GetMessageAsync(serverToRemove.MessageID.Value));
                    if (msg != null)
                    {
                        await msg.DeleteAsync();
                    }
                }
                catch (Exception e)
                {
                    _logger.LogError(e, $"Error trying to remove message for game server {endPoint.Address}");
                }
            }
            _dbContext.GameServers.Remove(serverToRemove);
            await _dbContext.SaveChangesAsync();
        }
Пример #4
0
        public static async Task <DiscordMessage> GetMessageAsync(DiscordChannel channel, ulong messageID)
        {
            if (!ChannelHasPermission(channel, Permissions.ReadMessageHistory))
            {
                return(null);
            }

            try
            {
                return(await channel.GetMessageAsync(messageID));
            }
            catch (DSharpPlus.Exceptions.ServerErrorException e)
            {
                Logger.Debug(e.ToString());
                return(null);
            }
            catch (DSharpPlus.Exceptions.NotFoundException e)
            {
                Logger.Debug(e.ToString());
                return(null);
            }
            catch (Exception e)
            {
                Logger.Error("Error occurred when attempting to read message with ID " + messageID + " from channel \"" + channel.Name + "\". Error message: " + e);
                return(null);
            }
        }
Пример #5
0
 public static async Task <DiscordMessage> GetMessage(this DiscordChannel channel, ulong messageId)
 {
     try
     {
         return(await channel.GetMessageAsync(messageId));
     }
     catch (Exception)
     {
         return(null);
     }
 }
Пример #6
0
        private async Task <DiscordMessage> FindStarPost(DiscordChannel starboardChannel, ulong messageId,
                                                         bool timeLimited = true)
        {
            var dateThreshold = DateTimeOffset.Now.AddDays(-1);

            // TODO: optimize this with a cache when we hit 100+ servers with star msg id -> chan,msg id


            var cacheEntry = await _database.StarboardCache.FirstOrDefaultAsync(e => e.MessageId == messageId && e.GuildId == starboardChannel.GuildId);

            if (cacheEntry != null)
            {
                var message = await starboardChannel.GetMessageAsync(cacheEntry.StarboardId);

                return(message);
            }

            var messageIdStr = messageId.ToString();
            var messages     = await starboardChannel.GetMessagesAsync();

            var count = 0;

            while (messages.Count > 0)
            {
                foreach (var message in messages)
                {
                    count++;

                    // break when message is too old.
                    if (timeLimited && message.CreationTimestamp <= dateThreshold)
                    {
                        return(null);
                    }

                    if (message.Author.Id == _client.CurrentUser.Id && message.Embeds
                        .SelectMany(e => e.Fields ?? EmptyEmbedFields)
                        .Any(f => f.Name == "Message ID" && f.Value == messageIdStr))
                    {
                        return(message);
                    }
                }

                // break when we hit 400 messages
                if (count > 400)
                {
                    return(null);
                }

                messages = await starboardChannel.GetMessagesBeforeAsync(messages.Last().Id);
            }

            return(null);
        }
Пример #7
0
        internal static async Task RoleMessageEdit(DiscordChannel channel,
                                                   ulong messageId,
                                                   string content)
        {
            DiscordMessage message = await channel.GetMessageAsync(messageId);

            // Only continue if the message was found.
            if (!(message is null) && (message.Id == messageId))
            {
                await message.ModifyAsync(content);
            }
        }
Пример #8
0
        public static async Task <DiscordMessage> GetRestartStatusMessageAsync(DiscordClient client)
        {
            string[] lines = File.ReadAllLines("restart");

            DiscordChannel channel = await client.GetChannelAsync(ulong.Parse(lines[0]));

            DiscordMessage message = await channel.GetMessageAsync(ulong.Parse(lines[1]));

            File.Delete("restart");

            return(message);
        }
Пример #9
0
        public async Task <TryResolveResultObject <DiscordMessage> > TryResolveMessage(DiscordChannel channel, ulong messageId)
        {
            try
            {
                var message = await channel.GetMessageAsync(messageId);

                return(new TryResolveResultObject <DiscordMessage>(message));
            }
            catch (Exception)
            {
                return(new TryResolveResultObject <DiscordMessage>(false, "Message not found"));
            }
        }
Пример #10
0
        private DiscordMessage GetMessage(string message)
        {
            try
            {
                return(Channel.GetMessageAsync(GetID(message)).Result);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);

                return(null);
            }
        }
Пример #11
0
        public async Task AddAndStartPollAsync(Poll poll)
        {
            DiscordGuild guild = await _discordClient.GetGuildAsync(poll.GuildId);

            DiscordChannel channel     = guild?.GetChannel(poll.ChannelId);
            DiscordMessage pollMessage = await channel.GetMessageAsync(poll.MessageId);

            await pollMessage.PinAsync();

            await _dbContext.Polls.AddAsync(poll);

            await _dbContext.SaveChangesAsync();

            await StartPollAsync(poll);
        }
Пример #12
0
        public async Task RestoreState(object state)
        {
            SerializablePendingApplication application = (SerializablePendingApplication)state;
            DiscordGuild guild = await Bot.Client.GetGuildAsync(application.GuildID).ConfigureAwait(false);

            DiscordChannel channel = guild.GetChannel(application.ChannelID);
            DiscordMessage message = await channel.GetMessageAsync(application.MessageID).ConfigureAwait(false);

            DiscordMember applicant = await guild.GetMemberAsync(application.ApplicatntID).ConfigureAwait(false);

            this.Message           = message;
            this.Applicant         = applicant;
            this.ApplicantRespones = application.ApplicantResponses;
            this.Title             = application.Title;
        }
Пример #13
0
        public async Task <DiscordMessage?> ResolveMessage(DiscordChannel channel, ulong messageId)
        {
            try
            {
                var message = await channel.GetMessageAsync(messageId);

                return(message);
            }
            catch (Exception ex)
            {
                await _discordErrorLogger.LogDiscordError(ex.ToString());

                return(null);
            }
        }
Пример #14
0
        private async Task ProfanityFilterRemove(DiscordClient dClient, MessageReactionAddEventArgs args)
        {
            if (args.User.Id == dClient.CurrentUser.Id || (args.Channel?.Id != SBGChannels.Bloonside && !args.Emoji.Equals(DiscordEmoji.FromName(this.dClient, ":wastebasket:"))))
            {
                return;
            }

            DiscordChannel bloonside = await this.dClient.GetChannelAsync(SBGChannels.Bloonside);

            DiscordMessage foulEmbed = await bloonside.GetMessageAsync(args.Message.Id);

            if (args.Message.Channel.Id == SBGChannels.Bloonside && foulEmbed.Author.Id == dClient.CurrentUser.Id && foulEmbed.Embeds.Count > 0 && foulEmbed.Embeds[0].Title.Contains("Censor"))
            {
                await foulEmbed.DeleteAsync();
            }

            return;
        }
Пример #15
0
        internal static async Task RoleEmbedAppendRole(CommandContext ctx,
                                                       DiscordChannel channel,
                                                       ulong messageId,
                                                       DiscordEmoji emoji,
                                                       DiscordRole role)
        {
            var a = CheckEmoteMessageExists(messageId, emoji);
            var b = channel.GetMessageAsync(messageId);

            await Task.WhenAll(a, b);

            bool           emoteExistsAlready = a.Result;
            DiscordMessage message            = b.Result;

            // Check if that role is already on this message.
            if (!emoteExistsAlready)
            {   // It does not, so let's continue.
                var c = message.ModifyAsync(String.Format("{0}\n{1} {2}",
                                                          arg0: message.Content,
                                                          arg1: EmojiConverter.GetEmojiString(emoji),
                                                          arg2: role.Mention));
                var d = message.CreateReactionAsync(emoji);
                var e = AddMessageToDatabase(messageId, role, emoji);

                await Task.WhenAll(c, d, e);

                await ctx.RespondAsync(
                    embed : Generics.GenericEmbedTemplate(
                        color: Generics.NeutralColor,
                        description: $"Tasks:\nEdit Success: {c.IsCompletedSuccessfully}\n" +
                        $"Create Reaction Success: {d.IsCompletedSuccessfully}\n" +
                        $"Database Success: {e.IsCompletedSuccessfully}",
                        title: @"Add new roles onto embed"));
            }
            else
            {
                await ctx.RespondAsync(
                    embed : Generics.GenericEmbedTemplate(
                        color: Generics.NegativeColor,
                        description: Generics.NegativeDirectResponseTemplate(
                            mention: ctx.Member.Mention,
                            body: $"that message already has emote {EmojiConverter.GetEmojiString(emoji)} on it...")));
            }
        }
Пример #16
0
        private async Task OnMessageReactionAdded(DiscordClient dClient, MessageReactionAddEventArgs args)
        {
            if (args.Guild.Id != Guilds.Bloon || args.Channel.Id != BloonChannels.Settings || args.User.Id == dClient.CurrentUser.Id)
            {
                return;
            }

            DiscordChannel settingsChannel = await this.dClient.GetChannelAsync(BloonChannels.Settings);

            DiscordChannel botMods = await this.dClient.GetChannelAsync(BloonChannels.BotMods);

            DiscordMessage featureMessage = await settingsChannel.GetMessageAsync(args.Message.Id);

            Feature feature = this.featureManager.Features.Where(f => f.Name == featureMessage.Embeds[0]?.Title).FirstOrDefault();

            if (feature == null)
            {
                return;
            }
            else if (args.Emoji.Id == FeatureEmojis.ToggleOff && feature.Enabled)
            {
                await feature.Disable();

                await this.featureManager.UpdateFeatureStatusAsync(feature.Name, false);

                await botMods.SendMessageAsync($"{args.User.Username}#{args.User.Discriminator} *disabled* `{feature.Name}` at {DateTime.Now}\n" +
                                               $"{featureMessage.JumpLink}");
            }
            else if (args.Emoji.Id == FeatureEmojis.ToggleOn && !feature.Enabled)
            {
                await feature.Enable();

                await this.featureManager.UpdateFeatureStatusAsync(feature.Name, true);

                await botMods.SendMessageAsync($"{args.User.Username}#{args.User.Discriminator} *enabled* `{feature.Name}` at {DateTime.Now}\n" +
                                               $"{featureMessage.JumpLink}");
            }

            await featureMessage.ModifyAsync(embed : CreateFeatureEmbed(feature));

            await featureMessage.DeleteReactionAsync(args.Emoji, args.User);
        }
Пример #17
0
        private async Task UpdateRolePost(CommandArgs <RoleBotConfig> args)
        {
            if (args.Config.RolePostChannelID != 0 && args.Config.RolePostID != 0)
            {
                DiscordChannel channel = args.Guild.GetChannel(args.Config.RolePostChannelID);
                DiscordMessage message = await channel?.GetMessageAsync(args.Config.RolePostID);

                if (message != null)
                {
                    await message.ModifyAsync(FormatRolePost(args.Guild, args.Config));

                    await message.DeleteAllReactionsAsync();

                    foreach (var emojiRole in args.Config.EmojiRoles)
                    {
                        DiscordEmoji emoji = DiscordEmoji.FromName(Instance.Client, emojiRole.Key);
                        await message.CreateReactionAsync(emoji);
                    }
                }
            }
        }
Пример #18
0
        private async Task OperationUpdated(OperationUpdatedEventArgs e)
        {
            DiscordChannel channel = null;
            await _repository.SaveAsync(_ops);

            try
            {
                channel = await _client.GetChannelAsync(_opBotChannelId);

                DiscordMessage message = await channel.GetMessageAsync(e.Operation.MessageId);

                await message.ModifyAsync(e.Operation.GetOperationMessageText());
            }
            catch (NotFoundException)
            {
                if (channel != null)
                {
                    await SendError(channel, "I was unable to update the operation message. Someone appears to have deleted the operation");
                }
            }
        }
Пример #19
0
        internal static async Task BotClientMessageDeleted(MessageDeleteEventArgs e)
        {
            if (e.Channel.Id == Program.Settings.RimboardChannelId)
            {
                // Be warned: OriginalReactCount is always equal to -1.
                PinInfo pinInfo = await QueryPinInfoFromRimboardId(e.Message.Id);

                if (!pinInfo.Equals(PinInfo.Invalid))
                {
                    // Get the channels.
                    DiscordChannel originalChannel = e.Guild.GetChannel(pinInfo.OriginalChannelId);

                    DiscordMessage originalMessage = await originalChannel.GetMessageAsync(pinInfo.OriginalMessageId);

                    var a = originalMessage.DeleteAllReactionsAsync();
                    var b = RemovePinFromDatabase(pinInfo);

                    await Task.WhenAll(a, b);
                }
            }
        }
Пример #20
0
        internal async Task Initialize(DiscordGuild guild = null)
        {
            if (guild != null)
            {
                Guild = guild;
            }
            //GuildId = guild.Id;

            ConnectToVoice             = Guild.Channels.FirstOrDefault(c => c.Value.Name == ConnectToVoiceName).Value;
            SetRandomReactionOnChannel = Guild.GetChannel(SetRandomReactionOnChannelId);
            if (SetRandomReactionOnChannel != null)
            {
                SetRandomReactionOnMessage = await SetRandomReactionOnChannel?.GetMessageAsync(SetRandomReactionOnMessageId);
            }

            try {
                var r = SetRandomReactionOnMessage.Reactions[new Random().Next(0, 2)];                //Assuming Gender reactinos are always first
                await SetRandomReactionOnMessage.CreateReactionAsync(r.Emoji);

                _ = DummyBot.Instance.VoiceNextConfiguration.ConnectAsync(ConnectToVoice).ConfigureAwait(false);
            } catch (Exception e) {
                Console.WriteLine(e);
            }
        }
Пример #21
0
        private async Task OperationClosed(OperationDeletedEventArgs e)
        {
            DiscordChannel channel = null;
            await _repository.SaveAsync(_ops);

            try
            {
                channel = await _client.GetChannelAsync(_opBotChannelId);

                DiscordMessage message = await channel.GetMessageAsync(e.MessageId);

                await message.ModifyAsync($"{DiscordText.NoEntry} {DiscordText.BigText("closed")}  {message.Content}");

                await message.UnpinAsync();
            }
            catch (NotFoundException)
            {
                // do nothing
            }
            catch (UnauthorizedException)
            {
                await channel.SendMessageAsync("Unable to perform unpin. I need the 'Manage Messages' permission to do so.");
            }
        }
Пример #22
0
 /// <summary>
 ///     Deletes a single <see cref="DiscordMessage" /> by id.
 /// </summary>
 /// <param name="channel">Represents the <see cref="DiscordChannel" />.</param>
 /// <param name="messageId">Represents the id of the <see cref="DiscordMessage" />.</param>
 /// <returns></returns>
 public static async Task DeleteMessageByIdAsync(this DiscordChannel channel, ulong messageId)
 {
     await channel.GetMessageAsync(messageId)
     .Result.DeleteAsync();
 }
Пример #23
0
        public void BeginTimeboxMeeting()
        {
            Task.Run(async() => {
                DiscordChannel statsChannel = await CreateTimeboxStatsChannel();
                DiscordMessage statsMessage = null;

                while (currentTimeboxTime > 0 && !meetingClosed)
                {
                    //Refresh the channel.
                    statsChannel = guild.GetChannel(statsChannel.Id);

                    //Make sure stats channel exists.
                    if (statsChannel == null)
                    {
                        statsChannel = await CreateTimeboxStatsChannel();
                    }


                    //Handle message deletions.
                    if (statsMessage != null)
                    {
                        try {
                            statsMessage = await statsChannel.GetMessageAsync(statsMessage.Id);
                        }
                        catch (Exception) {
                            await statsChannel.AddOverwriteAsync(guild.EveryoneRole, DSharpPlus.Permissions.SendMessages, DSharpPlus.Permissions.None);
                            statsMessage = null;
                        }
                    }

                    if (statsMessage == null)
                    {
                        try {
                            statsMessage = await new DiscordMessageBuilder()
                                           .WithContent(getTimeboxStatsMessage())
                                           .SendAsync(statsChannel);
                        }
                        catch (Exception) {
                            //Cry me a f*****g river.
                        }
                        await statsChannel.AddOverwriteAsync(guild.EveryoneRole, DSharpPlus.Permissions.None, DSharpPlus.Permissions.SendMessages);
                    }
                    else
                    {
                        try {
                            await statsMessage.ModifyAsync(getTimeboxStatsMessage());
                        }
                        catch (Exception) {
                            //Again, just throwing random ass exceptions for no apparent reason.
                            //Thanks DSharpPlus, you're my favourite API :D
                        }
                    }

                    //10 second update.
                    await Task.Delay(1000 * 10);
                    currentTimeboxTime -= 10;
                }

                await CloseMeeting();
            });
        }
Пример #24
0
        private async void ObserveLobbies()
        {
            try
            {
                TargetChannel = await Program.Client.GetChannelAsync(Convert.ToUInt64(PalantirEndpoint.ChannelID));

                TargetMessage = await TargetChannel.GetMessageAsync(Convert.ToUInt64(PalantirEndpoint.MessageID));
            }
            catch (Exception e)
            {
                Console.WriteLine(DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss") + " > Exception: " + e.ToString() + "at Channel:" + PalantirEndpoint.ChannelID + ", Msg: " + PalantirEndpoint.MessageID + ", Guild:" + PalantirEndpoint.GuildName);
                //RemoveTether();
                return;
            }

            int    notFound    = 0;
            string lastContent = "";

            while (!abort)
            {
                try
                {
                    // try to build lobby message
                    string content = BuildLobbyContent();
                    if (content == lastContent)
                    {
                        await TargetChannel.TriggerTypingAsync();

                        Thread.Sleep(4000);
                        continue;
                    }
                    else
                    {
                        lastContent = content;
                    }
                    DiscordMessage split;
                    try
                    {
                        do
                        {
                            split = (await TargetChannel.GetMessagesAfterAsync(TargetMessage.Id, 1)).First();
                        }while (split.Author.Id != Program.Client.CurrentUser.Id);
                    }
                    catch
                    {
                        // no split message found -> not required yet
                        split = null;
                    }
                    if (content.Length <= 1900)
                    {
                        TargetMessage = await TargetMessage.ModifyAsync(content.Replace(" ", ""));

                        if (!(split is null))
                        {
                            await split.ModifyAsync("_ _");
                        }
                    }
                    else
                    {
                        int lastLobbyBreak = content.Length > 1900 ? 1900 : content.Length;
                        while (content[lastLobbyBreak] != ' ' || lastLobbyBreak < 1000)
                        {
                            lastLobbyBreak--;
                        }
                        TargetMessage = await TargetMessage.ModifyAsync(content.Substring(0, lastLobbyBreak - 1).Replace(" ", ""));

                        if (split is null)
                        {
                            split = await TargetChannel.SendMessageAsync("_ _");
                        }
                        split = await split.ModifyAsync(content.Substring(lastLobbyBreak + 1, content.Length - lastLobbyBreak - 1).Replace(" ", ""));
                    }
                    await TargetChannel.TriggerTypingAsync();

                    notFound = 0;
                }
                catch (Microsoft.Data.Sqlite.SqliteException e) // catch sql exceptions
                {
                    if (e.SqliteErrorCode == 8)
                    {
                        Console.WriteLine(DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss") + " > Locked DB. Skipped writing lobby data for this cycle.");
                    }
                    else
                    {
                        Console.WriteLine(DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss") + " > DB Error: " + e.SqliteErrorCode + ". Skipped writing lobby data for this cycle.\n" + e.ToString());
                    }
                }
                catch (DSharpPlus.Exceptions.NotFoundException e) // catch Discord api axceptions
                {
                    notFound++;
                    if (notFound > maxErrorCount)
                    {
                        Console.WriteLine(DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss")
                                          + " > Target Message couldnt be edited. Not found incremented to " + notFound + " / " + maxErrorCount
                                          + " Error: " + e.ToString());
                        RemoveTether();
                        return;
                    }
                }
                catch (DSharpPlus.Exceptions.UnauthorizedException e) // catch Discord api axceptions
                {
                    notFound++;
                    if (notFound > maxErrorCount)
                    {
                        Console.WriteLine(DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss")
                                          + " > Target Message couldnt be edited. Not found incremented to " + notFound + " / " + maxErrorCount
                                          + " Error: " + e.ToString());
                        //RemoveTether();
                        return;
                    }
                }
                catch (Exception e) // catch other exceptions
                {
                    int line = new StackTrace(e, true).GetFrame(0).GetFileLineNumber();
                    Console.WriteLine(DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss") + " > Unhandled exception on line " + line + " - Target message couldnt be edited. No removal of tether, just 15s timeout. Error: " + e.ToString());
                    Thread.Sleep(15000);
                }
                Thread.Sleep(4000);
            }
        }
Пример #25
0
        private async Task StartPollAsync(Poll poll)
        {
            DiscordGuild guild = await _discordClient.GetGuildAsync(poll.GuildId);

            DiscordChannel channel     = guild?.GetChannel(poll.ChannelId);
            DiscordMember  pollCreator = await guild.GetMemberAsync(poll.CreatorId);

            DiscordMessage pollMessage = await channel.GetMessageAsync(poll.MessageId);

            pollMessage = await pollMessage.ModifyAsync(x => x.AddComponents(PollMessageUpdater.BuildAnswerButtons(poll.PossibleAnswers)));

            var pollMessageUpdater = PollMessageUpdater.Create(pollMessage);

            TimeSpan pollDuration      = poll.EndTimeUTC - DateTime.UtcNow;
            var      cancelTokenSource = new CancellationTokenSource();

            cancelTokenSource.CancelAfter(pollDuration);

            while (!cancelTokenSource.IsCancellationRequested)
            {
                var btnClick = await pollMessage.WaitForButtonAsync(cancelTokenSource.Token);

                if (!btnClick.TimedOut)
                {
                    var user     = btnClick.Result.User;
                    var answerId = btnClick.Result.Id;

                    var answer = poll.PossibleAnswers.First(x => x.Id == answerId);

                    answer.UpdateCount(user.Id);
                    _dbContext.Update(poll);
                    await _dbContext.SaveChangesAsync(cancelTokenSource.Token);

                    await btnClick.Result.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage);

                    await pollMessageUpdater.UpdateAnswers(poll.PossibleAnswers);
                }
            }

            var pollResult = poll.PossibleAnswers
                             .Select(r => (Emoji: r.Emoji, Count: r.Count))
                             .ToList();

            await pollMessageUpdater.SetAsEnded(poll.EndTimeUTC);

            await pollMessage.UnpinAsync();

            if (!pollResult.Any(r => r.Count > 0))
            {
                await channel.SendMessageAsync($"No one participated in the poll {poll.Question} :(");

                return;
            }

            Dictionary <DiscordEmoji, string> emojiMapping = GetEmojiMapping(poll.PossibleAnswers.Select(x => x.Value).ToList());
            int totalVotes      = pollResult.Sum(r => r.Count);
            var pollResultEmbed = new DiscordEmbedBuilder()
                                  .WithTitle($"Poll results: {poll.Question}")
                                  .WithColor(DiscordColor.Azure)
                                  .WithDescription(
                $"**{pollCreator.Mention}{(pollCreator.DisplayName.EndsWith('s') ? "'" : "'s")} poll ended. Here are the results:**\n\n" +
                string.Join("\n", emojiMapping
                            .Select(ans =>
                                    new { Answer = ans.Value, Votes = pollResult.Single(r => r.Emoji == ans.Key).Count })
                            .Select(ans =>
                                    $"**{ans.Answer}**: {"vote".ToQuantity(ans.Votes)} ({100.0 * ans.Votes / totalVotes:F1} %)"))
                );
            await channel.SendMessageAsync(embed : pollResultEmbed.Build());

            _dbContext.Polls.Remove(poll);
            await _dbContext.SaveChangesAsync();
        }
Пример #26
0
        public async Task EditAsync([TextChannel] DiscordChannel channel, ulong messageId, [Remainder] string message)
        {
            var permissions = channel.Guild.CurrentMember.PermissionsIn(channel);

            if (!permissions.HasPermission(Permissions.AccessChannels))
            {
                await ReplyErrorAsync(Localization.AdministrationTextChannelNoViewPermission);

                return;
            }

            if (!permissions.HasPermission(Permissions.SendMessages))
            {
                await ReplyErrorAsync(Localization.BotTextChannelNoSendMessagesPermission);

                return;
            }

            var discordMessage = await channel.GetMessageAsync(messageId);

            if (discordMessage is null)
            {
                await ReplyErrorAsync(Localization.BotMessageNotFound);

                return;
            }

            if (discordMessage.MessageType != MessageType.Default)
            {
                await ReplyErrorAsync(Localization.BotMessageNotUserMessage);

                return;
            }

            if (discordMessage.Author.Id != channel.Guild.CurrentMember.Id)
            {
                await ReplyErrorAsync(Localization.BotMessageNotSelf);

                return;
            }

            switch (RiasUtilities.TryParseMessage(message, out var customMessage))
            {
            case true when string.IsNullOrEmpty(customMessage.Content) && customMessage.Embed is null:
                await ReplyErrorAsync(Localization.AdministrationNullCustomMessage);

                return;

            case true:
                await discordMessage.ModifyAsync(customMessage.Content, customMessage.Embed?.Build() ?? (Optional <DiscordEmbed>) default);

                break;

            default:
                await discordMessage.ModifyAsync(message);

                break;
            }

            await ReplyConfirmationAsync(Localization.BotMessageEdited);
        }
Пример #27
0
 public static async Task <DiscordMessage> GetMessageAsync(DiscordChannel channel, ulong id)
 {
     return(await RunSafeAsync(async() => await channel.GetMessageAsync(id).ConfigureAwait(false)).ConfigureAwait(false));
 }
Пример #28
0
 public static Task <DiscordMessage> GetMessage(this DiscordChannel channel, ulong id) =>
 WrapDiscordCall(channel.GetMessageAsync(id));
Пример #29
0
        /// <summary>
        /// Fire this after receiving a message from the web bridge.
        /// Current actions supported: Send, Delete
        /// </summary>
        /// <param name="message">The message coming from the SignalR hub.</param>
        /// <returns>The task representing the message's processing status.</returns>
        public async Task IngestSignalR(BridgeMessage message)
        {
            if (!Ready)
            {
                throw new NullReferenceException("Guild not found.");
            }

            if (message.SignalRMessage.Action == "NewMessage")
            {
                DiscordChannel bridgeChannel = await this.discordClient.GetChannelAsync(ChannelId);

                DiscordMember guildMember = await bridgeChannel.Guild.GetMemberAsync(message.UserId);

                NewMessage newMessage = message.SignalRMessage as NewMessage;

                MatchCollection colonEmotes       = Regex.Matches(newMessage.Content, @":[a-zA-Z0-9_~]+:(?!\d+)");
                string          translatedContent = newMessage.Content;
                List <string>   translatedEmotes  = new List <string>(colonEmotes.Count);

                foreach (Match colonEmote in colonEmotes)
                {
                    if (translatedEmotes.Contains(colonEmote.Value))
                    {
                        break;
                    }

                    try
                    {
                        DiscordEmoji emote = DiscordEmoji.FromName(discordClient, colonEmote.Value);
                        if (emote.Id == 0)
                        {
                            translatedContent = translatedContent.Replace(colonEmote.Value, emote.Name);
                        }
                        else if (emote.IsAnimated)
                        {
                            translatedContent = translatedContent.Replace(colonEmote.Value, $"<a:{emote.Name}:{emote.Id}>");
                        }
                        else if (!emote.IsAnimated)
                        {
                            translatedContent = translatedContent.Replace(colonEmote.Value, $"<:{emote.Name}:{emote.Id}>");
                        }

                        translatedEmotes.Add(colonEmote.Value);
                    }
                    catch
                    {
                        // The emote doesn't exist on the target server, or it's been deleted.
                        // Just do nothing (don't attempt to translate it)
                    }
                }

                if (guildMember == null)
                {
                    throw new UnauthorizedAccessException("Not in Discord guild.");
                }
                else
                {
                    await webhookClient.Webhooks[0].ExecuteAsync(new DiscordWebhookBuilder()
                    {
                        Content   = translatedContent,
                        Username  = guildMember.DisplayName,
                        AvatarUrl = guildMember.AvatarUrl,
                        IsTTS     = false
                    });
                }
            }
            else if (message.SignalRMessage.Action == "DeleteMessage")
            {
                DiscordChannel bridgeChannel = await this.discordClient.GetChannelAsync(ChannelId);

                DiscordMember guildMember = await bridgeChannel.Guild.GetMemberAsync(message.UserId);

                if (guildMember == null)
                {
                    return;
                }

                if (bridgeChannel.PermissionsFor(guildMember).HasPermission(Permissions.ManageMessages))
                {
                    DiscordMessage delMessage = await bridgeChannel.GetMessageAsync(ulong.Parse(message.SignalRMessage.MessageId));

                    await delMessage.DeleteAsync();

                    return;
                }

                // Nothing to do, user doesn't have permission to delete the message.
                return;
            }
            else
            {
                throw new InvalidOperationException("Undefined action.");
            }
        }
        private async Task SendAdjustedDate(DiscordClient c, MessageReactionAddEventArgs e)
        {
            if (e.User.IsBot)
            {
                return;
            }

            if (e.Channel.IsPrivate)
            {
                return;
            }

            DiscordChannel channel = await c.GetChannelAsync(e.Channel.Id);

            _ = Task.Run(async() =>
            {
                if (e.Emoji.Equals(this.ClockEmoji))
                {
                    try
                    {
                        DiscordMember reactor = (DiscordMember)e.User;
                        DiscordMessage msg    = await channel.GetMessageAsync(e.Message.Id);

                        DbResult <UserTimeZone> opTimeZoneResult = await this.Mediator.Send(new UserTimeZones.GetUsersTimeZone(msg.Author));
                        if (!opTimeZoneResult.TryGetValue(out UserTimeZone? opTimeZoneEntity))
                        {
                            await reactor.SendMessageAsync("The original poster has not set up a time zone yet.");
                            return;
                        }

                        string opTimeZoneId = opTimeZoneEntity.TimeZoneId;

                        DateTimeZone?opTimeZone = this.TimeZoneProvider.GetZoneOrNull(opTimeZoneId);

                        DbResult <UserTimeZone> reactorTimeZoneResult = await this.Mediator.Send(new UserTimeZones.GetUsersTimeZone(msg.Author));
                        if (!reactorTimeZoneResult.TryGetValue(out UserTimeZone? reactorTimeZoneEntity))
                        {
                            await reactor.SendMessageAsync("You have not set up a time zone yet. Use `time init` to set up your time zone.");
                            return;
                        }

                        string reactorTimeZoneId = reactorTimeZoneEntity.TimeZoneId;

                        DateTimeZone?reactorTimeZone = this.TimeZoneProvider.GetZoneOrNull(reactorTimeZoneId);

                        if (opTimeZone == null || reactorTimeZone == null)
                        {
                            await reactor.SendMessageAsync("There was a problem, please reach out to your bot developer.");
                            return;
                        }

                        ZonedDateTime zonedMessageDateTime = ZonedDateTime.FromDateTimeOffset(msg.CreationTimestamp);
                        DateTime opRefTime = zonedMessageDateTime.WithZone(opTimeZone).ToDateTimeOffset().DateTime;

                        IEnumerable <DateTimeV2ModelResult> parserList = Recognizers.RecognizeDateTime(e.Message.Content, opRefTime, DateTimeV2Type.Time, DateTimeV2Type.DateTime);

                        if (!parserList.Any())
                        {
                            await reactor.SendMessageAsync("This message does not have a recognizable time in it.");
                            return;
                        }

                        DiscordEmbedBuilder reactorTimeEmbed = new DiscordEmbedBuilder().WithTitle("You requested a timezone conversion");



                        IEnumerable <(string, DateTimeV2Value)> results = parserList.SelectMany(x => x.Values.Select(y => (x.Text, y)));
                        foreach ((string parsedText, DateTimeV2Value result) in results)
                        {
                            string outputString;
                            if (result.Type is DateTimeV2Type.Time)
                            {
                                LocalTime localParsedTime          = (LocalTime)result.Value;
                                LocalDateTime localParsedDateTime  = localParsedTime.On(zonedMessageDateTime.LocalDateTime.Date);
                                ZonedDateTime zonedOpDateTime      = localParsedDateTime.InZoneStrictly(opTimeZone);
                                ZonedDateTime zonedReactorDateTime = zonedOpDateTime.WithZone(reactorTimeZone);
                                outputString = zonedReactorDateTime.LocalDateTime.TimeOfDay.ToString("t", null);
                            }
                            else
                            {
                                LocalDateTime localParsedDateTime  = (LocalDateTime)result.Value;
                                ZonedDateTime zonedOpDateTime      = localParsedDateTime.InZoneStrictly(opTimeZone);
                                ZonedDateTime zonedReactorDateTime = zonedOpDateTime.WithZone(reactorTimeZone);
                                outputString = zonedReactorDateTime.LocalDateTime.ToString("g", null);
                            }

                            reactorTimeEmbed
                            .AddField("Poster's Time", $"\"{parsedText}\"")
                            .AddField("Your time", $"{outputString}");
                        }
                        await reactor.SendMessageAsync(embed: reactorTimeEmbed);
                    }
                    catch (Exception exception)
                    {
                        this.Logger.Log(LogLevel.Error, exception, "Error in sending reactor the DM");
                    }
                }
            });
        }