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 <IActionResult> GetInviteNetwork([FromQuery][Required] string inviteUrl) { InviteRepository inviteRepository = InviteRepository.CreateDefault(_serviceProvider); List <UserInvite> invites = await inviteRepository.GetInvitesByCode(inviteUrl); if (invites == null || invites.Count == 0) { return(NotFound()); } await RequirePermission(invites[0].GuildId, DiscordPermission.Moderator); DiscordGuildView guild = new(_discordAPI.FetchGuildInfo(invites[0].GuildId, CacheBehavior.Default)); List <UserInviteExpandedView> inviteViews = new(); foreach (UserInvite invite in invites) { inviteViews.Add(new UserInviteExpandedView( invite, await _discordAPI.FetchUserInfo(invite.JoinedUserId, CacheBehavior.OnlyCache), await _discordAPI.FetchUserInfo(invite.InviteIssuerId, CacheBehavior.OnlyCache) )); } return(Ok(new { invites = inviteViews, guild })); }
public async Task Whois([Summary("user", "user to scan")] IUser user) { await Context.Interaction.RespondAsync("Getting WHOIS information..."); IGuildUser member = null; try { member = Context.Guild.GetUser(user.Id); } catch (Exception) { } EmbedBuilder embed = new EmbedBuilder() .WithFooter($"UserId: {user.Id}") .WithTimestamp(DateTime.UtcNow) .WithColor(Color.Blue) .WithDescription(user.Mention); List <UserInvite> invites = await InviteRepository.CreateDefault(ServiceProvider).GetusedInvitesForUserAndGuild(user.Id, Context.Guild.Id); List <UserInvite> filteredInvites = invites.OrderByDescending(x => x.JoinedAt).ToList(); if (member != null && member.JoinedAt != null) { filteredInvites = filteredInvites.FindAll(x => x.JoinedAt >= member.JoinedAt.Value.UtcDateTime); } StringBuilder joinedInfo = new(); if (member != null) { joinedInfo.AppendLine(member.JoinedAt.Value.DateTime.ToDiscordTS()); } if (filteredInvites.Count > 0) { UserInvite usedInvite = filteredInvites.First(); joinedInfo.AppendLine(Translator.T().CmdWhoisUsedInvite(usedInvite.UsedInvite)); if (usedInvite.InviteIssuerId != 0) { joinedInfo.AppendLine(Translator.T().CmdWhoisInviteBy(usedInvite.InviteIssuerId)); } } if (!string.IsNullOrEmpty(joinedInfo.ToString())) { embed.AddField(Translator.T().Joined(), joinedInfo.ToString(), true); } embed.AddField(Translator.T().Registered(), user.CreatedAt.DateTime.ToDiscordTS(), true); embed.WithAuthor(user); embed.WithThumbnailUrl(user.GetAvatarOrDefaultUrl(size: 1024)); try { UserNote userNote = await UserNoteRepository.CreateDefault(ServiceProvider, CurrentIdentity).GetUserNote(Context.Guild.Id, user.Id); embed.AddField(Translator.T().UserNote(), userNote.Description.Truncate(1000), false); } catch (ResourceNotFoundException) { } List <UserMapping> userMappings = await UserMapRepository.CreateDefault(ServiceProvider, CurrentIdentity).GetUserMapsByGuildAndUser(Context.Guild.Id, user.Id); if (userMappings.Count > 0) { StringBuilder userMappingsInfo = new(); foreach (UserMapping userMapping in userMappings.Take(5)) { ulong otherUser = userMapping.UserA == user.Id ? userMapping.UserB : userMapping.UserA; userMappingsInfo.AppendLine($"<@{otherUser}> - {userMapping.Reason.Truncate(80)}"); } if (userMappings.Count > 5) { userMappingsInfo.Append("[...]"); } embed.AddField($"{Translator.T().UserMaps()} [{userMappings.Count}]", userMappingsInfo.ToString(), false); } List <ModCase> cases = await ModCaseRepository.CreateWithBotIdentity(ServiceProvider).GetCasesForGuildAndUser(Context.Guild.Id, user.Id); List <ModCase> activeCases = cases.FindAll(c => c.PunishmentActive); if (cases.Count > 0) { StringBuilder caseInfo = new(); foreach (ModCase modCase in cases.Take(5)) { caseInfo.Append($"[{modCase.CaseId} - {modCase.Title.Truncate(50)}]"); caseInfo.Append($"({Config.GetBaseUrl()}/guilds/{modCase.GuildId}/cases/{modCase.CaseId})\n"); } if (cases.Count > 5) { caseInfo.Append("[...]"); } embed.AddField($"{Translator.T().Cases()} [{cases.Count}]", caseInfo.ToString(), false); if (activeCases.Count > 0) { StringBuilder activeInfo = new(); foreach (ModCase modCase in activeCases.Take(5)) { activeInfo.Append($"{modCase.GetPunishment(Translator)} "); if (modCase.PunishedUntil != null) { activeInfo.Append($"({Translator.T().Until()} {modCase.PunishedUntil.Value.ToDiscordTS()}) "); } activeInfo.Append($"[{modCase.CaseId} - {modCase.Title.Truncate(50)}]"); activeInfo.Append($"({Config.GetBaseUrl()}/guilds/{modCase.GuildId}/cases/{modCase.CaseId})\n"); } if (activeCases.Count > 5) { activeInfo.Append("[...]"); } embed.AddField($"{Translator.T().ActivePunishments()} [{activeCases.Count}]", activeInfo.ToString(), false); } } else { embed.AddField($"{Translator.T().Cases()} [0]", Translator.T().CmdWhoisNoCases(), false); } await Context.Interaction.ModifyOriginalResponseAsync(message => { message.Content = ""; message.Embed = embed.Build(); }); }
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 async Task Track([Summary("invite", "Either enter the invite code or the url")] string inviteCode) { await Context.Interaction.RespondAsync("Tracking invite code..."); if (!inviteCode.ToLower().Contains("https://discord.gg/")) { inviteCode = $"https://discord.gg/{inviteCode}"; } List <UserInvite> invites = await InviteRepository.CreateDefault(ServiceProvider).GetInvitesByCode(inviteCode); invites = invites.Where(x => x.GuildId == Context.Guild.Id).OrderByDescending(x => x.JoinedAt).ToList(); DateTime?createdAt = null; IUser creator = null; int? usages = invites.Count; Dictionary <ulong, IUser> invitees = new(); if (invites.Count > 0) { createdAt = invites[0].InviteCreatedAt; if (invites[0].InviteIssuerId != 0) { creator = await DiscordAPI.FetchUserInfo(invites[0].InviteIssuerId, CacheBehavior.Default); } int count = 0; foreach (UserInvite invite in invites) { if (count > 20) { break; } if (!invitees.ContainsKey(invite.JoinedUserId)) { invitees.Add(invite.JoinedUserId, await DiscordAPI.FetchUserInfo(invite.JoinedUserId, CacheBehavior.Default)); } } } else { string code = inviteCode.Split("/").Last(); try { var fetchedInvite = await Context.Client.GetInviteAsync(code); if (fetchedInvite.GuildId != Context.Guild.Id) { await Context.Interaction.ModifyOriginalResponseAsync(message => message.Content = Translator.T().CmdTrackInviteNotFromThisGuild()); return; } try { usages = fetchedInvite.Uses; creator = await DiscordAPI.FetchUserInfo(fetchedInvite.Inviter.Id, CacheBehavior.Default); } catch (NullReferenceException) { } } catch (HttpException e) { if (e.HttpCode == HttpStatusCode.NotFound) { await Context.Interaction.ModifyOriginalResponseAsync(message => message.Content = Translator.T().CmdTrackCannotFindInvite()); } else { await Context.Interaction.ModifyOriginalResponseAsync(message => message.Content = Translator.T().CmdTrackFailedToFetchInvite()); } return; } } EmbedBuilder embed = new(); embed.WithDescription(inviteCode); if (creator != null) { embed.WithAuthor(creator); if (createdAt.HasValue && createdAt.Value != default) { embed.WithDescription(Translator.T().CmdTrackCreatedByAt(inviteCode, creator, createdAt.Value)); } else { embed.WithDescription(Translator.T().CmdTrackCreatedBy(inviteCode, creator)); } } else if (createdAt.HasValue && createdAt.Value != default) { embed.WithDescription(Translator.T().CmdTrackCreatedAt(inviteCode, createdAt.Value)); } StringBuilder usedBy = new(); foreach (UserInvite invite in invites) { if (usedBy.Length > 900) { break; } usedBy.Append("- "); if (invitees.ContainsKey(invite.JoinedUserId)) { IUser user = invitees[invite.JoinedUserId]; usedBy.Append($"`{user.Username}#{user.Discriminator}` "); } usedBy.AppendLine($"`{invite.JoinedUserId}` - {invite.JoinedAt.ToDiscordTS()}"); } if (invites.Count == 0) { usedBy.Clear(); usedBy.Append(Translator.T().CmdTrackNotTrackedYet()); } embed.AddField(Translator.T().CmdTrackUsedBy(usages.GetValueOrDefault()), usedBy.ToString(), false); embed.WithFooter($"Invite: {inviteCode}"); embed.WithTimestamp(DateTime.UtcNow); embed.WithColor(Color.Gold); await Context.Interaction.ModifyOriginalResponseAsync(message => { message.Content = ""; message.Embed = embed.Build(); }); }
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); } }