2021-02-02 06:31:24 +00:00
|
|
|
|
using BirthdayBot.Data;
|
2021-10-14 04:36:00 +00:00
|
|
|
|
using Discord;
|
2021-02-02 06:31:24 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
2021-10-14 04:36:00 +00:00
|
|
|
|
namespace BirthdayBot.BackgroundServices;
|
2021-02-02 06:31:24 +00:00
|
|
|
|
|
2021-10-14 04:36:00 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Rather than use up unnecessary resources by auto-downloading the user list in -every-
|
|
|
|
|
/// server we're in, this service checks if fetching the user list is warranted for each
|
|
|
|
|
/// guild before proceeding to request it.
|
|
|
|
|
/// </summary>
|
|
|
|
|
class SelectiveAutoUserDownload : BackgroundService {
|
|
|
|
|
private readonly HashSet<ulong> _fetchRequests = new();
|
2021-02-02 06:31:24 +00:00
|
|
|
|
|
2021-10-14 04:36:00 +00:00
|
|
|
|
public SelectiveAutoUserDownload(ShardInstance instance) : base(instance) { }
|
2021-02-02 06:31:24 +00:00
|
|
|
|
|
2021-10-15 01:55:04 +00:00
|
|
|
|
public override async Task OnTick(int tickCount, CancellationToken token) {
|
2021-10-14 04:36:00 +00:00
|
|
|
|
IEnumerable<ulong> requests;
|
|
|
|
|
lock (_fetchRequests) {
|
|
|
|
|
requests = _fetchRequests.ToArray();
|
|
|
|
|
_fetchRequests.Clear();
|
2021-02-02 06:31:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-10-14 04:36:00 +00:00
|
|
|
|
foreach (var guild in ShardInstance.DiscordClient.Guilds) {
|
2021-10-15 01:55:04 +00:00
|
|
|
|
// Has the potential to disconnect while in the middle of processing.
|
|
|
|
|
if (ShardInstance.DiscordClient.ConnectionState != ConnectionState.Connected) return;
|
2021-10-14 04:36:00 +00:00
|
|
|
|
|
|
|
|
|
// Determine if there is action to be taken...
|
|
|
|
|
if (guild.HasAllMembers) continue;
|
|
|
|
|
if (requests.Contains(guild.Id) || await GuildUserAnyAsync(guild.Id).ConfigureAwait(false)) {
|
|
|
|
|
await guild.DownloadUsersAsync().ConfigureAwait(false);
|
|
|
|
|
// Must delay after a download request. Seems to hang indefinitely otherwise.
|
|
|
|
|
await Task.Delay(300, CancellationToken.None).ConfigureAwait(false);
|
2021-02-02 06:31:24 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2021-10-14 04:36:00 +00:00
|
|
|
|
}
|
2021-02-02 06:31:24 +00:00
|
|
|
|
|
2021-10-14 04:36:00 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Determines if the user database contains any entries corresponding to this guild.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>True if any entries exist.</returns>
|
|
|
|
|
private static async Task<bool> 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();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void RequestDownload(ulong guildId) {
|
|
|
|
|
lock (_fetchRequests) _fetchRequests.Add(guildId);
|
2021-02-02 06:31:24 +00:00
|
|
|
|
}
|
|
|
|
|
}
|