2024-08-20 21:03:03 +02:00
|
|
|
using Catalogger.Backend.Cache;
|
2024-08-21 17:31:39 +02:00
|
|
|
using Catalogger.Backend.Cache.InMemoryCache;
|
2024-08-20 21:03:03 +02:00
|
|
|
using Catalogger.Backend.Database;
|
|
|
|
|
using Catalogger.Backend.Database.Queries;
|
|
|
|
|
using Catalogger.Backend.Extensions;
|
|
|
|
|
using Catalogger.Backend.Services;
|
|
|
|
|
using Humanizer;
|
2024-08-21 17:31:39 +02:00
|
|
|
using Remora.Discord.API;
|
2024-08-20 21:03:03 +02:00
|
|
|
using Remora.Discord.API.Abstractions.Gateway.Events;
|
2024-09-02 15:59:16 +02:00
|
|
|
using Remora.Discord.API.Abstractions.Objects;
|
2024-08-20 21:03:03 +02:00
|
|
|
using Remora.Discord.API.Abstractions.Rest;
|
|
|
|
|
using Remora.Discord.API.Objects;
|
|
|
|
|
using Remora.Discord.Extensions.Embeds;
|
|
|
|
|
using Remora.Discord.Gateway.Responders;
|
|
|
|
|
using Remora.Results;
|
|
|
|
|
|
|
|
|
|
namespace Catalogger.Backend.Bot.Responders.Guilds;
|
|
|
|
|
|
|
|
|
|
public class GuildMemberAddResponder(
|
|
|
|
|
ILogger logger,
|
|
|
|
|
DatabaseContext db,
|
|
|
|
|
IMemberCache memberCache,
|
2024-08-21 17:31:39 +02:00
|
|
|
UserCache userCache,
|
2024-08-20 21:03:03 +02:00
|
|
|
WebhookExecutorService webhookExecutor,
|
|
|
|
|
IDiscordRestGuildAPI guildApi,
|
2024-10-09 17:35:11 +02:00
|
|
|
PluralkitApiService pluralkitApi
|
|
|
|
|
) : IResponder<IGuildMemberAdd>
|
2024-08-20 21:03:03 +02:00
|
|
|
{
|
|
|
|
|
private readonly ILogger _logger = logger.ForContext<GuildMemberAddResponder>();
|
|
|
|
|
private static readonly TimeSpan NewAccountThreshold = 7.Days();
|
|
|
|
|
|
|
|
|
|
public async Task<Result> RespondAsync(IGuildMemberAdd member, CancellationToken ct = default)
|
|
|
|
|
{
|
|
|
|
|
await memberCache.SetAsync(member.GuildID, member);
|
|
|
|
|
|
|
|
|
|
var user = member.User.GetOrThrow();
|
|
|
|
|
|
|
|
|
|
var builder = new EmbedBuilder()
|
|
|
|
|
.WithTitle("Member joined")
|
|
|
|
|
.WithColour(DiscordUtils.Green)
|
|
|
|
|
.WithAuthor(user.Tag(), null, user.AvatarUrl())
|
|
|
|
|
.WithDescription($"<@{user.ID}>")
|
|
|
|
|
.WithCurrentTimestamp()
|
|
|
|
|
.WithFooter($"ID: {user.ID}");
|
|
|
|
|
|
|
|
|
|
var guildConfig = await db.GetGuildAsync(member.GuildID, ct);
|
|
|
|
|
var guildRes = await guildApi.GetGuildAsync(member.GuildID, withCounts: true, ct);
|
|
|
|
|
if (guildRes.IsSuccess)
|
2024-10-09 17:35:11 +02:00
|
|
|
builder.Description +=
|
|
|
|
|
$"\n{guildRes.Entity.ApproximateMemberCount.Value.Ordinalize()} to join";
|
2024-08-20 21:03:03 +02:00
|
|
|
|
2024-08-21 17:31:39 +02:00
|
|
|
builder.Description +=
|
|
|
|
|
$"\ncreated {user.ID.Timestamp.Prettify()} ago\n<t:{user.ID.Timestamp.ToUnixTimeSeconds()}:F>";
|
2024-08-20 21:03:03 +02:00
|
|
|
|
|
|
|
|
var pkSystem = await pluralkitApi.GetPluralKitSystemAsync(user.ID.Value, ct);
|
|
|
|
|
if (pkSystem != null)
|
|
|
|
|
{
|
2024-10-09 17:35:11 +02:00
|
|
|
var createdAt =
|
|
|
|
|
pkSystem.Created != null
|
|
|
|
|
? $"{pkSystem.Created.Value.Prettify()} ago (<t:{pkSystem.Created.Value.ToUnixTimeSeconds()}:F>)"
|
|
|
|
|
: "*(unknown)*";
|
|
|
|
|
builder.AddField(
|
|
|
|
|
"PluralKit system",
|
|
|
|
|
$"""
|
|
|
|
|
**ID:** {pkSystem.Id} (`{pkSystem.Uuid}`)
|
|
|
|
|
**Name:** {pkSystem.Name ?? "*(none)*"}
|
|
|
|
|
**Tag:** {pkSystem.Tag ?? "*(none)*"}
|
|
|
|
|
**Created:** {createdAt}
|
|
|
|
|
"""
|
|
|
|
|
);
|
2024-08-20 21:03:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: find used invite
|
|
|
|
|
|
|
|
|
|
List<Embed> embeds = [builder.Build().GetOrThrow()];
|
|
|
|
|
|
|
|
|
|
if (user.ID.Timestamp > DateTimeOffset.Now - NewAccountThreshold)
|
|
|
|
|
{
|
2024-10-09 17:35:11 +02:00
|
|
|
embeds.Add(
|
|
|
|
|
new EmbedBuilder()
|
|
|
|
|
.WithTitle("New account")
|
|
|
|
|
.WithColour(DiscordUtils.Orange)
|
|
|
|
|
.WithDescription($"\u26a0\ufe0f Created {user.ID.Timestamp.Prettify()} ago")
|
|
|
|
|
.Build()
|
|
|
|
|
.GetOrThrow()
|
|
|
|
|
);
|
2024-08-21 17:31:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var watchlist = await db.GetWatchlistEntryAsync(member.GuildID, user.ID, ct);
|
|
|
|
|
if (watchlist != null)
|
|
|
|
|
{
|
2024-10-09 17:35:11 +02:00
|
|
|
var moderator = await userCache.GetUserAsync(
|
|
|
|
|
DiscordSnowflake.New(watchlist.ModeratorId)
|
|
|
|
|
);
|
|
|
|
|
var mod =
|
|
|
|
|
moderator != null
|
|
|
|
|
? $"{moderator.Tag()} (<@{moderator.ID}>)"
|
|
|
|
|
: $"<@{watchlist.ModeratorId}>";
|
|
|
|
|
|
|
|
|
|
embeds.Add(
|
|
|
|
|
new EmbedBuilder()
|
|
|
|
|
.WithTitle("⚠️ User on watchlist")
|
|
|
|
|
.WithColour(DiscordUtils.Red)
|
|
|
|
|
.WithDescription(
|
|
|
|
|
$"**{user.Tag()}** is on this server's watch list.\n\n{watchlist.Reason}"
|
|
|
|
|
)
|
|
|
|
|
.WithFooter($"ID: {user.ID} | Added")
|
|
|
|
|
.WithTimestamp(watchlist.AddedAt.ToDateTimeOffset())
|
|
|
|
|
.AddField("Moderator", mod)
|
|
|
|
|
.GetOrThrow()
|
|
|
|
|
.Build()
|
|
|
|
|
.GetOrThrow()
|
|
|
|
|
);
|
2024-08-20 21:03:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pkSystem != null)
|
|
|
|
|
{
|
2024-10-09 17:35:11 +02:00
|
|
|
if (
|
|
|
|
|
guildConfig.BannedSystems.Contains(pkSystem.Id)
|
|
|
|
|
|| guildConfig.BannedSystems.Contains(pkSystem.Uuid.ToString())
|
|
|
|
|
)
|
2024-08-20 21:03:03 +02:00
|
|
|
{
|
2024-10-09 17:35:11 +02:00
|
|
|
embeds.Add(
|
|
|
|
|
new EmbedBuilder()
|
|
|
|
|
.WithTitle("Banned system")
|
|
|
|
|
.WithDescription(
|
|
|
|
|
"\u26a0\ufe0f The system associated with this account has been banned from the server."
|
|
|
|
|
)
|
|
|
|
|
.WithColour(DiscordUtils.Red)
|
|
|
|
|
.WithFooter($"ID: {pkSystem.Id}")
|
|
|
|
|
.Build()
|
|
|
|
|
.GetOrThrow()
|
|
|
|
|
);
|
2024-08-20 21:03:03 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (embeds.Count > 1)
|
2024-10-09 17:35:11 +02:00
|
|
|
await webhookExecutor.SendLogAsync(
|
|
|
|
|
guildConfig.Channels.GuildMemberAdd,
|
|
|
|
|
embeds.Cast<IEmbed>().ToList(),
|
|
|
|
|
[]
|
|
|
|
|
);
|
|
|
|
|
else
|
|
|
|
|
webhookExecutor.QueueLog(guildConfig.Channels.GuildMemberAdd, embeds[0]);
|
2024-08-20 21:03:03 +02:00
|
|
|
|
|
|
|
|
return Result.Success;
|
|
|
|
|
}
|
2024-10-09 17:35:11 +02:00
|
|
|
}
|