Example #1
0
        public Task GetRunDstAsync(params string[] args)
        {
            var runKind = (RunDisplayTypeBA)(-1);
            var color   = new Color();

            if (args.Length != 0)
            {
                try
                {
                    runKind = (RunDisplayTypeBA)Enum.Parse(typeof(RunDisplayTypeBA), args[0], true);
                    var runKindColor = RunDisplayTypes.GetColor(runKind);
                    color = new Color(runKindColor.RGB[0], runKindColor.RGB[1], runKindColor.RGB[2]);
                }
                catch (ArgumentException) { /* Nothing to do */ }
            }

            var embed = new EmbedBuilder()
                        .WithTitle($"Historical Scheduled Runs by Hour {(Enum.IsDefined(typeof(RunDisplayTypeBA), runKind) ? $"({runKind})" : string.Empty)}")
                        .WithColor(Enum.IsDefined(typeof(RunDisplayTypeBA), runKind) ? color : Color.DarkTeal)
                        .WithFooter("RSVP'd users may not be reflective of users who actually took part in a run.");

            var runsByHour = Db.Events
                             .Where(@event => @event.Notified && !Enum.IsDefined(typeof(RunDisplayTypeBA), runKind) || @event.RunKind == runKind)
                             .Select(@event =>
            {
                var runTime = DateTime.FromBinary(@event.RunTime);
                return(new { Value = @event, Hour = runTime.Hour * 2 });
            })
                             .GroupBy(kvp => kvp.Hour, kvp => kvp.Value)
                             .OrderBy(bucket => bucket.Key);

            foreach (var runBucket in runsByHour)
            {
                var hour = runBucket.Key / 2;
                if (hour > 12)
                {
                    hour -= 12;
                }
                var label = $"{hour}:00 {(runBucket.Key > 24 ? "PM" : "AM")}";
                embed = embed.AddField(label, $"{runBucket.Count()} runs (Average {Math.Round(runBucket.Aggregate(0, (i, @event) => i += @event.SubscribedUsers.Count) / (double)runBucket.Count(), 2)} users per run)");
            }

            return(ReplyAsync(embed: embed.Build()));
        }
Example #2
0
        public async Task ScheduleAsync([Remainder] string content) // Schedules a sink.
        {
            var guildConfig = Db.Guilds.FirstOrDefault(g => g.Id == Context.Guild.Id);

            if (guildConfig == null)
            {
                return;
            }
            if (Context.Channel.Id != guildConfig.ScheduleInputChannel)
            {
                return;
            }
            var prefix = guildConfig.Prefix == ' ' ? Db.Config.Prefix : guildConfig.Prefix;

            var splitIndex = content.IndexOf("|", StringComparison.Ordinal);

            if (splitIndex == -1)
            {
                await ReplyAsync($"{Context.User.Mention}, please provide parameters with that command.\n" +
                                 "A well-formed command would look something like:\n" +
                                 $"`{prefix}schedule OZ Tuesday 5:00PM | This is a fancy description!`");

                return;
            }

            var parameters  = content.Substring(0, splitIndex).Trim();
            var description = content.Substring(splitIndex + 1).Trim();

            if (parameters.IndexOf(":", StringComparison.Ordinal) == -1)
            {
                await ReplyAsync($"{Context.User.Mention}, please specify a time for your run in your command!");

                return;
            }

            var coolParameters = RegexSearches.Whitespace.Split(parameters);

            if (coolParameters.Length == 0)
            {
                await ReplyAsync($"{Context.User.Mention}, please provide parameters with that command.\n" +
                                 "A well-formed command would look something like:\n" +
                                 $"`{prefix}schedule OZ Tuesday 5:00PM | This is a fancy description!`");

                return;
            }

            IUserMessage message    = Context.Message;
            var          multiplier = 1;

            for (var i = 0; i < multiplier; i++)
            {
                if (i != 0)
                {
                    message = await ReplyAsync($"This message carries the RSVPs for run {i + 1} of this sequence.");
                }

                var @event = new ScheduledEvent
                {
                    Description     = description,
                    LeaderId        = Context.User.Id,
                    GuildId         = Context.Guild.Id,
                    MessageId3      = message.Id,
                    SubscribedUsers = new List <string>(),
                };

                foreach (var coolParameter in coolParameters)
                {
                    if (RegexSearches.Multiplier.Match(coolParameter).Success)
                    {
                        multiplier = int.Parse(RegexSearches.NonNumbers.Replace(coolParameter, string.Empty));
                        if (multiplier > 12)
                        {
                            await ReplyAsync(
                                $"{Context.User.Mention}, for your own sake, you cannot schedule more than 36 hours-worth of runs at a time.");

                            return;
                        }
                    }

                    foreach (var runType in Enum.GetNames(typeof(RunDisplayTypeBA)))
                    {
                        if (string.Equals(coolParameter, runType, StringComparison.InvariantCultureIgnoreCase))
                        {
                            @event.RunKind = Enum.Parse <RunDisplayTypeBA>(runType, true);
                            break;
                        }
                    }
                }

                if (Context.Channel.Id == guildConfig.ScheduleInputChannel)
                {
                    if (!Enum.IsDefined(typeof(RunDisplayTypeBA), @event.RunKind))
                    {
                        await ReplyAsync(
                            $"{Context.User.Mention}, please specify a kind of run in your parameter list.\n" +
                            $"Run kinds include: `[{string.Join(' ', Enum.GetNames(typeof(RunDisplayTypeBA)))}]`");

                        return;
                    }
                }
                else
                {
                    @event.RunKindCastrum = RunDisplayTypeCastrum.LL;
                }

                DateTime runTime;
                try
                {
                    runTime = Util.GetDateTime(parameters).AddHours(3 * i);
                }
                catch (ArgumentOutOfRangeException)
                {
                    await ReplyAsync($"{Context.User.Mention}, that date or time is invalid.");

                    return;
                }

                if (!await RuntimeIsValid(runTime))
                {
                    return;
                }

                @event.RunTime = runTime.ToBinary();

                var tzi     = TimeZoneInfo.FindSystemTimeZoneById(Util.PstIdString());
                var tzAbbrs = TZNames.GetAbbreviationsForTimeZone(tzi.Id, "en-US");
                var tzAbbr  = tzi.IsDaylightSavingTime(DateTime.Now) ? tzAbbrs.Daylight : tzAbbrs.Standard;

                await Context.Channel.SendMessageAsync(
                    $"{Context.User.Mention} has just scheduled a run on {runTime.DayOfWeek} at {runTime.ToShortTimeString()} ({tzAbbr})!\n" +
                    $"React to the 📳 on their message to be notified 30 minutes before it begins!");

                await message.AddReactionAsync(new Emoji("📳"));

                var color      = @event.RunKindCastrum == RunDisplayTypeCastrum.None ? RunDisplayTypes.GetColor(@event.RunKind) : RunDisplayTypes.GetColorCastrum();
                var leaderName = (Context.User as IGuildUser)?.Nickname ?? Context.User.Username;

                if (Context.Channel.Id == guildConfig.ScheduleInputChannel)
                {
                    var embed = new EmbedBuilder()
                                .WithTitle(
                        $"Run scheduled by {leaderName} on {runTime.DayOfWeek} at {runTime.ToShortTimeString()} ({tzAbbr}) " +
                        $"[{runTime.DayOfWeek}, {(Month) runTime.Month} {runTime.Day}]!")
                                .WithColor(new Color(color.RGB[0], color.RGB[1], color.RGB[2]))
                                .WithDescription(
                        "React to the :vibration_mode: on their message to be notified 30 minutes before it begins!\n\n" +
                        $"**{Context.User.Mention}'s full message: {message.GetJumpUrl()}**\n\n" +
                        $"{new string(@event.Description.Take(1650).ToArray())}{(@event.Description.Length > 1650 ? "..." : "")}\n\n" +
                        $"**Schedule Overview: <{guildConfig.BASpreadsheetLink}>**")
                                .WithFooter(footer => { footer.Text = "Localized time:"; })
                                .WithTimestamp(runTime.AddHours(-tzi.BaseUtcOffset.Hours))
                                .Build();

                    var scheduleOutputChannel = Context.Guild.GetTextChannel(guildConfig.ScheduleOutputChannel);
                    var embedMessage          = await scheduleOutputChannel.SendMessageAsync(embed : embed);

                    @event.EmbedMessageId = embedMessage.Id;

                    await Db.AddScheduledEvent(@event);

                    await Sheets.AddEvent(@event, guildConfig.BASpreadsheetId);
                }
            }
        }
Example #3
0
        public async Task Announce([Remainder] string args)
        {
            var outputChannel = GetOutputChannel();

            if (outputChannel == null)
            {
                return;
            }

            var prefix = Db.Config.Prefix;

            var splitIndex = args.IndexOf("|", StringComparison.Ordinal);

            if (splitIndex == -1)
            {
                await ReplyAsync($"{Context.User.Mention}, please provide parameters with that command.\n" +
                                 "A well-formed command would look something like:\n" +
                                 $"`{prefix}announce 5:00PM | This is a fancy description!`");

                return;
            }

            var parameters         = args.Substring(0, splitIndex).Trim();
            var description        = args.Substring(splitIndex + 1).Trim();
            var trimmedDescription = description.Substring(0, Math.Min(1700, description.Length));

            if (trimmedDescription.Length != description.Length)
            {
                trimmedDescription += "...";
            }

            if (parameters.IndexOf(":", StringComparison.Ordinal) == -1)
            {
                await ReplyAsync($"{Context.User.Mention}, please specify a time for your run in your command!");

                return;
            }

            var time = Util.GetDateTime(parameters);

            if (time < DateTime.Now)
            {
                await ReplyAsync("You cannot announce an event in the past!");

                return;
            }

            var tzi     = TimeZoneInfo.FindSystemTimeZoneById(Util.PstIdString());
            var tzAbbrs = TZNames.GetAbbreviationsForTimeZone(tzi.Id, "en-US");
            var tzAbbr  = tzi.IsDaylightSavingTime(DateTime.Now) ? tzAbbrs.Daylight : tzAbbrs.Standard;

            var eventLink =
#if DEBUG
                await Calendar.PostEvent("drs", new MiniEvent
#else
                await Calendar.PostEvent(GetCalendarCode(outputChannel.Id), new MiniEvent
#endif
            {
                Title       = Context.User.ToString(),
                Description = description,
                StartTime   = XmlConvert.ToString(time.AddHours(-tzi.BaseUtcOffset.Hours), XmlDateTimeSerializationMode.Utc),
            });

            var color = RunDisplayTypes.GetColorCastrum();
            await outputChannel.SendMessageAsync(Context.Message.Id.ToString(), embed : new EmbedBuilder()
                                                 .WithAuthor(new EmbedAuthorBuilder()
                                                             .WithIconUrl(Context.User.GetAvatarUrl())
                                                             .WithName(Context.User.ToString()))
                                                 .WithColor(new Color(color.RGB[0], color.RGB[1], color.RGB[2]))
                                                 .WithTimestamp(time.AddHours(-tzi.BaseUtcOffset.Hours))
                                                 .WithTitle($"Event scheduled by {Context.User} on {time.DayOfWeek} at {time.ToShortTimeString()} ({tzAbbr})!")
                                                 .WithDescription(trimmedDescription + $"\n\n[Copy to Google Calendar]({eventLink})\nMessage Link: {Context.Message.GetJumpUrl()}")
                                                 .WithFooter(Context.Message.Id.ToString())
                                                 .Build());

            await ReplyAsync($"Event announced! Announcement posted in <#{outputChannel.Id}>. React to the announcement in " +
                             $"<#{outputChannel.Id}> with :vibration_mode: to be notified before the event begins.");
            await SortEmbeds(outputChannel, Context.Guild);
        }