Beispiel #1
0
        private async Task PostMessage(IGuild guild, IGuildUser user, Color color, string message)
        {
            SocketTextChannel?channel = await GetChannel(guild.Id);

            if (channel == null)
            {
                return;
            }

            // don't push logs to different guilds.
            if (user.GuildId != channel.Guild.Id)
            {
                return;
            }

            EmbedBuilder builder = new EmbedBuilder();

            builder.Color        = color;
            builder.Title        = user.Username + " " + message + " " + user.Guild.Name;
            builder.Timestamp    = DateTimeOffset.Now;
            builder.ThumbnailUrl = user.GetAvatarUrl();

            if (user is SocketGuildUser guildUser)
            {
                builder.Title = guildUser.Nickname + " (" + user.Username + ") " + message;
                builder.AddField("Joined", TimeUtils.GetDateString(guildUser.JoinedAt), true);
            }

            builder.AddField("Created", TimeUtils.GetDateString(user.CreatedAt), true);

            builder.Footer      = new EmbedFooterBuilder();
            builder.Footer.Text = "ID: " + user.Id;

            await channel.SendMessageAsync(null, false, builder.Build());
        }
        public static async Task <RestUserMessage?> GetNotifyMessage(this Event.Instance self, Event evt)
        {
            if (self.NotifyMessageId == null)
            {
                return(null);
            }

            SocketTextChannel?channel = evt.GetChannel();

            if (channel is null)
            {
                return(null);
            }

            IMessage message = await channel.GetMessageAsync(ulong.Parse(self.NotifyMessageId));

            if (message is null)
            {
                return(null);
            }

            if (message is RestUserMessage userMessage)
            {
                return(userMessage);
            }

            throw new Exception("Message: \"" + self.NotifyMessageId + "\" is not a user message.");
        }
Beispiel #3
0
        public static async Task Post(this NewsItem self, ulong channelID)
        {
            SocketTextChannel?channel = (SocketTextChannel)Program.DiscordClient.GetChannel(channelID);

            if (channel == null)
            {
                return;
            }

            await channel.SendMessageAsync(null, false, self.ToEmbed());
        }
Beispiel #4
0
    public async Task PublishToReleaseChannelAsync(EmbedBuilder builder)
    {
        SocketTextChannel?socketTextChannel = this.GetChannel(this._botConfiguration.ReleaseChannel);

        if (socketTextChannel == null)
        {
            return;
        }

        await PublishCommonAsync(builder : builder, socketTextChannel : socketTextChannel);
    }
Beispiel #5
0
        public static async Task Close(this Poll self)
        {
            Log.Write("Closing poll: \"" + self.Comment + "\" (" + self.Id + ")", "Bot");

            SocketTextChannel?channel = Program.DiscordClient.GetChannel(self.ChannelId) as SocketTextChannel;

            if (channel is null)
            {
                return;
            }

            RestUserMessage?pollMessage = await channel.GetMessageAsync(self.MessageId) as RestUserMessage;

            if (pollMessage != null)
            {
                await pollMessage.RemoveAllReactionsAsync();
            }

            self.ClosesInstant = TimeUtils.Now;
        }
Beispiel #6
0
        public static async Task <bool> IsValid(this Poll self)
        {
            SocketTextChannel?channel = Program.DiscordClient.GetChannel(self.ChannelId) as SocketTextChannel;

            if (channel is null)
            {
                return(false);
            }

            if (self.MessageId != 0)
            {
                RestUserMessage?pollMessage = await channel.GetMessageAsync(self.MessageId) as RestUserMessage;

                if (pollMessage == null)
                {
                    return(false);
                }
            }

            return(true);
        }
Beispiel #7
0
        public static async Task UpdateMessage(this Poll self)
        {
            Log.Write("Updating poll: \"" + self.Comment + "\" (" + self.Id + ")", "Bot");
            SocketTextChannel?channel = Program.DiscordClient.GetChannel(self.ChannelId) as SocketTextChannel;

            if (channel == null)
            {
                throw new Exception("Poll channel: " + self.ChannelId + " missing");
            }

            Embed embed = await self.ToEmbed();

            RestUserMessage?pollMessage = null;

            if (self.MessageId != 0)
            {
                pollMessage = await channel.GetMessageAsync(self.MessageId) as RestUserMessage;
            }

            if (pollMessage == null)
            {
                pollMessage = await channel.SendMessageAsync(null, false, embed);

                self.MessageId = pollMessage.Id;

                for (int i = 0; i < self.Options.Count; i++)
                {
                    await pollMessage.AddReactionAsync(new Emoji(PollService.ListEmotes[i]));
                }
            }
            else
            {
                await pollMessage.ModifyAsync((x) =>
                {
                    x.Embed = embed;
                });
            }
        }
Beispiel #8
0
        public async Task Update()
        {
            if (this.Event == null)
            {
                throw new Exception("Notice has no owner");
            }

            SocketTextChannel?channel = Program.DiscordClient.GetChannel(this.Event.Channel) as SocketTextChannel;

            if (channel is null)
            {
                return;
            }

            EmbedBuilder builder = await this.BuildEmbed();

            RestUserMessage?message = null;

            if (this.EventNotice.MessageId != null)
            {
                message = await channel.GetMessageAsync((ulong)this.EventNotice.MessageId) as RestUserMessage;
            }

            if (message is null)
            {
                message = await channel.SendMessageAsync(null, false, builder.Build());

                this.EventNotice.MessageId = message.Id;
                await EventsService.SaveEvent(this.Event);
            }
            else
            {
                await message.ModifyAsync(x =>
                {
                    x.Embed = builder.Build();
                });
            }
        }
Beispiel #9
0
        public async Task Update()
        {
            // TODO: store event ID's in a separate table so we aren't scanning the entire events db each update.
            List <Event> events = await EventsDatabase.LoadAll();

            foreach (Event evt in events)
            {
                if (evt.Id == null)
                {
                    continue;
                }

                // delete non repeating events that have passed
                if (!evt.DoesRepeat())
                {
                    Occurance?next = evt.GetNextOccurance();

                    // will never occur (past event)
                    if (next == null)
                    {
                        Log.Write("Delete Event: \"" + evt.Name + "\" (" + evt.Id + ")", "Bot");
                        await EventsDatabase.Delete(evt.Id);

                        if (evt.Notify != null)
                        {
                            await evt.Notify.Delete(evt);
                        }

                        continue;
                    }
                }

                SocketTextChannel?channel = evt.GetChannel();

                if (channel is null)
                {
                    continue;
                }

                if (this.ShouldNotify(evt))
                {
                    if (evt.Notify == null)
                    {
                        evt.Notify = new Event.Instance();
                    }

                    this.Watch(evt);

                    await evt.CheckReactions();

                    await evt.Notify.Post(evt);

                    await evt.Notify.Notify(evt);

                    await EventsDatabase.Save(evt);
                }
                else
                {
                    if (evt.Notify != null)
                    {
                        // remove notification
                        await evt.Notify.Delete(evt);

                        evt.Notify = null;
                        await EventsDatabase.Save(evt);
                    }
                }
            }
        }
Beispiel #10
0
        public static Task <Embed> ToEmbed(this Poll self)
        {
            SocketTextChannel?channel = Program.DiscordClient.GetChannel(self.ChannelId) as SocketTextChannel;

            if (channel == null)
            {
                throw new Exception("Poll channel: " + self.ChannelId + " missing");
            }

            int totalVotes = self.CountTotalVotes();

            StringBuilder description = new StringBuilder();

            description.AppendLine(self.Comment);
            description.AppendLine();

            if (!self.Closed())
            {
                description.Append("__Poll closes in ");
                description.Append(TimeUtils.GetDurationString(self.ClosesInstant));
                description.AppendLine("__");
                description.AppendLine();
            }

            for (int i = 0; i < self.Options.Count; i++)
            {
                Poll.Option op = self.Options[i];

                description.Append(PollService.ListEmotes[i]);
                description.Append(" - _");
                description.Append(op.Votes.Count);
                description.Append(op.Votes.Count == 1 ? " vote_ - **" : " votes_ - **");
                description.Append(op.Text);
                description.AppendLine("**");

                if (totalVotes < 20 && !self.Anon)
                {
                    foreach (ulong userId in op.Votes)
                    {
                        string          name = "Unknown";
                        SocketGuildUser?user = channel.GetUser(userId);
                        if (user != null)
                        {
                            name = user.GetName();
                        }

                        description.Append(Utils.Characters.Tab);
                        description.Append(Utils.Characters.Tab);
                        description.Append(Utils.Characters.Tab);
                        description.Append(" - ");
                        description.AppendLine(name);
                    }

                    if (op.Votes.Count > 0)
                    {
                        description.AppendLine();
                    }
                }
            }

            StringBuilder   title  = new StringBuilder();
            SocketGuildUser?author = channel.GetUser(self.Author);

            /*if (author != null && CommandsService.GetPermissions(author) == Permissions.Administrators)
             * {
             *      title.Append("FCChan");
             * }*/

            title.Append(author == null ? "Someone" : author.GetName());

            if (self.Closed())
            {
                title.Append(" asked:");
            }
            else
            {
                title.Append(" asks:");
            }

            EmbedBuilder builder = new EmbedBuilder();

            builder.Title       = title.ToString();
            builder.Footer      = new EmbedFooterBuilder();
            builder.Footer.Text = self.Closed() ? "Poll closed. Thanks for voting!" : "Vote for an option by selecting a reaction below";
            builder.Description = description.ToString();

            return(Task.FromResult(builder.Build()));
        }
        public static async Task Post(this Event.Instance self, Event evt)
        {
            SocketTextChannel?channel = evt.GetChannel();

            if (channel is null)
            {
                return;
            }

            EmbedBuilder builder = new EmbedBuilder
            {
                Color       = evt.Color.ToDiscordColor(),
                Title       = evt.Name,
                Description = evt.Description,
                ImageUrl    = evt.Image,
            };

            /*
             * Due to a bug on Android, we cannot use the Timestamp field for dates in the future.
             * If discord ever fixes this, we should use timestamps as they automatically adjust to the clients
             * time zone.
             * https://trello.com/c/RO4zrt25
             */
            /*StringBuilder footerBuilder = new StringBuilder();
             * footerBuilder.Append(TimeUtils.GetDurationString(evt.Duration));
             * footerBuilder.Append(" ");
             * footerBuilder.Append(evt.GetRepeatsString());
             *
             * builder.Footer = new EmbedFooterBuilder();
             * builder.Footer.Text = footerBuilder.ToString();
             * builder.Timestamp = evt.NextOccurance();*/

            StringBuilder descBuilder = new StringBuilder();

            // Starts in: 1 hour 45 minutes
            descBuilder.Append("__");
            descBuilder.Append(evt.GetWhenString());
            descBuilder.AppendLine("__");
            descBuilder.AppendLine();

            Occurance?occurance = evt.GetNextOccurance();

            if (occurance != null)
            {
                descBuilder.AppendLine(occurance.GetDisplayString());
                descBuilder.AppendLine();
            }

            // description
            descBuilder.AppendLine(evt.Description);
            builder.Description = descBuilder.ToString();

            if (evt.StatusType == Event.Statuses.Roles)
            {
                builder.AddStatus(evt, Emotes.Tank);
                builder.AddStatus(evt, Emotes.Healer);
                builder.AddStatus(evt, Emotes.DPS);
            }
            else if (evt.StatusType == Event.Statuses.Attending)
            {
                builder.AddStatus(evt, Emotes.Yes);
                builder.AddStatus(evt, Emotes.Maybe);
                builder.AddStatus(evt, Emotes.No);
            }

            // Notification bell field
            bool shouldBell = true;

            if (occurance != null)
            {
                Duration timeTill = occurance.GetInstant() - TimeUtils.RoundInstant(TimeUtils.Now);
                if (timeTill.TotalMinutes < 60)
                {
                    shouldBell = false;
                }
            }

            if (shouldBell)
            {
                builder.AddField(Emotes.Bell.GetString() + " Notify", evt.GetReminderString());
            }

            RestUserMessage?message = await self.GetMessage(evt);

            if (message is null)
            {
                Log.Write("Posting Instance: \"" + evt.Name + "\" (" + evt.Id + ") in channel: \"" + channel.Name + "\" (" + channel.Id + ")", "Bot");

                message = await channel.SendMessageAsync(evt.Message, false, builder.Build());

                self.MessageId = message.Id.ToString();

                List <IEmote> reactions = new List <IEmote>();
                if (evt.StatusType == Event.Statuses.Roles)
                {
                    reactions.Add(Emotes.Tank);
                    reactions.Add(Emotes.Healer);
                    reactions.Add(Emotes.DPS);
                }
                else
                {
                    reactions.Add(Emotes.Yes);
                    reactions.Add(Emotes.Maybe);
                }

                reactions.Add(Emotes.No);
                reactions.Add(Emotes.Bell);

                await message.AddReactionsAsync(reactions.ToArray());

                EventsService.Instance.Watch(evt);
            }
            else
            {
                Log.Write("Updating Instance: \"" + evt.Name + "\" (" + evt.Id + ") in channel: \"" + channel.Name + "\" (" + channel.Id + ")", "Bot");

                await message.ModifyAsync(x =>
                {
                    x.Embed   = builder.Build();
                    x.Content = evt.Message;
                });
            }
        }
        public static async Task Notify(this Event.Instance self, Event evt)
        {
            if (!string.IsNullOrEmpty(self.NotifyMessageId))
            {
                return;
            }

            SocketTextChannel?channel = evt.GetChannel();

            if (channel is null)
            {
                return;
            }

            Occurance?nextOccurance = evt.GetNextOccurance();

            if (nextOccurance is null)
            {
                return;
            }

            Duration timeTill = nextOccurance.GetInstant() - TimeUtils.RoundInstant(TimeUtils.Now);

            if (timeTill.TotalMinutes > 60)
            {
                return;
            }

            // Do notify
            StringBuilder builder = new StringBuilder();

            builder.Append("Hey! ");
            foreach (Event.Instance.Attendee attendee in self.Attendees)
            {
                if (!attendee.Notify)
                {
                    continue;
                }

                builder.Append(attendee.GetMention(evt));
                builder.Append(", ");
            }

            builder.AppendLine();
            builder.Append("The event: [");
            builder.Append(evt.Name);
            builder.Append("](");
            builder.Append("https://discordapp.com/channels/");
            builder.Append(evt.ServerIdStr);
            builder.Append("/");
            builder.Append(evt.ChannelId);
            builder.Append("/");
            builder.Append(self.MessageId);
            builder.Append(" \"");
            builder.Append(evt.Description);
            builder.Append("\") starts in ");
            builder.Append(Math.Round(timeTill.TotalMinutes, 2));
            builder.Append(" minutes!");

            EmbedBuilder embedBuilder = new EmbedBuilder();

            embedBuilder.Description = builder.ToString();

            RestUserMessage message = await channel.SendMessageAsync(null, false, embedBuilder.Build());

            self.NotifyMessageId = message.Id.ToString();
        }
Beispiel #13
0
        private async Task RunCommand(string commandStr, string[] args, CommandMessage message)
        {
            if (Program.Initializing)
            {
                IUserMessage waitMessage = await message.Channel.SendMessageAsync("Just drinking my morning coffee... Give me a minute...");

                while (Program.Initializing)
                {
                    await Task.Delay(1000);
                }

                await waitMessage.DeleteAsync();
            }

            if (commandHandlers.ContainsKey(commandStr))
            {
                SocketTextChannel?textChannel = message.Channel as SocketTextChannel;

                if (textChannel == null)
                {
                    return;
                }

                using (textChannel.EnterTypingState())
                {
                    Exception?lastException = null;
                    foreach (Command command in commandHandlers[commandStr])
                    {
                        try
                        {
                            lastException = null;
                            await command.Invoke(args, message);

                            break;
                        }
                        catch (ParameterException ex)
                        {
                            lastException = ex;
                        }
                        catch (Exception ex)
                        {
                            lastException = ex;
                            break;
                        }
                    }

                    if (lastException != null)
                    {
                        if (lastException is UserException userEx)
                        {
                            await message.Channel.SendMessageAsync(userEx.Message);
                        }
                        else if (lastException is ParameterException paramEx)
                        {
                            await message.Channel.SendMessageAsync(paramEx.Message);

                            await message.Channel.SendMessageAsync(null, false, await HelpService.GetHelp(message, commandStr));
                        }
                        else if (lastException is NotImplementedException)
                        {
                            await message.Channel.SendMessageAsync("I'm sorry, seems like I don't quite know how to do that yet.");
                        }
                        else if (lastException is WebException webEx)
                        {
                            HttpStatusCode?status = (webEx.Response as HttpWebResponse)?.StatusCode;
                            if (status == null || status != HttpStatusCode.ServiceUnavailable)
                            {
                                Log.Write(lastException);
                                await message.Channel.SendMessageAsync("I'm sorry, something went wrong while handling that.");
                            }
                            else
                            {
                                await message.Channel.SendMessageAsync("I'm sorry, the service is unavailable right now.");
                            }
                        }
                        else
                        {
                            Log.Write(lastException);
                            await message.Channel.SendMessageAsync("I'm sorry, something went wrong while handling that.");
                        }
                    }
                }
            }
            else
            {
                await message.Channel.SendMessageAsync("I'm sorry, I didn't understand that command.");
            }
        }
        public async Task RunTaskAsync(DiscordSocketClient client, IReadOnlyDictionary <string, object> taskSettings,
                                       CancellationToken cancellationToken)
        {
            if (client is null)
            {
                throw new ArgumentNullException(nameof(client));
            }
            if (taskSettings is null)
            {
                throw new ArgumentNullException(nameof(taskSettings));
            }

            try
            {
                var guildIdStr = (string)taskSettings[SettingsKeyGuildId]
                                 ?? throw new Exception(
                                           $"Setting with key \"{nameof(SettingsKeyGuildId)}\" missing from {nameof(DeleteExpiredShiftCodesTask)} settings.");
                var guildId = ulong.Parse(guildIdStr);
                var guild   = client.GetGuild(guildId);

                var channelIdStr = (string)taskSettings[SettingsKeyChannelId]
                                   ?? throw new Exception(
                                             $"Setting with key \"{nameof(SettingsKeyChannelId)}\" missing from {nameof(DeleteExpiredShiftCodesTask)} settings.");
                var channelId = ulong.Parse(channelIdStr);
                var channel   = guild.GetTextChannel(channelId);

                taskSettings.TryGetValue(SettingsKeyReportToChannelId, out var reportToChannelIdVal);

                var reportToChannelIdStr          = reportToChannelIdVal as string;
                SocketTextChannel?reportToChannel = null;
                if (!string.IsNullOrEmpty(reportToChannelIdStr))
                {
                    var reportToChannelId = ulong.Parse(reportToChannelIdStr);
                    reportToChannel = guild.GetTextChannel(reportToChannelId);
                }

                var messages = (await channel.GetMessagesAsync(BatchSize)
                                .FlattenAsync())
                               .ToList();

                if (messages.Any())
                {
                    var messagesToDelete = ExpiredCodesHelpers.GetMessagesWithExpiredCodes(messages, _logger);

                    var plural = messagesToDelete.Count == 1 ? "" : "s";
                    _logger.LogInformation("Found {count} message{s} with expired codes to delete.",
                                           messagesToDelete.Count, plural);

                    // Only messages < 14 days old can be bulk deleted.
                    var bulkDeletableMessages   = new List <IMessage>();
                    var singleDeletableMessages = new List <IMessage>();

                    foreach (var message in messagesToDelete)
                    {
                        var bulkDeleteCutoff = DateTimeOffset.Now.AddMinutes(5).AddDays(-14);

                        if (message.Timestamp >= bulkDeleteCutoff)
                        {
                            bulkDeletableMessages.Add(message);
                        }
                        else
                        {
                            singleDeletableMessages.Add(message);
                        }
                    }

                    if (bulkDeletableMessages.Any())
                    {
                        await channel.DeleteMessagesAsync(bulkDeletableMessages);

                        await Task.Delay(Constants.DelayAfterCommandMs);
                    }

                    foreach (var singleDeletableMessage in singleDeletableMessages)
                    {
                        await channel.DeleteMessageAsync(singleDeletableMessage);

                        await Task.Delay(Constants.DelayAfterCommandMs);
                    }

                    if (messagesToDelete.Count > 0 && reportToChannel != null)
                    {
                        await reportToChannel.SendMessageAsync($"Deleted {messagesToDelete.Count} expired code{plural} in {channel.ToMessageRef()}.");

                        await Task.Delay(Constants.DelayAfterCommandMs);
                    }
                }
            }
            catch (Exception e)
            {
                _logger.LogError(e, "Error trying to prune expired messages :(");
            }
        }