using StackExchange.Redis; namespace PluralKit.Core; public class RedisService { public ConnectionMultiplexer? Connection { get; set; } public async Task InitAsync(CoreConfig config) { if (config.RedisAddr != null) Connection = await ConnectionMultiplexer.ConnectAsync(config.RedisAddr); } private string LastMessageKey(ulong userId, ulong channelId) => $"user_last_message:{userId}:{channelId}"; public Task SetLastMessage(ulong userId, ulong channelId, ulong mid) => Connection.GetDatabase().UlongSetAsync(LastMessageKey(userId, channelId), mid, expiry: TimeSpan.FromMinutes(10)); public Task GetLastMessage(ulong userId, ulong channelId) => Connection.GetDatabase().UlongGetAsync(LastMessageKey(userId, channelId)); private string LoggerCleanKey(ulong userId, ulong guildId) => $"log_cleanup:{userId}:{guildId}"; public Task SetLogCleanup(ulong userId, ulong guildId) => Connection.GetDatabase().StringSetAsync(LoggerCleanKey(userId, guildId), 1, expiry: TimeSpan.FromSeconds(3)); public Task HasLogCleanup(ulong userId, ulong guildId) => Connection.GetDatabase().KeyExistsAsync(LoggerCleanKey(userId, guildId)); // note: these methods are named weird - they actually get the proxied mid from the original mid // but anything else would've been more confusing private string OriginalMidKey(ulong original_mid) => $"original_mid:{original_mid}"; public Task SetOriginalMid(ulong original_mid, ulong proxied_mid) => Connection.GetDatabase().UlongSetAsync(OriginalMidKey(original_mid), proxied_mid, expiry: TimeSpan.FromMinutes(30)); public Task GetOriginalMid(ulong original_mid) => Connection.GetDatabase().UlongGetAsync(OriginalMidKey(original_mid)); } public static class RedisExt { public static async Task UlongGetAsync(this StackExchange.Redis.IDatabase database, string key) { var data = await database.StringGetAsync(key); if (data == RedisValue.Null) return null; if (ulong.TryParse(data, out var value)) return value; return null; } public static Task UlongSetAsync(this StackExchange.Redis.IDatabase database, string key, ulong value, TimeSpan? expiry = null) => database.StringSetAsync(key, value.ToString(), expiry); }