mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-10 17:28:27 -04:00
Killed history
This commit is contained in:
77
NadekoBot.Core/Services/Common/GreetGrouper.cs
Normal file
77
NadekoBot.Core/Services/Common/GreetGrouper.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace NadekoBot.Core.Services
|
||||
{
|
||||
public class GreetGrouper<T>
|
||||
{
|
||||
private readonly Dictionary<ulong, HashSet<T>> group;
|
||||
private readonly object locker = new object();
|
||||
|
||||
public GreetGrouper()
|
||||
{
|
||||
group = new Dictionary<ulong, HashSet<T>>();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a group, if group already exists, adds the specified user
|
||||
/// </summary>
|
||||
/// <param name="guildId">Id of the server for which to create group for</param>
|
||||
/// <param name="toAddIfExists">User to add if group already exists</param>
|
||||
/// <returns></returns>
|
||||
public bool CreateOrAdd(ulong guildId, T toAddIfExists)
|
||||
{
|
||||
lock (locker)
|
||||
{
|
||||
if (group.TryGetValue(guildId, out var list))
|
||||
{
|
||||
list.Add(toAddIfExists);
|
||||
return false;
|
||||
}
|
||||
|
||||
group[guildId] = new HashSet<T>();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove the specified amount of items from the group. If all items are removed, group will be removed.
|
||||
/// </summary>
|
||||
/// <param name="guildId">Id of the group</param>
|
||||
/// <param name="count">Maximum number of items to retrieve</param>
|
||||
/// <param name="items">Items retrieved</param>
|
||||
/// <returns>Whether the group has no more items left and is deleted</returns>
|
||||
public bool ClearGroup(ulong guildId, int count, out IEnumerable<T> items)
|
||||
{
|
||||
lock (locker)
|
||||
{
|
||||
if (group.TryGetValue(guildId, out var set))
|
||||
{
|
||||
// if we want more than there are, return everything
|
||||
if (count >= set.Count)
|
||||
{
|
||||
items = set;
|
||||
group.Remove(guildId);
|
||||
return true;
|
||||
}
|
||||
|
||||
// if there are more in the group than what's needed
|
||||
// take the requested number, remove them from the set
|
||||
// and return them
|
||||
var toReturn = set.TakeWhile(item => count-- != 0).ToList();
|
||||
foreach (var item in toReturn)
|
||||
set.Remove(item);
|
||||
|
||||
items = toReturn;
|
||||
// returning falsemeans group is not yet deleted
|
||||
// because there are items left
|
||||
return false;
|
||||
}
|
||||
|
||||
items = Enumerable.Empty<T>();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
141
NadekoBot.Core/Services/Common/ImageLoader.cs
Normal file
141
NadekoBot.Core/Services/Common/ImageLoader.cs
Normal file
@@ -0,0 +1,141 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using StackExchange.Redis;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Serilog;
|
||||
|
||||
namespace NadekoBot.Core.Services.Common
|
||||
{
|
||||
public class ImageLoader
|
||||
{
|
||||
private readonly HttpClient _http;
|
||||
private readonly ConnectionMultiplexer _con;
|
||||
|
||||
public Func<string, RedisKey> GetKey { get; }
|
||||
|
||||
private IDatabase _db => _con.GetDatabase();
|
||||
|
||||
private readonly List<Task<KeyValuePair<RedisKey, RedisValue>>> uriTasks = new List<Task<KeyValuePair<RedisKey, RedisValue>>>();
|
||||
|
||||
public ImageLoader(HttpClient http, ConnectionMultiplexer con, Func<string, RedisKey> getKey)
|
||||
{
|
||||
_http = http;
|
||||
_con = con;
|
||||
GetKey = getKey;
|
||||
}
|
||||
|
||||
private async Task<byte[]> GetImageData(Uri uri)
|
||||
{
|
||||
if (uri.IsFile)
|
||||
{
|
||||
try
|
||||
{
|
||||
var bytes = await File.ReadAllBytesAsync(uri.LocalPath);
|
||||
return bytes;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warning(ex, "Failed reading image bytes");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return await _http.GetByteArrayAsync(uri);
|
||||
}
|
||||
}
|
||||
|
||||
async Task HandleJArray(JArray arr, string key)
|
||||
{
|
||||
var tasks = arr.Where(x => x.Type == JTokenType.String)
|
||||
.Select(async x =>
|
||||
{
|
||||
try
|
||||
{
|
||||
return await GetImageData((Uri)x).ConfigureAwait(false);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Log.Error("Error retreiving image for key {Key}: {Data}", key, x);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
byte[][] vals = Array.Empty<byte[]>();
|
||||
vals = await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||
if (vals.Any(x => x == null))
|
||||
vals = vals.Where(x => x != null).ToArray();
|
||||
|
||||
await _db.KeyDeleteAsync(GetKey(key)).ConfigureAwait(false);
|
||||
await _db.ListRightPushAsync(GetKey(key),
|
||||
vals.Where(x => x != null)
|
||||
.Select(x => (RedisValue)x)
|
||||
.ToArray()).ConfigureAwait(false);
|
||||
|
||||
if (arr.Count != vals.Length)
|
||||
{
|
||||
Log.Information("{2}/{1} URIs for the key '{0}' have been loaded. Some of the supplied URIs are either unavailable or invalid.", key, arr.Count, vals.Count());
|
||||
}
|
||||
}
|
||||
|
||||
async Task<KeyValuePair<RedisKey, RedisValue>> HandleUri(Uri uri, string key)
|
||||
{
|
||||
try
|
||||
{
|
||||
RedisValue data = await GetImageData(uri).ConfigureAwait(false);
|
||||
return new KeyValuePair<RedisKey, RedisValue>(GetKey(key), data);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Log.Information("Setting '{0}' image failed. The URI you provided is either unavailable or invalid.", key.ToLowerInvariant());
|
||||
return new KeyValuePair<RedisKey, RedisValue>("", "");
|
||||
}
|
||||
}
|
||||
|
||||
Task HandleJObject(JObject obj, string parent = "")
|
||||
{
|
||||
string GetParentString()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(parent))
|
||||
return "";
|
||||
else
|
||||
return parent + "_";
|
||||
}
|
||||
List<Task> tasks = new List<Task>();
|
||||
Task t;
|
||||
// go through all of the kvps in the object
|
||||
foreach (var kvp in obj)
|
||||
{
|
||||
// if it's a JArray, resole it using jarray method which will
|
||||
// return task<byte[][]> aka an array of all images' bytes
|
||||
if (kvp.Value.Type == JTokenType.Array)
|
||||
{
|
||||
t = HandleJArray((JArray)kvp.Value, GetParentString() + kvp.Key);
|
||||
tasks.Add(t);
|
||||
}
|
||||
else if (kvp.Value.Type == JTokenType.String)
|
||||
{
|
||||
var uriTask = HandleUri((Uri)kvp.Value, GetParentString() + kvp.Key);
|
||||
uriTasks.Add(uriTask);
|
||||
}
|
||||
else if (kvp.Value.Type == JTokenType.Object)
|
||||
{
|
||||
t = HandleJObject((JObject)kvp.Value, GetParentString() + kvp.Key);
|
||||
tasks.Add(t);
|
||||
}
|
||||
}
|
||||
return Task.WhenAll(tasks);
|
||||
}
|
||||
|
||||
public async Task LoadAsync(JObject obj)
|
||||
{
|
||||
await HandleJObject(obj).ConfigureAwait(false);
|
||||
var results = await Task.WhenAll(uriTasks).ConfigureAwait(false);
|
||||
await _db.StringSetAsync(results.Where(x => x.Key != "").ToArray()).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
52
NadekoBot.Core/Services/Common/RedisImageArray.cs
Normal file
52
NadekoBot.Core/Services/Common/RedisImageArray.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using StackExchange.Redis;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace NadekoBot.Core.Services.Common
|
||||
{
|
||||
public sealed class RedisImageArray : IReadOnlyList<byte[]>
|
||||
{
|
||||
public byte[] this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (index < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
|
||||
return _con.GetDatabase().ListGetByIndex(_key, index);
|
||||
}
|
||||
}
|
||||
|
||||
public int Count => _data.IsValueCreated
|
||||
? _data.Value.Length
|
||||
: (int)_con.GetDatabase().ListLength(_key);
|
||||
|
||||
private readonly ConnectionMultiplexer _con;
|
||||
private readonly string _key;
|
||||
|
||||
private readonly Lazy<byte[][]> _data;
|
||||
|
||||
public RedisImageArray(string key, ConnectionMultiplexer con)
|
||||
{
|
||||
_con = con;
|
||||
_key = key;
|
||||
_data = new Lazy<byte[][]>(() => _con.GetDatabase().ListRange(_key).Select(x => (byte[])x).ToArray(), true);
|
||||
}
|
||||
|
||||
public IEnumerator<byte[]> GetEnumerator()
|
||||
{
|
||||
var actualData = _data.Value;
|
||||
for (int i = 0; i < actualData.Length; i++)
|
||||
{
|
||||
yield return actualData[i];
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return _data.Value.GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user