mirror of
https://github.com/NoiTheCat/BirthdayBot.git
synced 2024-11-21 13:54:36 +00:00
Implement per-shard reporting
This commit is contained in:
parent
2965dd0ea1
commit
2a15fc21c8
1 changed files with 65 additions and 25 deletions
|
@ -1,48 +1,88 @@
|
|||
using System;
|
||||
using System.Net;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BirthdayBot.BackgroundServices
|
||||
{
|
||||
class GuildStatistics : BackgroundService
|
||||
{
|
||||
private string DBotsToken { get; }
|
||||
private static readonly HttpClient _httpClient = new HttpClient();
|
||||
|
||||
public GuildStatistics(BirthdayBot instance) : base(instance) => DBotsToken = instance.Config.DBotsToken;
|
||||
public GuildStatistics(BirthdayBot instance) : base(instance) { }
|
||||
|
||||
public async override Task OnTick()
|
||||
{
|
||||
var count = BotInstance.DiscordClient.Guilds.Count;
|
||||
Log($"Currently in {count} guild(s).");
|
||||
var counts = GetGuildCounts();
|
||||
|
||||
await SendExternalStatistics(count);
|
||||
// Build this report
|
||||
int goodCount = 0;
|
||||
int badCount = 0;
|
||||
int goodShards = 0;
|
||||
int badShards = 0;
|
||||
foreach (var status in counts)
|
||||
{
|
||||
if (status.Item2.ShardConnected)
|
||||
{
|
||||
goodShards++;
|
||||
goodCount += status.Item2.GuildCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
badShards++;
|
||||
badCount += status.Item2.GuildCount;
|
||||
}
|
||||
}
|
||||
Log($"{goodShards} shard(s) connected, serving {goodCount} guild(s).");
|
||||
if (badShards != 0) Log($"{badShards} shard(s) unavailable, >={badCount} guild(s) will not count in the next report.");
|
||||
|
||||
// Report only connected shards (to not have fluctuating member numbers on initial startup)
|
||||
await SendExternalStatistics(counts.Where(t => t.Item2.ShardConnected), counts.Count());
|
||||
}
|
||||
|
||||
private struct ShardStatus
|
||||
{
|
||||
public bool ShardConnected;
|
||||
public int GuildCount;
|
||||
}
|
||||
|
||||
private IEnumerable<(int, ShardStatus)> GetGuildCounts()
|
||||
{
|
||||
var results = new List<(int, ShardStatus)>();
|
||||
var shards = BotInstance.DiscordClient.Shards;
|
||||
foreach (var shard in shards)
|
||||
{
|
||||
results.Add((shard.ShardId, new ShardStatus()
|
||||
{
|
||||
ShardConnected = shard.ConnectionState == Discord.ConnectionState.Connected,
|
||||
GuildCount = shard.Guilds.Count
|
||||
}));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send statistical information to external services.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Only Discord Bots is currently supported. No plans to support others any time soon.
|
||||
/// </remarks>
|
||||
async Task SendExternalStatistics(int guildCount)
|
||||
async Task SendExternalStatistics(IEnumerable<(int, ShardStatus)> shardStats, int totalShards)
|
||||
{
|
||||
var rptToken = BotInstance.Config.DBotsToken;
|
||||
if (rptToken == null) return;
|
||||
|
||||
const string apiUrl = "https://discord.bots.gg/api/v1/bots/{0}/stats";
|
||||
using (var client = new WebClient())
|
||||
var dbotsToken = BotInstance.Config.DBotsToken;
|
||||
if (dbotsToken != null)
|
||||
{
|
||||
var uri = new Uri(string.Format(apiUrl, BotInstance.DiscordClient.CurrentUser.Id));
|
||||
var data = $"{{ \"guildCount\": {guildCount} }}";
|
||||
client.Headers[HttpRequestHeader.Authorization] = rptToken;
|
||||
client.Headers[HttpRequestHeader.ContentType] = "application/json";
|
||||
try
|
||||
const string dBotsApiUrl = "https://discord.bots.gg/api/v1/bots/{0}/stats";
|
||||
const string Body = "{{ \"shardCount\": {0}, \"shardId\": {1}, \"guildCount\": {2} }}";
|
||||
var uri = new Uri(string.Format(dBotsApiUrl, BotInstance.DiscordClient.CurrentUser.Id));
|
||||
foreach (var shard in shardStats)
|
||||
{
|
||||
await client.UploadStringTaskAsync(uri, data);
|
||||
Log("Discord Bots: Report sent successfully.");
|
||||
} catch (WebException ex)
|
||||
{
|
||||
Log("Discord Bots: Encountered an error. " + ex.Message);
|
||||
var post = new HttpRequestMessage(HttpMethod.Post, uri);
|
||||
post.Headers.Add("Authorization", dbotsToken);
|
||||
var data = string.Format(Body, totalShards, shard.Item1, shard.Item2.GuildCount);
|
||||
post.Content = new StringContent(data, Encoding.UTF8, "application/json");
|
||||
await Task.Delay(80); // Discord Bots rate limit for this endpoint is 20 per second
|
||||
await _httpClient.SendAsync(post);
|
||||
Log("Discord Bots: Reports sent successfully.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue