A lot of things fixed/improved. Basis for db is done.

This commit is contained in:
Kwoth 2016-08-24 03:32:48 +02:00
parent fa5317b2ee
commit 03ac084437
26 changed files with 1331 additions and 44 deletions

View File

@ -0,0 +1,36 @@
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using NadekoBot.Services.Database.Impl;
namespace NadekoBot.Migrations
{
[DbContext(typeof(NadekoSqliteContext))]
[Migration("20160824013005_FirstMigration")]
partial class FirstMigration
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
modelBuilder
.HasAnnotation("ProductVersion", "1.0.0-rtm-21431");
modelBuilder.Entity("NadekoBot.Services.Database.Models.Quote", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Keyword");
b.Property<string>("Text");
b.Property<string>("UserName");
b.HasKey("Id");
b.ToTable("Quotes");
});
}
}
}

View File

@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations
{
public partial class FirstMigration : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Quotes",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Autoincrement", true),
Keyword = table.Column<string>(nullable: true),
Text = table.Column<string>(nullable: true),
UserName = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Quotes", x => x.Id);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Quotes");
}
}
}

View File

@ -0,0 +1,35 @@
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using NadekoBot.Services.Database.Impl;
namespace NadekoBot.Migrations
{
[DbContext(typeof(NadekoSqliteContext))]
partial class NadekoSqliteContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
modelBuilder
.HasAnnotation("ProductVersion", "1.0.0-rtm-21431");
modelBuilder.Entity("NadekoBot.Services.Database.Models.Quote", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Keyword");
b.Property<string>("Text");
b.Property<string>("UserName");
b.HasKey("Id");
b.ToTable("Quotes");
});
}
}
}

View File

@ -52,7 +52,7 @@ namespace NadekoBot.Modules.Administration
// else // else
// await channel.SendMessageAsync("❗`Stopped automatic deletion of successfull command invokations.`"); // await channel.SendMessageAsync("❗`Stopped automatic deletion of successfull command invokations.`");
//} //}
[LocalizedCommand, LocalizedDescription, LocalizedSummary] [LocalizedCommand, LocalizedDescription, LocalizedSummary]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageRoles)] [RequirePermission(GuildPermission.ManageRoles)]

View File

@ -51,7 +51,7 @@ namespace NadekoBot.Modules.Searches
.ConfigureAwait(false))["data"] as JArray; .ConfigureAwait(false))["data"] as JArray;
var dataList = data.Distinct(new ChampionNameComparer()).Take(showCount).ToList(); var dataList = data.Distinct(new ChampionNameComparer()).Take(showCount).ToList();
var sb = new StringBuilder(); var sb = new StringBuilder();
sb.AppendLine($"**Showing {showCount} top banned champions.**"); sb.AppendLine($"**Showing {dataList.Count} top banned champions.**");
sb.AppendLine($"`{trashTalk[new Random().Next(0, trashTalk.Length)]}`"); sb.AppendLine($"`{trashTalk[new Random().Next(0, trashTalk.Length)]}`");
for (var i = 0; i < dataList.Count; i++) for (var i = 0; i < dataList.Count; i++)
{ {

View File

@ -133,9 +133,9 @@ namespace NadekoBot.Modules.Searches
var acc = CalculateAcc(item, m); var acc = CalculateAcc(item, m);
var mods = ResolveMods(Int32.Parse($"{item["enabled_mods"]}")); var mods = ResolveMods(Int32.Parse($"{item["enabled_mods"]}"));
if (mods != "+") if (mods != "+")
sb.AppendLine($"{pp + "pp",-7} | {acc + "%",-7} | {map["artist"] + "-" + map["title"] + " (" + map["version"],-40}) | **{mods,-10}** | /b/{item["beatmap_id"]}"); sb.AppendLine($"{pp + "pp",-7} | {acc + "%",-7} | {map["artist"] + "-" + map["title"] + " (" + map["version"] + ")",-40} | **{mods,-10}** | /b/{item["beatmap_id"]}");
else else
sb.AppendLine($"{pp + "pp",-7} | {acc + "%",-7} | {map["artist"] + "-" + map["title"] + " (" + map["version"],-40}) | /b/{item["beatmap_id"]}"); sb.AppendLine($"{pp + "pp",-7} | {acc + "%",-7} | {map["artist"] + "-" + map["title"] + " (" + map["version"] + ")",-40} | /b/{item["beatmap_id"]}");
} }
sb.Append("```"); sb.Append("```");
await channel.SendMessageAsync(sb.ToString()).ConfigureAwait(false); await channel.SendMessageAsync(sb.ToString()).ConfigureAwait(false);

View File

@ -25,7 +25,7 @@ namespace NadekoBot.Modules.Utility
[LocalizedCommand, LocalizedDescription, LocalizedSummary] [LocalizedCommand, LocalizedDescription, LocalizedSummary]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task WhoPlays(IMessage imsg, [Remainder] string game = null) public async Task WhosPlaying(IMessage imsg, [Remainder] string game = null)
{ {
var channel = (ITextChannel)imsg.Channel; var channel = (ITextChannel)imsg.Channel;
game = game.Trim().ToUpperInvariant(); game = game.Trim().ToUpperInvariant();

View File

@ -3813,7 +3813,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Shows top 6 banned champions ordered by ban rate. Ban these champions and you will be Plat 5 in no time.. /// Looks up a localized string similar to Shows top banned champions ordered by ban rate..
/// </summary> /// </summary>
public static string lolban_desc { public static string lolban_desc {
get { get {
@ -7433,27 +7433,27 @@ namespace NadekoBot.Resources {
/// <summary> /// <summary>
/// Looks up a localized string similar to Shows a list of users who are playing the specified game.. /// Looks up a localized string similar to Shows a list of users who are playing the specified game..
/// </summary> /// </summary>
public static string whoplays_desc { public static string whosplaying_desc {
get { get {
return ResourceManager.GetString("whoplays_desc", resourceCulture); return ResourceManager.GetString("whosplaying_desc", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to `.whoplays Overwatch`. /// Looks up a localized string similar to `.whoplays Overwatch`.
/// </summary> /// </summary>
public static string whoplays_summary { public static string whosplaying_summary {
get { get {
return ResourceManager.GetString("whoplays_summary", resourceCulture); return ResourceManager.GetString("whosplaying_summary", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to whoplays. /// Looks up a localized string similar to whosplaying.
/// </summary> /// </summary>
public static string whoplays_text { public static string whosplaying_text {
get { get {
return ResourceManager.GetString("whoplays_text", resourceCulture); return ResourceManager.GetString("whosplaying_text", resourceCulture);
} }
} }

View File

@ -864,13 +864,13 @@
<data name="userinfo_summary" xml:space="preserve"> <data name="userinfo_summary" xml:space="preserve">
<value>`.uinfo @SomeUser`</value> <value>`.uinfo @SomeUser`</value>
</data> </data>
<data name="whoplays_text" xml:space="preserve"> <data name="whosplaying_text" xml:space="preserve">
<value>whoplays</value> <value>whosplaying</value>
</data> </data>
<data name="whoplays_desc" xml:space="preserve"> <data name="whosplaying_desc" xml:space="preserve">
<value>Shows a list of users who are playing the specified game.</value> <value>Shows a list of users who are playing the specified game.</value>
</data> </data>
<data name="whoplays_summary" xml:space="preserve"> <data name="whosplaying_summary" xml:space="preserve">
<value>`.whoplays Overwatch`</value> <value>`.whoplays Overwatch`</value>
</data> </data>
<data name="inrole_text" xml:space="preserve"> <data name="inrole_text" xml:space="preserve">
@ -1939,7 +1939,7 @@
<value>lolban</value> <value>lolban</value>
</data> </data>
<data name="lolban_desc" xml:space="preserve"> <data name="lolban_desc" xml:space="preserve">
<value>Shows top 6 banned champions ordered by ban rate. Ban these champions and you will be Plat 5 in no time.</value> <value>Shows top banned champions ordered by ban rate.</value>
</data> </data>
<data name="lolban_summary" xml:space="preserve"> <data name="lolban_summary" xml:space="preserve">
<value>`~lolban`</value> <value>`~lolban`</value>

View File

@ -0,0 +1,15 @@
using NadekoBot.Services.Database.Repositories;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NadekoBot.Services.Database
{
public interface IUnitOfWork : IDisposable
{
IQuoteRepository Quotes { get; }
Task<int> Complete();
}
}

View File

@ -0,0 +1,18 @@
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using System.Threading.Tasks;
//using Microsoft.EntityFrameworkCore;
//namespace NadekoBot.Services.Database.Impl
//{
// public class NadekoSqlServerContext : NadekoContext
// {
// protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
// {
// //CONFIGURE SQL SERVER HERE
// optionsBuilder.UseSqlite("Filename=./NadekoBot.db");
// }
// }
//}

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
namespace NadekoBot.Services.Database.Impl
{
public class NadekoSqliteContext : NadekoContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite("Filename=./NadekoBot.db");
}
}
}

View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NadekoBot.Services.Database.Models
{
public class DbEntity
{
[Key]
public int Id { get; set; }
public DateTime DateAdded { get; } = DateTime.UtcNow;
}
}

View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NadekoBot.Services.Database.Models
{
public class Quote : DbEntity
{
public string UserName { get; set; }
public string Keyword { get; set; }
public string Text { get; set; }
}
}

View File

@ -0,0 +1,17 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using JetBrains.Annotations;
using NadekoBot.Services.Database.Models;
namespace NadekoBot.Services.Database
{
public abstract class NadekoContext : DbContext
{
public DbSet<Quote> Quotes { get; }
protected abstract override void OnConfiguring(DbContextOptionsBuilder optionsBuilder);
}
}

View File

@ -0,0 +1,52 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using NadekoBot.Services.Database.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
namespace NadekoBot.Services.Database.Repositories
{
//some guy from stack overflow wrotethis, thanks to him :D
public static class Extensions
{
public static TEntity Find<TEntity>(this DbSet<TEntity> set, params object[] keyValues) where TEntity : DbEntity
{
var context = ((IInfrastructure<IServiceProvider>)set).GetService<DbContext>();
var entityType = context.Model.FindEntityType(typeof(TEntity));
var key = entityType.FindPrimaryKey();
var entries = context.ChangeTracker.Entries<TEntity>();
var i = 0;
foreach (var property in key.Properties)
{
entries = entries.Where(e => e.Property(property.Name).CurrentValue == keyValues[i]);
i++;
}
var entry = entries.FirstOrDefault();
if (entry != null)
{
// Return the local object if it exists.
return entry.Entity;
}
// TODO: Build the real LINQ Expression
// set.Where(x => x.Id == keyValues[0]);
var parameter = Expression.Parameter(typeof(TEntity), "x");
var query = set.Where((Expression<Func<TEntity, bool>>)
Expression.Lambda(
Expression.Equal(
Expression.Property(parameter, "Id"),
Expression.Constant(keyValues[0])),
parameter));
// Look in the database
return query.FirstOrDefault();
}
}
}

View File

@ -0,0 +1,15 @@
using NadekoBot.Services.Database.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NadekoBot.Services.Database.Repositories
{
public interface IQuoteRepository : IRepository<Quote>
{
IEnumerable<Quote> GetQuotesByText(string text);
Task<Quote> GetRandomQuoteByTextAsync(string text);
}
}

View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using NadekoBot.Services.Database.Models;
namespace NadekoBot.Services.Database.Repositories
{
public interface IRepository<T> where T : DbEntity
{
T Get(int id);
IEnumerable<T> GetAll();
void Add(T obj);
void AddRange(params T[] objs);
void Remove(int id);
void Remove(T obj);
void RemoveRange(params T[] ids);
void Update(T obj);
void UpdateRange(params T[] objs);
}
}

View File

@ -0,0 +1,27 @@
using NadekoBot.Services.Database.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using NadekoBot.Services.Database;
namespace NadekoBot.Services.Database.Repositories.Impl
{
public class QuoteRepository : Repository<Quote>, IQuoteRepository
{
public QuoteRepository(DbContext context) : base(context)
{
}
public IEnumerable<Quote> GetQuotesByText(string text) =>
_set.Where(q => q.Text == text);
public Task<Quote> GetRandomQuoteByTextAsync(string text)
{
var rng = new Random();
return _set.Where(q => q.Text == text).OrderBy(q => rng.Next()).FirstOrDefaultAsync();
}
}
}

View File

@ -0,0 +1,49 @@
using Microsoft.EntityFrameworkCore;
using NadekoBot.Services.Database.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NadekoBot.Services.Database.Repositories.Impl
{
public class Repository<T> : IRepository<T> where T : DbEntity
{
protected DbContext _context;
protected DbSet<T> _set;
public Repository(DbContext context)
{
_context = context;
_set = context.Set<T>();
}
public void Add(T obj) =>
_set.Add(obj);
public void AddRange(params T[] objs) =>
_set.AddRange(objs);
public T Get(int id) =>
_set.Find(id);
public IEnumerable<T> GetAll() =>
_set.ToList();
public void Remove(int id) =>
_set.Remove(_set.Find(id));
public void Remove(T obj) =>
_set.Remove(obj);
public void RemoveRange(params T[] objs) =>
_set.RemoveRange(objs);
public void Update(T obj) =>
_set.Update(obj);
public void UpdateRange(params T[] objs) =>
_set.UpdateRange(objs);
}
}

View File

@ -0,0 +1,43 @@
using NadekoBot.Services.Database.Repositories;
using NadekoBot.Services.Database.Repositories.Impl;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NadekoBot.Services.Database
{
public class UnitOfWork : IUnitOfWork
{
private NadekoContext _context;
private IQuoteRepository _quotes;
public IQuoteRepository Quotes => _quotes ?? (_quotes = new QuoteRepository(_context));
public UnitOfWork(NadekoContext context)
{
}
public Task<int> Complete() =>
_context.SaveChangesAsync();
private bool disposed = false;
protected void Dispose(bool disposing)
{
if (!this.disposed)
if (disposing)
_context.Dispose();
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}

View File

@ -0,0 +1,42 @@
using NadekoBot.Services.Database;
using NadekoBot.Services.Database.Impl;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NadekoBot.Services
{
public class DbHandler
{
private Type dbType;
private static DbHandler _instance = null;
public static DbHandler Instance = _instance ?? (_instance = new DbHandler());
static DbHandler() { }
private DbHandler() {
switch (NadekoBot.Credentials.Db.Type.ToUpperInvariant())
{
case "SQLITE":
dbType = typeof(NadekoSqliteContext);
break;
//case "SQLSERVER":
// dbType = typeof(NadekoSqlServerContext);
// break;
default:
break;
}
}
public NadekoContext GetDbContext() =>
Activator.CreateInstance(dbType) as NadekoContext;
public UnitOfWork GetUnitOfWork() =>
new UnitOfWork(GetDbContext());
}
}

View File

@ -13,6 +13,19 @@ namespace NadekoBot.Services
string MashapeKey { get; } string MashapeKey { get; }
string LoLApiKey { get; } string LoLApiKey { get; }
DB Db { get; }
bool IsOwner(IUser u); bool IsOwner(IUser u);
} }
public class DB
{
public DB(string type, string connString)
{
this.Type = type;
this.ConnectionString = connString;
}
public string Type { get; }
public string ConnectionString { get; }
}
} }

View File

@ -27,6 +27,8 @@ namespace NadekoBot.Services.Impl
public string OsuApiKey { get; } public string OsuApiKey { get; }
public string SoundCloudClientId { get; } public string SoundCloudClientId { get; }
public DB Db { get; }
public BotCredentials() public BotCredentials()
{ {
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
@ -40,6 +42,7 @@ namespace NadekoBot.Services.Impl
MashapeKey = cm.MashapeKey; MashapeKey = cm.MashapeKey;
OsuApiKey = cm.OsuApiKey; OsuApiKey = cm.OsuApiKey;
SoundCloudClientId = cm.SoundCloudClientId; SoundCloudClientId = cm.SoundCloudClientId;
Db = new DB(string.IsNullOrWhiteSpace(cm.Db.Type) ? cm.Db.Type : "sqlite", cm.Db.ConnectionString);
} }
else else
_log.Fatal("credentials.json is missing. Failed to start."); _log.Fatal("credentials.json is missing. Failed to start.");
@ -54,6 +57,13 @@ namespace NadekoBot.Services.Impl
public string MashapeKey { get; set; } public string MashapeKey { get; set; }
public string OsuApiKey { get; set; } public string OsuApiKey { get; set; }
public string SoundCloudClientId { get; set; } public string SoundCloudClientId { get; set; }
public DB Db { get; set; }
}
private class DbModel
{
public string Type { get; set; }
public string ConnectionString { get; set; }
} }
public bool IsOwner(IUser u) => OwnerIds.Contains(u.Id); public bool IsOwner(IUser u) => OwnerIds.Contains(u.Id);

View File

@ -27,9 +27,14 @@
"Google.Apis.Urlshortener.v1": "1.15.0.138", "Google.Apis.Urlshortener.v1": "1.15.0.138",
"System.Diagnostics.Contracts": "4.0.1", "System.Diagnostics.Contracts": "4.0.1",
"NLog": "4.4.0-betaV15", "NLog": "4.4.0-betaV15",
"VideoLibrary": "1.3.4" "VideoLibrary": "1.3.4",
"Microsoft.EntityFrameworkCore": "1.0.0",
"Microsoft.EntityFrameworkCore.Design": "1.0.0-preview2-final",
"Microsoft.EntityFrameworkCore.Sqlite": "1.0.0"
},
"tools": {
"Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final"
}, },
"frameworks": { "frameworks": {
"netcoreapp1.0": { "netcoreapp1.0": {
"imports": [ "imports": [

File diff suppressed because it is too large Load Diff