diff --git a/src/NadekoBot/Migrations/20160824013005_FirstMigration.Designer.cs b/src/NadekoBot/Migrations/20160824125525_QuoteMigration.Designer.cs similarity index 60% rename from src/NadekoBot/Migrations/20160824013005_FirstMigration.Designer.cs rename to src/NadekoBot/Migrations/20160824125525_QuoteMigration.Designer.cs index eefddece..1668813d 100644 --- a/src/NadekoBot/Migrations/20160824013005_FirstMigration.Designer.cs +++ b/src/NadekoBot/Migrations/20160824125525_QuoteMigration.Designer.cs @@ -8,8 +8,8 @@ using NadekoBot.Services.Database.Impl; namespace NadekoBot.Migrations { [DbContext(typeof(NadekoSqliteContext))] - [Migration("20160824013005_FirstMigration")] - partial class FirstMigration + [Migration("20160824125525_QuoteMigration")] + partial class QuoteMigration { protected override void BuildTargetModel(ModelBuilder modelBuilder) { @@ -21,14 +21,24 @@ namespace NadekoBot.Migrations b.Property("Id") .ValueGeneratedOnAdd(); - b.Property("Keyword"); + b.Property("AuthorId"); - b.Property("Text"); + b.Property("AuthorName") + .IsRequired(); - b.Property("UserName"); + b.Property("GuildId"); + + b.Property("Keyword") + .IsRequired(); + + b.Property("Text") + .IsRequired(); b.HasKey("Id"); + b.HasIndex("GuildId", "Keyword") + .IsUnique(); + b.ToTable("Quotes"); }); } diff --git a/src/NadekoBot/Migrations/20160824013005_FirstMigration.cs b/src/NadekoBot/Migrations/20160824125525_QuoteMigration.cs similarity index 57% rename from src/NadekoBot/Migrations/20160824013005_FirstMigration.cs rename to src/NadekoBot/Migrations/20160824125525_QuoteMigration.cs index 4cafa3d3..22218352 100644 --- a/src/NadekoBot/Migrations/20160824013005_FirstMigration.cs +++ b/src/NadekoBot/Migrations/20160824125525_QuoteMigration.cs @@ -4,7 +4,7 @@ using Microsoft.EntityFrameworkCore.Migrations; namespace NadekoBot.Migrations { - public partial class FirstMigration : Migration + public partial class QuoteMigration : Migration { protected override void Up(MigrationBuilder migrationBuilder) { @@ -14,14 +14,22 @@ namespace NadekoBot.Migrations { Id = table.Column(nullable: false) .Annotation("Autoincrement", true), - Keyword = table.Column(nullable: true), - Text = table.Column(nullable: true), - UserName = table.Column(nullable: true) + AuthorId = table.Column(nullable: false), + AuthorName = table.Column(nullable: false), + GuildId = table.Column(nullable: false), + Keyword = table.Column(nullable: false), + Text = table.Column(nullable: false) }, constraints: table => { table.PrimaryKey("PK_Quotes", x => x.Id); }); + + migrationBuilder.CreateIndex( + name: "IX_Quotes_GuildId_Keyword", + table: "Quotes", + columns: new[] { "GuildId", "Keyword" }, + unique: true); } protected override void Down(MigrationBuilder migrationBuilder) diff --git a/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs b/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs index d9137a28..a116fa4a 100644 --- a/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs +++ b/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs @@ -20,14 +20,24 @@ namespace NadekoBot.Migrations b.Property("Id") .ValueGeneratedOnAdd(); - b.Property("Keyword"); + b.Property("AuthorId"); - b.Property("Text"); + b.Property("AuthorName") + .IsRequired(); - b.Property("UserName"); + b.Property("GuildId"); + + b.Property("Keyword") + .IsRequired(); + + b.Property("Text") + .IsRequired(); b.HasKey("Id"); + b.HasIndex("GuildId", "Keyword") + .IsUnique(); + b.ToTable("Quotes"); }); } diff --git a/src/NadekoBot/Modules/Searches/Searches.cs b/src/NadekoBot/Modules/Searches/Searches.cs index 1f587161..b729efa7 100644 --- a/src/NadekoBot/Modules/Searches/Searches.cs +++ b/src/NadekoBot/Modules/Searches/Searches.cs @@ -313,16 +313,6 @@ $@"🌍 **Weather for** 【{obj["target"]}】 await channel.SendMessageAsync("💢 Failed finding a definition for that tag.").ConfigureAwait(false); } } - //todo DB - //[LocalizedCommand, LocalizedDescription, LocalizedSummary] - //[RequireContext(ContextType.Guild)] - //public async Task Quote(IMessage imsg) - //{ - // var channel = (ITextChannel)imsg.Channel; - - // var quote = NadekoBot.Config.Quotes[rng.Next(0, NadekoBot.Config.Quotes.Count)].ToString(); - // await channel.SendMessageAsync(quote).ConfigureAwait(false); - //} [LocalizedCommand, LocalizedDescription, LocalizedSummary] [RequireContext(ContextType.Guild)] diff --git a/src/NadekoBot/Modules/Utility/Commands/QuoteCommands.cs b/src/NadekoBot/Modules/Utility/Commands/QuoteCommands.cs new file mode 100644 index 00000000..2f059674 --- /dev/null +++ b/src/NadekoBot/Modules/Utility/Commands/QuoteCommands.cs @@ -0,0 +1,114 @@ +using Discord; +using Discord.Commands; +using NadekoBot.Attributes; +using NadekoBot.Services; +using NadekoBot.Services.Database; +using NadekoBot.Services.Database.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NadekoBot.Modules.Utility.Commands +{ + public partial class Utility + { + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Quote(IMessage imsg, string keyword) + { + var channel = imsg.Channel as ITextChannel; + + if (string.IsNullOrWhiteSpace(keyword)) + return; + + Quote quote; + using (var uow = DbHandler.Instance.GetUnitOfWork()) + { + quote = await uow.Quotes.GetRandomQuoteByKeywordAsync(channel.Guild.Id, keyword); + } + + if (quote == null) + return; + + await channel.SendMessageAsync(":megaphone: " + quote.Text); + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task AddQuote(IMessage imsg, string keyword, [Remainder] string text) + { + var channel = imsg.Channel as ITextChannel; + + if (string.IsNullOrWhiteSpace(keyword) || string.IsNullOrWhiteSpace(text)) + return; + + keyword = keyword.ToUpperInvariant(); + + using (var uow = DbHandler.UnitOfWork()) + { + uow.Quotes.Add(new Quote + { + AuthorId = imsg.Author.Id, + AuthorName = imsg.Author.Username, + GuildId = channel.Guild.Id, + Keyword = keyword, + Text = text, + }); + await uow.CompleteAsync(); + await channel.SendMessageAsync("`Quote added.`"); + } + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task DelQuote(IMessage imsg, string keyword) + { + var channel = imsg.Channel as ITextChannel; + + if (string.IsNullOrWhiteSpace(keyword)) + return; + + keyword = keyword.ToUpperInvariant(); + + using (var uow = DbHandler.UnitOfWork()) + { + var q = await uow.Quotes.GetRandomQuoteByKeywordAsync(channel.Guild.Id, keyword); + + if (q == null) + { + await channel.SendMessageAsync("`No quotes found.`"); + return; + } + + uow.Quotes.Remove(q); + await uow.CompleteAsync(); + } + await channel.SendMessageAsync("`Deleted a random quote.`"); + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task DelAllQuotes(IMessage imsg, string keyword) + { + var channel = imsg.Channel as ITextChannel; + + if (string.IsNullOrWhiteSpace(keyword)) + return; + + keyword = keyword.ToUpperInvariant(); + + using (var uow = DbHandler.UnitOfWork()) + { + var quotes = uow.Quotes.GetAllQuotesByKeyword(keyword); + + uow.Quotes.RemoveRange(quotes.Select(q => q.Id).ToArray());//wtf?! + + await uow.CompleteAsync(); + } + + await channel.SendMessageAsync($"`Deleted all quotes with '{keyword}' keyword`"); + } + } +} diff --git a/src/NadekoBot/Services/Database/IUnitOfWork.cs b/src/NadekoBot/Services/Database/IUnitOfWork.cs index e7bcbff7..9f92656a 100644 --- a/src/NadekoBot/Services/Database/IUnitOfWork.cs +++ b/src/NadekoBot/Services/Database/IUnitOfWork.cs @@ -10,6 +10,7 @@ namespace NadekoBot.Services.Database public interface IUnitOfWork : IDisposable { IQuoteRepository Quotes { get; } - Task Complete(); + int Complete(); + Task CompleteAsync(); } } diff --git a/src/NadekoBot/Services/Database/Impl/NadekoSqliteContext.cs b/src/NadekoBot/Services/Database/Impl/NadekoSqliteContext.cs index 72e52ee0..595ab14b 100644 --- a/src/NadekoBot/Services/Database/Impl/NadekoSqliteContext.cs +++ b/src/NadekoBot/Services/Database/Impl/NadekoSqliteContext.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; +using NadekoBot.Services.Database.Models; namespace NadekoBot.Services.Database.Impl { diff --git a/src/NadekoBot/Services/Database/Models/Quote.cs b/src/NadekoBot/Services/Database/Models/Quote.cs index 77883503..0d769c12 100644 --- a/src/NadekoBot/Services/Database/Models/Quote.cs +++ b/src/NadekoBot/Services/Database/Models/Quote.cs @@ -9,8 +9,13 @@ namespace NadekoBot.Services.Database.Models { public class Quote : DbEntity { - public string UserName { get; set; } + public ulong GuildId { get; set; } + [Required] public string Keyword { get; set; } + [Required] + public string AuthorName { get; set; } + public ulong AuthorId { get; set; } + [Required] public string Text { get; set; } } } diff --git a/src/NadekoBot/Services/Database/NadekoContext.cs b/src/NadekoBot/Services/Database/NadekoContext.cs index 9bf8f89a..eac45f89 100644 --- a/src/NadekoBot/Services/Database/NadekoContext.cs +++ b/src/NadekoBot/Services/Database/NadekoContext.cs @@ -12,6 +12,29 @@ namespace NadekoBot.Services.Database { public DbSet Quotes { get; } + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + #region QUOTES + //// guildid and keyword are unique pair + var quoteEntity = modelBuilder.Entity(); + //quoteEntity + // .HasAlternateKey(q => q.GuildId) + // .HasName("AK_GuildId_Keyword"); + + //quoteEntity + // .HasAlternateKey(q => q.Keyword) + // .HasName("AK_GuildId_Keyword"); + + quoteEntity + .HasIndex(q => new { q.GuildId, q.Keyword }) + .IsUnique(); + + + #endregion + + #region + #endregion + } protected abstract override void OnConfiguring(DbContextOptionsBuilder optionsBuilder); } } diff --git a/src/NadekoBot/Services/Database/Repositories/IQuoteRepository.cs b/src/NadekoBot/Services/Database/Repositories/IQuoteRepository.cs index 349a7bca..3bbef352 100644 --- a/src/NadekoBot/Services/Database/Repositories/IQuoteRepository.cs +++ b/src/NadekoBot/Services/Database/Repositories/IQuoteRepository.cs @@ -9,7 +9,7 @@ namespace NadekoBot.Services.Database.Repositories { public interface IQuoteRepository : IRepository { - IEnumerable GetQuotesByText(string text); - Task GetRandomQuoteByTextAsync(string text); + IEnumerable GetAllQuotesByKeyword(string keyword); + Task GetRandomQuoteByKeywordAsync(ulong guildId, string keyword); } } diff --git a/src/NadekoBot/Services/Database/Repositories/IRepository.cs b/src/NadekoBot/Services/Database/Repositories/IRepository.cs index e48a145a..2f616219 100644 --- a/src/NadekoBot/Services/Database/Repositories/IRepository.cs +++ b/src/NadekoBot/Services/Database/Repositories/IRepository.cs @@ -18,7 +18,7 @@ namespace NadekoBot.Services.Database.Repositories void Remove(int id); void Remove(T obj); - void RemoveRange(params T[] ids); + void RemoveRange(params int[] ids); void Update(T obj); void UpdateRange(params T[] objs); diff --git a/src/NadekoBot/Services/Database/Repositories/Impl/QuoteRepository.cs b/src/NadekoBot/Services/Database/Repositories/Impl/QuoteRepository.cs index 44b8789f..a2e95121 100644 --- a/src/NadekoBot/Services/Database/Repositories/Impl/QuoteRepository.cs +++ b/src/NadekoBot/Services/Database/Repositories/Impl/QuoteRepository.cs @@ -15,10 +15,10 @@ namespace NadekoBot.Services.Database.Repositories.Impl { } - public IEnumerable GetQuotesByText(string text) => - _set.Where(q => q.Text == text); + public IEnumerable GetAllQuotesByKeyword(string keyword) => + _set.Where(q => q.Keyword == keyword); - public Task GetRandomQuoteByTextAsync(string text) + public Task GetRandomQuoteByKeywordAsync(ulong guildId, string text) { var rng = new Random(); return _set.Where(q => q.Text == text).OrderBy(q => rng.Next()).FirstOrDefaultAsync(); diff --git a/src/NadekoBot/Services/Database/UnitOfWork.cs b/src/NadekoBot/Services/Database/UnitOfWork.cs index d5934865..a477d86c 100644 --- a/src/NadekoBot/Services/Database/UnitOfWork.cs +++ b/src/NadekoBot/Services/Database/UnitOfWork.cs @@ -21,7 +21,10 @@ namespace NadekoBot.Services.Database } - public Task Complete() => + public int Complete() => + _context.SaveChanges(); + + public Task CompleteAsync() => _context.SaveChangesAsync(); private bool disposed = false; diff --git a/src/NadekoBot/Services/DbHandler.cs b/src/NadekoBot/Services/DbHandler.cs index f84f669f..76437166 100644 --- a/src/NadekoBot/Services/DbHandler.cs +++ b/src/NadekoBot/Services/DbHandler.cs @@ -38,5 +38,8 @@ namespace NadekoBot.Services public UnitOfWork GetUnitOfWork() => new UnitOfWork(GetDbContext()); + + public static UnitOfWork UnitOfWork() => + DbHandler.Instance.GetUnitOfWork(); } }