Remove all dependencies on redis

This commit is contained in:
runebaas 2020-05-30 17:02:17 +02:00
parent 2e501008df
commit 33b17b373f
No known key found for this signature in database
GPG key ID: 2677AF508D0300D6
11 changed files with 129 additions and 77 deletions

View file

@ -170,23 +170,16 @@ namespace Geekbot.net.Commands.Admin
[RequireUserPermission(GuildPermission.ManageRoles)]
[Summary("Give a role by clicking on an emoji")]
[Command("listen", RunMode = RunMode.Async)]
public async Task AddListener([Summary("message-ID")] string messageId, [Summary("Emoji")] string emoji, [Summary("@role")] IRole role)
public async Task AddListener([Summary("message-ID")] string messageIdStr, [Summary("Emoji")] string emoji, [Summary("@role")] IRole role)
{
try
{
var message = (IUserMessage) await Context.Channel.GetMessageAsync(ulong.Parse(messageId));
IEmote emote;
if (!emoji.StartsWith('<'))
{
var emo = new Emoji(emoji);
emote = emo;
}
else
{
emote = Emote.Parse(emoji);
}
var messageId = ulong.Parse(messageIdStr);
var message = (IUserMessage) await Context.Channel.GetMessageAsync(messageId);
var emote = _reactionListener.ConvertStringToEmote(emoji);
await message.AddReactionAsync(emote);
await _reactionListener.AddRoleToListener(messageId, emote, role);
await _reactionListener.AddRoleToListener(messageId, Context.Guild.Id, emoji, role);
await Context.Message.DeleteAsync();
}
catch (HttpException e)

View file

@ -4,26 +4,25 @@ using System.Threading.Tasks;
using Discord.Commands;
using Geekbot.net.Database;
using Geekbot.net.Database.Models;
using Geekbot.net.Lib.AlmostRedis;
using Geekbot.net.Lib.ErrorHandling;
using Geekbot.net.Lib.Extensions;
using Geekbot.net.Lib.KvInMemoryStore;
using Geekbot.net.Lib.Localization;
using Geekbot.net.Lib.RandomNumberGenerator;
using StackExchange.Redis;
namespace Geekbot.net.Commands.Games
{
public class Roll : ModuleBase
{
private readonly IErrorHandler _errorHandler;
private readonly IAlmostRedis _redis;
private readonly IKvInMemoryStore _kvInMemoryStore;
private readonly ITranslationHandler _translation;
private readonly DatabaseContext _database;
private readonly IRandomNumberGenerator _randomNumberGenerator;
public Roll(IAlmostRedis redis, IErrorHandler errorHandler, ITranslationHandler translation, DatabaseContext database, IRandomNumberGenerator randomNumberGenerator)
public Roll(IKvInMemoryStore kvInMemoryStore,IErrorHandler errorHandler, ITranslationHandler translation, DatabaseContext database, IRandomNumberGenerator randomNumberGenerator)
{
_redis = redis;
_kvInMemoryStore = kvInMemoryStore;
_translation = translation;
_database = database;
_randomNumberGenerator = randomNumberGenerator;
@ -37,28 +36,28 @@ namespace Geekbot.net.Commands.Games
try
{
var number = _randomNumberGenerator.Next(1, 100);
var guess = 1000;
int.TryParse(stuff, out guess);
int.TryParse(stuff, out var guess);
var transContext = await _translation.GetGuildContext(Context);
if (guess <= 100 && guess > 0)
{
var prevRoll = _redis.Db.HashGet($"{Context.Guild.Id}:RollsPrevious2", Context.Message.Author.Id).ToString()?.Split('|');
if (prevRoll?.Length == 2)
var kvKey = $"{Context.Guild.Id}:{Context.User.Id}:RollsPrevious";
var prevRoll = _kvInMemoryStore.Get<int>(kvKey);
if (prevRoll > 0)
{
if (prevRoll[0] == guess.ToString() && DateTime.Parse(prevRoll[1]) > DateTime.Now.AddDays(-1))
if (prevRoll == guess)
{
await ReplyAsync(transContext.GetString("NoPrevGuess", Context.Message.Author.Mention));
return;
}
}
_redis.Db.HashSet($"{Context.Guild.Id}:RollsPrevious2", new[] {new HashEntry(Context.Message.Author.Id, $"{guess}|{DateTime.Now}")});
_kvInMemoryStore.Set(kvKey, guess);
await ReplyAsync(transContext.GetString("Rolled", Context.Message.Author.Mention, number, guess));
if (guess == number)
{
await ReplyAsync(transContext.GetString("Gratz", Context.Message.Author));
_redis.Db.HashIncrement($"{Context.Guild.Id}:Rolls", Context.User.Id.ToString());
var user = await GetUser(Context.User.Id);
user.Rolls += 1;
_database.Rolls.Update(user);

View file

@ -4,7 +4,6 @@ using System.Threading.Tasks;
using Discord;
using Discord.Commands;
using Geekbot.net.Database;
using Geekbot.net.Lib.AlmostRedis;
using Geekbot.net.Lib.CommandPreconditions;
using Geekbot.net.Lib.ErrorHandling;
using Geekbot.net.Lib.Extensions;
@ -16,12 +15,10 @@ namespace Geekbot.net.Commands.User
{
private readonly IErrorHandler _errorHandler;
private readonly ILevelCalc _levelCalc;
private readonly IAlmostRedis _redis;
private readonly DatabaseContext _database;
public Stats(IAlmostRedis redis, DatabaseContext database, IErrorHandler errorHandler, ILevelCalc levelCalc)
public Stats(DatabaseContext database, IErrorHandler errorHandler, ILevelCalc levelCalc)
{
_redis = redis;
_database = database;
_errorHandler = errorHandler;
_levelCalc = levelCalc;

View file

@ -18,5 +18,6 @@ namespace Geekbot.net.Database
public DbSet<RoleSelfServiceModel> RoleSelfService { get; set; }
public DbSet<PollModel> Polls { get; set; }
public DbSet<CookiesModel> Cookies { get; set; }
public DbSet<ReactionListenerModel> ReactionListeners { get; set; }
}
}

View file

@ -0,0 +1,22 @@
using System.ComponentModel.DataAnnotations;
namespace Geekbot.net.Database.Models
{
public class ReactionListenerModel
{
[Key]
public int Id { get; set; }
[Required]
public long GuildId { get; set; }
[Required]
public long MessageId { get; set; }
[Required]
public long RoleId { get; set; }
[Required]
public string Reaction { get; set; }
}
}

View file

@ -9,12 +9,12 @@ using Discord.Rest;
using Discord.WebSocket;
using Geekbot.net.Database;
using Geekbot.net.Database.Models;
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 Microsoft.EntityFrameworkCore;
namespace Geekbot.net
{
public class Handlers

View file

@ -0,0 +1,9 @@
namespace Geekbot.net.Lib.KvInMemoryStore
{
public interface IKvInMemoryStore
{
public T Get<T>(string key);
public void Set<T>(string key, T value);
public void Remove(string key);
}
}

View file

@ -0,0 +1,32 @@
using System.Collections.Generic;
namespace Geekbot.net.Lib.KvInMemoryStore
{
public class KvInInMemoryStore : IKvInMemoryStore
{
private readonly Dictionary<string, object> _storage = new Dictionary<string, object>();
public T Get<T>(string key)
{
try
{
return (T) _storage[key];
}
catch
{
return default;
}
}
public void Set<T>(string key, T value)
{
_storage.Remove(key);
_storage.Add(key, value);
}
public void Remove(string key)
{
_storage.Remove(key);
}
}
}

View file

@ -7,8 +7,9 @@ namespace Geekbot.net.Lib.ReactionListener
public interface IReactionListener
{
bool IsListener(ulong id);
Task AddRoleToListener(string messageId, IEmote emoji, IRole role);
Task AddRoleToListener(ulong messageId, ulong guildId, string emoji, IRole role);
void RemoveRole(ISocketMessageChannel channel, SocketReaction reaction);
void GiveRole(ISocketMessageChannel message, SocketReaction reaction);
IEmote ConvertStringToEmote(string emoji);
}
}

View file

@ -1,80 +1,66 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Discord;
using Discord.WebSocket;
using StackExchange.Redis;
using Geekbot.net.Database;
using Geekbot.net.Database.Models;
using Geekbot.net.Lib.Extensions;
namespace Geekbot.net.Lib.ReactionListener
{
public class ReactionListener : IReactionListener
{
private readonly IDatabase _redis;
private Dictionary<string, Dictionary<IEmote, ulong>> _listener;
private readonly DatabaseContext _database;
private Dictionary<ulong, Dictionary<IEmote, ulong>> _listener;
public ReactionListener(IDatabase redis)
public ReactionListener(DatabaseContext database)
{
_redis = redis;
_database = database;
LoadListeners();
}
private void LoadListeners()
{
var ids = _redis.SetMembers("MessageIds");
_listener = new Dictionary<string, Dictionary<IEmote, ulong>>();
foreach (var id in ids)
_listener = new Dictionary<ulong, Dictionary<IEmote, ulong>>();
foreach (var row in _database.ReactionListeners)
{
var reactions = _redis.HashGetAll($"Messages:{id}");
var messageId = id;
var emojiDict = new Dictionary<IEmote, ulong>();
foreach (var r in reactions)
var messageId = row.MessageId.AsUlong();
if (!_listener.ContainsKey(messageId))
{
IEmote emote;
if (!r.Name.ToString().StartsWith('<'))
{
var emo = new Emoji(r.Name);
emote = emo;
}
else
{
emote = Emote.Parse(r.Name);
}
emojiDict.Add(emote, ulong.Parse(r.Value));
_listener.Add(messageId, new Dictionary<IEmote, ulong>());
}
_listener.Add(messageId, emojiDict);
_listener[messageId].Add(ConvertStringToEmote(row.Reaction), row.RoleId.AsUlong());
}
}
public bool IsListener(ulong id)
{
return _listener.ContainsKey(id.ToString());
return _listener.ContainsKey(id);
}
public Task AddRoleToListener(string messageId, IEmote emoji, IRole role)
public async Task AddRoleToListener(ulong messageId, ulong guildId, string emoji, IRole role)
{
if (_redis.SetMembers("MessageIds").All(e => e.ToString() != messageId))
{
_redis.SetAdd("MessageIds", messageId);
}
_redis.HashSet($"Messages:{messageId}", new[] {new HashEntry(emoji.ToString(), role.Id.ToString())});
_redis.SetAdd("MessageIds", messageId);
if (_listener.ContainsKey(messageId))
{
_listener[messageId].Add(emoji, role.Id);
return Task.CompletedTask;
}
var emote = ConvertStringToEmote(emoji);
var dict = new Dictionary<IEmote, ulong>
await _database.ReactionListeners.AddAsync(new ReactionListenerModel()
{
{emoji, role.Id}
};
_listener.Add(messageId, dict);
return Task.CompletedTask;
GuildId = guildId.AsLong(),
MessageId = messageId.AsLong(),
RoleId = role.Id.AsLong(),
Reaction = emoji
});
if (!_listener.ContainsKey(messageId))
{
_listener.Add(messageId, new Dictionary<IEmote, ulong>());
}
_listener[messageId].Add(emote, role.Id);
}
public async void RemoveRole(ISocketMessageChannel channel, SocketReaction reaction)
{
var roleId = _listener[reaction.MessageId.ToString()][reaction.Emote];
var roleId = _listener[reaction.MessageId][reaction.Emote];
var guild = (SocketGuildChannel) channel;
var role = guild.Guild.GetRole(roleId);
await ((IGuildUser) reaction.User.Value).RemoveRoleAsync(role);
@ -82,10 +68,19 @@ namespace Geekbot.net.Lib.ReactionListener
public async void GiveRole(ISocketMessageChannel channel, SocketReaction reaction)
{
var roleId = _listener[reaction.MessageId.ToString()][reaction.Emote];
var roleId = _listener[reaction.MessageId][reaction.Emote];
var guild = (SocketGuildChannel) channel;
var role = guild.Guild.GetRole(roleId);
await ((IGuildUser) reaction.User.Value).AddRoleAsync(role);
}
public IEmote ConvertStringToEmote(string emoji)
{
if (!emoji.StartsWith('<'))
{
return new Emoji(emoji);
}
return Emote.Parse(emoji);
}
}
}

View file

@ -14,6 +14,7 @@ using Geekbot.net.Lib.Converters;
using Geekbot.net.Lib.ErrorHandling;
using Geekbot.net.Lib.GlobalSettings;
using Geekbot.net.Lib.Highscores;
using Geekbot.net.Lib.KvInMemoryStore;
using Geekbot.net.Lib.Levels;
using Geekbot.net.Lib.Localization;
using Geekbot.net.Lib.Logger;
@ -125,6 +126,7 @@ namespace Geekbot.net
var mtgManaConverter = new MtgManaConverter();
var wikipediaClient = new WikipediaClient();
var randomNumberGenerator = new RandomNumberGenerator();
var kvMemoryStore = new KvInInMemoryStore();
_services.AddSingleton(_redis);
_services.AddSingleton(_userRepository);
@ -137,6 +139,7 @@ namespace Geekbot.net
_services.AddSingleton<IMtgManaConverter>(mtgManaConverter);
_services.AddSingleton<IWikipediaClient>(wikipediaClient);
_services.AddSingleton<IRandomNumberGenerator>(randomNumberGenerator);
_services.AddSingleton<IKvInMemoryStore>(kvMemoryStore);
_services.AddSingleton(_globalSettings);
_services.AddTransient<IHighscoreManager>(e => new HighscoreManager(_databaseInitializer.Initialize(), _userRepository));
_services.AddTransient(e => _databaseInitializer.Initialize());
@ -164,7 +167,7 @@ namespace Geekbot.net
_logger.Information(LogSource.Geekbot, "Registering Stuff");
var translationHandler = new TranslationHandler(_databaseInitializer.Initialize(), _logger);
var errorHandler = new ErrorHandler(_logger, translationHandler, _runParameters.ExposeErrors);
var reactionListener = new ReactionListener(_redis.Db);
var reactionListener = new ReactionListener(_databaseInitializer.Initialize());
_services.AddSingleton<IErrorHandler>(errorHandler);
_services.AddSingleton<ITranslationHandler>(translationHandler);
_services.AddSingleton(_client);