NadekoBot/NadekoBot.Core/Services/Impl/StatsService.cs

229 lines
8.6 KiB
C#
Raw Normal View History

2016-08-18 21:00:54 +00:00
using Discord;
2017-01-15 01:08:14 +00:00
using Discord.WebSocket;
2016-08-18 21:00:54 +00:00
using NadekoBot.Extensions;
using System;
using System.Collections.Generic;
2017-02-16 20:49:30 +00:00
using System.Globalization;
2016-08-18 21:00:54 +00:00
using System.Linq;
using System.Net.Http;
2017-07-12 02:13:50 +00:00
using System.Runtime.InteropServices;
2017-07-12 01:39:44 +00:00
using System.Security.Cryptography;
using System.Text;
using System.Threading;
2016-08-18 21:00:54 +00:00
using System.Threading.Tasks;
using StackExchange.Redis;
2016-08-18 21:00:54 +00:00
namespace NadekoBot.Core.Services.Impl
2016-08-18 21:00:54 +00:00
{
public class StatsService : IStatsService
{
private readonly DiscordSocketClient _client;
2017-05-22 23:59:31 +00:00
private readonly IBotCredentials _creds;
private readonly DateTime _started;
2016-08-18 21:00:54 +00:00
2017-11-01 05:36:06 +00:00
public const string BotVersion = "2.3.2";
2016-08-18 21:00:54 +00:00
public string Author => "Kwoth#2560";
public string Library => "Discord.Net";
public string Heap => Math.Round((double)GC.GetTotalMemory(false) / 1.MiB(), 2)
.ToString(CultureInfo.InvariantCulture);
2017-01-08 07:56:28 +00:00
public double MessagesPerSecond => MessageCounter / GetUptime().TotalSeconds;
2017-01-07 17:32:33 +00:00
2017-02-16 20:49:30 +00:00
private long _textChannels;
public long TextChannels => Interlocked.Read(ref _textChannels);
private long _voiceChannels;
public long VoiceChannels => Interlocked.Read(ref _voiceChannels);
private long _messageCounter;
public long MessageCounter => Interlocked.Read(ref _messageCounter);
private long _commandsRan;
public long CommandsRan => Interlocked.Read(ref _commandsRan);
private readonly Timer _carbonitexTimer;
2017-07-12 01:39:44 +00:00
private readonly Timer _dataTimer;
private readonly ConnectionMultiplexer _redis;
2016-08-18 21:00:54 +00:00
public StatsService(DiscordSocketClient client, CommandHandler cmdHandler,
IBotCredentials creds, NadekoBot nadeko,
IDataCache cache)
2016-08-18 21:00:54 +00:00
{
2017-02-16 20:49:30 +00:00
_client = client;
2017-05-22 23:59:31 +00:00
_creds = creds;
_redis = cache.Redis;
2016-08-18 21:00:54 +00:00
2017-06-12 23:40:39 +00:00
_started = DateTime.UtcNow;
2017-02-16 20:49:30 +00:00
_client.MessageReceived += _ => Task.FromResult(Interlocked.Increment(ref _messageCounter));
cmdHandler.CommandExecuted += (_, e) => Task.FromResult(Interlocked.Increment(ref _commandsRan));
2016-08-18 21:00:54 +00:00
2017-02-16 20:49:30 +00:00
_client.ChannelCreated += (c) =>
2017-01-07 17:32:33 +00:00
{
var _ = Task.Run(() =>
{
if (c is ITextChannel)
Interlocked.Increment(ref _textChannels);
else if (c is IVoiceChannel)
Interlocked.Increment(ref _voiceChannels);
});
2017-01-15 01:28:33 +00:00
return Task.CompletedTask;
2017-01-07 17:32:33 +00:00
};
2017-02-16 20:49:30 +00:00
_client.ChannelDestroyed += (c) =>
2017-01-07 17:32:33 +00:00
{
var _ = Task.Run(() =>
{
if (c is ITextChannel)
Interlocked.Decrement(ref _textChannels);
else if (c is IVoiceChannel)
Interlocked.Decrement(ref _voiceChannels);
});
2017-02-16 20:49:30 +00:00
return Task.CompletedTask;
};
_client.GuildAvailable += (g) =>
{
var _ = Task.Run(() =>
{
var tc = g.Channels.Count(cx => cx is ITextChannel);
var vc = g.Channels.Count - tc;
Interlocked.Add(ref _textChannels, tc);
Interlocked.Add(ref _voiceChannels, vc);
});
return Task.CompletedTask;
};
2017-01-15 01:28:33 +00:00
2017-02-16 20:49:30 +00:00
_client.JoinedGuild += (g) =>
{
var _ = Task.Run(() =>
{
var tc = g.Channels.Count(cx => cx is ITextChannel);
var vc = g.Channels.Count - tc;
Interlocked.Add(ref _textChannels, tc);
Interlocked.Add(ref _voiceChannels, vc);
});
2017-01-15 01:28:33 +00:00
return Task.CompletedTask;
2017-01-07 17:32:33 +00:00
};
2017-02-16 20:49:30 +00:00
_client.GuildUnavailable += (g) =>
2017-01-07 17:32:33 +00:00
{
2017-02-16 20:49:30 +00:00
var _ = Task.Run(() =>
{
var tc = g.Channels.Count(cx => cx is ITextChannel);
var vc = g.Channels.Count - tc;
Interlocked.Add(ref _textChannels, -tc);
Interlocked.Add(ref _voiceChannels, -vc);
});
2017-01-15 01:28:33 +00:00
return Task.CompletedTask;
2017-01-07 17:32:33 +00:00
};
2017-02-16 20:49:30 +00:00
_client.LeftGuild += (g) =>
2017-01-07 17:41:10 +00:00
{
2017-02-16 20:49:30 +00:00
var _ = Task.Run(() =>
{
var tc = g.Channels.Count(cx => cx is ITextChannel);
var vc = g.Channels.Count - tc;
Interlocked.Add(ref _textChannels, -tc);
Interlocked.Add(ref _voiceChannels, -vc);
});
2017-01-15 01:28:33 +00:00
return Task.CompletedTask;
2017-01-07 17:41:10 +00:00
};
if (_client.ShardId == 0)
{
_carbonitexTimer = new Timer(async (state) =>
{
if (string.IsNullOrWhiteSpace(_creds.CarbonKey))
return;
try
{
using (var http = new HttpClient())
{
using (var content = new FormUrlEncodedContent(
new Dictionary<string, string> {
{ "servercount", nadeko.GuildCount.ToString() },
{ "key", _creds.CarbonKey }}))
{
content.Headers.Clear();
content.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
await http.PostAsync("https://www.carbonitex.net/discord/data/botdata.php", content).ConfigureAwait(false);
}
}
}
catch
{
// ignored
}
}, null, TimeSpan.FromHours(1), TimeSpan.FromHours(1));
2017-07-12 01:39:44 +00:00
2017-07-12 02:13:50 +00:00
var platform = "other";
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
platform = "linux";
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
platform = "osx";
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
platform = "windows";
2017-07-12 01:39:44 +00:00
_dataTimer = new Timer(async (state) =>
{
try
{
using (var http = new HttpClient())
{
using (var content = new FormUrlEncodedContent(
new Dictionary<string, string> {
{ "id", string.Concat(MD5.Create().ComputeHash(Encoding.ASCII.GetBytes(_creds.ClientId.ToString())).Select(x => x.ToString("X2"))) },
{ "guildCount", nadeko.GuildCount.ToString() },
2017-07-12 02:13:50 +00:00
{ "version", BotVersion },
{ "platform", platform }}))
2017-07-12 01:39:44 +00:00
{
content.Headers.Clear();
content.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
await http.PostAsync("https://selfstats.nadekobot.me/", content).ConfigureAwait(false);
}
}
}
catch
{
2017-07-12 13:38:34 +00:00
// ignored
}
}, null, TimeSpan.FromSeconds(1), TimeSpan.FromHours(1));
}
2016-08-18 21:00:54 +00:00
}
2017-01-15 01:08:14 +00:00
public void Initialize()
{
2017-04-15 00:54:19 +00:00
var guilds = _client.Guilds.ToArray();
2017-02-14 13:30:21 +00:00
_textChannels = guilds.Sum(g => g.Channels.Count(cx => cx is ITextChannel));
2017-01-15 01:08:14 +00:00
_voiceChannels = guilds.Sum(g => g.Channels.Count) - _textChannels;
}
2016-12-17 04:09:04 +00:00
public Task<string> Print()
{
2017-04-15 00:54:19 +00:00
SocketSelfUser curUser;
while ((curUser = _client.CurrentUser) == null) Task.Delay(1000).ConfigureAwait(false);
2016-12-17 04:09:04 +00:00
return Task.FromResult($@"
Author: [{Author}] | Library: [{Library}]
2016-11-19 12:22:49 +00:00
Bot Version: [{BotVersion}]
2016-11-19 17:12:26 +00:00
Bot ID: {curUser.Id}
2017-05-22 23:59:31 +00:00
Owner ID(s): {string.Join(", ", _creds.OwnerIds)}
2016-11-19 12:22:49 +00:00
Uptime: {GetUptimeString()}
2017-04-15 00:54:19 +00:00
Servers: {_client.Guilds.Count} | TextChannels: {TextChannels} | VoiceChannels: {VoiceChannels}
Commands Ran this session: {CommandsRan}
2016-12-17 04:09:04 +00:00
Messages: {MessageCounter} [{MessagesPerSecond:F2}/sec] Heap: [{Heap} MB]");
}
2016-08-18 21:00:54 +00:00
public TimeSpan GetUptime() =>
2017-06-12 23:40:39 +00:00
DateTime.UtcNow - _started;
2016-08-18 21:00:54 +00:00
public string GetUptimeString(string separator = ", ")
2016-08-18 21:00:54 +00:00
{
var time = GetUptime();
return $"{time.Days} days{separator}{time.Hours} hours{separator}{time.Minutes} minutes";
2016-08-18 21:00:54 +00:00
}
}
}