private async Task AddMember(params string[] args) { if (args.Length != 2) { await ReplyAsync("Provide 2 arguments, group id and discord user id"); return; } if (!int.TryParse(args[0], out int groupId)) { await ReplyAsync($"Unable to parse {args[0]} as group id"); return; } if (!ulong.TryParse(args[1], out ulong discordUserId)) { await ReplyAsync($"Unable to parse {args[1]} as discord user id"); } await BrobotService.AddDiscordUserToSecretSantaGroup(groupId, discordUserId); await ReplyAsync("Added"); }
internal async override Task ExecuteJobAsync(CancellationToken stoppingToken) { try { var today = DateTime.Now; foreach (var channel in Job.Channels) { var discordChannel = DiscordClient.GetChannel(channel.ChannelId); if (!(discordChannel is SocketTextChannel socketTextChannel)) { continue; } var channelUsers = await BrobotService.GetDiscordUsersForChannel(channel.ChannelId); foreach (var user in channelUsers.Where(cu => cu.Birthdate.HasValue && cu.Birthdate.Value.Month == today.Month && cu.Birthdate.Value.Day == today.Day)) { var discordUser = socketTextChannel.GetUser(user.DiscordUserId); if (discordUser == null) { continue; } await socketTextChannel.SendMessageAsync($"Happy Birthday {discordUser.Mention}! :birthday:"); NumberOfFailures = 0; } } } catch (Exception ex) { Logger.LogError(ex, "Failed to execute birthday job."); NumberOfFailures++; } }
private async Task CreateEvent(string[] args) { if (args.Length != 1) { await ReplyAsync("Provide 1 argument, the group to create the event for"); return; } if (!int.TryParse(args[0], out int groupId)) { await ReplyAsync($"Unable to parse {args[0]} as group id"); return; } var newEvent = await BrobotService.CreateSecretSantaEvent(groupId, DateTime.Now.Year, Context.User.Id); foreach (var pairing in newEvent.SecretSantaPairings) { var user = Context.Client.GetUser(pairing.Giver.DiscordUserId); var dmChannel = await user.GetOrCreateDMChannelAsync(); await dmChannel.SendMessageAsync($":santa: You have {pairing.Recipient.Username}"); } await ReplyAsync("Pairings sent!"); }
private async Task CreateGroup(params string[] args) { if (args.Length < 1 || args.Length > 2) { await ReplyAsync("Invalid arguments. Supply a group name and optional check past year"); return; } var checkPastYear = false; if (args.Length == 2) { if (!bool.TryParse(args[1], out checkPastYear)) { await ReplyAsync($"Unable to parse {args[1]} for use past year value. Use true or false"); } } var secretSantaGroup = new SecretSantaGroup { Name = args[0], CheckPastYearPairings = checkPastYear }; var newSecretSantaGroup = await BrobotService.CreateSecretSantaGroup(secretSantaGroup); await ReplyAsync($"Created group {newSecretSantaGroup.Name} with an ID of {newSecretSantaGroup.SecretSantaGroupId}"); }
public async Task Reminder(string reminderDateTime, string reminderMessage) { try { if (string.IsNullOrWhiteSpace(reminderDateTime) || string.IsNullOrWhiteSpace(reminderMessage)) { await ReplyAsync("Invalid arguments. Please supply two arguments: a date in yyyy-MM-dd HH:mm format and a reminder message"); return; } if (!DateTime.TryParse(reminderDateTime, out DateTime dateTimeResult)) { await ReplyAsync($"{reminderDateTime} is not in the format. Please use yyyy-MM-dd HH:mm format (ex: 2020-01-01 18:00)"); return; } var reminder = new Reminder { ChannelId = Context.Channel.Id, OwnerId = Context.Message.Author.Id, Message = reminderMessage, ReminderDateUtc = dateTimeResult }; await BrobotService.PostReminder(reminder); await ReplyAsync("Reminder has been set"); } catch (Exception) { await ReplyAsync("Failed to set reminder message"); } }
internal override async Task ExecuteJobAsync(CancellationToken stoppingToken) { try { var activeReminders = await BrobotService.GetReminders(reminderDateUtc : DateTime.UtcNow); foreach (var channel in Job.Channels) { var discordChannel = DiscordClient.GetChannel(channel.ChannelId); if (!(discordChannel is SocketTextChannel socketTextChannel)) { continue; } foreach (var reminder in activeReminders.Where(r => r.ChannelId == channel.ChannelId && r.SentDateUtc == null)) { await socketTextChannel.SendMessageAsync($"@everyone {reminder.Message}"); reminder.SentDateUtc = DateTime.UtcNow; await BrobotService.UpdateReminder(reminder); } } NumberOfFailures = 0; } catch (Exception ex) { Logger.LogError(ex, "Failed to start reminders job"); NumberOfFailures++; } }
internal async override Task ExecuteJobAsync(CancellationToken stoppingToken) { try { var containsParameter = Job.JobParameters.FirstOrDefault(p => p.Name.Equals("contains", StringComparison.OrdinalIgnoreCase)); var handlerParameter = Job.JobParameters.FirstOrDefault(p => p.Name.Equals("twitterhandle", StringComparison.OrdinalIgnoreCase)); var lastCheckParameter = Job.JobParameters.FirstOrDefault(p => p.Name.Equals("lastcheckdatetimeutc", StringComparison.OrdinalIgnoreCase)); if (string.IsNullOrWhiteSpace(handlerParameter?.Value)) { Logger.LogError($"Job {Job.Name} does not contain required parameter TwitterHandler. Exiting job"); NumberOfFailures = MaxNumberOfFailures; return; } if (string.IsNullOrWhiteSpace(lastCheckParameter?.Value)) { Logger.LogError($"Job {Job.Name} does not contain required parameter LatestTweetId. Exiting job"); NumberOfFailures = MaxNumberOfFailures; return; } if (!DateTime.TryParse(lastCheckParameter.Value, out DateTime latestCheck)) { Logger.LogError($"Job {Job.Name}: {lastCheckParameter.Name} is not a datetime. Exiting job"); NumberOfFailures = MaxNumberOfFailures; return; } var tweets = await _twitterService.GetTweetsAsync(from : handlerParameter?.Value, contains : containsParameter?.Value, startTime : latestCheck.ToUniversalTime()); var newCheckTime = DateTime.UtcNow; foreach (var channel in Job.Channels) { var discordChannel = DiscordClient.GetChannel(channel.ChannelId); if (!(discordChannel is SocketTextChannel socketTextChannel)) { continue; } foreach (var tweet in tweets.OrderBy(t => t.CreatedAt)) { await socketTextChannel.SendMessageAsync($"https://www.twitter.com/{handlerParameter.Value}/status/{tweet.Id}"); } } lastCheckParameter.Value = newCheckTime.ToString("yyyy-MM-ddTHH:mm:ssZ"); await BrobotService.UpdateJobParameter(Job.JobId, lastCheckParameter.JobParameterId, lastCheckParameter); NumberOfFailures = 0; } catch (Exception ex) { Logger.LogError(ex, "Failed to start reminders job"); NumberOfFailures++; } }
public async Task HotOp() { try { var hotOpScoreboards = await BrobotService.GetHotOpScoreboards(Context.Channel.Id); if (hotOpScoreboards.Count() == 0) { await ReplyAsync("No current hot ops"); return; } foreach (var hotOpScoreboard in hotOpScoreboards) { var builder = new EmbedBuilder { Color = new Color(114, 137, 218), Description = $"Operation Hot {hotOpScoreboard.HotOpOwnerName}" }; foreach (var score in hotOpScoreboard.Scores.OrderByDescending(s => s.Score)) { builder.AddField(x => { x.Name = score.DiscordUserName; x.Value = score.Score; x.IsInline = false; }); } await ReplyAsync("", false, builder.Build()); } } catch (Exception) { await ReplyAsync("Failed to get hot op scores"); } }
public async Task SecretSanta(string subcommand, params string[] args) { try { var discordUser = await BrobotService.GetDiscordUser(Context.Message.Author.Id); if (!discordUser.BrobotAdmin) { return; } var subcommandLower = subcommand.ToLower(); if (!_subcommands.ContainsKey(subcommandLower)) { await ReplyAsync($"{subcommand} is not a valid subcommand"); return; } await _subcommands[subcommandLower](args); } catch (BrobotServiceException bsEx) { if (!string.IsNullOrWhiteSpace(bsEx.MessageFromServer)) { await ReplyAsync(bsEx.MessageFromServer); } else { await ReplyAsync(bsEx.Message); } } catch (Exception ex) { await ReplyAsync($"Failed to execute secret santa command: {ex.Message}"); } }
internal override async Task ExecuteJobAsync(CancellationToken stoppingToken) { try { var wordCloudParameter = Job.JobParameters.FirstOrDefault(jp => jp.Name.Equals("GenerateWordCloud", StringComparison.OrdinalIgnoreCase)); bool.TryParse(wordCloudParameter?.Value ?? "false", out bool generateWordCloud); HashSet <string> stopWords = null; var now = DateTime.UtcNow; var startOfThisMonth = new DateTime(now.Year, now.Month, 1, 0, 0, 0); var startOfLastMonth = startOfThisMonth.AddMonths(-1); if (generateWordCloud) { stopWords = new HashSet <string>((await BrobotService.GetStopWords()).Select(sw => sw.Word)); } string[] separatingStrings = { " ", "\t", "\n", "\r\n", ",", ":", ".", "!", "/", "\\", "%", "&", "?", "(", ")", "\"", "@" }; foreach (var channel in Job.Channels) { TimeSpan lastMonthOffset = TimeSpan.Zero, currentOffset = TimeSpan.Zero; if (!string.IsNullOrWhiteSpace(channel.PrimaryTimezone)) { var tzInfo = TZConvert.GetTimeZoneInfo(channel.PrimaryTimezone); lastMonthOffset = tzInfo.GetUtcOffset(startOfLastMonth); currentOffset = tzInfo.GetUtcOffset(startOfThisMonth); } var startDateTime = new DateTimeOffset(startOfLastMonth, lastMonthOffset); var endDateTime = new DateTimeOffset(startOfThisMonth, currentOffset); var discordChannel = DiscordClient.GetChannel(channel.ChannelId); if (!(discordChannel is SocketTextChannel socketTextChannel)) { continue; } var messageCount = new Dictionary <ulong, (string UserName, int MessageCount)>(); var words = new Dictionary <string, int>(); foreach (var user in discordChannel.Users) { messageCount.Add(user.Id, (UserName: user.Username, MessageCount: 0)); } foreach (var message in await socketTextChannel.GetMessagesAsync(startDateTime, endDateTime)) { if (messageCount.TryGetValue(message.Author.Id, out var count)) { count.MessageCount++; messageCount[message.Author.Id] = count; } if (generateWordCloud) { foreach (var word in message.Content.Split(separatingStrings, StringSplitOptions.RemoveEmptyEntries).Where(w => !stopWords.Contains(w, StringComparer.OrdinalIgnoreCase))) { if (!words.ContainsKey(word.ToLower())) { words.Add(word.ToLower(), 0); } words[word.ToLower()]++; } } } var builder = new StringBuilder(); foreach (var count in messageCount.Values.OrderByDescending(c => c.MessageCount)) { builder.AppendLine($"{count.UserName}: {count.MessageCount}"); } await socketTextChannel.SendMessageAsync(builder.ToString()); if (generateWordCloud) { try { var wc = new WordCloud(1280, 720); var frequencies = words .OrderByDescending(w => w.Value) .Take(100) .Select(w => new { Frequency = w.Value, Word = w.Key }); wc.Draw(frequencies.Select(f => f.Word).ToList(), frequencies.Select(f => f.Frequency).ToList()).Save(_wordcloudPath); await socketTextChannel.SendFileAsync(_wordcloudPath, string.Empty); File.Delete(_wordcloudPath); } catch (Exception ex) // if there was an error with the word cloud, don't kill the entire process { Logger.LogWarning(ex, "Failed to generate word cloud"); } } } } catch (ArgumentException argEx) { Logger.LogError(argEx, "Invalid argument, stopping job"); await StopAsync(); } catch (Exception ex) { Logger.LogError(ex, "Failed to execute stats job."); NumberOfFailures++; } }
internal override async Task ExecuteJobAsync(CancellationToken stoppingToken) { try { var startingHotOps = await BrobotService.GetHotOps(startDateTimeUtc : DateTime.UtcNow); foreach (var hotOp in startingHotOps.Where(ho => ho.PrimaryChannelId.HasValue && Job.Channels.Any(c => c.ChannelId == ho.PrimaryChannelId.Value))) { var channel = DiscordClient.GetChannel(hotOp.PrimaryChannelId.Value); if (!(channel is SocketTextChannel textChannel)) { continue; } await textChannel.SendMessageAsync($"Operation Hot {hotOp.Owner.Username} has begun!"); } var expiringHotOps = await BrobotService.GetHotOps(endDateTimeUtc : DateTime.UtcNow); foreach (var hotOp in expiringHotOps) { var utcNow = DateTime.UtcNow; foreach (var openSession in hotOp.Sessions.Where(s => s.EndDateTimeUtc == null)) { openSession.EndDateTimeUtc = utcNow; await BrobotService.UpdateHotOpSession(hotOp.Id, openSession); } if (hotOp.PrimaryChannelId == null || !Job.Channels.Any(c => c.ChannelId == hotOp.PrimaryChannelId)) { continue; } var channel = DiscordClient.GetChannel(hotOp.PrimaryChannelId.Value); if (!(channel is SocketTextChannel textChannel)) { continue; } var scoreboard = await BrobotService.GetHotOpScoreboard(hotOp.Id); var scores = new List <HotOpScore>(scoreboard.Scores); foreach (var user in textChannel.Users.Where(u => !u.IsBot && u.Id != scoreboard.HotOpOwnerId && !scoreboard.Scores.Any(s => s.DiscordUserId == u.Id))) { scores.Add(new HotOpScore { DiscordUserId = user.Id, DiscordUserName = user.Username, Score = 0 }); } var builder = new EmbedBuilder { Color = new Color(114, 137, 218), Description = $"Operation Hot {scoreboard.HotOpOwnerName}" }; foreach (var score in scores.OrderByDescending(s => s.Score)) { builder.AddField(x => { x.Name = score.DiscordUserName; x.Value = score.Score; x.IsInline = false; }); } await textChannel.SendMessageAsync($"Operation Hot Op {scoreboard.HotOpOwnerName} has finished. Final score:", false, builder.Build()); } } catch (Exception ex) { Logger.LogError(ex, "Failed to start hot op job"); NumberOfFailures++; } }