// Copyright (C) 2021-present sam (starshines.gay) // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published // by the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . using Catalogger.Backend.Database.Redis; using Remora.Discord.API; using Remora.Discord.API.Abstractions.Objects; using Remora.Discord.API.Objects; using Remora.Rest.Core; namespace Catalogger.Backend.Cache.RedisCache; public class RedisInviteCache(RedisService redisService) : IInviteCache { public async Task> TryGetAsync(Snowflake guildId) { var redisInvites = await redisService.GetAsync>(InvitesKey(guildId)) ?? []; return redisInvites.Select(r => r.ToRemoraInvite()); } public async Task SetAsync(Snowflake guildId, IEnumerable invites) => await redisService.SetAsync(InvitesKey(guildId), invites.Select(RedisInvite.FromIInvite)); public async Task RemoveAsync(Snowflake guildId) => await redisService.GetDatabase().KeyDeleteAsync(InvitesKey(guildId)); private static string InvitesKey(Snowflake guildId) => $"guild-invites:{guildId}"; } internal record RedisInvite( string Code, RedisPartialGuild? Guild, RedisPartialChannel? Channel, int Uses, int MaxUses, TimeSpan MaxAge, bool IsTemporary, DateTimeOffset CreatedAt, RedisUser? Inviter, DateTimeOffset? ExpiresAt ) { public static RedisInvite FromIInvite(IInviteWithMetadata invite) => new( invite.Code, invite.Guild.Map(RedisPartialGuild.FromIPartialGuild).OrDefault(), invite.Channel != null ? RedisPartialChannel.FromIPartialChannel(invite.Channel) : null, invite.Uses, invite.MaxUses, invite.MaxAge, invite.IsTemporary, invite.CreatedAt, invite.Inviter.Map(RedisUser.FromIUser).OrDefault(), invite.ExpiresAt.OrDefault() ); public InviteWithMetadata ToRemoraInvite() => new( Code, Guild?.ToRemoraPartialGuild() ?? new Optional(), Channel?.ToRemoraPartialChannel(), Uses, MaxUses, MaxAge, IsTemporary, CreatedAt, Inviter?.ToRemoraUser() ?? new Optional(), ExpiresAt: ExpiresAt ); } internal record RedisPartialGuild(ulong Id, string? Name) { public static RedisPartialGuild FromIPartialGuild(IPartialGuild guild) => new(guild.ID.Value.Value, guild.Name.OrDefault(null)); public PartialGuild ToRemoraPartialGuild() => new(DiscordSnowflake.New(Id), Name ?? new Optional()); } internal record RedisPartialChannel(ulong Id, string? Name) { public static RedisPartialChannel FromIPartialChannel(IPartialChannel channel) => new(channel.ID.Value.Value, channel.Name.OrDefault(null)); public PartialChannel ToRemoraPartialChannel() => new(DiscordSnowflake.New(Id), Name: Name); }