.convert rewritten a bit, isn't saved in the database anymore, but in redis.

This commit is contained in:
Master Kwoth 2017-10-16 12:34:16 +02:00
parent 099ae62c0b
commit f155619793
13 changed files with 1999 additions and 202 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,34 @@
using Microsoft.EntityFrameworkCore.Migrations;
using System;
using System.Collections.Generic;
namespace NadekoBot.Migrations
{
public partial class removeconvertunits : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "ConversionUnits");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "ConversionUnits",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
DateAdded = table.Column<DateTime>(nullable: true),
InternalTrigger = table.Column<string>(nullable: true),
Modifier = table.Column<decimal>(nullable: false),
UnitType = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_ConversionUnits", x => x.Id);
});
}
}
}

View File

@ -320,24 +320,6 @@ namespace NadekoBot.Migrations
b.ToTable("CommandPrice"); b.ToTable("CommandPrice");
}); });
modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.ConvertUnit", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime?>("DateAdded");
b.Property<string>("InternalTrigger");
b.Property<decimal>("Modifier");
b.Property<string>("UnitType");
b.HasKey("Id");
b.ToTable("ConversionUnits");
});
modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.Currency", b => modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.Currency", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")

View File

@ -0,0 +1,9 @@
namespace NadekoBot.Modules.Utility.Common
{
public class ConvertUnit
{
public string[] Triggers { get; set; }
public string UnitType { get; set; }
public decimal Modifier { get; set; }
}
}

View File

@ -7,137 +7,86 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord.WebSocket; using Discord.WebSocket;
using NadekoBot.Core.Services; using NadekoBot.Core.Services;
using NadekoBot.Core.Services.Database.Models;
using Newtonsoft.Json; using Newtonsoft.Json;
using NLog; using NLog;
using NadekoBot.Modules.Utility.Common;
using NadekoBot.Extensions;
namespace NadekoBot.Modules.Utility.Services namespace NadekoBot.Modules.Utility.Services
{ {
//todo rewrite
public class ConverterService : INService, IUnloadableService public class ConverterService : INService, IUnloadableService
{ {
public List<ConvertUnit> Units { get; } = new List<ConvertUnit>(); public ConvertUnit[] Units =>
_cache.Redis.GetDatabase()
.StringGet("converter_units")
.ToString()
.MapJson<ConvertUnit[]>();
private readonly Logger _log; private readonly Logger _log;
private readonly Timer _currencyUpdater; private readonly Timer _currencyUpdater;
private readonly TimeSpan _updateInterval = new TimeSpan(12, 0, 0); private readonly TimeSpan _updateInterval = new TimeSpan(12, 0, 0);
private readonly DbService _db; private readonly DbService _db;
private readonly ConvertUnit[] fileData; private readonly IDataCache _cache;
private readonly HttpClient _http;
public ConverterService(DiscordSocketClient client, DbService db) public ConverterService(DiscordSocketClient client, DbService db,
IDataCache cache)
{ {
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
_db = db; _db = db;
_cache = cache;
_http = new HttpClient();
if (client.ShardId == 0) if (client.ShardId == 0)
{ {
try _currencyUpdater = new Timer(async (shouldLoad) => await UpdateCurrency((bool)shouldLoad),
{ client.ShardId == 0,
fileData = JsonConvert.DeserializeObject<List<MeasurementUnit>>( TimeSpan.Zero,
File.ReadAllText("data/units.json")) _updateInterval);
.Select(u => new ConvertUnit()
{
Modifier = u.Modifier,
UnitType = u.UnitType,
InternalTrigger = string.Join("|", u.Triggers)
}).ToArray();
using (var uow = _db.UnitOfWork)
{
if (uow.ConverterUnits.Empty())
{
uow.ConverterUnits.AddRange(fileData);
Units = uow.ConverterUnits.GetAll().ToList();
uow.Complete();
}
}
}
catch (Exception ex)
{
_log.Warn("Could not load units: " + ex.Message);
}
} }
_currencyUpdater = new Timer(async (shouldLoad) => await UpdateCurrency((bool)shouldLoad),
client.ShardId == 0,
TimeSpan.FromSeconds(1),
_updateInterval);
} }
private async Task<Rates> GetCurrencyRates() private async Task<Rates> GetCurrencyRates()
{ {
using (var http = new HttpClient()) var res = await _http.GetStringAsync("http://api.fixer.io/latest").ConfigureAwait(false);
{ return JsonConvert.DeserializeObject<Rates>(res);
var res = await http.GetStringAsync("http://api.fixer.io/latest").ConfigureAwait(false);
return JsonConvert.DeserializeObject<Rates>(res);
}
} }
private async Task UpdateCurrency(bool shouldLoad) private async Task UpdateCurrency(bool shouldLoad)
{ {
try var unitTypeString = "currency";
if (shouldLoad)
{ {
var unitTypeString = "currency"; var currencyRates = await GetCurrencyRates();
if (shouldLoad) var baseType = new ConvertUnit()
{ {
var currencyRates = await GetCurrencyRates(); Triggers = new[] { currencyRates.Base },
var baseType = new ConvertUnit() Modifier = decimal.One,
{ UnitType = unitTypeString
Triggers = new[] { currencyRates.Base }, };
Modifier = decimal.One, var range = currencyRates.ConversionRates.Select(u => new ConvertUnit()
UnitType = unitTypeString
};
var range = currencyRates.ConversionRates.Select(u => new ConvertUnit()
{
InternalTrigger = u.Key,
Modifier = u.Value,
UnitType = unitTypeString
}).ToArray();
var toRemove = Units.Where(u => u.UnitType == unitTypeString);
using (var uow = _db.UnitOfWork)
{
if(toRemove.Any())
uow.ConverterUnits.RemoveRange(toRemove.ToArray());
uow.ConverterUnits.Add(baseType);
uow.ConverterUnits.AddRange(range);
await uow.CompleteAsync().ConfigureAwait(false);
}
Units.RemoveAll(u => u.UnitType == unitTypeString);
Units.Add(baseType);
Units.AddRange(range);
Units.AddRange(fileData);
}
else
{ {
using (var uow = _db.UnitOfWork) Triggers = new[] { u.Key },
{ Modifier = u.Value,
Units.RemoveAll(u => u.UnitType == unitTypeString); UnitType = unitTypeString
Units.AddRange(uow.ConverterUnits.GetAll().ToArray()); }).ToArray();
}
} var fileData = JsonConvert.DeserializeObject<ConvertUnit[]>(
} File.ReadAllText("data/units.json"));
catch
{ var data = JsonConvert.SerializeObject(range.Append(baseType).Concat(fileData).ToList());
_log.Warn("Failed updating currency. Ignore this."); _cache.Redis.GetDatabase()
.StringSet("converter_units", data);
} }
} }
public Task Unload() public Task Unload()
{ {
_currencyUpdater.Change(Timeout.Infinite, Timeout.Infinite); _currencyUpdater?.Change(Timeout.Infinite, Timeout.Infinite);
return Task.CompletedTask; return Task.CompletedTask;
} }
} }
public class MeasurementUnit
{
public List<string> Triggers { get; set; }
public string UnitType { get; set; }
public decimal Modifier { get; set; }
}
public class Rates public class Rates
{ {
public string Base { get; set; } public string Base { get; set; }

View File

@ -26,11 +26,12 @@ namespace NadekoBot.Modules.Utility
.OrderBy(x => x))))); .OrderBy(x => x)))));
await Context.Channel.EmbedAsync(res); await Context.Channel.EmbedAsync(res);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public async Task Convert(string origin, string target, decimal value) public async Task Convert(string origin, string target, decimal value)
{ {
var originUnit = _service.Units.Find(x => x.Triggers.Select(y => y.ToLowerInvariant()).Contains(origin.ToLowerInvariant())); var originUnit = _service.Units.FirstOrDefault(x => x.Triggers.Select(y => y.ToLowerInvariant()).Contains(origin.ToLowerInvariant()));
var targetUnit = _service.Units.Find(x => x.Triggers.Select(y => y.ToLowerInvariant()).Contains(target.ToLowerInvariant())); var targetUnit = _service.Units.FirstOrDefault(x => x.Triggers.Select(y => y.ToLowerInvariant()).Contains(target.ToLowerInvariant()));
if (originUnit == null || targetUnit == null) if (originUnit == null || targetUnit == null)
{ {
await ReplyErrorLocalized("convert_not_found", Format.Bold(origin), Format.Bold(target)).ConfigureAwait(false); await ReplyErrorLocalized("convert_not_found", Format.Bold(origin), Format.Bold(target)).ConfigureAwait(false);

View File

@ -14,7 +14,6 @@ namespace NadekoBot.Core.Services.Database
IReminderRepository Reminders { get; } IReminderRepository Reminders { get; }
ISelfAssignedRolesRepository SelfAssignedRoles { get; } ISelfAssignedRolesRepository SelfAssignedRoles { get; }
IBotConfigRepository BotConfig { get; } IBotConfigRepository BotConfig { get; }
IUnitConverterRepository ConverterUnits { get; }
ICustomReactionRepository CustomReactions { get; } ICustomReactionRepository CustomReactions { get; }
ICurrencyRepository Currency { get; } ICurrencyRepository Currency { get; }
ICurrencyTransactionsRepository CurrencyTransactions { get; } ICurrencyTransactionsRepository CurrencyTransactions { get; }

View File

@ -1,47 +0,0 @@
using System.ComponentModel;
using System.ComponentModel.DataAnnotations.Schema;
namespace NadekoBot.Core.Services.Database.Models
{
public class ConvertUnit : DbEntity
{
public ConvertUnit() { }
[NotMapped]
private string[] _triggersValue;
[NotMapped]
public string[] Triggers
{
get
{
return _triggersValue ?? (_triggersValue = InternalTrigger.Split('|'));
}
set
{
_triggersValue = value;
InternalTrigger = string.Join("|", _triggersValue);
}
}
//protected or private?
/// <summary>
/// DO NOT CALL THIS
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public string InternalTrigger { get; set; }
public string UnitType { get; set; }
public decimal Modifier { get; set; }
public override bool Equals(object obj)
{
var cu = obj as ConvertUnit;
if (cu == null)
return false;
return cu.UnitType == this.UnitType;
}
public override int GetHashCode()
{
return this.UnitType.GetHashCode();
}
}
}

View File

@ -33,7 +33,6 @@ namespace NadekoBot.Core.Services.Database
public DbSet<SelfAssignedRole> SelfAssignableRoles { get; set; } public DbSet<SelfAssignedRole> SelfAssignableRoles { get; set; }
public DbSet<BotConfig> BotConfig { get; set; } public DbSet<BotConfig> BotConfig { get; set; }
public DbSet<Currency> Currency { get; set; } public DbSet<Currency> Currency { get; set; }
public DbSet<ConvertUnit> ConversionUnits { get; set; }
public DbSet<MusicPlaylist> MusicPlaylists { get; set; } public DbSet<MusicPlaylist> MusicPlaylists { get; set; }
public DbSet<CustomReaction> CustomReactions { get; set; } public DbSet<CustomReaction> CustomReactions { get; set; }
public DbSet<CurrencyTransaction> CurrencyTransactions { get; set; } public DbSet<CurrencyTransaction> CurrencyTransactions { get; set; }

View File

@ -1,11 +0,0 @@
using NadekoBot.Core.Services.Database.Models;
using System;
namespace NadekoBot.Core.Services.Database.Repositories
{
public interface IUnitConverterRepository : IRepository<ConvertUnit>
{
void AddOrUpdate(Func<ConvertUnit, bool> check, ConvertUnit toAdd, Func<ConvertUnit, ConvertUnit> toUpdate);
bool Empty();
}
}

View File

@ -1,26 +0,0 @@
using NadekoBot.Core.Services.Database.Models;
using System;
using System.Linq;
using Microsoft.EntityFrameworkCore;
namespace NadekoBot.Core.Services.Database.Repositories.Impl
{
public class UnitConverterRepository : Repository<ConvertUnit>, IUnitConverterRepository
{
public UnitConverterRepository(DbContext context) : base(context)
{
}
public void AddOrUpdate(Func<ConvertUnit, bool> check, ConvertUnit toAdd, Func<ConvertUnit, ConvertUnit> toUpdate)
{
var existing = _set.FirstOrDefault(check);
if (existing != null)
{
existing = toUpdate.Invoke(existing);
}
else _set.Add(toAdd);
}
public bool Empty() => !_set.Any();
}
}

View File

@ -33,9 +33,6 @@ namespace NadekoBot.Core.Services.Database
private ICurrencyTransactionsRepository _currencyTransactions; private ICurrencyTransactionsRepository _currencyTransactions;
public ICurrencyTransactionsRepository CurrencyTransactions => _currencyTransactions ?? (_currencyTransactions = new CurrencyTransactionsRepository(_context)); public ICurrencyTransactionsRepository CurrencyTransactions => _currencyTransactions ?? (_currencyTransactions = new CurrencyTransactionsRepository(_context));
private IUnitConverterRepository _conUnits;
public IUnitConverterRepository ConverterUnits => _conUnits ?? (_conUnits = new UnitConverterRepository(_context));
private IMusicPlaylistRepository _musicPlaylists; private IMusicPlaylistRepository _musicPlaylists;
public IMusicPlaylistRepository MusicPlaylists => _musicPlaylists ?? (_musicPlaylists = new MusicPlaylistRepository(_context)); public IMusicPlaylistRepository MusicPlaylists => _musicPlaylists ?? (_musicPlaylists = new MusicPlaylistRepository(_context));

View File

@ -1,4 +1,5 @@
using System; using Newtonsoft.Json;
using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -9,6 +10,9 @@ namespace NadekoBot.Extensions
{ {
public static class StringExtensions public static class StringExtensions
{ {
public static T MapJson<T>(this string str)
=> JsonConvert.DeserializeObject<T>(str);
public static string StripHTML(this string input) public static string StripHTML(this string input)
{ {
return Regex.Replace(input, "<.*?>", String.Empty); return Regex.Replace(input, "<.*?>", String.Empty);