chore: format with csharpier
This commit is contained in:
parent
2f516dcb73
commit
4f54077c68
59 changed files with 2000 additions and 942 deletions
|
|
@ -30,18 +30,17 @@ public class DatabaseContext : DbContext
|
|||
}.ConnectionString;
|
||||
|
||||
var dataSourceBuilder = new NpgsqlDataSourceBuilder(connString);
|
||||
dataSourceBuilder
|
||||
.EnableDynamicJson()
|
||||
.UseNodaTime();
|
||||
dataSourceBuilder.EnableDynamicJson().UseNodaTime();
|
||||
_dataSource = dataSourceBuilder.Build();
|
||||
_loggerFactory = loggerFactory;
|
||||
}
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
=> optionsBuilder
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) =>
|
||||
optionsBuilder
|
||||
.ConfigureWarnings(c =>
|
||||
c.Ignore(CoreEventId.ManyServiceProvidersCreatedWarning)
|
||||
.Ignore(CoreEventId.SaveChangesFailed))
|
||||
.Ignore(CoreEventId.SaveChangesFailed)
|
||||
)
|
||||
.UseNpgsql(_dataSource, o => o.UseNodaTime())
|
||||
.UseSnakeCaseNamingConvention()
|
||||
.UseLoggerFactory(_loggerFactory)
|
||||
|
|
@ -53,14 +52,17 @@ public class DatabaseContext : DbContext
|
|||
configurationBuilder.Properties<List<ulong>>().HaveConversion<UlongArrayValueConverter>();
|
||||
}
|
||||
|
||||
private static readonly ValueComparer<List<ulong>> UlongListValueComparer = new(
|
||||
(c1, c2) => c1 != null && c2 != null && c1.SequenceEqual(c2),
|
||||
c => c.Aggregate(0, (a, v) => HashCode.Combine(a, v.GetHashCode()))
|
||||
);
|
||||
private static readonly ValueComparer<List<ulong>> UlongListValueComparer =
|
||||
new(
|
||||
(c1, c2) => c1 != null && c2 != null && c1.SequenceEqual(c2),
|
||||
c => c.Aggregate(0, (a, v) => HashCode.Combine(a, v.GetHashCode()))
|
||||
);
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<Guild>().Property(g => g.KeyRoles)
|
||||
modelBuilder
|
||||
.Entity<Guild>()
|
||||
.Property(g => g.KeyRoles)
|
||||
.Metadata.SetValueComparer(UlongListValueComparer);
|
||||
|
||||
modelBuilder.Entity<Invite>().HasKey(i => i.Code);
|
||||
|
|
@ -76,22 +78,25 @@ public class DesignTimeDatabaseContextFactory : IDesignTimeDbContextFactory<Data
|
|||
public DatabaseContext CreateDbContext(string[] args)
|
||||
{
|
||||
// Read the configuration file
|
||||
var config = new ConfigurationBuilder()
|
||||
.AddConfiguration()
|
||||
.Build()
|
||||
// Get the configuration as our config class
|
||||
.Get<Config>() ?? new();
|
||||
var config =
|
||||
new ConfigurationBuilder()
|
||||
.AddConfiguration()
|
||||
.Build()
|
||||
// Get the configuration as our config class
|
||||
.Get<Config>() ?? new();
|
||||
|
||||
return new DatabaseContext(config, null);
|
||||
}
|
||||
}
|
||||
|
||||
public class UlongValueConverter() : ValueConverter<ulong, long>(
|
||||
convertToProviderExpression: x => (long)x,
|
||||
convertFromProviderExpression: x => (ulong)x
|
||||
);
|
||||
public class UlongValueConverter()
|
||||
: ValueConverter<ulong, long>(
|
||||
convertToProviderExpression: x => (long)x,
|
||||
convertFromProviderExpression: x => (ulong)x
|
||||
);
|
||||
|
||||
public class UlongArrayValueConverter() : ValueConverter<List<ulong>, List<long>>(
|
||||
convertToProviderExpression: x => x.Select(i => (long)i).ToList(),
|
||||
convertFromProviderExpression: x => x.Select(i => (ulong)i).ToList()
|
||||
);
|
||||
public class UlongArrayValueConverter()
|
||||
: ValueConverter<List<ulong>, List<long>>(
|
||||
convertToProviderExpression: x => x.Select(i => (long)i).ToList(),
|
||||
convertFromProviderExpression: x => x.Select(i => (ulong)i).ToList()
|
||||
);
|
||||
|
|
|
|||
|
|
@ -33,4 +33,4 @@ public class EncryptionService(Config config) : IEncryptionService
|
|||
|
||||
return Encoding.UTF8.GetString(plaintext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,4 +4,4 @@ public interface IEncryptionService
|
|||
{
|
||||
public byte[] Encrypt(string data);
|
||||
public string Decrypt(byte[] input);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,23 +20,22 @@ namespace Catalogger.Backend.Database.Migrations
|
|||
id = table.Column<long>(type: "bigint", nullable: false),
|
||||
channels = table.Column<Guild.ChannelConfig>(type: "jsonb", nullable: false),
|
||||
banned_systems = table.Column<List<string>>(type: "text[]", nullable: false),
|
||||
key_roles = table.Column<List<long>>(type: "bigint[]", nullable: false)
|
||||
key_roles = table.Column<List<long>>(type: "bigint[]", nullable: false),
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_guilds", x => x.id);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "ignored_messages",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<long>(type: "bigint", nullable: false)
|
||||
},
|
||||
columns: table => new { id = table.Column<long>(type: "bigint", nullable: false) },
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_ignored_messages", x => x.id);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "invites",
|
||||
|
|
@ -44,12 +43,13 @@ namespace Catalogger.Backend.Database.Migrations
|
|||
{
|
||||
code = table.Column<string>(type: "text", nullable: false),
|
||||
guild_id = table.Column<long>(type: "bigint", nullable: false),
|
||||
name = table.Column<string>(type: "text", nullable: false)
|
||||
name = table.Column<string>(type: "text", nullable: false),
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_invites", x => x.code);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "messages",
|
||||
|
|
@ -65,12 +65,13 @@ namespace Catalogger.Backend.Database.Migrations
|
|||
username = table.Column<byte[]>(type: "bytea", nullable: false),
|
||||
content = table.Column<byte[]>(type: "bytea", nullable: false),
|
||||
metadata = table.Column<byte[]>(type: "bytea", nullable: true),
|
||||
attachment_size = table.Column<int>(type: "integer", nullable: false)
|
||||
attachment_size = table.Column<int>(type: "integer", nullable: false),
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_messages", x => x.id);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "watchlists",
|
||||
|
|
@ -78,38 +79,39 @@ namespace Catalogger.Backend.Database.Migrations
|
|||
{
|
||||
guild_id = table.Column<long>(type: "bigint", nullable: false),
|
||||
user_id = table.Column<long>(type: "bigint", nullable: false),
|
||||
added_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
added_at = table.Column<Instant>(
|
||||
type: "timestamp with time zone",
|
||||
nullable: false,
|
||||
defaultValueSql: "now()"
|
||||
),
|
||||
moderator_id = table.Column<long>(type: "bigint", nullable: false),
|
||||
reason = table.Column<string>(type: "text", nullable: false)
|
||||
reason = table.Column<string>(type: "text", nullable: false),
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_watchlists", x => new { x.guild_id, x.user_id });
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_invites_guild_id",
|
||||
table: "invites",
|
||||
column: "guild_id");
|
||||
column: "guild_id"
|
||||
);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "guilds");
|
||||
migrationBuilder.DropTable(name: "guilds");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "ignored_messages");
|
||||
migrationBuilder.DropTable(name: "ignored_messages");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "invites");
|
||||
migrationBuilder.DropTable(name: "invites");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "messages");
|
||||
migrationBuilder.DropTable(name: "messages");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "watchlists");
|
||||
migrationBuilder.DropTable(name: "watchlists");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,18 +9,26 @@ public class Guild
|
|||
[DatabaseGenerated(DatabaseGeneratedOption.None)]
|
||||
public required ulong Id { get; init; }
|
||||
|
||||
[Column(TypeName = "jsonb")] public ChannelConfig Channels { get; init; } = new();
|
||||
[Column(TypeName = "jsonb")]
|
||||
public ChannelConfig Channels { get; init; } = new();
|
||||
public List<string> BannedSystems { get; init; } = [];
|
||||
public List<ulong> KeyRoles { get; init; } = [];
|
||||
|
||||
public bool IsMessageIgnored(Snowflake channelId, Snowflake userId)
|
||||
{
|
||||
if (Channels is { MessageDelete: 0, MessageUpdate: 0, MessageDeleteBulk: 0 } ||
|
||||
Channels.IgnoredChannels.Contains(channelId.ToUlong()) ||
|
||||
Channels.IgnoredUsers.Contains(userId.ToUlong())) return true;
|
||||
if (
|
||||
Channels is { MessageDelete: 0, MessageUpdate: 0, MessageDeleteBulk: 0 }
|
||||
|| Channels.IgnoredChannels.Contains(channelId.ToUlong())
|
||||
|| Channels.IgnoredUsers.Contains(userId.ToUlong())
|
||||
)
|
||||
return true;
|
||||
|
||||
if (Channels.IgnoredUsersPerChannel.TryGetValue(channelId.ToUlong(),
|
||||
out var thisChannelIgnoredUsers))
|
||||
if (
|
||||
Channels.IgnoredUsersPerChannel.TryGetValue(
|
||||
channelId.ToUlong(),
|
||||
out var thisChannelIgnoredUsers
|
||||
)
|
||||
)
|
||||
return thisChannelIgnoredUsers.Contains(userId.ToUlong());
|
||||
|
||||
return false;
|
||||
|
|
@ -56,4 +64,4 @@ public class Guild
|
|||
public ulong MessageDelete { get; set; }
|
||||
public ulong MessageDeleteBulk { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,4 +5,4 @@ public class Invite
|
|||
public required ulong GuildId { get; init; }
|
||||
public required string Code { get; init; }
|
||||
public required string Name { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,13 +15,16 @@ public class Message
|
|||
public string? Member { get; set; }
|
||||
public string? System { get; set; }
|
||||
|
||||
[Column("username")] public byte[] EncryptedUsername { get; set; } = [];
|
||||
[Column("content")] public byte[] EncryptedContent { get; set; } = [];
|
||||
[Column("metadata")] public byte[]? EncryptedMetadata { get; set; }
|
||||
[Column("username")]
|
||||
public byte[] EncryptedUsername { get; set; } = [];
|
||||
|
||||
[Column("content")]
|
||||
public byte[] EncryptedContent { get; set; } = [];
|
||||
|
||||
[Column("metadata")]
|
||||
public byte[]? EncryptedMetadata { get; set; }
|
||||
|
||||
public int AttachmentSize { get; set; } = 0;
|
||||
}
|
||||
|
||||
public record IgnoredMessage(
|
||||
[property: DatabaseGenerated(DatabaseGeneratedOption.None)]
|
||||
ulong Id);
|
||||
public record IgnoredMessage([property: DatabaseGenerated(DatabaseGeneratedOption.None)] ulong Id);
|
||||
|
|
|
|||
|
|
@ -10,4 +10,4 @@ public class Watchlist
|
|||
|
||||
public required ulong ModeratorId { get; set; }
|
||||
public required string Reason { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,11 @@ using DbMessage = Catalogger.Backend.Database.Models.Message;
|
|||
|
||||
namespace Catalogger.Backend.Database.Queries;
|
||||
|
||||
public class MessageRepository(ILogger logger, DatabaseContext db, IEncryptionService encryptionService)
|
||||
public class MessageRepository(
|
||||
ILogger logger,
|
||||
DatabaseContext db,
|
||||
IEncryptionService encryptionService
|
||||
)
|
||||
{
|
||||
private readonly ILogger _logger = logger.ForContext<MessageRepository>();
|
||||
|
||||
|
|
@ -14,8 +18,10 @@ public class MessageRepository(ILogger logger, DatabaseContext db, IEncryptionSe
|
|||
{
|
||||
_logger.Debug("Saving message {MessageId}", msg.ID);
|
||||
|
||||
var metadata = new Metadata(IsWebhook: msg.WebhookID.HasValue,
|
||||
msg.Attachments.Select(a => new Attachment(a.Filename, a.Size, a.ContentType.Value)));
|
||||
var metadata = new Metadata(
|
||||
IsWebhook: msg.WebhookID.HasValue,
|
||||
msg.Attachments.Select(a => new Attachment(a.Filename, a.Size, a.ContentType.Value))
|
||||
);
|
||||
|
||||
var dbMessage = new DbMessage
|
||||
{
|
||||
|
|
@ -24,12 +30,22 @@ public class MessageRepository(ILogger logger, DatabaseContext db, IEncryptionSe
|
|||
ChannelId = msg.ChannelID.ToUlong(),
|
||||
GuildId = msg.GuildID.ToUlong(),
|
||||
|
||||
EncryptedContent =
|
||||
await Task.Run(
|
||||
() => encryptionService.Encrypt(string.IsNullOrWhiteSpace(msg.Content) ? "None" : msg.Content), ct),
|
||||
EncryptedUsername = await Task.Run(() => encryptionService.Encrypt(msg.Author.Tag()), ct),
|
||||
EncryptedMetadata = await Task.Run(() => encryptionService.Encrypt(JsonSerializer.Serialize(metadata)), ct),
|
||||
AttachmentSize = msg.Attachments.Select(a => a.Size).Sum()
|
||||
EncryptedContent = await Task.Run(
|
||||
() =>
|
||||
encryptionService.Encrypt(
|
||||
string.IsNullOrWhiteSpace(msg.Content) ? "None" : msg.Content
|
||||
),
|
||||
ct
|
||||
),
|
||||
EncryptedUsername = await Task.Run(
|
||||
() => encryptionService.Encrypt(msg.Author.Tag()),
|
||||
ct
|
||||
),
|
||||
EncryptedMetadata = await Task.Run(
|
||||
() => encryptionService.Encrypt(JsonSerializer.Serialize(metadata)),
|
||||
ct
|
||||
),
|
||||
AttachmentSize = msg.Attachments.Select(a => a.Size).Sum(),
|
||||
};
|
||||
|
||||
db.Add(dbMessage);
|
||||
|
|
@ -56,17 +72,32 @@ public class MessageRepository(ILogger logger, DatabaseContext db, IEncryptionSe
|
|||
}
|
||||
else
|
||||
{
|
||||
var metadata = new Metadata(IsWebhook: msg.WebhookID.HasValue,
|
||||
msg.Attachments.Select(a => new Attachment(a.Filename, a.Size, a.ContentType.Value)));
|
||||
var metadata = new Metadata(
|
||||
IsWebhook: msg.WebhookID.HasValue,
|
||||
msg.Attachments.Select(a => new Attachment(a.Filename, a.Size, a.ContentType.Value))
|
||||
);
|
||||
|
||||
var dbMsg = await db.Messages.FindAsync(msg.ID.Value);
|
||||
if (dbMsg == null) throw new CataloggerError("Message was null despite HasProxyInfoAsync returning true");
|
||||
if (dbMsg == null)
|
||||
throw new CataloggerError(
|
||||
"Message was null despite HasProxyInfoAsync returning true"
|
||||
);
|
||||
|
||||
dbMsg.EncryptedContent = await Task.Run(
|
||||
() => encryptionService.Encrypt(string.IsNullOrWhiteSpace(msg.Content) ? "None" : msg.Content), ct);
|
||||
dbMsg.EncryptedUsername = await Task.Run(() => encryptionService.Encrypt(msg.Author.Tag()), ct);
|
||||
dbMsg.EncryptedMetadata =
|
||||
await Task.Run(() => encryptionService.Encrypt(JsonSerializer.Serialize(metadata)), ct);
|
||||
() =>
|
||||
encryptionService.Encrypt(
|
||||
string.IsNullOrWhiteSpace(msg.Content) ? "None" : msg.Content
|
||||
),
|
||||
ct
|
||||
);
|
||||
dbMsg.EncryptedUsername = await Task.Run(
|
||||
() => encryptionService.Encrypt(msg.Author.Tag()),
|
||||
ct
|
||||
);
|
||||
dbMsg.EncryptedMetadata = await Task.Run(
|
||||
() => encryptionService.Encrypt(JsonSerializer.Serialize(metadata)),
|
||||
ct
|
||||
);
|
||||
|
||||
db.Update(dbMsg);
|
||||
await db.SaveChangesAsync(ct);
|
||||
|
|
@ -80,17 +111,26 @@ public class MessageRepository(ILogger logger, DatabaseContext db, IEncryptionSe
|
|||
_logger.Debug("Retrieving message {MessageId}", id);
|
||||
|
||||
var dbMsg = await db.Messages.FindAsync(id);
|
||||
if (dbMsg == null) return null;
|
||||
if (dbMsg == null)
|
||||
return null;
|
||||
|
||||
return new Message(dbMsg.Id, dbMsg.OriginalId, dbMsg.UserId, dbMsg.ChannelId, dbMsg.GuildId, dbMsg.Member,
|
||||
return new Message(
|
||||
dbMsg.Id,
|
||||
dbMsg.OriginalId,
|
||||
dbMsg.UserId,
|
||||
dbMsg.ChannelId,
|
||||
dbMsg.GuildId,
|
||||
dbMsg.Member,
|
||||
dbMsg.System,
|
||||
Username: await Task.Run(() => encryptionService.Decrypt(dbMsg.EncryptedUsername), ct),
|
||||
Content: await Task.Run(() => encryptionService.Decrypt(dbMsg.EncryptedContent), ct),
|
||||
Metadata: dbMsg.EncryptedMetadata != null
|
||||
? JsonSerializer.Deserialize<Metadata>(
|
||||
await Task.Run(() => encryptionService.Decrypt(dbMsg.EncryptedMetadata), ct))
|
||||
await Task.Run(() => encryptionService.Decrypt(dbMsg.EncryptedMetadata), ct)
|
||||
)
|
||||
: null,
|
||||
dbMsg.AttachmentSize);
|
||||
dbMsg.AttachmentSize
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -101,12 +141,19 @@ public class MessageRepository(ILogger logger, DatabaseContext db, IEncryptionSe
|
|||
{
|
||||
_logger.Debug("Checking if message {MessageId} has proxy information", id);
|
||||
|
||||
var msg = await db.Messages.Select(m => new { m.Id, m.OriginalId }).FirstOrDefaultAsync(m => m.Id == id);
|
||||
var msg = await db
|
||||
.Messages.Select(m => new { m.Id, m.OriginalId })
|
||||
.FirstOrDefaultAsync(m => m.Id == id);
|
||||
return (msg != null, msg?.OriginalId != null);
|
||||
}
|
||||
|
||||
public async Task SetProxiedMessageDataAsync(ulong id, ulong originalId, ulong authorId, string? systemId,
|
||||
string? memberId)
|
||||
public async Task SetProxiedMessageDataAsync(
|
||||
ulong id,
|
||||
ulong originalId,
|
||||
ulong authorId,
|
||||
string? systemId,
|
||||
string? memberId
|
||||
)
|
||||
{
|
||||
_logger.Debug("Setting proxy information for message {MessageId}", id);
|
||||
|
||||
|
|
@ -151,4 +198,4 @@ public class MessageRepository(ILogger logger, DatabaseContext db, IEncryptionSe
|
|||
public record Metadata(bool IsWebhook, IEnumerable<Attachment> Attachments);
|
||||
|
||||
public record Attachment(string Filename, int Size, string ContentType);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,21 +6,34 @@ namespace Catalogger.Backend.Database.Queries;
|
|||
|
||||
public static class QueryExtensions
|
||||
{
|
||||
public static async ValueTask<Guild> GetGuildAsync(this DatabaseContext db, Snowflake id,
|
||||
CancellationToken ct = default) => await db.GetGuildAsync(id.ToUlong(), ct);
|
||||
public static async ValueTask<Guild> GetGuildAsync(
|
||||
this DatabaseContext db,
|
||||
Snowflake id,
|
||||
CancellationToken ct = default
|
||||
) => await db.GetGuildAsync(id.ToUlong(), ct);
|
||||
|
||||
public static async ValueTask<Guild> GetGuildAsync(this DatabaseContext db, Optional<Snowflake> id,
|
||||
CancellationToken ct = default) => await db.GetGuildAsync(id.ToUlong(), ct);
|
||||
public static async ValueTask<Guild> GetGuildAsync(
|
||||
this DatabaseContext db,
|
||||
Optional<Snowflake> id,
|
||||
CancellationToken ct = default
|
||||
) => await db.GetGuildAsync(id.ToUlong(), ct);
|
||||
|
||||
public static async ValueTask<Guild> GetGuildAsync(this DatabaseContext db, ulong id,
|
||||
CancellationToken ct = default)
|
||||
public static async ValueTask<Guild> GetGuildAsync(
|
||||
this DatabaseContext db,
|
||||
ulong id,
|
||||
CancellationToken ct = default
|
||||
)
|
||||
{
|
||||
var guild = await db.Guilds.FindAsync([id], ct);
|
||||
if (guild == null) throw new CataloggerError("Guild not found, was not initialized during guild create");
|
||||
if (guild == null)
|
||||
throw new CataloggerError("Guild not found, was not initialized during guild create");
|
||||
return guild;
|
||||
}
|
||||
|
||||
public static async Task<Watchlist?> GetWatchlistEntryAsync(this DatabaseContext db, Snowflake guildId,
|
||||
Snowflake userId, CancellationToken ct = default) =>
|
||||
await db.Watchlists.FindAsync([guildId.Value, userId.Value], ct);
|
||||
}
|
||||
public static async Task<Watchlist?> GetWatchlistEntryAsync(
|
||||
this DatabaseContext db,
|
||||
Snowflake guildId,
|
||||
Snowflake userId,
|
||||
CancellationToken ct = default
|
||||
) => await db.Watchlists.FindAsync([guildId.Value, userId.Value], ct);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@ namespace Catalogger.Backend.Database.Redis;
|
|||
|
||||
public class RedisService(Config config)
|
||||
{
|
||||
private readonly ConnectionMultiplexer _multiplexer = ConnectionMultiplexer.Connect(config.Database.Redis!);
|
||||
private readonly ConnectionMultiplexer _multiplexer = ConnectionMultiplexer.Connect(
|
||||
config.Database.Redis!
|
||||
);
|
||||
|
||||
private readonly JsonSerializerOptions _options = new()
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower
|
||||
};
|
||||
private readonly JsonSerializerOptions _options =
|
||||
new() { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower };
|
||||
|
||||
public IDatabase GetDatabase(int db = -1) => _multiplexer.GetDatabase(db);
|
||||
|
||||
|
|
@ -32,10 +32,18 @@ public class RedisService(Config config)
|
|||
await GetDatabase().HashSetAsync(hashKey, fieldKey, json);
|
||||
}
|
||||
|
||||
public async Task SetHashAsync<T>(string hashKey, IEnumerable<T> values, Func<T, string> keySelector)
|
||||
public async Task SetHashAsync<T>(
|
||||
string hashKey,
|
||||
IEnumerable<T> values,
|
||||
Func<T, string> keySelector
|
||||
)
|
||||
{
|
||||
var hashEntries = values
|
||||
.Select(v => new { Key = keySelector(v), Value = JsonSerializer.Serialize(v, _options) })
|
||||
.Select(v => new
|
||||
{
|
||||
Key = keySelector(v),
|
||||
Value = JsonSerializer.Serialize(v, _options),
|
||||
})
|
||||
.Select(v => new HashEntry(v.Key, v.Value));
|
||||
await GetDatabase().HashSetAsync(hashKey, hashEntries.ToArray());
|
||||
}
|
||||
|
|
@ -45,4 +53,4 @@ public class RedisService(Config config)
|
|||
var value = await GetDatabase().HashGetAsync(hashKey, fieldKey);
|
||||
return value.IsNull ? default : JsonSerializer.Deserialize<T>(value!, _options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue