Abstract away redis even more with AlmostRedis.cs

This commit is contained in:
Runebaas 2018-05-26 02:33:45 +02:00
parent f53258e348
commit 35f0a5c8f8
No known key found for this signature in database
GPG key ID: 2677AF508D0300D6
10 changed files with 153 additions and 78 deletions

View file

@ -3,11 +3,11 @@ using System.Threading.Tasks;
using Discord.Commands;
using Discord.WebSocket;
using Geekbot.net.Database;
using Geekbot.net.Lib.AlmostRedis;
using Geekbot.net.Lib.ErrorHandling;
using Geekbot.net.Lib.GlobalSettings;
using Geekbot.net.Lib.Logger;
using Geekbot.net.Lib.UserRepository;
using StackExchange.Redis;
namespace Geekbot.net.Commands.Admin
{
@ -20,10 +20,10 @@ namespace Geekbot.net.Commands.Admin
private readonly DatabaseContext _database;
private readonly IGlobalSettings _globalSettings;
private readonly IGeekbotLogger _logger;
private readonly IDatabase _redis;
private readonly IAlmostRedis _redis;
private readonly IUserRepository _userRepository;
public Owner(IDatabase redis, DiscordSocketClient client, IGeekbotLogger logger, IUserRepository userRepositry, IErrorHandler errorHandler, DatabaseContext database, IGlobalSettings globalSettings)
public Owner(IAlmostRedis redis, DiscordSocketClient client, IGeekbotLogger logger, IUserRepository userRepositry, IErrorHandler errorHandler, DatabaseContext database, IGlobalSettings globalSettings)
{
_redis = redis;
_client = client;

View file

@ -1,6 +1,7 @@
using System;
using System.Threading.Tasks;
using Discord.Commands;
using Geekbot.net.Lib.AlmostRedis;
using Geekbot.net.Lib.ErrorHandling;
using Geekbot.net.Lib.Localization;
using StackExchange.Redis;
@ -10,10 +11,10 @@ namespace Geekbot.net.Commands.Games
public class Roll : ModuleBase
{
private readonly IErrorHandler _errorHandler;
private readonly IDatabase _redis;
private readonly IAlmostRedis _redis;
private readonly ITranslationHandler _translation;
public Roll(IDatabase redis, IErrorHandler errorHandler, ITranslationHandler translation)
public Roll(IAlmostRedis redis, IErrorHandler errorHandler, ITranslationHandler translation)
{
_redis = redis;
_translation = translation;
@ -32,20 +33,20 @@ namespace Geekbot.net.Commands.Games
var transDict = _translation.GetDict(Context);
if (guess <= 100 && guess > 0)
{
var prevRoll = _redis.HashGet($"{Context.Guild.Id}:RollsPrevious", Context.Message.Author.Id);
var prevRoll = _redis.Db.HashGet($"{Context.Guild.Id}:RollsPrevious", Context.Message.Author.Id);
if (!prevRoll.IsNullOrEmpty && prevRoll.ToString() == guess.ToString())
{
await ReplyAsync(string.Format(transDict["NoPrevGuess"], Context.Message.Author.Mention));
return;
}
_redis.HashSet($"{Context.Guild.Id}:RollsPrevious",
_redis.Db.HashSet($"{Context.Guild.Id}:RollsPrevious",
new[] {new HashEntry(Context.Message.Author.Id, guess)});
await ReplyAsync(string.Format(transDict["Rolled"], Context.Message.Author.Mention, number, guess));
if (guess == number)
{
await ReplyAsync(string.Format(transDict["Gratz"], Context.Message.Author));
_redis.HashIncrement($"{Context.Guild.Id}:Rolls", Context.User.Id.ToString());
_redis.Db.HashIncrement($"{Context.Guild.Id}:Rolls", Context.User.Id.ToString());
}
}
else

View file

@ -5,6 +5,7 @@ using System.Text;
using System.Threading.Tasks;
using Discord.Commands;
using Geekbot.net.Database;
using Geekbot.net.Lib.AlmostRedis;
using Geekbot.net.Lib.Converters;
using Geekbot.net.Lib.ErrorHandling;
using Geekbot.net.Lib.Extensions;
@ -19,10 +20,10 @@ namespace Geekbot.net.Commands.User.Ranking
private readonly IErrorHandler _errorHandler;
private readonly DatabaseContext _database;
private readonly IUserRepository _userRepository;
private readonly IDatabase _redis;
private readonly IAlmostRedis _redis;
public Rank(DatabaseContext database, IErrorHandler errorHandler, IUserRepository userRepository,
IEmojiConverter emojiConverter, IDatabase redis)
IEmojiConverter emojiConverter, IAlmostRedis redis)
{
_database = database;
_errorHandler = errorHandler;
@ -138,7 +139,7 @@ namespace Geekbot.net.Commands.User.Ranking
private Dictionary<ulong, int> GetMessageList(int amount)
{
return _redis
return _redis.Db
.HashGetAll($"{Context.Guild.Id}:Messages").ToDictionary().Take(amount + 1)
.Where(user => !user.Key.Equals(0))
.ToDictionary(user => ulong.Parse(user.Key), user => int.Parse(user.Value));

View file

@ -4,10 +4,10 @@ using System.Threading.Tasks;
using Discord;
using Discord.Commands;
using Geekbot.net.Database;
using Geekbot.net.Lib.AlmostRedis;
using Geekbot.net.Lib.ErrorHandling;
using Geekbot.net.Lib.Extensions;
using Geekbot.net.Lib.Levels;
using StackExchange.Redis;
namespace Geekbot.net.Commands.User
{
@ -15,10 +15,10 @@ namespace Geekbot.net.Commands.User
{
private readonly IErrorHandler _errorHandler;
private readonly ILevelCalc _levelCalc;
private readonly IDatabase _redis;
private readonly IAlmostRedis _redis;
private readonly DatabaseContext _database;
public Stats(IDatabase redis, DatabaseContext database, IErrorHandler errorHandler, ILevelCalc levelCalc)
public Stats(IAlmostRedis redis, DatabaseContext database, IErrorHandler errorHandler, ILevelCalc levelCalc)
{
_redis = redis;
_database = database;
@ -39,8 +39,8 @@ namespace Geekbot.net.Commands.User
var age = Math.Floor((DateTime.Now - createdAt).TotalDays);
var joinedDayAgo = Math.Floor((DateTime.Now - joinedAt).TotalDays);
var messages = (int) _redis.HashGet($"{Context.Guild.Id}:Messages", userInfo.Id.ToString());
var guildMessages = (int) _redis.HashGet($"{Context.Guild.Id}:Messages", 0.ToString());
var messages = (int) _redis.Db.HashGet($"{Context.Guild.Id}:Messages", userInfo.Id.ToString());
var guildMessages = (int) _redis.Db.HashGet($"{Context.Guild.Id}:Messages", 0.ToString());
var level = _levelCalc.GetLevel(messages);
var percent = Math.Round((double) (100 * messages) / guildMessages, 2);

View file

@ -6,21 +6,21 @@ using Discord;
using Discord.WebSocket;
using Geekbot.net.Commands.Utils.Quote;
using Geekbot.net.Database.Models;
using Geekbot.net.Lib.AlmostRedis;
using Geekbot.net.Lib.Extensions;
using Geekbot.net.Lib.Logger;
using Newtonsoft.Json;
using StackExchange.Redis;
namespace Geekbot.net.Database
{
public class RedisMigration
{
private readonly DatabaseContext _database;
private readonly IDatabase _redis;
private readonly IAlmostRedis _redis;
private readonly IGeekbotLogger _logger;
private readonly DiscordSocketClient _client;
public RedisMigration(DatabaseContext database, IDatabase redis, IGeekbotLogger logger, DiscordSocketClient client)
public RedisMigration(DatabaseContext database, IAlmostRedis redis, IGeekbotLogger logger, DiscordSocketClient client)
{
_database = database;
_redis = redis;
@ -46,7 +46,7 @@ namespace Geekbot.net.Database
*/
try
{
var data = _redis.SetScan($"{guild.Id}:Quotes");
var data = _redis.Db.SetScan($"{guild.Id}:Quotes");
foreach (var q in data)
{
try
@ -74,7 +74,7 @@ namespace Geekbot.net.Database
*/
try
{
var data = _redis.HashGetAll($"{guild.Id}:Karma");
var data = _redis.Db.HashGetAll($"{guild.Id}:Karma");
foreach (var q in data)
{
try
@ -107,7 +107,7 @@ namespace Geekbot.net.Database
*/
try
{
var data = _redis.HashGetAll($"{guild.Id}:Rolls");
var data = _redis.Db.HashGetAll($"{guild.Id}:Rolls");
foreach (var q in data)
{
try
@ -139,8 +139,8 @@ namespace Geekbot.net.Database
*/
try
{
var given = _redis.HashGetAll($"{guild.Id}:SlapsGiven");
var gotten = _redis.HashGetAll($"{guild.Id}:SlapsGiven");
var given = _redis.Db.HashGetAll($"{guild.Id}:SlapsGiven");
var gotten = _redis.Db.HashGetAll($"{guild.Id}:SlapsGiven");
foreach (var q in given)
{
try
@ -171,32 +171,32 @@ namespace Geekbot.net.Database
/**
* Messages
*/
try
{
var data = _redis.HashGetAll($"{guild.Id}:Messages");
foreach (var q in data)
{
try
{
var user = new MessagesModel()
{
GuildId = guild.Id.AsLong(),
UserId = ulong.Parse(q.Name).AsLong(),
MessageCount= int.Parse(q.Value)
};
_database.Messages.Add(user);
await _database.SaveChangesAsync();
}
catch (Exception e)
{
_logger.Error(LogSource.Geekbot, $"Messages failed for: {q.Name}", e);
}
}
}
catch (Exception e)
{
_logger.Error(LogSource.Geekbot, "Messages migration failed", e);
}
// try
// {
// var data = _redis.Db.HashGetAll($"{guild.Id}:Messages");
// foreach (var q in data)
// {
// try
// {
// var user = new MessagesModel()
// {
// GuildId = guild.Id.AsLong(),
// UserId = ulong.Parse(q.Name).AsLong(),
// MessageCount= int.Parse(q.Value)
// };
// _database.Messages.Add(user);
// await _database.SaveChangesAsync();
// }
// catch (Exception e)
// {
// _logger.Error(LogSource.Geekbot, $"Messages failed for: {q.Name}", e);
// }
// }
// }
// catch (Exception e)
// {
// _logger.Error(LogSource.Geekbot, "Messages migration failed", e);
// }
#endregion
#region Ships
@ -205,7 +205,7 @@ namespace Geekbot.net.Database
*/
try
{
var data = _redis.HashGetAll($"{guild.Id}:Ships");
var data = _redis.Db.HashGetAll($"{guild.Id}:Ships");
var done = new List<string>();
foreach (var q in data)
{
@ -241,7 +241,7 @@ namespace Geekbot.net.Database
*/
try
{
var data = _redis.HashGetAll($"{guild.Id}:Settings");
var data = _redis.Db.HashGetAll($"{guild.Id}:Settings");
var settings = new GuildSettingsModel()
{
GuildId = guild.Id.AsLong(),
@ -305,7 +305,7 @@ namespace Geekbot.net.Database
await Task.Delay(100);
if (user.Username == null) break;
}
var namesSerialized = _redis.HashGet($"User:{user.Id}", "UsedNames").ToString();
var namesSerialized = _redis.Db.HashGet($"User:{user.Id}", "UsedNames").ToString();
var names = namesSerialized != null
? Utf8Json.JsonSerializer.Deserialize<string[]>(namesSerialized)
: new string[] {user.Username};

View file

@ -6,11 +6,11 @@ using Discord;
using Discord.Commands;
using Discord.WebSocket;
using Geekbot.net.Database;
using Geekbot.net.Lib.AlmostRedis;
using Geekbot.net.Lib.Extensions;
using Geekbot.net.Lib.Logger;
using Geekbot.net.Lib.ReactionListener;
using Geekbot.net.Lib.UserRepository;
using StackExchange.Redis;
namespace Geekbot.net
{
@ -19,13 +19,13 @@ namespace Geekbot.net
private readonly DatabaseContext _database;
private readonly IDiscordClient _client;
private readonly IGeekbotLogger _logger;
private readonly IDatabase _redis;
private readonly IAlmostRedis _redis;
private readonly IServiceProvider _servicesProvider;
private readonly CommandService _commands;
private readonly IUserRepository _userRepository;
private readonly IReactionListener _reactionListener;
public Handlers(DatabaseContext database, IDiscordClient client, IGeekbotLogger logger, IDatabase redis,
public Handlers(DatabaseContext database, IDiscordClient client, IGeekbotLogger logger, IAlmostRedis redis,
IServiceProvider servicesProvider, CommandService commands, IUserRepository userRepository,
IReactionListener reactionListener)
{
@ -105,8 +105,8 @@ namespace Geekbot.net
}
var channel = (SocketGuildChannel) message.Channel;
_redis.HashIncrementAsync($"{channel.Guild.Id}:Messages", message.Author.Id.ToString());
_redis.HashIncrementAsync($"{channel.Guild.Id}:Messages", 0.ToString());
_redis.Db.HashIncrementAsync($"{channel.Guild.Id}:Messages", message.Author.Id.ToString());
_redis.Db.HashIncrementAsync($"{channel.Guild.Id}:Messages", 0.ToString());
if (message.Author.IsBot) return Task.CompletedTask;
_logger.Information(LogSource.Message, message.Content, SimpleConextConverter.ConvertSocketMessage(message));

View file

@ -0,0 +1,44 @@
using System.Collections.Generic;
using Geekbot.net.Lib.Logger;
using StackExchange.Redis;
namespace Geekbot.net.Lib.AlmostRedis
{
// if anyone ever sees this, please come up with a better fucking name, i'd appriciate it
public class AlmostRedis : IAlmostRedis
{
private readonly GeekbotLogger _logger;
private readonly RunParameters _runParameters;
private IDatabase _database;
private ConnectionMultiplexer _connection;
private IAlmostRedis _almostRedisImplementation;
public AlmostRedis(GeekbotLogger logger, RunParameters runParameters)
{
_logger = logger;
_runParameters = runParameters;
}
public void Connect()
{
_connection = ConnectionMultiplexer.Connect($"{_runParameters.RedisHost}:{_runParameters.RedisPort}");
_database = _connection.GetDatabase(int.Parse(_runParameters.RedisDatabase));
_logger.Information(LogSource.Redis, $"Connected to Redis on {_connection.Configuration} at {_database.Database}");
}
public IDatabase Db
{
get { return _database; }
}
public ConnectionMultiplexer Connection
{
get { return _connection; }
}
public IEnumerable<RedisKey> GetAllKeys()
{
return _connection.GetServer($"{_runParameters.RedisHost}:{_runParameters.RedisPort}", int.Parse(_runParameters.RedisDatabase)).Keys();
}
}
}

View file

@ -0,0 +1,13 @@
using System.Collections.Generic;
using StackExchange.Redis;
namespace Geekbot.net.Lib.AlmostRedis
{
public interface IAlmostRedis
{
void Connect();
IDatabase Db { get; }
ConnectionMultiplexer Connection { get; }
IEnumerable<RedisKey> GetAllKeys();
}
}

View file

@ -4,24 +4,26 @@ using System.IO;
using System.Linq;
using Discord.Commands;
using Discord.WebSocket;
using Geekbot.net.Database;
using Geekbot.net.Database.Models;
using Geekbot.net.Lib.Extensions;
using Geekbot.net.Lib.Logger;
using StackExchange.Redis;
using Utf8Json;
namespace Geekbot.net.Lib.Localization
{
public class TranslationHandler : ITranslationHandler
{
private readonly DatabaseContext _database;
private readonly IGeekbotLogger _logger;
private readonly IDatabase _redis;
private Dictionary<string, Dictionary<string, Dictionary<string, string>>> _translations;
private Dictionary<ulong, string> _serverLanguages;
private List<string> _supportedLanguages;
public TranslationHandler(IReadOnlyCollection<SocketGuild> clientGuilds, IDatabase redis, IGeekbotLogger logger)
public TranslationHandler(IReadOnlyCollection<SocketGuild> clientGuilds, DatabaseContext database, IGeekbotLogger logger)
{
_database = database;
_logger = logger;
_redis = redis;
_logger.Information(LogSource.Geekbot, "Loading Translations");
LoadTranslations();
LoadServerLanguages(clientGuilds);
@ -81,14 +83,16 @@ namespace Geekbot.net.Lib.Localization
_serverLanguages = new Dictionary<ulong, string>();
foreach (var guild in clientGuilds)
{
var language = _redis.HashGet($"{guild.Id}:Settings", "Language");
var language = _database.GuildSettings
.FirstOrDefault(g => g.GuildId.Equals(guild.Id.AsLong()))
?.Language ?? "EN";
if (string.IsNullOrEmpty(language) || !_supportedLanguages.Contains(language))
{
_serverLanguages[guild.Id] = "EN";
}
else
{
_serverLanguages[guild.Id] = language.ToString();
_serverLanguages[guild.Id] = language;
}
}
}
@ -137,7 +141,9 @@ namespace Geekbot.net.Lib.Localization
try
{
if (!_supportedLanguages.Contains(language)) return false;
_redis.HashSet($"{guildId}:Settings", new[]{ new HashEntry("Language", language) });
var guild = GetGuild(guildId);
guild.Language = language;
_database.GuildSettings.Update(guild);
_serverLanguages[guildId] = language;
return true;
}
@ -152,5 +158,17 @@ namespace Geekbot.net.Lib.Localization
{
return _supportedLanguages;
}
private GuildSettingsModel GetGuild(ulong guildId)
{
var guild = _database.GuildSettings.FirstOrDefault(g => g.GuildId.Equals(guildId.AsLong()));
if (guild != null) return guild;
_database.GuildSettings.Add(new GuildSettingsModel
{
GuildId = guildId.AsLong()
});
_database.SaveChanges();
return _database.GuildSettings.FirstOrDefault(g => g.GuildId.Equals(guildId.AsLong()));
}
}
}

View file

@ -8,6 +8,7 @@ using Discord.Commands;
using Discord.WebSocket;
using Geekbot.net.Database;
using Geekbot.net.Lib;
using Geekbot.net.Lib.AlmostRedis;
using Geekbot.net.Lib.Audio;
using Geekbot.net.Lib.Clients;
using Geekbot.net.Lib.Converters;
@ -20,7 +21,6 @@ using Geekbot.net.Lib.Media;
using Geekbot.net.Lib.ReactionListener;
using Geekbot.net.Lib.UserRepository;
using Microsoft.Extensions.DependencyInjection;
using StackExchange.Redis;
using WikipediaApi;
namespace Geekbot.net
@ -29,15 +29,15 @@ namespace Geekbot.net
{
private DiscordSocketClient _client;
private CommandService _commands;
private IDatabase _redis;
private DatabaseContext _database;
private IGlobalSettings _globalSettings;
private IServiceCollection _services;
private IServiceProvider _servicesProvider;
private RedisValue _token;
private string _token;
private GeekbotLogger _logger;
private IUserRepository _userRepository;
private RunParameters _runParameters;
private IAlmostRedis _redis;
private static void Main(string[] args)
{
@ -52,8 +52,7 @@ namespace Geekbot.net
logo.AppendLine(@"| | _| _| | _| | ' /| _ \| | | || |");
logo.AppendLine(@"| |_| | |___| |___| . \| |_) | |_| || |");
logo.AppendLine(@" \____|_____|_____|_|\_\____/ \___/ |_|");
logo.AppendLine("=========================================");
logo.AppendLine($"Version {Constants.BotVersion()}");
logo.AppendLine($"Version {Constants.BotVersion()} ".PadRight(41, '='));
Console.WriteLine(logo.ToString());
var sumologicActive = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("GEEKBOT_SUMO"));
var logger = new GeekbotLogger(runParameters, sumologicActive);
@ -88,9 +87,8 @@ namespace Geekbot.net
try
{
var redisMultiplexer = ConnectionMultiplexer.Connect($"{runParameters.RedisHost}:{runParameters.RedisPort}");
_redis = redisMultiplexer.GetDatabase(int.Parse(runParameters.RedisDatabase));
logger.Information(LogSource.Redis, $"Connected to db {_redis.Database}");
_redis = new AlmostRedis(logger, runParameters);
_redis.Connect();
}
catch (Exception e)
{
@ -99,7 +97,7 @@ namespace Geekbot.net
}
_token = runParameters.Token ?? _globalSettings.GetKey("DiscordToken");
if (_token.IsNullOrEmpty)
if (string.IsNullOrEmpty(_token))
{
Console.Write("Your bot Token: ");
var newToken = Console.ReadLine();
@ -120,7 +118,7 @@ namespace Geekbot.net
var wikipediaClient = new WikipediaClient();
var audioUtils = new AudioUtils();
_services.AddSingleton<IDatabase>(_redis);
_services.AddSingleton<IAlmostRedis>(_redis);
_services.AddSingleton<IUserRepository>(_userRepository);
_services.AddSingleton<IGeekbotLogger>(logger);
_services.AddSingleton<ILevelCalc>(levelCalc);
@ -154,9 +152,9 @@ namespace Geekbot.net
_logger.Information(LogSource.Geekbot, $"Now Connected as {_client.CurrentUser.Username} to {_client.Guilds.Count} Servers");
_logger.Information(LogSource.Geekbot, "Registering Stuff");
var translationHandler = new TranslationHandler(_client.Guilds, _redis, _logger);
var translationHandler = new TranslationHandler(_client.Guilds, _database, _logger);
var errorHandler = new ErrorHandler(_logger, translationHandler, _runParameters.ExposeErrors);
var reactionListener = new ReactionListener(_redis);
var reactionListener = new ReactionListener(_redis.Db);
await _commands.AddModulesAsync(Assembly.GetEntryAssembly());
_services.AddSingleton(_commands);
_services.AddSingleton<IErrorHandler>(errorHandler);
@ -185,7 +183,7 @@ namespace Geekbot.net
}
catch (Exception e)
{
_logger.Error(LogSource.Geekbot, "Could not connect...", e);
_logger.Error(LogSource.Geekbot, "Could not connect to Discord", e);
Environment.Exit(GeekbotExitCode.CouldNotLogin.GetHashCode());
}
}