/// <summary> /// Increments messageNum. /// If greater than/equal to <see cref="AdvertThreshold"/>, send random (advertisement) message from the DB. /// </summary> /// <param name="args">Message arguments.</param> /// <returns>Task.</returns> private async Task GeneralSpamAsync(DiscordClient dClient, MessageCreateEventArgs args) { if (args.Author.IsBot || args.Channel.Id != SBGChannels.General) { return; } this.messageCounter += 1; if (this.messageCounter >= AdvertThreshold && args.Channel.Id == SBGChannels.General) { Random rnd = new Random(); using IServiceScope scope = this.scopeFactory.CreateScope(); using BloonContext db = scope.ServiceProvider.GetRequiredService <BloonContext>(); int messageCount = db.SpamMessages.Count(); int random = rnd.Next(0, messageCount); SpamMessage randomMessage = db.SpamMessages.Skip(random).FirstOrDefault(); this.messageCounter = 0; await args.Channel.SendMessageAsync(randomMessage.Value); } }
public async Task Execute() { DiscordGuild sbg = await this.dClient.GetGuildAsync(Guilds.SBG); DiscordRole ltpRole = sbg.GetRole(SBGRoles.LookingToPlay); List <DiscordMember> roleMembers = sbg.Members .Select(m => m.Value) .Where(m => m.Roles.Any(r => r.Id == ltpRole.Id)) .ToList(); List <LTPJoin> prunable; using IServiceScope scope = this.scopeFactory.CreateScope(); using BloonContext db = scope.ServiceProvider.GetRequiredService <BloonContext>(); prunable = db.LTPJoins .Where(l => roleMembers.Select(m => m.Id).Contains(l.UserId) && l.Timestamp <= DateTime.UtcNow.AddDays(-MaxDuration)) .ToList(); foreach (DiscordMember member in roleMembers) { if (!prunable.Any(p => p.UserId == member.Id)) { continue; } await member.RevokeRoleAsync(ltpRole); this.bloonLog.Information(LogConsole.RoleEdits, ManageRoleEmojis.Demotion, $"**Role Demotion**: {member.Username} - LTP"); } db.LTPJoins.RemoveRange(prunable); await db.SaveChangesAsync(); }
/// <summary> /// Track SBA activity for the inactivity job. /// </summary> /// <param name="args">Message arguments.</param> /// <returns>Task.</returns> private async Task TrackSBAAsync(DiscordClient dClient, MessageCreateEventArgs args) { if (args.Author.IsBot || args.Channel.Id != SBGChannels.SecretBaseAlpha) { return; } using IServiceScope scope = this.scopeFactory.CreateScope(); using BloonContext db = scope.ServiceProvider.GetRequiredService <BloonContext>(); SBAInactivityTracking tracking = db.SBAInactivityTracking .Where(s => s.UserId == args.Author.Id) .FirstOrDefault(); if (tracking == null) { tracking = new SBAInactivityTracking() { UserId = args.Author.Id, }; db.Add(tracking); } tracking.LastMessage = DateTime.UtcNow; await db.SaveChangesAsync(); }
private async Task OnGuildMemberAdded(DiscordClient dClient, GuildMemberAddEventArgs args) { if (args.Guild.Id != Guilds.SBG || args.Member.IsBot) { return; } IServiceScope scope = this.scopeFactory.CreateScope(); BloonContext db = scope.ServiceProvider.GetRequiredService <BloonContext>(); List <ulong> roleIds = await db.RoleMembers.AsNoTracking() .Where(r => r.MemberId == args.Member.Id) .Select(r => r.RoleId) .ToListAsync(); List <string> addedRoleNames = new List <string>(); for (int i = 0; i < roleIds.Count; i++) { if (args.Guild.Roles.TryGetValue(roleIds[i], out DiscordRole role) && role.Position < args.Guild.CurrentMember.Hierarchy) { addedRoleNames.Add(role.Name); await args.Member.GrantRoleAsync(role); } } if (addedRoleNames.Count == 0) { return; } await args.Guild.GetChannel(SBGChannels.Bloonside) .SendMessageAsync($"Granted **{string.Join(", ", addedRoleNames)}** to **{args.Member.Username}**."); }
private async Task OnGuildBanAdded(DiscordClient dClient, GuildBanAddEventArgs args) { if (args.Guild.Id != Guilds.SBG) { return; } IServiceScope scope = this.scopeFactory.CreateScope(); BloonContext db = scope.ServiceProvider.GetRequiredService <BloonContext>(); await db.Database.ExecuteSqlRawAsync("DELETE FROM `role_member` WHERE `id` = {0}", args.Member.Id); }
public override Task Enable() { using IServiceScope scope = this.provider.CreateScope(); using BloonContext db = scope.ServiceProvider.GetRequiredService <BloonContext>(); this.censorer.Init(db.Censors.ToList()); this.cNext.RegisterCommands <CensorCommands>(); this.dClient.MessageCreated += this.CensorAsync; this.dClient.MessageReactionAdded += this.ProfanityFilterRemove; return(base.Enable()); }
public override Task Enable() { using IServiceScope scope = this.scopeFactory.CreateScope(); using BloonContext db = scope.ServiceProvider.GetRequiredService <BloonContext>(); List <Faq> dbFaqs = db.Faqs.ToList(); this.faqManager.Init(dbFaqs); //this.cNext.RegisterCommands<FAQCommands>(); this.dClient.MessageCreated += this.ProcessFAQAsync; return(base.Enable()); }
public async Task InitializeAsync() { using IServiceScope scope = this.provider.CreateScope(); using BloonContext db = scope.ServiceProvider.GetRequiredService <BloonContext>(); List <FeatureStatus> featureStatuses = await db.FeatureStatuses .ToListAsync(); foreach (Type type in Assembly.GetEntryAssembly() .GetTypes() .Where(t => typeof(Feature).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract) .OrderBy(t => t.Name)) { Feature feature = ActivatorUtilities.CreateInstance(this.provider, type) as Feature; if (this.features.Any(f => f.Name == feature.Name)) { throw new DuplicateNameException($"Duplicate feature name \"{feature.Name}\" for \"{type.Name}\"!"); } FeatureStatus featureStatus = featureStatuses.Where(m => m.Name == feature.Name).FirstOrDefault(); if (featureStatus == null) { featureStatus = new FeatureStatus { Name = feature.Name, Enabled = true, }; if (!feature.Protected) { db.FeatureStatuses.Add(featureStatus); } } Log.Information("Loaded feature {0} - {1}", feature.Name.PadRight(32), featureStatus.Enabled); await feature.Initialize(); if (featureStatus.Enabled) { this.featuresToEnable.Add(feature); } this.features.Add(feature); } await db.SaveChangesAsync(); }
private async Task OnGuildMembersChunked(DiscordClient dClient, GuildMembersChunkEventArgs args) { if (args.Guild.Id != Guilds.SBG) { return; } IServiceScope scope = this.scopeFactory.CreateScope(); BloonContext db = scope.ServiceProvider.GetRequiredService <BloonContext>(); List <RoleMember> roleMembers = await db.RoleMembers .Where(r => args.Members.Select(m => m.Id).Contains(r.MemberId)) .ToListAsync(); db.RoleMembers.RemoveRange(roleMembers); foreach (DiscordMember member in args.Members) { IEnumerable <DiscordRole> roles = member.Roles.Where(r => ShouldPersist(args.Guild, r)); if (!roles.Any() || member.IsBot) { continue; } foreach (DiscordRole role in roles) { RoleMember roleMember = roleMembers.Where(r => r.MemberId == member.Id && r.RoleId == role.Id) .FirstOrDefault(); if (roleMember != null) { db.Entry(roleMember).State = EntityState.Unchanged; } else { db.RoleMembers.Add(new RoleMember { MemberId = member.Id, RoleId = role.Id, }); } } } await db.SaveChangesAsync(); }
public async Task <bool> TryStoreNewAsync(YouTubeVideo video) { using IServiceScope scope = this.scopeFactory.CreateScope(); using BloonContext db = scope.ServiceProvider.GetRequiredService <BloonContext>(); if (db.YoutubeVideos.Any(x => x.UID == video.UID)) { Log.Information("No new YouTube videos"); return(false); } Log.Information("[YOUTUBE] New Video!"); db.YoutubeVideos.Add(video); await db.SaveChangesAsync(); return(true); }
/// <summary> /// Attempt to store the new helprace post in the DB. If entry exists with matching ID, don't store it. /// </summary> /// <param name="entry">A helprace post.</param> /// <returns>True or false if it stored it or not.</returns> public async Task <bool> TryStoreNewAsync(HelpracePost entry) { using IServiceScope scope = this.scopeFactory.CreateScope(); using BloonContext db = scope.ServiceProvider.GetRequiredService <BloonContext>(); if (db.HelpracePosts.Any(x => x.UID == entry.UID)) { Log.Information("No new helprace posts"); return(false); } Log.Information("[HELPRACE] Found new post. Adding {0}. Author: {1}", entry.UID, entry.Author); db.HelpracePosts.Add(entry); await db.SaveChangesAsync(); return(true); }
public async Task <bool> TryStoreNewAsync(WikiArticle entry) { using IServiceScope scope = this.scopeFactory.CreateScope(); using BloonContext db = scope.ServiceProvider.GetRequiredService <BloonContext>(); if (db.WikiArticles.Any(x => x.UID == entry.UID)) { Log.Information("No new wiki posts found"); return(false); } Log.Information("[WIKI] Post Found!"); db.WikiArticles.Add(entry); await db.SaveChangesAsync(); return(true); }
public async Task <bool> TryStoreNewAsync(SocialItemWorkshopMap map) { using IServiceScope scope = this.scopeFactory.CreateScope(); using BloonContext db = scope.ServiceProvider.GetRequiredService <BloonContext>(); if (db.SocialItemWorkshopMap.Any(x => x.UID == map.UID)) { Log.Information("No new Workshop maps"); return(false); } Log.Information("[WORKSHOP] New Map!"); db.SocialItemWorkshopMap.Add(map); await db.SaveChangesAsync(); return(true); }
public async Task <bool> TryStoreNewAsync(SteamNewsPost post) { using IServiceScope scope = this.scopeFactory.CreateScope(); using BloonContext db = scope.ServiceProvider.GetRequiredService <BloonContext>(); if (db.SteamNewsPosts.Any(x => x.UID == post.UID)) { Log.Information("No new Steam posts"); return(false); } Log.Information("[STEAM] New POST!"); db.SteamNewsPosts.Add(post); await db.SaveChangesAsync(); return(true); }
private Task ManageNowPlayingAsync(DiscordClient dClient, PresenceUpdateEventArgs args) { _ = Task.Run(async() => { // Ignore non-SBG events if (args.PresenceAfter.Guild.Id != Variables.Guilds.SBG) { return; } bool wasPlaying = args.PresenceBefore?.Activities.Any(a => a.Name == "Intruder") ?? false; bool nowPlaying = args.PresenceAfter.Activities.Any(a => a.Name == "Intruder"); if ((!wasPlaying && !nowPlaying) || (wasPlaying && nowPlaying)) { return; } DiscordRole nowPlayingRole = args.PresenceAfter.Guild.GetRole(SBGRoles.NowPlaying); DiscordMember member = await args.PresenceAfter.Guild.GetMemberAsync(args.UserAfter.Id); // User started playing Intruder if (!wasPlaying && nowPlaying) { await member.GrantRoleAsync(nowPlayingRole); using IServiceScope scope = this.scopeFactory.CreateScope(); using BloonContext db = scope.ServiceProvider.GetRequiredService <BloonContext>(); LTPJoin join = db.LTPJoins.Where(l => l.UserId == args.UserAfter.Id).FirstOrDefault(); if (join != null) { join.Timestamp = DateTime.UtcNow; await db.SaveChangesAsync(); } } // User stopped playing Intruder else if (wasPlaying && (!nowPlaying || args.PresenceAfter.Status == UserStatus.Invisible || args.PresenceAfter.Status == UserStatus.Offline)) { await member.RevokeRoleAsync(nowPlayingRole); } }); return(Task.CompletedTask); }
public async Task UpdateFeatureStatusAsync(string featureName, bool enabled) { using IServiceScope scope = this.provider.CreateScope(); using BloonContext db = scope.ServiceProvider.GetRequiredService <BloonContext>(); FeatureStatus featureStatus = await db.FeatureStatuses .Where(m => m.Name == featureName) .FirstOrDefaultAsync(); if (featureStatus == null) { featureStatus = new FeatureStatus { Name = featureName, }; db.FeatureStatuses.Add(featureStatus); } featureStatus.Enabled = enabled; await db.SaveChangesAsync(); }
/// <summary> /// Try and store the Tweet in the database. /// </summary> /// <param name="tweet">Tweet.</param> /// <returns>Bool, if new or not.</returns> public async Task <bool> TryStoreNewAsync(Status tweet) { using IServiceScope scope = this.scopeFactory.CreateScope(); using BloonContext db = scope.ServiceProvider.GetRequiredService <BloonContext>(); if (db.Tweets.Any(x => x.UID == tweet.StatusID.ToString(CultureInfo.CurrentCulture))) { Log.Information("No new tweets"); return(false); } Log.Information("[TWITTER] New Tweet!"); db.Tweets.Add(new Tweet() { UID = tweet.StatusID.ToString(CultureInfo.CurrentCulture), Author = tweet.User.Name, Title = tweet.FullText, Timestamp = tweet.CreatedAt.ToUniversalTime(), }); await db.SaveChangesAsync(); return(true); }
private async Task OnGuildMemberUpdated(DiscordClient dClient, GuildMemberUpdateEventArgs args) { if (args.Guild.Id != Guilds.SBG || args.RolesBefore.Count == args.RolesAfter.Count || args.Member.IsBot) { return; } bool roleAssigned = args.RolesBefore.Count < args.RolesAfter.Count; IEnumerable <DiscordRole> modifiedRoles = roleAssigned ? args.RolesAfter.Except(args.RolesBefore) : args.RolesBefore.Except(args.RolesAfter); IServiceScope scope = this.scopeFactory.CreateScope(); BloonContext db = scope.ServiceProvider.GetRequiredService <BloonContext>(); foreach (DiscordRole role in modifiedRoles.Where(m => ShouldPersist(args.Guild, m))) { RoleMember roleMember = await db.RoleMembers.Where(r => r.MemberId == args.Member.Id && r.RoleId == role.Id) .FirstOrDefaultAsync(); if (roleMember == null && roleAssigned) { db.RoleMembers.Add(new RoleMember { MemberId = args.Member.Id, RoleId = role.Id, }); } else if (roleMember != null && !roleAssigned) { db.RoleMembers.Remove(roleMember); } } await db.SaveChangesAsync(); }
public FAQCommands(BloonContext db, FAQManager faqManager) { this.db = db; this.faqManager = faqManager; }
public LTPSlashCommand(BloonContext db) { this.db = db; }
/// <summary> /// Finds the latest, new updated RedditPost. Should trigger whenever Guardbot can see the post. /// </summary> /// <param name="posts">Reddit Posts.</param> /// <returns>Reddit Embed containing Newly Discovered Post.</returns> private async Task NewUpdatedAsync(List <Post> posts) { if (posts.Count == 0) { Log.Information($"[REDDIT] No news posts!"); return; } Log.Information("[REDDIT] Received {0} new post(s)!", posts.Count); DiscordChannel sbgGen = await this.dClient.GetChannelAsync(SBGChannels.General); foreach (Post post in posts) { if (post.Author == "GuardBloon") { continue; } string postUrl = "https://reddit.com" + post.Permalink; DiscordEmbed redditEmbed = new DiscordEmbedBuilder { Author = new DiscordEmbedBuilder.EmbedAuthor() { Name = post.Author, Url = postUrl, }, Footer = new DiscordEmbedBuilder.EmbedFooter() { IconUrl = DiscordEmoji.FromGuildEmote(this.dClient, PlatformEmojis.Reddit).Url, Text = "/r/Intruder", }, Color = new DiscordColor(255, 69, 0), Timestamp = post.Created.ToUniversalTime(), Description = $"[{post.Title}]({postUrl})", }; using IServiceScope scope = this.scopeFactory.CreateScope(); using BloonContext db = scope.ServiceProvider.GetRequiredService <BloonContext>(); db.RedditPosts.Add(new RedditPost() { UID = post.Id, Author = post.Author, Timestamp = post.Created.ToUniversalTime(), Title = post.Title, }); await db.SaveChangesAsync(); if (string.IsNullOrEmpty(post.Listing.Thumbnail) || post.Listing.Thumbnail == "self" || post.Listing.Thumbnail == "default") { await sbgGen.SendMessageAsync(embed : redditEmbed); } else { DiscordChannel sbgPNV = await this.dClient.GetChannelAsync(SBGChannels.PicsNVids); redditEmbed = new DiscordEmbedBuilder(redditEmbed) { Thumbnail = new DiscordEmbedBuilder.EmbedThumbnail { Url = post.Listing.Thumbnail, }, }; await sbgPNV.SendMessageAsync(embed : redditEmbed); } } Log.Information($"[REDDIT] Finished processing new posts!"); }
public CensorCommands(BloonContext db, Censorer censorer) { this.db = db; this.censorer = censorer; }
private async void TimerElapsed(object sender, ElapsedEventArgs e) { List <ITimedJob> timedJobs = new List <ITimedJob>(); using IServiceScope scope = this.factory.CreateScope(); using BloonContext db = scope.ServiceProvider.GetRequiredService <BloonContext>(); List <Job> dbJobs = db.Jobs.ToList(); foreach (ITimedJob timedJob in this.jobs) { string jobName = timedJob.GetType().FullName !; Job job = dbJobs.Where(j => j.Name == jobName).FirstOrDefault(); if (job == null) { job = new Job() { Name = jobName, LastExecution = DateTime.UnixEpoch.ToUniversalTime(), }; db.Jobs.Add(job); } if ((DateTime.UtcNow - job.LastExecution).TotalMinutes >= timedJob.Interval) { timedJobs.Add(timedJob); job.LastExecution = DateTime.UtcNow; } } await db.SaveChangesAsync(); if (timedJobs.Count > 0) { Task jobs = Task.WhenAll(timedJobs.Select(t => t.Execute())); try { await jobs; } #pragma warning disable CA1031 // Do not catch general exception types catch (Exception ex) #pragma warning restore CA1031 // Do not catch general exception types { if (jobs.Exception != null) { for (int i = 0; i < jobs.Exception.InnerExceptions.Count; i++) { this.bloonLog.Error($"{jobs.Exception.InnerExceptions[i].ToString().Truncate(1500)}"); } } else { this.bloonLog.Error($"{ex.ToString().Truncate(1500)}"); } Log.Error(jobs.Exception, "One or more jobs failed."); } // this.bloonLog.Information(LogConsole.Jobs, SBGEmojis.Bloon, $"Jobs finished:\n- {string.Join("\n- ", timedJobs.Select(j => $"{DiscordEmoji.FromGuildEmote(this.dClient, j.Emoji)} {j.GetType().Name}"))}"); } }
public LTPCommands(BloonContext db) { this.db = db; }
public GeneralSlashCommands(BloonContext db) { this.db = db; }
public async Task Execute() { DiscordGuild sbg = await this.dClient.GetGuildAsync(Guilds.SBG); DiscordRole sbaRole = sbg.GetRole(SBGRoles.SBA); DiscordChannel sbaChannel = await this.dClient.GetChannelAsync(SBGChannels.SecretBaseAlpha); List <DiscordMember> roleMembers = sbg.Members .Select(m => m.Value) .Where(m => m.Roles.Any(r => r.Id == sbaRole.Id)) .ToList(); Dictionary <ulong, SBAInactivityTracking> tracked; using IServiceScope scope = this.scopeFactory.CreateScope(); using BloonContext db = scope.ServiceProvider.GetRequiredService <BloonContext>(); tracked = db.SBAInactivityTracking .Where(s => roleMembers.Select(m => m.Id).Contains(s.UserId)) .ToDictionary(x => x.UserId, x => x); // Check each user within the guild with the SBA role. Wonder if this cares if the user is online or not? foreach (DiscordMember user in roleMembers) { if (!tracked.ContainsKey(user.Id)) { this.bloonLog.Information(LogConsole.RoleEdits, ManageRoleEmojis.Warning, $"**Inactivity Error**: No stored message for {user.Username} - SBA"); continue; } SBAInactivityTracking trackedUser = tracked[user.Id]; double daysInactive = (DateTime.UtcNow - trackedUser.LastMessage).TotalDays; if (daysInactive < 14) { continue; } double daysSinceLastWarning = trackedUser.WarningTimestamp.HasValue ? (DateTime.UtcNow - trackedUser.WarningTimestamp.Value).TotalDays : -1; // Last chance if (daysSinceLastWarning == -1 || daysSinceLastWarning >= 14) { string dmMessage = "Hello agent,\n" + "It seems you haven't been active in the SuperbossGames Discord for over 2 weeks.\n" + "The 'Secret Base Alpha' role and access levels will be removed if you remain inactive!\n" + $"Last activity: {trackedUser.LastMessage.ToString("D", CultureInfo.InvariantCulture)}"; await this.SendDM(user, dmMessage, false); this.bloonLog.Information(LogConsole.RoleEdits, ManageRoleEmojis.Warning, $"**Inactivity Warning**: {user.Username} - SBA"); trackedUser.WarningTimestamp = DateTime.Now; db.Update(trackedUser); } // Too late else if (daysInactive >= 21 && daysSinceLastWarning >= 7) { await user.RevokeRoleAsync(sbaRole); string dmMessage = "Hello again,\n" + "Your 'Secret Base Alpha' role and access levels have been removed due to inactivity!\n" + "I'm truly sorry, but I have my orders.\n\n" + "P.S. I did warn you"; await this.SendDM(user, dmMessage, true); db.Remove(trackedUser); this.bloonLog.Information(LogConsole.RoleEdits, ManageRoleEmojis.Demotion, $"**Inactivity Role Demotion**: {user.Username} - SBA"); } await db.SaveChangesAsync(); } }
public Z26Commands(BloonContext db) { this.db = db; }