diff --git a/app/Desktop/Main/Pages/DebugPageModel.cs b/app/Desktop/Main/Pages/DebugPageModel.cs index 894aecc..b1da288 100644 --- a/app/Desktop/Main/Pages/DebugPageModel.cs +++ b/app/Desktop/Main/Pages/DebugPageModel.cs @@ -10,164 +10,164 @@ using DHT.Server; using DHT.Server.Data; using DHT.Server.Service; -namespace DHT.Desktop.Main.Pages { - sealed class DebugPageModel { - public string GenerateChannels { get; set; } = "0"; - public string GenerateUsers { get; set; } = "0"; - public string GenerateMessages { get; set; } = "0"; +namespace DHT.Desktop.Main.Pages; - private readonly Window window; - private readonly State state; +sealed class DebugPageModel { + public string GenerateChannels { get; set; } = "0"; + public string GenerateUsers { get; set; } = "0"; + public string GenerateMessages { get; set; } = "0"; - [Obsolete("Designer")] - public DebugPageModel() : this(null!, State.Dummy) {} + private readonly Window window; + private readonly State state; - public DebugPageModel(Window window, State state) { - this.window = window; - this.state = state; + [Obsolete("Designer")] + public DebugPageModel() : this(null!, State.Dummy) {} + + public DebugPageModel(Window window, State state) { + this.window = window; + this.state = state; + } + + public async void OnClickAddRandomDataToDatabase() { + if (!int.TryParse(GenerateChannels, out int channels) || channels < 1) { + await Dialog.ShowOk(window, "Generate Random Data", "Amount of channels must be at least 1!"); + return; } - public async void OnClickAddRandomDataToDatabase() { - if (!int.TryParse(GenerateChannels, out int channels) || channels < 1) { - await Dialog.ShowOk(window, "Generate Random Data", "Amount of channels must be at least 1!"); - return; - } - - if (!int.TryParse(GenerateUsers, out int users) || users < 1) { - await Dialog.ShowOk(window, "Generate Random Data", "Amount of users must be at least 1!"); - return; - } - - if (!int.TryParse(GenerateMessages, out int messages) || messages < 1) { - await Dialog.ShowOk(window, "Generate Random Data", "Amount of messages must be at least 1!"); - return; - } - - await ProgressDialog.Show(window, "Generating Random Data", async (_, callback) => await GenerateRandomData(channels, users, messages, callback)); + if (!int.TryParse(GenerateUsers, out int users) || users < 1) { + await Dialog.ShowOk(window, "Generate Random Data", "Amount of users must be at least 1!"); + return; } - private const int BatchSize = 500; + if (!int.TryParse(GenerateMessages, out int messages) || messages < 1) { + await Dialog.ShowOk(window, "Generate Random Data", "Amount of messages must be at least 1!"); + return; + } - private async Task GenerateRandomData(int channelCount, int userCount, int messageCount, IProgressCallback callback) { - int batchCount = (messageCount + BatchSize - 1) / BatchSize; - await callback.Update("Adding messages in batches of " + BatchSize, 0, batchCount); + await ProgressDialog.Show(window, "Generating Random Data", async (_, callback) => await GenerateRandomData(channels, users, messages, callback)); + } - var rand = new Random(); - var server = new DHT.Server.Data.Server { - Id = RandomId(rand), - Name = RandomName("s"), - Type = ServerType.Server, - }; + private const int BatchSize = 500; - var channels = Enumerable.Range(0, channelCount).Select(i => new Channel { - Id = RandomId(rand), - Server = server.Id, - Name = RandomName("c"), - ParentId = null, - Position = i, - Topic = RandomText(rand, 10), - Nsfw = rand.Next(4) == 0, + private async Task GenerateRandomData(int channelCount, int userCount, int messageCount, IProgressCallback callback) { + int batchCount = (messageCount + BatchSize - 1) / BatchSize; + await callback.Update("Adding messages in batches of " + BatchSize, 0, batchCount); + + var rand = new Random(); + var server = new DHT.Server.Data.Server { + Id = RandomId(rand), + Name = RandomName("s"), + Type = ServerType.Server, + }; + + var channels = Enumerable.Range(0, channelCount).Select(i => new Channel { + Id = RandomId(rand), + Server = server.Id, + Name = RandomName("c"), + ParentId = null, + Position = i, + Topic = RandomText(rand, 10), + Nsfw = rand.Next(4) == 0, + }).ToArray(); + + var users = Enumerable.Range(0, userCount).Select(_ => new User { + Id = RandomId(rand), + Name = RandomName("u"), + AvatarUrl = null, + Discriminator = rand.Next(0, 9999).ToString(), + }).ToArray(); + + await state.Db.Users.Add(users); + await state.Db.Servers.Add([server]); + await state.Db.Channels.Add(channels); + + var now = DateTimeOffset.Now; + int batchIndex = 0; + + while (messageCount > 0) { + int hourOffset = batchIndex; + + var messages = Enumerable.Range(0, Math.Min(messageCount, BatchSize)).Select(i => { + DateTimeOffset time = now.AddHours(hourOffset).AddMinutes(i * 60.0 / BatchSize); + DateTimeOffset? edit = rand.Next(100) == 0 ? time.AddSeconds(rand.Next(1, 60)) : null; + + var timeMillis = time.ToUnixTimeMilliseconds(); + var editMillis = edit?.ToUnixTimeMilliseconds(); + + return new Message { + Id = (ulong) timeMillis, + Sender = RandomBiasedIndex(rand, users).Id, + Channel = RandomBiasedIndex(rand, channels).Id, + Text = RandomText(rand, 100), + Timestamp = timeMillis, + EditTimestamp = editMillis, + RepliedToId = null, + Attachments = ImmutableList.Empty, + Embeds = ImmutableList.Empty, + Reactions = ImmutableList.Empty, + }; }).ToArray(); - var users = Enumerable.Range(0, userCount).Select(_ => new User { - Id = RandomId(rand), - Name = RandomName("u"), - AvatarUrl = null, - Discriminator = rand.Next(0, 9999).ToString(), - }).ToArray(); + await state.Db.Messages.Add(messages); - await state.Db.Users.Add(users); - await state.Db.Servers.Add([server]); - await state.Db.Channels.Add(channels); - - var now = DateTimeOffset.Now; - int batchIndex = 0; - - while (messageCount > 0) { - int hourOffset = batchIndex; - - var messages = Enumerable.Range(0, Math.Min(messageCount, BatchSize)).Select(i => { - DateTimeOffset time = now.AddHours(hourOffset).AddMinutes(i * 60.0 / BatchSize); - DateTimeOffset? edit = rand.Next(100) == 0 ? time.AddSeconds(rand.Next(1, 60)) : null; - - var timeMillis = time.ToUnixTimeMilliseconds(); - var editMillis = edit?.ToUnixTimeMilliseconds(); - - return new Message { - Id = (ulong) timeMillis, - Sender = RandomBiasedIndex(rand, users).Id, - Channel = RandomBiasedIndex(rand, channels).Id, - Text = RandomText(rand, 100), - Timestamp = timeMillis, - EditTimestamp = editMillis, - RepliedToId = null, - Attachments = ImmutableList.Empty, - Embeds = ImmutableList.Empty, - Reactions = ImmutableList.Empty, - }; - }).ToArray(); - - await state.Db.Messages.Add(messages); - - messageCount -= BatchSize; - await callback.Update("Adding messages in batches of " + BatchSize, ++batchIndex, batchCount); - } + messageCount -= BatchSize; + await callback.Update("Adding messages in batches of " + BatchSize, ++batchIndex, batchCount); } + } - private static ulong RandomId(Random rand) { - ulong h = unchecked((ulong) rand.Next()); - ulong l = unchecked((ulong) rand.Next()); - return (h << 32) | l; - } + private static ulong RandomId(Random rand) { + ulong h = unchecked((ulong) rand.Next()); + ulong l = unchecked((ulong) rand.Next()); + return (h << 32) | l; + } - private static string RandomName(string prefix) { - return prefix + "-" + ServerUtils.GenerateRandomToken(5); - } + private static string RandomName(string prefix) { + return prefix + "-" + ServerUtils.GenerateRandomToken(5); + } - private static T RandomBiasedIndex(Random rand, T[] options) { - return options[(int) Math.Floor(options.Length * rand.NextDouble() * rand.NextDouble())]; - } + private static T RandomBiasedIndex(Random rand, T[] options) { + return options[(int) Math.Floor(options.Length * rand.NextDouble() * rand.NextDouble())]; + } - private static readonly string[] RandomWords = [ - "apple", "apricot", "artichoke", "arugula", "asparagus", "avocado", - "banana", "bean", "beechnut", "beet", "blackberry", "blackcurrant", "blueberry", "boysenberry", "bramble", "broccoli", - "cabbage", "cacao", "cantaloupe", "caper", "carambola", "carrot", "cauliflower", "celery", "chard", "cherry", "chokeberry", "citron", "clementine", "coconut", "corn", "crabapple", "cranberry", "cucumber", "currant", - "daikon", "date", "dewberry", "durian", - "edamame", "eggplant", "elderberry", "endive", - "fig", - "garlic", "ginger", "gooseberry", "grape", "grapefruit", "guava", - "honeysuckle", "horseradish", "huckleberry", - "jackfruit", "jicama", - "kale", "kiwi", "kohlrabi", "kumquat", - "leek", "lemon", "lentil", "lettuce", "lime", - "mandarin", "mango", "mushroom", "myrtle", - "nectarine", "nut", - "olive", "okra", "onion", "orange", - "papaya", "parsnip", "pawpaw", "peach", "pear", "pea", "pepper", "persimmon", "pineapple", "plum", "plantain", "pomegranate", "pomelo", "potato", "prune", "pumpkin", - "quandong", "quinoa", - "radicchio", "radish", "raisin", "raspberry", "redcurrant", "rhubarb", "rutabaga", - "spinach", "strawberry", "squash", - "tamarind", "tangerine", "tomatillo", "tomato", "turnip", - "vanilla", - "watercress", "watermelon", - "yam", - "zucchini" - ]; + private static readonly string[] RandomWords = [ + "apple", "apricot", "artichoke", "arugula", "asparagus", "avocado", + "banana", "bean", "beechnut", "beet", "blackberry", "blackcurrant", "blueberry", "boysenberry", "bramble", "broccoli", + "cabbage", "cacao", "cantaloupe", "caper", "carambola", "carrot", "cauliflower", "celery", "chard", "cherry", "chokeberry", "citron", "clementine", "coconut", "corn", "crabapple", "cranberry", "cucumber", "currant", + "daikon", "date", "dewberry", "durian", + "edamame", "eggplant", "elderberry", "endive", + "fig", + "garlic", "ginger", "gooseberry", "grape", "grapefruit", "guava", + "honeysuckle", "horseradish", "huckleberry", + "jackfruit", "jicama", + "kale", "kiwi", "kohlrabi", "kumquat", + "leek", "lemon", "lentil", "lettuce", "lime", + "mandarin", "mango", "mushroom", "myrtle", + "nectarine", "nut", + "olive", "okra", "onion", "orange", + "papaya", "parsnip", "pawpaw", "peach", "pear", "pea", "pepper", "persimmon", "pineapple", "plum", "plantain", "pomegranate", "pomelo", "potato", "prune", "pumpkin", + "quandong", "quinoa", + "radicchio", "radish", "raisin", "raspberry", "redcurrant", "rhubarb", "rutabaga", + "spinach", "strawberry", "squash", + "tamarind", "tangerine", "tomatillo", "tomato", "turnip", + "vanilla", + "watercress", "watermelon", + "yam", + "zucchini" + ]; - private static string RandomText(Random rand, int maxWords) { - int wordCount = 1 + (int) Math.Floor(maxWords * Math.Pow(rand.NextDouble(), 3)); - return string.Join(' ', Enumerable.Range(0, wordCount).Select(_ => RandomWords[rand.Next(RandomWords.Length)])); - } + private static string RandomText(Random rand, int maxWords) { + int wordCount = 1 + (int) Math.Floor(maxWords * Math.Pow(rand.NextDouble(), 3)); + return string.Join(' ', Enumerable.Range(0, wordCount).Select(_ => RandomWords[rand.Next(RandomWords.Length)])); } } #else -namespace DHT.Desktop.Main.Pages { - sealed class DebugPageModel { - public string GenerateChannels { get; set; } = "0"; - public string GenerateUsers { get; set; } = "0"; - public string GenerateMessages { get; set; } = "0"; +namespace DHT.Desktop.Main.Pages; - public void OnClickAddRandomDataToDatabase() {} - } +sealed class DebugPageModel { + public string GenerateChannels { get; set; } = "0"; + public string GenerateUsers { get; set; } = "0"; + public string GenerateMessages { get; set; } = "0"; + + public void OnClickAddRandomDataToDatabase() {} } #endif diff --git a/app/Server/Database/Import/LegacyArchiveImport.cs b/app/Server/Database/Import/LegacyArchiveImport.cs index b98db7c..de41c2b 100644 --- a/app/Server/Database/Import/LegacyArchiveImport.cs +++ b/app/Server/Database/Import/LegacyArchiveImport.cs @@ -161,7 +161,7 @@ public static class LegacyArchiveImport { var messagesObj = data.HasKey(channelIdStr) ? data.RequireObject(channelIdStr, DataPath) : (JsonElement?) null; if (messagesObj == null) { - return Array.Empty(); + return []; } return messagesObj.Value.EnumerateObject().Select(item => { diff --git a/app/Server/Database/Sqlite/Repositories/SqliteDownloadRepository.cs b/app/Server/Database/Sqlite/Repositories/SqliteDownloadRepository.cs index 2565320..ca88a77 100644 --- a/app/Server/Database/Sqlite/Repositories/SqliteDownloadRepository.cs +++ b/app/Server/Database/Sqlite/Repositories/SqliteDownloadRepository.cs @@ -15,14 +15,8 @@ using Microsoft.Data.Sqlite; namespace DHT.Server.Database.Sqlite.Repositories; -sealed class SqliteDownloadRepository : BaseSqliteRepository, IDownloadRepository { +sealed class SqliteDownloadRepository(SqliteConnectionPool pool) : BaseSqliteRepository(Log), IDownloadRepository { private static readonly Log Log = Log.ForType(); - - private readonly SqliteConnectionPool pool; - - public SqliteDownloadRepository(SqliteConnectionPool pool) : base(Log) { - this.pool = pool; - } internal sealed class NewDownloadCollector : IAsyncDisposable { private readonly SqliteDownloadRepository repository; diff --git a/app/Server/Database/Sqlite/Repositories/SqliteMessageRepository.cs b/app/Server/Database/Sqlite/Repositories/SqliteMessageRepository.cs index 5eacf84..3cf7a1f 100644 --- a/app/Server/Database/Sqlite/Repositories/SqliteMessageRepository.cs +++ b/app/Server/Database/Sqlite/Repositories/SqliteMessageRepository.cs @@ -183,11 +183,11 @@ sealed class SqliteMessageRepository : BaseSqliteRepository, IMessageRepository return await conn.ExecuteReaderAsync("SELECT COUNT(*) FROM messages" + filter.GenerateConditions().BuildWhereClause(), static reader => reader?.GetInt64(0) ?? 0L, cancellationToken); } - private sealed class MesageToManyCommand : IAsyncDisposable { + private sealed class MessageToManyCommand : IAsyncDisposable { private readonly SqliteCommand cmd; private readonly Func readItem; - public MesageToManyCommand(ISqliteConnection conn, string sql, Func readItem) { + public MessageToManyCommand(ISqliteConnection conn, string sql, Func readItem) { this.cmd = conn.Command(sql); this.cmd.Add(":message_id", SqliteType.Integer); @@ -223,7 +223,7 @@ sealed class SqliteMessageRepository : BaseSqliteRepository, IMessageRepository WHERE message_id = :message_id """; - await using var attachmentCmd = new MesageToManyCommand(conn, AttachmentSql, static reader => new Attachment { + await using var attachmentCmd = new MessageToManyCommand(conn, AttachmentSql, static reader => new Attachment { Id = reader.GetUint64(0), Name = reader.GetString(1), Type = reader.IsDBNull(2) ? null : reader.GetString(2), @@ -241,7 +241,7 @@ sealed class SqliteMessageRepository : BaseSqliteRepository, IMessageRepository WHERE message_id = :message_id """; - await using var embedCmd = new MesageToManyCommand(conn, EmbedSql, static reader => new Embed { + await using var embedCmd = new MessageToManyCommand(conn, EmbedSql, static reader => new Embed { Json = reader.GetString(0) }); @@ -252,7 +252,7 @@ sealed class SqliteMessageRepository : BaseSqliteRepository, IMessageRepository WHERE message_id = :message_id """; - await using var reactionsCmd = new MesageToManyCommand(conn, ReactionSql, static reader => new Reaction { + await using var reactionsCmd = new MessageToManyCommand(conn, ReactionSql, static reader => new Reaction { EmojiId = reader.IsDBNull(0) ? null : reader.GetUint64(0), EmojiName = reader.IsDBNull(1) ? null : reader.GetString(1), EmojiFlags = (EmojiFlags) reader.GetInt16(2), diff --git a/app/Utils/Collections/LinqExtensions.cs b/app/Utils/Collections/LinqExtensions.cs index dde6057..402a73e 100644 --- a/app/Utils/Collections/LinqExtensions.cs +++ b/app/Utils/Collections/LinqExtensions.cs @@ -8,7 +8,7 @@ public static class LinqExtensions { HashSet? seenKeys = null; foreach (var item in collection) { - seenKeys ??= new HashSet(); + seenKeys ??= []; if (seenKeys.Add(getKeyFromItem(item))) { yield return item;