Partial progress on DBCache

This commit is contained in:
Noikoio 2017-11-01 16:24:22 -07:00
parent 2568b11c8e
commit 244debadf2
2 changed files with 145 additions and 29 deletions

View file

@ -47,7 +47,7 @@ namespace Noikoio.RegexBot.ConfigItem
_enabled = true; _enabled = true;
} }
public async Task<NpgsqlConnection> OpenConnectionAsync(ulong? guildId) private async Task<NpgsqlConnection> P_OpenConnectionAsync(ulong? guildId = null)
{ {
if (!Enabled) return null; if (!Enabled) return null;
@ -64,5 +64,24 @@ namespace Noikoio.RegexBot.ConfigItem
await db.OpenAsync(); await db.OpenAsync();
return db; return db;
} }
public Task<NpgsqlConnection> OpenConnectionAsync(ulong guildId) => P_OpenConnectionAsync(guildId);
public async Task CreateGuildSchemaAsync(ulong gid)
{
if (!Enabled) return;
const string cs = "CREATE SCHEMA IF NOT EXISTS {0}";
string sn = "g_" + gid.ToString();
using (var db = await P_OpenConnectionAsync())
{
using (var c = db.CreateCommand())
{
c.CommandText = string.Format(cs, sn);
await c.ExecuteNonQueryAsync();
}
}
}
} }
} }

View file

@ -1,9 +1,9 @@
using System; using Discord.WebSocket;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Discord.WebSocket;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Noikoio.RegexBot.ConfigItem;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Noikoio.RegexBot.Feature.DBCache namespace Noikoio.RegexBot.Feature.DBCache
{ {
@ -13,62 +13,159 @@ namespace Noikoio.RegexBot.Feature.DBCache
/// </summary> /// </summary>
class DBCache : BotFeature class DBCache : BotFeature
{ {
private readonly DatabaseConfig _db;
public override string Name => "Database cache"; public override string Name => "Database cache";
public DBCache(DiscordSocketClient client) : base(client) public DBCache(DiscordSocketClient client) : base(client)
{ {
_db = RegexBot.Config.Database;
client.GuildAvailable += Client_GuildAvailable; client.GuildAvailable += Client_GuildAvailable;
client.GuildUpdated += Client_GuildUpdated; client.GuildUpdated += Client_GuildUpdated;
client.GuildMemberUpdated += Client_GuildMemberUpdated; client.GuildMemberUpdated += Client_GuildMemberUpdated;
// it may not be necessary to handle JoinedGuild, as GuildAvailable still provides info
client.MessageReceived += Client_MessageReceived; client.MessageReceived += Client_MessageReceived;
client.MessageUpdated += Client_MessageUpdated; //client.MessageUpdated += Client_MessageUpdated;
} }
public override Task<object> ProcessConfiguration(JToken configSection) => Task.FromResult<object>(null); public override Task<object> ProcessConfiguration(JToken configSection) => Task.FromResult<object>(null);
#region Guild and user cache #region Event handling
/* Note: // Guild _and_ guild member information has become available
* We save information per guild in their own schemas named "g_NUM", where NUM is the Guild ID. private async Task Client_GuildAvailable(SocketGuild arg)
* {
* The creation of these schemas is handled within here, but we're possibly facing a short delay
* in the event that other events that we're listening for come in without a schema having been if (!_db.Enabled) return;
* created yet in which to put them in. await CreateCacheTables(arg.Id);
* Got to figure that out.
*/ await Task.Run(() => UpdateGuild(arg));
await Task.Run(() => UpdateGuildMember(arg.Id, arg.Users));
}
// Guild information has changed // Guild information has changed
private Task Client_GuildUpdated(SocketGuild arg1, SocketGuild arg2) private async Task Client_GuildUpdated(SocketGuild arg1, SocketGuild arg2)
{
if (!_db.Enabled) return;
throw new NotImplementedException();
}
// Guild member information has changed
private async Task Client_GuildMemberUpdated(SocketGuildUser arg1, SocketGuildUser arg2)
{
if (!_db.Enabled) return;
await Task.Run(() => UpdateGuildMember(arg2));
}
// A new message has been created
private async Task Client_MessageReceived(SocketMessage arg)
{
if (!_db.Enabled) return;
throw new NotImplementedException();
}
//private Task Client_MessageUpdated(Discord.Cacheable<Discord.IMessage, ulong> arg1, SocketMessage arg2, ISocketMessageChannel arg3)
/*
* Edited messages seem to retain their ID. This is a problem.
* The point of this message cache was to have another feature be able to relay
* both the previous and current message at once.
* For now: Do nothing on updated messages.
*/
#endregion
#region Table setup
const string TableGuild = "cache_guild";
const string TableUser = "cache_users";
const string TableMessage = "cache_messages";
private async Task CreateCacheTables(ulong gid)
{
/* Note:
* We save information per guild in their own schemas named "g_NUM", where NUM is the Guild ID.
*
* The creation of these schemas is handled within here, but we're possibly facing a short delay
* in the event that other events that we're listening for come in without a schema having been
* created yet in which to put them in.
* Got to figure that out.
*/
await _db.CreateGuildSchemaAsync(gid);
using (var db = await _db.OpenConnectionAsync(gid))
{
Task<int> c1, c2, c3;
// Uh... didn't think this through. For now this is a table that'll only ever have one column.
// Got to rethink this in particular.
using (var c = db.CreateCommand())
{
c.CommandText = "CREATE TABLE IF NOT EXISTS " + TableGuild + "("
+ "snowflake bigint primary key, "
+ "current_name text not null, "
+ "display_name text null"
+ ")";
c1 = c.ExecuteNonQueryAsync();
}
using (var c = db.CreateCommand())
{
c.CommandText = "CREATE TABLE IF NOT EXISTS " + TableUser + "("
+ "snowflake bigint primary key, "
+ "cache_date timestamptz not null, "
+ "username text not null, "
+ "discriminator text not null, "
+ "nickname text null, "
+ "avatar_url text null"
+ ")";
c2 = c.ExecuteNonQueryAsync();
}
using (var c = db.CreateCommand())
{
c.CommandText = "CREATE TABLE IF NOT EXISTS " + TableMessage + "("
+ "snowflake bigint primary key, "
+ "cache_date timestamptz not null, "
+ "author bigint not null"
+ ")";
c3 = c.ExecuteNonQueryAsync();
}
await c1;
await c2;
await c3;
}
}
#endregion
#region Guild and user cache updates
private async Task UpdateGuild(SocketGuild g)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
// Single guild member information has changed private async Task UpdateGuildMember(ulong gid, IEnumerable<SocketGuildUser> users)
private Task Client_GuildMemberUpdated(SocketGuildUser arg1, SocketGuildUser arg2)
{ {
// which is old and which is new?
throw new NotImplementedException(); throw new NotImplementedException();
} }
// All member data in a guild has become known private Task UpdateGuildMember(SocketGuildUser user)
private Task Client_GuildAvailable(SocketGuild arg)
{ {
throw new NotImplementedException(); var gid = user.Guild.Id;
var ml = new SocketGuildUser[] { user };
return UpdateGuildMember(gid, ml);
} }
#endregion #endregion
#region Message cache #region Message cache
private Task Client_MessageUpdated(Discord.Cacheable<Discord.IMessage, ulong> arg1, SocketMessage arg2, ISocketMessageChannel arg3) private async Task CacheMessage(SocketMessage msg)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
private Task Client_MessageReceived(SocketMessage arg) private async Task UpdateMessage(SocketMessage msg)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
#endregion #endregion
} }
} }