using BirthdayBot.Data;
namespace BirthdayBot.BackgroundServices;
///
/// Proactively fills the user cache for guilds in which any birthday data already exists.
///
class AutoUserDownload : BackgroundService {
public AutoUserDownload(ShardInstance instance) : base(instance) { }
public override async Task OnTick(int tickCount, CancellationToken token) {
foreach (var guild in ShardInstance.DiscordClient.Guilds) {
// Has the potential to disconnect while in the middle of processing.
if (ShardInstance.DiscordClient.ConnectionState != ConnectionState.Connected) return;
// Determine if there is action to be taken...
if (!guild.HasAllMembers && await GuildUserAnyAsync(guild.Id).ConfigureAwait(false)) {
await guild.DownloadUsersAsync().ConfigureAwait(false); // This is already on a separate thread; no need to Task.Run
await Task.Delay(200, CancellationToken.None).ConfigureAwait(false); // Must delay, or else it seems to hang...
}
}
}
///
/// Determines if the user database contains any entries corresponding to this guild.
///
/// True if any entries exist.
private static async Task GuildUserAnyAsync(ulong guildId) {
using var db = await Database.OpenConnectionAsync().ConfigureAwait(false);
using var c = db.CreateCommand();
c.CommandText = $"select true from {GuildUserConfiguration.BackingTable} where guild_id = @Gid limit 1";
c.Parameters.Add("@Gid", NpgsqlTypes.NpgsqlDbType.Bigint).Value = (long)guildId;
await c.PrepareAsync(CancellationToken.None).ConfigureAwait(false);
using var r = await c.ExecuteReaderAsync(CancellationToken.None).ConfigureAwait(false);
return r.Read();
}
}