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())); }
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); } } }
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); }