#nullable disable warnings using LinqToDB; using LinqToDB.Data; using LinqToDB.EntityFrameworkCore; using NadekoBot.Common.Yml; using NadekoBot.Db.Models; namespace NadekoBot.Modules.Utility; public sealed class QuoteService : IQuoteService, INService { private readonly DbService _db; public QuoteService(DbService db) { _db = db; } /// /// Delete all quotes created by the author in a guild /// /// ID of the guild /// ID of the user /// Number of deleted qutoes public async Task DeleteAllAuthorQuotesAsync(ulong guildId, ulong userId) { await using var ctx = _db.GetDbContext(); var deleted = await ctx.GetTable() .Where(x => x.GuildId == guildId && x.AuthorId == userId) .DeleteAsync(); return deleted; } /// /// Delete all quotes in a guild /// /// ID of the guild /// Number of deleted qutoes public async Task DeleteAllQuotesAsync(ulong guildId) { await using var ctx = _db.GetDbContext(); var deleted = await ctx.GetTable() .Where(x => x.GuildId == guildId) .DeleteAsync(); return deleted; } public async Task> GetAllQuotesAsync(ulong guildId, int page, OrderType order) { await using var uow = _db.GetDbContext(); var q = uow.Set() .ToLinqToDBTable() .Where(x => x.GuildId == guildId); if (order == OrderType.Keyword) q = q.OrderBy(x => x.Keyword); else q = q.OrderBy(x => x.Id); return await q.Skip(15 * page).Take(15).ToArrayAsyncLinqToDB(); } public async Task GetQuoteByKeywordAsync(ulong guildId, string keyword) { await using var uow = _db.GetDbContext(); var quotes = await uow.GetTable() .Where(q => q.GuildId == guildId && q.Keyword == keyword) .ToArrayAsyncLinqToDB(); return quotes.RandomOrDefault(); } public async Task> SearchQuoteKeywordTextAsync( ulong guildId, string? keyword, string text) { keyword = keyword?.ToUpperInvariant(); await using var uow = _db.GetDbContext(); var quotes = await uow.GetTable() .Where(q => q.GuildId == guildId && (keyword == null || q.Keyword == keyword)) .ToArrayAsync(); var toReturn = new List(quotes.Length); foreach (var q in quotes) { if (q.AuthorName.Contains(text, StringComparison.InvariantCultureIgnoreCase) || q.Text.Contains(text, StringComparison.InvariantCultureIgnoreCase)) { toReturn.Add(q); } } return toReturn; } public async Task> GetGuildQuotesAsync(ulong guildId) { await using var uow = _db.GetDbContext(); var quotes = await uow.GetTable() .Where(x => x.GuildId == guildId) .ToListAsyncLinqToDB(); return quotes; } public Task RemoveAllByKeyword(ulong guildId, string keyword) { keyword = keyword.ToUpperInvariant(); using var uow = _db.GetDbContext(); var count = uow.GetTable() .Where(x => x.GuildId == guildId && x.Keyword == keyword) .DeleteAsync(); return count; } public async Task GetQuoteByIdAsync(ulong guildId, int quoteId) { await using var uow = _db.GetDbContext(); var quote = await uow.GetTable() .Where(x => x.Id == quoteId && x.GuildId == guildId) .FirstOrDefaultAsyncLinqToDB(); return quote; } public async Task AddQuoteAsync( ulong guildId, ulong authorId, string authorName, string keyword, string text) { keyword = keyword.ToUpperInvariant(); Quote q; await using var uow = _db.GetDbContext(); uow.Set() .Add(q = new() { AuthorId = authorId, AuthorName = authorName, GuildId = guildId, Keyword = keyword, Text = text }); await uow.SaveChangesAsync(); return q; } public async Task EditQuoteAsync(ulong authorId, int quoteId, string text) { await using var uow = _db.GetDbContext(); var result = await uow.GetTable() .Where(x => x.Id == quoteId && x.AuthorId == authorId) .Set(x => x.Text, text) .UpdateWithOutputAsync((del, ins) => ins); var q = result.FirstOrDefault(); return q; } public async Task DeleteQuoteAsync( ulong guildId, ulong authorId, bool isQuoteManager, int quoteId) { await using var uow = _db.GetDbContext(); var q = uow.Set().GetById(quoteId); var count = await uow.GetTable() .Where(x => x.GuildId == guildId && x.Id == quoteId) .Where(x => isQuoteManager || (x.AuthorId == authorId)) .DeleteAsync(); return count > 0; } public async Task ImportQuotesAsync(ulong guildId, string input) { Dictionary> data; try { data = Yaml.Deserializer.Deserialize>>(input); } catch (Exception ex) { Log.Warning(ex, "Quote import failed: {Message}", ex.Message); return false; } var toImport = data.SelectMany(x => x.Value.Select(v => (Key: x.Key, Value: v))) .Where(x => !string.IsNullOrWhiteSpace(x.Key) && !string.IsNullOrWhiteSpace(x.Value?.Txt)); await using var uow = _db.GetDbContext(); await uow.GetTable() .BulkCopyAsync(toImport .Select(q => new Quote { GuildId = guildId, Keyword = q.Key, Text = q.Value.Txt, AuthorId = q.Value.Aid, AuthorName = q.Value.An })); return true; } }