Added channel cache to EntityCache
This commit is contained in:
parent
7e55acb5e6
commit
e5758e9aac
5 changed files with 186 additions and 10 deletions
154
EntityCache/CacheChannel.cs
Normal file
154
EntityCache/CacheChannel.cs
Normal file
|
@ -0,0 +1,154 @@
|
|||
using Discord.WebSocket;
|
||||
using Npgsql;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Noikoio.RegexBot.EntityCache
|
||||
{
|
||||
class CacheChannel
|
||||
{
|
||||
readonly ulong _channelId;
|
||||
readonly ulong _guildId;
|
||||
readonly DateTimeOffset _cacheDate;
|
||||
readonly string _channelName;
|
||||
|
||||
private CacheChannel(SocketGuildChannel c)
|
||||
{
|
||||
_channelId = c.Id;
|
||||
_guildId = c.Guild.Id;
|
||||
_cacheDate = DateTimeOffset.UtcNow;
|
||||
_channelName = c.Name;
|
||||
}
|
||||
|
||||
// Double-check SqlHelper if making changes to this constant
|
||||
const string QueryColumns = "channel_id, guild_id, cache_date, channel_name";
|
||||
private CacheChannel(DbDataReader r)
|
||||
{
|
||||
// Double-check ordinals if making changes to QueryColumns
|
||||
unchecked
|
||||
{
|
||||
_channelId = (ulong)r.GetInt64(0);
|
||||
_guildId = (ulong)r.GetInt64(1);
|
||||
}
|
||||
_cacheDate = r.GetDateTime(2).ToUniversalTime();
|
||||
_channelName = r.GetString(3);
|
||||
}
|
||||
|
||||
#region Queries
|
||||
// Accessible by EntityCache. Documentation is there.
|
||||
internal static async Task<CacheChannel> QueryAsync(DiscordSocketClient c, ulong guild, ulong channel)
|
||||
{
|
||||
// Local cache search
|
||||
var lresult = LocalQueryAsync(c, guild, channel);
|
||||
if (lresult != null) return lresult;
|
||||
|
||||
// Database cache search
|
||||
var db = await RegexBot.Config.GetOpenDatabaseConnectionAsync();
|
||||
if (db == null) return null; // Database not available for query.
|
||||
return await DbQueryAsync(db, guild, channel);
|
||||
}
|
||||
|
||||
private static CacheChannel LocalQueryAsync(DiscordSocketClient c, ulong guild, ulong channel)
|
||||
{
|
||||
var ch = c.GetGuild(guild)?.GetChannel(channel);
|
||||
if (ch == null) return null;
|
||||
return new CacheChannel(ch);
|
||||
}
|
||||
private static async Task<CacheChannel> DbQueryAsync(NpgsqlConnection db, ulong guild, ulong channel)
|
||||
{
|
||||
using (db)
|
||||
{
|
||||
using (var c = db.CreateCommand())
|
||||
{
|
||||
c.CommandText = $"SELECT {QueryColumns} from {SqlHelper.TableTextChannel} WHERE "
|
||||
+ "channel_id = @Cid AND guild_id = @Gid";
|
||||
c.Parameters.Add("@Cid", NpgsqlTypes.NpgsqlDbType.Bigint).Value = channel;
|
||||
c.Parameters.Add("@Gid", NpgsqlTypes.NpgsqlDbType.Bigint).Value = guild;
|
||||
c.Prepare();
|
||||
using (var r = await c.ExecuteReaderAsync())
|
||||
{
|
||||
if (await r.ReadAsync())
|
||||
{
|
||||
return new CacheChannel(r);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
// Accessible by EntityCache. Documentation is there.
|
||||
internal static async Task<IEnumerable<CacheChannel>> QueryAsync(DiscordSocketClient c, ulong guild, string search)
|
||||
{
|
||||
// Is search just a number? Assume ID, pass it on to the correct place.
|
||||
if (ulong.TryParse(search, out var presult))
|
||||
{
|
||||
var r = await QueryAsync(c, guild, presult);
|
||||
if (r == null) return new CacheChannel[0];
|
||||
else return new CacheChannel[] { r };
|
||||
}
|
||||
|
||||
// Split leading # from name, if exists
|
||||
if (search.Length > 0 && search[0] == '#') search = search.Substring(1);
|
||||
|
||||
// Local cache search
|
||||
var lresult = LocalQueryAsync(c, guild, search);
|
||||
if (lresult.Count() != 0) return lresult;
|
||||
|
||||
// Database cache search
|
||||
var db = await RegexBot.Config.GetOpenDatabaseConnectionAsync();
|
||||
if (db == null) return new CacheChannel[0];
|
||||
return await DbQueryAsync(db, guild, search);
|
||||
}
|
||||
|
||||
private static IEnumerable<CacheChannel> LocalQueryAsync(DiscordSocketClient c, ulong guild, string search)
|
||||
{
|
||||
var g = c.GetGuild(guild);
|
||||
if (g == null) return new CacheChannel[0];
|
||||
|
||||
var qresult = g.Channels
|
||||
.Where(i => string.Equals(i.Name, search, StringComparison.InvariantCultureIgnoreCase));
|
||||
var result = new List<CacheChannel>();
|
||||
foreach (var item in qresult)
|
||||
{
|
||||
result.Add(new CacheChannel(item));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static async Task<IEnumerable<CacheChannel>> DbQueryAsync(NpgsqlConnection db, ulong guild, string search)
|
||||
{
|
||||
var result = new List<CacheChannel>();
|
||||
|
||||
using (db)
|
||||
{
|
||||
using (var c = db.CreateCommand())
|
||||
{
|
||||
c.CommandText = $"SELECT {QueryColumns} FROM {SqlHelper.TableTextChannel} WHERE"
|
||||
+ " name = lower(@NameSearch)" // all channel names presumed to be lowercase already
|
||||
+ " ORDER BY cache_date desc, name";
|
||||
c.Parameters.Add("@NameSearch", NpgsqlTypes.NpgsqlDbType.Text).Value = search;
|
||||
c.Prepare();
|
||||
|
||||
using (var r = await c.ExecuteReaderAsync())
|
||||
{
|
||||
while (await r.ReadAsync())
|
||||
{
|
||||
result.Add(new CacheChannel(r));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -102,7 +102,7 @@ namespace Noikoio.RegexBot.EntityCache
|
|||
// Database cache search
|
||||
var db = await RegexBot.Config.GetOpenDatabaseConnectionAsync();
|
||||
if (db == null) return null; // Database not available for query.
|
||||
using (db) return await DbQueryAsync(db, guild, user);
|
||||
return await DbQueryAsync(db, guild, user);
|
||||
}
|
||||
|
||||
private static CacheUser LocalQueryAsync(DiscordSocketClient c, ulong guild, ulong user)
|
||||
|
@ -175,8 +175,8 @@ namespace Noikoio.RegexBot.EntityCache
|
|||
|
||||
// Database cache search
|
||||
var db = await RegexBot.Config.GetOpenDatabaseConnectionAsync();
|
||||
if (db == null) return null; // Database not available for query.
|
||||
using (db) return await DbQueryAsync(db, guild, name, disc);
|
||||
if (db == null) return new CacheUser[0]; // Database not available for query.
|
||||
return await DbQueryAsync(db, guild, name, disc);
|
||||
}
|
||||
|
||||
private static IEnumerable<CacheUser> LocalQueryAsync(DiscordSocketClient c, ulong guild, string name, string disc)
|
||||
|
@ -210,7 +210,7 @@ namespace Noikoio.RegexBot.EntityCache
|
|||
{
|
||||
var result = new List<CacheUser>();
|
||||
|
||||
using (db = await RegexBot.Config.GetOpenDatabaseConnectionAsync())
|
||||
using (db)
|
||||
{
|
||||
using (var c = db.CreateCommand())
|
||||
{
|
||||
|
|
|
@ -11,11 +11,11 @@ namespace Noikoio.RegexBot.EntityCache
|
|||
/// The function of this module should be transparent to the user, and thus no configuration is needed.
|
||||
/// This module should be initialized BEFORE any other modules that make use of the entity cache.
|
||||
/// </summary>
|
||||
class Module : BotModule
|
||||
class ECModule : BotModule
|
||||
{
|
||||
private readonly DatabaseConfig _db;
|
||||
|
||||
public Module(DiscordSocketClient client) : base(client)
|
||||
public ECModule(DiscordSocketClient client) : base(client)
|
||||
{
|
||||
if (RegexBot.Config.DatabaseAvailable)
|
||||
{
|
|
@ -24,15 +24,37 @@ namespace Noikoio.RegexBot.EntityCache
|
|||
/// Does not handle exceptions that may occur.
|
||||
/// </summary>
|
||||
/// <returns>Null on no result.</returns>
|
||||
internal static Task<CacheUser> QueryAsync(ulong guild, ulong user)
|
||||
internal static Task<CacheUser> QueryUserAsync(ulong guild, ulong user)
|
||||
=> CacheUser.QueryAsync(_client, guild, user);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to look up the user given a search string.
|
||||
/// This string looks up case-insensitive, exact matches of nicknames and usernames.
|
||||
/// </summary>
|
||||
/// <returns>An <see cref="IEnumerable{T}"/> containing zero or more query results, sorted by cache date.</returns>
|
||||
internal static Task<IEnumerable<CacheUser>> QueryAsync(ulong guild, string search)
|
||||
/// <returns>
|
||||
/// An <see cref="IEnumerable{T}"/> containing zero or more query results,
|
||||
/// sorted by cache date from most to least recent.
|
||||
/// </returns>
|
||||
internal static Task<IEnumerable<CacheUser>> QueryUserAsync(ulong guild, string search)
|
||||
=> CacheUser.QueryAsync(_client, guild, search);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to query for an exact result with the given parameters.
|
||||
/// Does not handle exceptions that may occur.
|
||||
/// </summary>
|
||||
/// <returns>Null on no result.</returns>
|
||||
internal static Task<CacheChannel> QueryChannelAsync(ulong guild, ulong channel)
|
||||
=> CacheChannel.QueryAsync(_client, guild, channel);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to look up the channel given a search string.
|
||||
/// This string looks up exact matches of the given name, regardless of if the channel has been deleted.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// An <see cref="IEnumerable{T}"/> containing zero or more query results,
|
||||
/// sorted by cache date from most to least recent.
|
||||
/// </returns>
|
||||
internal static Task<IEnumerable<CacheChannel>> QueryChannelAsync(ulong guild, string search)
|
||||
=> CacheChannel.QueryAsync(_client, guild, search);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ namespace Noikoio.RegexBot
|
|||
new Module.EntryAutoRole.EntryAutoRole(_client),
|
||||
|
||||
// EntityCache loads before anything using it
|
||||
new EntityCache.Module(_client),
|
||||
new EntityCache.ECModule(_client),
|
||||
new Module.ModLogs.ModLogs(_client)
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue