private async Task AnnounceUserNote(UserNote userNote, IUser actor, RestAction action) { using var scope = _serviceProvider.CreateScope(); _logger.LogInformation($"Announcing usernote {userNote.GuildId}/{userNote.UserId} ({userNote.Id})."); GuildConfig guildConfig = await GuildConfigRepository.CreateDefault(scope.ServiceProvider).GetGuildConfig(userNote.GuildId); if (!string.IsNullOrEmpty(guildConfig.ModInternalNotificationWebhook)) { _logger.LogInformation($"Sending internal webhook for usernote {userNote.GuildId}/{userNote.UserId} ({userNote.Id}) to {guildConfig.ModInternalNotificationWebhook}."); try { IUser user = await _discordAPI.FetchUserInfo(userNote.UserId, CacheBehavior.Default); EmbedBuilder embed = await userNote.CreateUserNoteEmbed(action, actor, user, scope.ServiceProvider); await _discordAPI.ExecuteWebhook(guildConfig.ModInternalNotificationWebhook, embed.Build()); } catch (Exception e) { _logger.LogError(e, $"Error while announcing usernote {userNote.GuildId}/{userNote.UserId} ({userNote.Id}) to {guildConfig.ModInternalNotificationWebhook}."); } } }
public async Task HandleMemberJoin(SocketGuildUser user) { using var scope = _serviceProvider.CreateScope(); Database database = scope.ServiceProvider.GetRequiredService <Database>(); GuildConfig guildConfig; try { guildConfig = await GuildConfigRepository.CreateDefault(scope.ServiceProvider).GetGuildConfig(user.Guild.Id); } catch (ResourceNotFoundException) { _logger.LogInformation($"Cannot execute punishment in guild {user.Guild.Id} - guildconfig not found."); return; } if (guildConfig.MutedRoles.Length == 0) { return; } List <ModCase> modCases = await database.SelectAllModCasesWithActiveMuteForGuildAndUser(user.Guild.Id, user.Id); if (modCases.Count == 0) { return; } _logger.LogInformation($"Muted member {user.Id} rejoined guild {user.Guild.Id}"); await ExecutePunishment(modCases[0]); }
public async Task UndoPunishment(ModCase modCase) { using var scope = _serviceProvider.CreateScope(); Database database = scope.ServiceProvider.GetRequiredService <Database>(); List <ModCase> parallelCases = await database.SelectAllModCasesThatHaveParallelPunishment(modCase); if (parallelCases.Count != 0) { _logger.LogInformation("Cannot undo punishment. There exists a parallel punishment for this case"); return; } GuildConfig guildConfig; try { guildConfig = await GuildConfigRepository.CreateDefault(scope.ServiceProvider).GetGuildConfig(modCase.GuildId); } catch (ResourceNotFoundException) { _logger.LogError($"Cannot execute punishment in guild {modCase.GuildId} - guildconfig not found."); return; } string reason = null; try { Translator translator = scope.ServiceProvider.GetRequiredService <Translator>(); reason = translator.T(guildConfig).NotificationDiscordAuditLogPunishmentsUndone(modCase.CaseId, modCase.Title.Truncate(400)); } catch (Exception ex) { _logger.LogError(ex, $"Failed to resolve audit log reason string for case {modCase.GuildId}/{modCase.CaseId}"); } switch (modCase.PunishmentType) { case PunishmentType.Mute: if (guildConfig.MutedRoles.Length != 0) { _logger.LogInformation($"Unmute User {modCase.UserId} in guild {modCase.GuildId} with roles " + string.Join(',', guildConfig.MutedRoles.Select(x => x.ToString()))); foreach (ulong role in guildConfig.MutedRoles) { await _discord.RemoveGuildUserRole(modCase.GuildId, modCase.UserId, role, reason); } } else { _logger.LogInformation($"Cannot Unmute User {modCase.UserId} in guild {modCase.GuildId} - mute role undefined."); } break; case PunishmentType.Ban: _logger.LogInformation($"Unban User {modCase.UserId} in guild {modCase.GuildId}."); await _discord.UnBanUser(modCase.GuildId, modCase.UserId, reason); _discord.RemoveFromCache(CacheKey.GuildBan(modCase.GuildId, modCase.UserId)); // refresh ban cache break; } }
public async Task <IActionResult> Status() { Identity currentIdentity = await GetIdentity(); if (!currentIdentity.IsSiteAdmin()) { return(Unauthorized()); } List <string> currentLogins = new(); foreach (var login in _identityManager.GetCurrentIdentities()) { if (login is DiscordOAuthIdentity) { try { var user = login.GetCurrentUser(); if (user == null) { currentLogins.Add($"Invalid user."); } else { currentLogins.Add($"{user.Username}#{user.Discriminator}"); } } catch (Exception e) { _logger.LogError(e, "Error getting logged in user."); currentLogins.Add($"Invalid user."); } } } StatusRepository repo = StatusRepository.CreateDefault(_serviceProvider); StatusDetail botDetails = repo.GetBotStatus(); StatusDetail dbDetails = await repo.GetDbStatus(); StatusDetail cacheDetails = repo.GetCacheStatus(); return(Ok(new { botStatus = botDetails, dbStatus = dbDetails, cacheStatus = cacheDetails, loginsInLast15Minutes = currentLogins, defaultLanguage = _config.GetDefaultLanguage(), trackedInvites = await InviteRepository.CreateDefault(_serviceProvider).CountInvites(), modCases = await ModCaseRepository.CreateDefault(_serviceProvider, currentIdentity).CountAllCases(), guilds = await GuildConfigRepository.CreateDefault(_serviceProvider).CountGuildConfigs(), automodEvents = await AutoModerationEventRepository.CreateDefault(_serviceProvider).CountEvents(), userNotes = await UserNoteRepository.CreateWithBotIdentity(_serviceProvider).CountUserNotes(), userMappings = await UserMapRepository.CreateWithBotIdentity(_serviceProvider).CountAllUserMaps(), apiTokens = await TokenRepository.CreateDefault(_serviceProvider).CountTokens(), nextCache = _scheduler.GetNextCacheSchedule(), cachedDataFromDiscord = _discordAPI.GetCache().Keys })); }
public async Task ExecutePunishment(ModCase modCase) { using var scope = _serviceProvider.CreateScope(); Database database = scope.ServiceProvider.GetRequiredService <Database>(); GuildConfig guildConfig; try { guildConfig = await GuildConfigRepository.CreateDefault(scope.ServiceProvider).GetGuildConfig(modCase.GuildId); } catch (ResourceNotFoundException) { _logger.LogError($"Cannot execute punishment in guild {modCase.GuildId} - guildconfig not found."); return; } string reason = null; try { Translator translator = scope.ServiceProvider.GetRequiredService <Translator>(); reason = translator.T(guildConfig).NotificationDiscordAuditLogPunishmentsExecute(modCase.CaseId, modCase.LastEditedByModId, modCase.Title.Truncate(400)); } catch (Exception ex) { _logger.LogError(ex, $"Failed to resolve audit log reason string for case {modCase.GuildId}/{modCase.CaseId}"); } switch (modCase.PunishmentType) { case PunishmentType.Mute: if (guildConfig.MutedRoles.Length != 0) { _logger.LogInformation($"Mute User {modCase.UserId} in guild {modCase.GuildId} with roles " + string.Join(',', guildConfig.MutedRoles.Select(x => x.ToString()))); foreach (ulong role in guildConfig.MutedRoles) { await _discord.GrantGuildUserRole(modCase.GuildId, modCase.UserId, role, reason); } } else { _logger.LogInformation($"Cannot Mute User {modCase.UserId} in guild {modCase.GuildId} - mute role undefined."); } break; case PunishmentType.Ban: _logger.LogInformation($"Ban User {modCase.UserId} in guild {modCase.GuildId}."); await _discord.BanUser(modCase.GuildId, modCase.UserId, reason); await _discord.GetGuildUserBan(modCase.GuildId, modCase.UserId, CacheBehavior.IgnoreCache); // refresh ban cache break; case PunishmentType.Kick: _logger.LogInformation($"Kick User {modCase.UserId} in guild {modCase.GuildId}."); await _discord.KickGuildUser(modCase.GuildId, modCase.UserId, reason); break; } }
public async Task <IActionResult> UpdateSpecificItem([FromRoute] ulong guildId, [FromBody] GuildConfigForPutDto newValue) { await RequirePermission(guildId, DiscordPermission.Admin); if (_config.IsDemoModeEnabled()) { if (!(await GetIdentity()).IsSiteAdmin()) { // siteadmins can overwrite in demo mode throw new BaseAPIException("Demo mode is enabled. Only site admins can edit guild configs.", APIError.NotAllowedInDemoMode); } } GuildConfig guildConfig = await GetRegisteredGuild(guildId); guildConfig.ModRoles = newValue.ModRoles; guildConfig.AdminRoles = newValue.AdminRoles; guildConfig.ModNotificationDM = newValue.ModNotificationDM; guildConfig.MutedRoles = newValue.MutedRoles; guildConfig.ModInternalNotificationWebhook = newValue.ModInternalNotificationWebhook; if (guildConfig.ModInternalNotificationWebhook != null) { guildConfig.ModInternalNotificationWebhook = guildConfig.ModInternalNotificationWebhook.Replace("discord.com", "discordapp.com"); } guildConfig.ModPublicNotificationWebhook = newValue.ModPublicNotificationWebhook; if (guildConfig.ModPublicNotificationWebhook != null) { guildConfig.ModPublicNotificationWebhook = guildConfig.ModPublicNotificationWebhook.Replace("discord.com", "discordapp.com"); } guildConfig.StrictModPermissionCheck = newValue.StrictModPermissionCheck; guildConfig.ExecuteWhoisOnJoin = newValue.ExecuteWhoisOnJoin; guildConfig.PublishModeratorInfo = newValue.PublishModeratorInfo; guildConfig.PreferredLanguage = newValue.PreferredLanguage; return(Ok(await GuildConfigRepository.CreateDefault(_serviceProvider).UpdateGuildConfig(guildConfig))); }
public async Task <IActionResult> CreateItem([FromBody] GuildConfigForCreateDto guildConfigForCreateDto, [FromQuery] bool importExistingBans = false) { await RequireSiteAdmin(); try { GuildConfig alreadyRegistered = await GetRegisteredGuild(guildConfigForCreateDto.GuildId); if (alreadyRegistered != null) { throw new GuildAlreadyRegisteredException(guildConfigForCreateDto.GuildId); } } catch (ResourceNotFoundException) { } catch (UnregisteredGuildException) { } GuildConfig guildConfig = new() { GuildId = guildConfigForCreateDto.GuildId, ModRoles = guildConfigForCreateDto.ModRoles, AdminRoles = guildConfigForCreateDto.AdminRoles, ModNotificationDM = guildConfigForCreateDto.ModNotificationDM, MutedRoles = guildConfigForCreateDto.MutedRoles, ModPublicNotificationWebhook = guildConfigForCreateDto.ModPublicNotificationWebhook, ModInternalNotificationWebhook = guildConfigForCreateDto.ModInternalNotificationWebhook, StrictModPermissionCheck = guildConfigForCreateDto.StrictModPermissionCheck, ExecuteWhoisOnJoin = guildConfigForCreateDto.ExecuteWhoisOnJoin, PublishModeratorInfo = guildConfigForCreateDto.PublishModeratorInfo, PreferredLanguage = guildConfigForCreateDto?.PreferredLanguage ?? _config.GetDefaultLanguage() }; guildConfig = await GuildConfigRepository.CreateDefault(_serviceProvider).CreateGuildConfig(guildConfig, importExistingBans); return(StatusCode(201, guildConfig)); }
public async Task SetContext(ulong guildId) { using var scope = _serviceProvider.CreateScope(); GuildConfig guildConfig = await GuildConfigRepository.CreateDefault(scope.ServiceProvider).GetGuildConfig(guildId); SetContext(guildConfig); }
private async Task AnnounceAutomoderationConfig(AutoModerationConfig config, IUser actor, RestAction action) { using var scope = _serviceProvider.CreateScope(); _logger.LogInformation($"Announcing automod config {config.GuildId}/{config.AutoModerationType} ({config.Id})."); GuildConfig guildConfig = await GuildConfigRepository.CreateDefault(scope.ServiceProvider).GetGuildConfig(config.GuildId); if (!string.IsNullOrEmpty(guildConfig.ModInternalNotificationWebhook)) { _logger.LogInformation($"Sending internal webhook for config {config.GuildId}/{config.AutoModerationType} ({config.Id}) to {guildConfig.ModInternalNotificationWebhook}."); try { EmbedBuilder embed = await config.CreateAutomodConfigEmbed(actor, action, _serviceProvider); await _discordAPI.ExecuteWebhook(guildConfig.ModInternalNotificationWebhook, embed.Build()); } catch (Exception e) { _logger.LogError(e, $"Error while announcing config {config.GuildId}/{config.AutoModerationType} ({config.Id}) to {guildConfig.ModInternalNotificationWebhook}."); } } }
public static async Task <AutoModerator> CreateDefault(IDiscordClient client, ulong guildId, IServiceProvider serviceProvider) { var guildConfig = await GuildConfigRepository.CreateDefault(serviceProvider).GetGuildConfig(guildId); var autoModerationConfigs = await AutoModerationConfigRepository.CreateWithBotIdentity(serviceProvider).GetConfigsByGuild(guildId); return(new AutoModerator(client, serviceProvider, guildConfig, autoModerationConfigs)); }
public async Task <IActionResult> DeleteSpecificItem([FromRoute] ulong guildId, [FromQuery] bool deleteData = false) { await RequireSiteAdmin(); await GetRegisteredGuild(guildId); await GuildConfigRepository.CreateDefault(_serviceProvider).DeleteGuildConfig(guildId, deleteData); return(Ok()); }
public async Task <IActionResult> GetUser() { Identity identity = await GetIdentity(); IUser currentUser = identity.GetCurrentUser(); List <UserGuild> currentUserGuilds = identity.GetCurrentUserGuilds(); List <DiscordGuildView> memberGuilds = new(); List <DiscordGuildView> modGuilds = new(); List <DiscordGuildView> adminGuilds = new(); List <DiscordGuildView> bannedGuilds = new(); bool siteAdmin = _config.GetSiteAdmins().Contains(currentUser.Id) || identity is TokenIdentity; if (identity is DiscordOAuthIdentity) { List <GuildConfig> registeredGuilds = await GuildConfigRepository.CreateDefault(_serviceProvider).GetAllGuildConfigs(); foreach (GuildConfig guild in registeredGuilds) { UserGuild userGuild = currentUserGuilds.FirstOrDefault(x => x.Id == guild.GuildId); if (userGuild != null) { IGuild userGuildFetched = _discordAPI.FetchGuildInfo(userGuild.Id, CacheBehavior.Default); if (userGuildFetched != null) { if (await identity.HasModRoleOrHigherOnGuild(guild.GuildId)) { if (await identity.HasAdminRoleOnGuild(guild.GuildId)) { adminGuilds.Add(new DiscordGuildView(userGuildFetched)); } else { modGuilds.Add(new DiscordGuildView(userGuildFetched)); } } else { memberGuilds.Add(new DiscordGuildView(userGuildFetched)); } } } else { try { _discordAPI.GetFromCache <IBan>(CacheKey.GuildBan(guild.GuildId, currentUser.Id)); bannedGuilds.Add(new DiscordGuildView(_discordAPI.FetchGuildInfo(guild.GuildId, CacheBehavior.Default))); } catch (NotFoundInCacheException) { } } } } return(Ok(new APIUser(memberGuilds, bannedGuilds, modGuilds, adminGuilds, currentUser, siteAdmin))); }
public async Task Say([Summary("message", "message content the bot shall write")] string message, [Summary("channel", "channel to write the message in, defaults to current")] ITextChannel channel = null) { if (channel is null && Context.Channel is not ITextChannel) { await Context.Interaction.RespondAsync(Translator.T().CmdOnlyTextChannel(), ephemeral : true); return; } if (channel is null) { channel = Context.Channel as ITextChannel; } try { IUserMessage createdMessage = await channel.SendMessageAsync(message); await Context.Interaction.RespondAsync(Translator.T().CmdSaySent(), ephemeral : true); try { GuildConfig guildConfig = await GuildConfigRepository.CreateDefault(ServiceProvider).GetGuildConfig(Context.Guild.Id); if (!string.IsNullOrEmpty(guildConfig.ModInternalNotificationWebhook)) { await DiscordAPI.ExecuteWebhook( guildConfig.ModInternalNotificationWebhook, null, Translator.T().CmdSaySentMod( Context.User, createdMessage, channel ), AllowedMentions.None ); } } catch (Exception ex) { Logger.LogError(ex, $"Something went wrong while sending the internal notification for the say command by {Context.User.Id} in {Context.Guild.Id}/{Context.Channel.Id}."); } } catch (HttpException e) { if (e.HttpCode == HttpStatusCode.Unauthorized) { await Context.Interaction.RespondAsync(Translator.T().CmdCannotViewOrDeleteInChannel(), ephemeral : true); } } catch (Exception e) { Logger.LogError(e, $"Error while writing message in channel {channel.Id}"); await Context.Interaction.RespondAsync(Translator.T().CmdSayFailed(), ephemeral : true); } }
protected async Task <GuildConfig> GetRegisteredGuild(ulong guildId) { try { return(await GuildConfigRepository.CreateDefault(_serviceProvider).GetGuildConfig(guildId)); } catch (ResourceNotFoundException) { throw new UnregisteredGuildException(guildId); } }
public async Task Report(IMessage msg) { GuildConfig guildConfig = await GuildConfigRepository.CreateDefault(ServiceProvider).GetGuildConfig(Context.Guild.Id); if (string.IsNullOrEmpty(guildConfig.ModInternalNotificationWebhook)) { await Context.Interaction.RespondAsync(Translator.T().CmdNoWebhookConfigured(), ephemeral : true); return; } StringBuilder sb = new(); sb.AppendLine(Translator.T().CmdReportContent(Context.User, msg, msg.Channel as ITextChannel)); if (!string.IsNullOrEmpty(msg.Content)) { sb.Append("```\n"); sb.Append(msg.Content.Truncate(1024)); sb.Append("\n``` "); } if (msg.Attachments.Count > 0) { sb.AppendLine(Translator.T().Attachments()); foreach (IAttachment attachment in msg.Attachments.Take(5)) { sb.Append($"- <{attachment.Url}>\n"); } if (msg.Attachments.Count > 5) { sb.AppendLine(Translator.T().AndXMore(msg.Attachments.Count - 5)); } } try { await DiscordAPI.ExecuteWebhook(guildConfig.ModInternalNotificationWebhook, null, sb.ToString(), AllowedMentions.None); } catch (Exception e) { Logger.LogError(e, "Failed to send internal notification to moderators for report command."); await Context.Interaction.RespondAsync(Translator.T().CmdReportFailed(), ephemeral : true); return; } await Context.Interaction.RespondAsync(Translator.T().CmdReportSent(), ephemeral : true); }
private static async Task RequireRegisteredGuild(IServiceProvider services, IInteractionContext context) { try { await GuildConfigRepository.CreateDefault(services).GetGuildConfig(context.Guild.Id); } catch (ResourceNotFoundException) { throw new UnregisteredGuildException(context.Guild.Id); } catch (NullReferenceException) { throw new BaseAPIException("Only usable in a guild.", APIError.OnlyUsableInAGuild); } }
public WARBOT() { Config = BotConfig.Load(); Client = new DiscordSocketClient(new DiscordSocketConfig { AlwaysDownloadUsers = false, }); commands = new CommandService(new CommandServiceConfig { DefaultRunMode = RunMode.Async, CaseSensitiveCommands = false, IgnoreExtraArgs = true, }); Log = new Util.Log(this); GuildRepo = new GuildConfigRepository(); TaskBot = new TaskBOT.TaskBOT(this); }
public PrefixCommandHandler(IServiceProvider provider, DiscordSocketClient client, CommandServiceConfig commandServiceConfig, CommandHandlerOptions options, CustomModuleBuilder moduleBuilder, IEnumerable <IPluginFactory> pluginFactories, ILogger <PrefixCommandHandler> logger, CommandService commandService, GuildConfigRepository guildConfigRepository, RepeatRepository repeatRepository) : base(provider, client, commandServiceConfig, moduleBuilder, pluginFactories, logger, commandService) { this.Options = options; this.logger = logger; this.CommandTriggered += this.CommandTriggeredAsync; this.CommandMissing += this.CommandMissingAsync; this.CommandSucceeded += this.CommandSucceededAsync; this.CommandFailed += this.CommandFailedAsync; this.CommandExecuted += this.CommandExecutedAsync; this._guildConfigRepository = guildConfigRepository; this._repeatRepository = repeatRepository; }
public async Task SendEmbed(EmbedBuilder embed, ulong guildID, GuildAuditLogEvent eventType) { var guildConfigRepository = GuildConfigRepository.CreateDefault(_serviceProvider); embed .WithColor(eventType switch { GuildAuditLogEvent.MessageSent => Color.Green, GuildAuditLogEvent.MessageUpdated => Color.Orange, GuildAuditLogEvent.MessageDeleted => Color.Red, GuildAuditLogEvent.UsernameUpdated => Color.Orange, GuildAuditLogEvent.AvatarUpdated => Color.Orange, GuildAuditLogEvent.NicknameUpdated => Color.Orange, GuildAuditLogEvent.MemberRolesUpdated => Color.Orange, GuildAuditLogEvent.MemberJoined => Color.Green, GuildAuditLogEvent.MemberRemoved => Color.Red, GuildAuditLogEvent.BanAdded => Color.Red, GuildAuditLogEvent.BanRemoved => Color.Green, GuildAuditLogEvent.InviteCreated => Color.Green, GuildAuditLogEvent.InviteDeleted => Color.Red, GuildAuditLogEvent.ThreadCreated => Color.Green, _ => throw new NotImplementedException(), })
private async Task AnnounceFile(UploadedFile file, ModCase modCase, IUser actor, RestAction action) { using var scope = _serviceProvider.CreateScope(); _logger.LogInformation($"Announcing file {modCase.GuildId}/{modCase.CaseId}/{file.Name}."); GuildConfig guildConfig = await GuildConfigRepository.CreateDefault(scope.ServiceProvider).GetGuildConfig(modCase.GuildId); if (!string.IsNullOrEmpty(guildConfig.ModInternalNotificationWebhook)) { _logger.LogInformation($"Sending internal webhook for file {modCase.GuildId}/{modCase.CaseId}/{file.Name} to {guildConfig.ModInternalNotificationWebhook}."); try { EmbedBuilder embed = await file.CreateFileEmbed(modCase, action, actor, scope.ServiceProvider); await _discordAPI.ExecuteWebhook(guildConfig.ModInternalNotificationWebhook, embed.Build()); } catch (Exception e) { _logger.LogError(e, $"Error while announcing file {modCase.GuildId}/{modCase.CaseId}/{file.Name} to {guildConfig.ModInternalNotificationWebhook}."); } } }
private async Task GuildMemberAddedHandler(SocketGuildUser member) { using var scope = _serviceProvider.CreateScope(); var translator = scope.ServiceProvider.GetRequiredService <Translator>(); await translator.SetContext(member.Guild.Id); // Refresh identity memberships IdentityManager identityManager = scope.ServiceProvider.GetRequiredService <IdentityManager>(); foreach (Identity identity in identityManager.GetCurrentIdentities()) { if (identity.GetCurrentUser().Id == member.Id) { identity.AddGuildMembership(member); } } // Refresh member cache DiscordAPIInterface discordAPI = scope.ServiceProvider.GetRequiredService <DiscordAPIInterface>(); discordAPI.AddOrUpdateCache(CacheKey.GuildMember(member.Guild.Id, member.Id), new CacheApiResponse(member)); GuildConfig guildConfig; try { guildConfig = await GuildConfigRepository.CreateDefault(scope.ServiceProvider).GetGuildConfig(member.Guild.Id); } catch (ResourceNotFoundException) { return; } try { Punishments handler = scope.ServiceProvider.GetRequiredService <Punishments>(); await handler.HandleMemberJoin(member); } catch (Exception ex) { _logger.LogError(ex, "Failed to handle punishment on member join."); } if (member.IsBot) { return; } List <TrackedInvite> newInvites = await FetchInvites(member.Guild); TrackedInvite usedInvite = null; try { usedInvite = InviteTracker.GetUsedInvite(member.Guild.Id, newInvites); } catch (Exception ex) { _logger.LogError(ex, "Failed to get used invite."); } InviteTracker.AddInvites(member.Guild.Id, newInvites); if (usedInvite != null) { UserInvite invite = new() { GuildId = member.Guild.Id, JoinedUserId = member.Id, JoinedAt = DateTime.UtcNow, InviteIssuerId = usedInvite.CreatorId, InviteCreatedAt = usedInvite.CreatedAt, TargetChannelId = usedInvite.TargetChannelId, UsedInvite = $"https://discord.gg/{usedInvite.Code}" }; _logger.LogInformation($"User {member.Username}#{member.Discriminator} joined guild {member.Guild.Name} with ID: {member.Guild.Id} using invite {usedInvite.Code}"); if (guildConfig.ExecuteWhoisOnJoin && !string.IsNullOrEmpty(guildConfig.ModInternalNotificationWebhook)) { string message; if (invite.InviteIssuerId != 0 && invite.InviteCreatedAt != null) { message = translator.T().NotificationAutoWhoisJoinWithAndFrom(member, invite.InviteIssuerId, invite.InviteCreatedAt.Value, member.CreatedAt.DateTime, invite.UsedInvite); } else { message = translator.T().NotificationAutoWhoisJoinWith(member, member.CreatedAt.DateTime, invite.UsedInvite); } await discordAPI.ExecuteWebhook(guildConfig.ModInternalNotificationWebhook, null, message, AllowedMentions.None); } await InviteRepository.CreateDefault(scope.ServiceProvider).CreateInvite(invite); } }
public async Task <bool> IsAllowedTo(APIActionPermission permission, ModCase modCase) { if (modCase == null) { return(false); } if (IsSiteAdmin()) { return(true); } switch (permission) { case APIActionPermission.View: if (currentUser == null) { return(false); } return(modCase.UserId == currentUser.Id || await HasPermissionOnGuild(DiscordPermission.Moderator, modCase.GuildId)); case APIActionPermission.Delete: return(await HasPermissionOnGuild(DiscordPermission.Moderator, modCase.GuildId)); case APIActionPermission.ForceDelete: return(false); // only siteadmin case APIActionPermission.Edit: GuildConfig guildConfig; try { using var scope = _serviceProvider.CreateScope(); guildConfig = await GuildConfigRepository.CreateDefault(scope.ServiceProvider).GetGuildConfig(modCase.GuildId); } catch (ResourceNotFoundException) { return(false); } if (guildConfig.StrictModPermissionCheck && modCase.PunishmentType != PunishmentType.Warn) { GuildPermission x = GuildPermission.CreateInstantInvite; if (modCase.PunishmentType == PunishmentType.Kick) { x = GuildPermission.KickMembers; } if (modCase.PunishmentType == PunishmentType.Ban) { x = GuildPermission.BanMembers; } if (modCase.PunishmentType == PunishmentType.Mute) { x = GuildPermission.ManageRoles; } if (await HasPermissionOnGuild(DiscordPermission.Admin, modCase.GuildId)) { return(true); } return(await HasPermissionOnGuild(DiscordPermission.Moderator, modCase.GuildId) && await HasRolePermissionInGuild(modCase.GuildId, x)); } return(await HasPermissionOnGuild(DiscordPermission.Moderator, modCase.GuildId)); } return(false); }
public async Task <IActionResult> GetSpecificItem([FromRoute] ulong guildId) { await RequirePermission(guildId, DiscordPermission.Admin); return(Ok(new GuildConfigView(await GuildConfigRepository.CreateDefault(_serviceProvider).GetGuildConfig(guildId)))); }
public async Task Features() { GuildConfig guildConfig = await GuildConfigRepository.CreateDefault(ServiceProvider).GetGuildConfig(Context.Guild.Id); GuildFeatureTest featureTest = new(guildConfig, Context.Guild.CurrentUser); EmbedBuilder embed = new(); embed.WithTimestamp(DateTime.UtcNow); StringBuilder missingBasicPermissions = new(); // kick if (featureTest.HasKickPermission()) { missingBasicPermissions.Append($"\n- {CHECK} {Translator.T().CmdFeaturesKickPermissionGranted()}"); } else { missingBasicPermissions.Append($"\n- {X_CHECK} {Translator.T().CmdFeaturesKickPermissionNotGranted()}"); } // ban if (featureTest.HasBanPermission()) { missingBasicPermissions.Append($"\n- {CHECK} {Translator.T().CmdFeaturesBanPermissionGranted()}"); } else { missingBasicPermissions.Append($"\n- {X_CHECK} {Translator.T().CmdFeaturesBanPermissionNotGranted()}"); } // mute if (featureTest.HasManagedRolePermission()) { missingBasicPermissions.Append($"\n- {CHECK} {Translator.T().CmdFeaturesManageRolePermissionGranted()}"); } else { missingBasicPermissions.Append($"\n- {X_CHECK} {Translator.T().CmdFeaturesManageRolePermissionNotGranted()}"); } // muted role if (!featureTest.HasMutedRolesDefined()) { missingBasicPermissions.Append($"\n- {X_CHECK} {Translator.T().CmdFeaturesMutedRoleUndefined()}"); } else { switch (featureTest.HasManagableMutedRoles()) { case GuildFeatureTestResult.Ok: missingBasicPermissions.Append($"\n- {CHECK} {Translator.T().CmdFeaturesMutedRoleDefined()}"); break; case GuildFeatureTestResult.RoleTooHigh: missingBasicPermissions.Append($"\n- {X_CHECK} {Translator.T().CmdFeaturesMutedRoleDefinedButTooHigh()}"); break; default: missingBasicPermissions.Append($"\n- {X_CHECK} {Translator.T().CmdFeaturesMutedRoleDefinedButInvalid()}"); break; } } // basic punishment feature if (featureTest.FeaturePunishmentExecution()) { embed.AddField($"{CHECK} {Translator.T().CmdFeaturesPunishmentExecution()}", Translator.T().CmdFeaturesPunishmentExecutionDescription(), false); } else { embed.AddField($"{X_CHECK} {Translator.T().CmdFeaturesPunishmentExecution()}", Translator.T().CmdFeaturesPunishmentExecutionDescription() + missingBasicPermissions.ToString(), false); } // unban feature if (featureTest.HasBanPermission()) { embed.AddField($"{CHECK} {Translator.T().CmdFeaturesUnbanRequests()}", Translator.T().CmdFeaturesUnbanRequestsDescriptionGranted(), false); } else { embed.AddField($"{X_CHECK} {Translator.T().CmdFeaturesUnbanRequests()}", Translator.T().CmdFeaturesUnbanRequestsDescriptionNotGranted(), false); } // report command if (featureTest.HasInternalWebhookDefined()) { embed.AddField($"{CHECK} {Translator.T().CmdFeaturesReportCommand()}", Translator.T().CmdFeaturesReportCommandDescriptionGranted(), false); } else { embed.AddField($"{X_CHECK} {Translator.T().CmdFeaturesReportCommand()}", Translator.T().CmdFeaturesReportCommandDescriptionNotGranted(), false); } // invite tracking if (featureTest.HasManagedGuildPermission()) { embed.AddField($"{CHECK} {Translator.T().CmdFeaturesInviteTracking()}", Translator.T().CmdFeaturesInviteTrackingDescriptionGranted(), false); } else { embed.AddField($"{X_CHECK} {Translator.T().CmdFeaturesInviteTracking()}", Translator.T().CmdFeaturesInviteTrackingDescriptionNotGranted(), false); } if (featureTest.SupportsAllFeatures()) { embed.WithTitle(Translator.T().CmdFeaturesSupportAllFeatures()) .WithDescription(Translator.T().CmdFeaturesSupportAllFeaturesDesc()) .WithColor(Color.Green); } else { embed.WithTitle(Translator.T().CmdFeaturesMissingFeatures()) .WithColor(Color.Red); } await Context.Interaction.RespondAsync(embed : embed.Build()); }
public NewGuildWatcher(GuildConfigRepository repository, DiscordSocketClient discordClient) { this._repository = repository; this._discordClient = discordClient; }
public override async Task <PreconditionResult> CheckRequirementsAsync(IInteractionContext context, ICommandInfo commandInfo, IServiceProvider services) { var identity = await services.GetRequiredService <IdentityManager>().GetIdentity(context.User); foreach (RequireCheckEnum check in _checks) { switch (check) { case RequireCheckEnum.GuildRegistered: await RequireRegisteredGuild(services, context); continue; case RequireCheckEnum.GuildMember: await RequireDiscordPermission(DiscordPermission.Member, services, context, identity); continue; case RequireCheckEnum.GuildModerator: await RequireDiscordPermission(DiscordPermission.Moderator, services, context, identity); continue; case RequireCheckEnum.GuildAdmin: await RequireDiscordPermission(DiscordPermission.Admin, services, context, identity); continue; case RequireCheckEnum.GuildMuteRole: try { GuildConfig guildConfig = await GuildConfigRepository.CreateDefault(services).GetGuildConfig(context.Guild.Id); if (guildConfig.MutedRoles.Length == 0) { throw new GuildWithoutMutedRoleException(context.Guild.Id); } } catch (ResourceNotFoundException) { throw new UnregisteredGuildException(context.Guild.Id); } continue; case RequireCheckEnum.SiteAdmin: if (!identity.IsSiteAdmin()) { throw new UnauthorizedException("Only site admins allowed."); } continue; case RequireCheckEnum.GuildStrictModeMute: await RequireStrictModeAccess(PunishmentType.Mute, services, context, identity); continue; case RequireCheckEnum.GuildStrictModeKick: await RequireStrictModeAccess(PunishmentType.Kick, services, context, identity); continue; case RequireCheckEnum.GuildStrictModeBan: await RequireStrictModeAccess(PunishmentType.Ban, services, context, identity); continue; } } return(PreconditionResult.FromSuccess()); }
public async Task <IActionResult> GetUserNetwork([FromQuery][Required] ulong userId) { Identity currentIdentity = await GetIdentity(); List <string> modGuilds = new(); List <DiscordGuildView> guildViews = new(); List <GuildConfig> guildConfigs = await GuildConfigRepository.CreateDefault(_serviceProvider).GetAllGuildConfigs(); if (guildConfigs.Count == 0) { throw new BaseAPIException("No guilds registered"); } foreach (GuildConfig guildConfig in guildConfigs) { if (await currentIdentity.HasPermissionOnGuild(DiscordPermission.Moderator, guildConfig.GuildId)) { modGuilds.Add(guildConfig.GuildId.ToString()); guildViews.Add(new DiscordGuildView(_discordAPI.FetchGuildInfo(guildConfig.GuildId, CacheBehavior.Default))); } } if (modGuilds.Count == 0) { return(Unauthorized()); } DiscordUserView searchedUser = DiscordUserView.CreateOrDefault(await _discordAPI.FetchUserInfo(userId, CacheBehavior.IgnoreButCacheOnError)); // invites // =============================================================================================== InviteRepository inviteRepository = InviteRepository.CreateDefault(_serviceProvider); List <UserInviteExpandedView> invited = new(); foreach (UserInvite invite in await inviteRepository.GetInvitedForUser(userId)) { if (!modGuilds.Contains(invite.GuildId.ToString())) { continue; } invited.Add(new UserInviteExpandedView( invite, await _discordAPI.FetchUserInfo(invite.JoinedUserId, CacheBehavior.OnlyCache), await _discordAPI.FetchUserInfo(invite.InviteIssuerId, CacheBehavior.OnlyCache) )); } List <UserInviteExpandedView> invitedBy = new(); foreach (UserInvite invite in await inviteRepository.GetusedInvitesForUser(userId)) { if (!modGuilds.Contains(invite.GuildId.ToString())) { continue; } invitedBy.Add(new UserInviteExpandedView( invite, await _discordAPI.FetchUserInfo(invite.JoinedUserId, CacheBehavior.OnlyCache), await _discordAPI.FetchUserInfo(invite.InviteIssuerId, CacheBehavior.OnlyCache) )); } // mappings // =============================================================================================== UserMapRepository userMapRepository = UserMapRepository.CreateDefault(_serviceProvider, currentIdentity); List <UserMappingExpandedView> userMappings = new(); foreach (UserMapping userMapping in await userMapRepository.GetUserMapsByUser(userId)) { if (!modGuilds.Contains(userMapping.GuildId.ToString())) { continue; } userMappings.Add(new UserMappingExpandedView( userMapping, await _discordAPI.FetchUserInfo(userMapping.UserA, CacheBehavior.OnlyCache), await _discordAPI.FetchUserInfo(userMapping.UserB, CacheBehavior.OnlyCache), await _discordAPI.FetchUserInfo(userMapping.CreatorUserId, CacheBehavior.OnlyCache) )); } ModCaseRepository modCaseRepository = ModCaseRepository.CreateDefault(_serviceProvider, currentIdentity); AutoModerationEventRepository autoModerationEventRepository = AutoModerationEventRepository.CreateDefault(_serviceProvider); UserNoteRepository userNoteRepository = UserNoteRepository.CreateDefault(_serviceProvider, currentIdentity); List <CaseView> modCases = (await modCaseRepository.GetCasesForUser(userId)).Where(x => modGuilds.Contains(x.GuildId.ToString())).Select(x => new CaseView(x)).ToList(); List <AutoModerationEventView> modEvents = (await autoModerationEventRepository.GetAllEventsForUser(userId)).Where(x => modGuilds.Contains(x.GuildId.ToString())).Select(x => new AutoModerationEventView(x)).ToList(); List <UserNoteView> userNotes = (await userNoteRepository.GetUserNotesByUser(userId)).Where(x => modGuilds.Contains(x.GuildId.ToString())).Select(x => new UserNoteView(x)).ToList(); return(Ok(new { guilds = guildViews, user = searchedUser, invited, invitedBy, modCases, modEvents, userMappings, userNotes })); }
public GuildConfigurationModule(GuildConfigRepository repository, CommandService commandService) { this._repository = repository; this._commandService = commandService; }
private async Task AnnounceModCase(ModCase modCase, IUser actor, bool announcePublic, bool announceDm, RestAction action) { using var scope = _serviceProvider.CreateScope(); _logger.LogInformation($"Announcing modcase {modCase.Id} in guild {modCase.GuildId}."); var translator = scope.ServiceProvider.GetRequiredService <Translator>(); IUser caseUser = await _discordAPI.FetchUserInfo(modCase.UserId, CacheBehavior.Default); GuildConfig guildConfig = await GuildConfigRepository.CreateDefault(scope.ServiceProvider).GetGuildConfig(modCase.GuildId); translator.SetContext(guildConfig); if (announceDm && action != RestAction.Deleted) { _logger.LogInformation($"Sending dm notification to {modCase.UserId} for case {modCase.GuildId}/{modCase.CaseId}"); try { IGuild guild = _discordAPI.FetchGuildInfo(modCase.GuildId, CacheBehavior.Default); string message = string.Empty; switch (modCase.PunishmentType) { case PunishmentType.Mute: if (modCase.PunishedUntil.HasValue) { message = translator.T().NotificationModcaseDMMuteTemp(modCase, guild, _config.GetBaseUrl()); } else { message = translator.T().NotificationModcaseDMMutePerm(guild, _config.GetBaseUrl()); } break; case PunishmentType.Kick: message = translator.T().NotificationModcaseDMKick(guild, _config.GetBaseUrl()); break; case PunishmentType.Ban: if (modCase.PunishedUntil.HasValue) { message = translator.T().NotificationModcaseDMBanTemp(modCase, guild, _config.GetBaseUrl()); } else { message = translator.T().NotificationModcaseDMBanPerm(guild, _config.GetBaseUrl()); } break; default: message = translator.T().NotificationModcaseDMWarn(guild, _config.GetBaseUrl()); break; } await _discordAPI.SendDmMessage(modCase.UserId, message); } catch (Exception e) { _logger.LogError(e, $"Error while announcing modcase {modCase.GuildId}/{modCase.CaseId} in DMs to {modCase.UserId}."); } } if (!string.IsNullOrEmpty(guildConfig.ModPublicNotificationWebhook) && announcePublic) { _logger.LogInformation($"Sending public webhook for modcase {modCase.GuildId}/{modCase.CaseId} to {guildConfig.ModPublicNotificationWebhook}."); try { EmbedBuilder embed = await modCase.CreateModcaseEmbed(action, actor, scope.ServiceProvider, caseUser, false); await _discordAPI.ExecuteWebhook(guildConfig.ModPublicNotificationWebhook, embed.Build(), $"<@{modCase.UserId}>"); } catch (Exception e) { _logger.LogError(e, $"Error while announcing modcase {modCase.GuildId}/{modCase.CaseId} public to {guildConfig.ModPublicNotificationWebhook}."); } } if (!string.IsNullOrEmpty(guildConfig.ModInternalNotificationWebhook)) { _logger.LogInformation($"Sending internal webhook for modcase {modCase.GuildId}/{modCase.CaseId} to {guildConfig.ModInternalNotificationWebhook}."); try { EmbedBuilder embed = await modCase.CreateModcaseEmbed(action, actor, scope.ServiceProvider, caseUser, true); await _discordAPI.ExecuteWebhook(guildConfig.ModInternalNotificationWebhook, embed.Build(), $"<@{modCase.UserId}>"); } catch (Exception e) { _logger.LogError(e, $"Error while announcing modcase {modCase.GuildId}/{modCase.CaseId} internal to {guildConfig.ModInternalNotificationWebhook}."); } } }
public QuotedCommandHandler(IServiceProvider provider, DiscordSocketClient client, CommandServiceConfig commandServiceConfig, CommandHandlerOptions options, CustomModuleBuilder moduleBuilder, IEnumerable <IPluginFactory> pluginFactories, ILogger <PrefixCommandHandler> logger, CommandService commandService, GuildConfigRepository guildConfigRepository, RepeatRepository repeatRepository) : base(provider, client, commandServiceConfig, options, moduleBuilder, pluginFactories, logger, commandService, guildConfigRepository, repeatRepository) { base.logger = logger; }