public async Task StartAsync() { Log.Information("Starting BotTerminator"); Wiki subredditWiki = (await RedditInstance.GetSubredditAsync(SubredditName, false)).GetWiki; try { const String pageName = "botConfig/botTerminator"; if (!(await subredditWiki.GetPageNamesAsync()).Contains(pageName.ToLower())) { GlobalConfig = new GlobalConfig(); await subredditWiki.EditPageAsync(pageName, JsonConvert.SerializeObject(GlobalConfig), null, "create BotTerminator configuration"); await subredditWiki.SetPageSettingsAsync(pageName, true, WikiPageSettings.WikiPagePermissionLevel.Mods); } else { GlobalConfig = JsonConvert.DeserializeObject <GlobalConfig>((await subredditWiki.GetPageAsync(pageName.ToLower())).MarkdownContent); } } catch (Exception ex) { Log.Warning("Failed to load or create subreddit configuration for {SubredditName}: {ExceptionMessage}", SubredditName, ex.Message); return; } Statistics = GlobalConfig.MetricIds.ToDictionary(key => key.Key, value => new Statistic() { MetricId = value.Value }); UserLookup = new CacheableBackedBotDatabase(new SplittableWikiBotDatabase((await RedditInstance.GetSubredditAsync(SubredditName, false)).GetWiki, UsersPageName), new TimeSpan(0, 5, 0)); await UserLookup.CheckUserAsync(CacheFreshenerUserName, String.Empty); await UpdateSubredditCacheAsync(); this.Modules = new List <BotModule>() { new CommentScannerModule(this), new PostScannerModule(this), new RemovedPostScannerModule(this), new InviteAcceptorModule(this), new CacheFreshenerModule(this), new UpdateBanListModule(this), new StatisticsPusherModule(this), new StatusPageStatusPusherModule(this), }; RedditInstance.RateLimit = RateLimitMode.SmallBurst; // we don't need to send lots of requests at once, let's pace ourselves await Task.WhenAll(Modules.Select(s => s.RunForeverAsync())); }
protected override async Task RunItemAsync(Thing messageAsThing) { const String modInviteMsg = "invitation to moderate /r/"; PrivateMessage privateMessage = (PrivateMessage)messageAsThing; bool shouldMarkRead = true; Log.Verbose("Found message {MessageFullname} to process", privateMessage.FullName); if (privateMessage.Subreddit != null && privateMessage.Subject.StartsWith(modInviteMsg) && privateMessage.Subject.Length > modInviteMsg.Length) { String subredditName = privateMessage.Subreddit; try { await(await RedditInstance.GetSubredditAsync(subredditName, false)).AcceptModeratorInviteAsync(); bot.IncrementStatisticIfExists("requestRate"); bot.IncrementStatisticIfExists("requestRate"); Log.Information("Accepted moderator invite to {Subreddit}", "/r/" + subredditName); } catch (RedditHttpException ex) { shouldMarkRead = !await AcceptQuarantineIfValidException(subredditName, ex); } catch (Exception ex) { Log.Error("Failed to accept moderator invite for subreddit {Subreddit}: {ExceptionMessage}", "/r/" + subredditName, ex.Message); } } else if (privateMessage.Subject == moderatorAddSubject) // these messages aren't sent as a subreddit { Match moderatorAddMatch = moderatorAddRegex.Match(privateMessage.Body); if (moderatorAddMatch != null && moderatorAddMatch.Groups.Count >= 2) { String subredditName = moderatorAddMatch.Groups[1].Value; try { Subreddit subreddit = await RedditInstance.GetSubredditAsync(subredditName, false); bot.IncrementStatisticIfExists("requestRate"); } catch (RedditHttpException ex) { // it is possible although rare that we could be added as a moderator to a subreddit that's quarantined await AcceptQuarantineIfValidException(subredditName, ex); } } } if (shouldMarkRead) { Log.Verbose("Marking message {MessageFullName} as read", privateMessage.FullName); try { await privateMessage.SetAsReadAsync(); bot.IncrementStatisticIfExists("requestRate"); } catch (Exception ex) { Log.Warning("Failed to mark message {MessageFullName} as read: {ExceptionMessage}", privateMessage.FullName, ex.Message); } } }