More restructuring

This commit is contained in:
Kwoth
2023-03-26 14:44:25 +02:00
parent 01f70f0a24
commit 308ba36b2e
319 changed files with 681 additions and 218 deletions

View File

@@ -1,78 +0,0 @@
#nullable disable
using Newtonsoft.Json;
namespace NadekoBot.Services;
public class SoundCloudApiService : INService
{
private readonly IHttpClientFactory _httpFactory;
public SoundCloudApiService(IHttpClientFactory factory)
=> _httpFactory = factory;
public async Task<SoundCloudVideo> ResolveVideoAsync(string url)
{
if (string.IsNullOrWhiteSpace(url))
throw new ArgumentNullException(nameof(url));
var response = string.Empty;
using (var http = _httpFactory.CreateClient())
{
response = await http.GetStringAsync($"https://scapi.nadeko.bot/resolve?url={url}");
}
var responseObj = JsonConvert.DeserializeObject<SoundCloudVideo>(response);
if (responseObj?.Kind != "track")
throw new InvalidOperationException("Url is either not a track, or it doesn't exist.");
return responseObj;
}
public async Task<SoundCloudVideo> GetVideoByQueryAsync(string query)
{
if (string.IsNullOrWhiteSpace(query))
throw new ArgumentNullException(nameof(query));
var response = string.Empty;
using (var http = _httpFactory.CreateClient())
{
response = await http.GetStringAsync(
new Uri($"https://scapi.nadeko.bot/tracks?q={Uri.EscapeDataString(query)}"));
}
var responseObj = JsonConvert.DeserializeObject<SoundCloudVideo[]>(response)
.FirstOrDefault(s => s.Streamable is true);
if (responseObj?.Kind != "track")
throw new InvalidOperationException("Query yielded no results.");
return responseObj;
}
}
public class SoundCloudVideo
{
public string Kind { get; set; } = string.Empty;
public long Id { get; set; } = 0;
public SoundCloudUser User { get; set; } = new();
public string Title { get; set; } = string.Empty;
public string FullName
=> User.Name + " - " + Title;
public bool? Streamable { get; set; } = false;
public int Duration { get; set; }
[JsonProperty("permalink_url")]
public string TrackLink { get; set; } = string.Empty;
[JsonProperty("artwork_url")]
public string ArtworkUrl { get; set; } = string.Empty;
}
public class SoundCloudUser
{
[JsonProperty("username")]
public string Name { get; set; }
}

View File

@@ -1,188 +0,0 @@
#nullable disable
using Humanizer.Localisation;
using NadekoBot.Common.ModuleBehaviors;
using System.Diagnostics;
namespace NadekoBot.Services;
public sealed class StatsService : IStatsService, IReadyExecutor, INService
{
public const string BOT_VERSION = "5.0.0-alpha1";
public string Author
=> "Kwoth#2452";
public double MessagesPerSecond
=> MessageCounter / GetUptime().TotalSeconds;
public long TextChannels
=> Interlocked.Read(ref textChannels);
public long VoiceChannels
=> Interlocked.Read(ref voiceChannels);
public long MessageCounter
=> Interlocked.Read(ref messageCounter);
public long CommandsRan
=> Interlocked.Read(ref commandsRan);
private readonly Process _currentProcess = Process.GetCurrentProcess();
private readonly DiscordSocketClient _client;
private readonly IBotCredentials _creds;
private readonly DateTime _started;
private long textChannels;
private long voiceChannels;
private long messageCounter;
private long commandsRan;
private readonly IHttpClientFactory _httpFactory;
public StatsService(
DiscordSocketClient client,
CommandHandler cmdHandler,
IBotCredentials creds,
IHttpClientFactory factory)
{
_client = client;
_creds = creds;
_httpFactory = factory;
_started = DateTime.UtcNow;
_client.MessageReceived += _ => Task.FromResult(Interlocked.Increment(ref messageCounter));
cmdHandler.CommandExecuted += (_, _) => Task.FromResult(Interlocked.Increment(ref commandsRan));
_client.ChannelCreated += c =>
{
_ = Task.Run(() =>
{
if (c is ITextChannel)
Interlocked.Increment(ref textChannels);
else if (c is IVoiceChannel)
Interlocked.Increment(ref voiceChannels);
});
return Task.CompletedTask;
};
_client.ChannelDestroyed += c =>
{
_ = Task.Run(() =>
{
if (c is ITextChannel)
Interlocked.Decrement(ref textChannels);
else if (c is IVoiceChannel)
Interlocked.Decrement(ref voiceChannels);
});
return Task.CompletedTask;
};
_client.GuildAvailable += g =>
{
_ = 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;
};
_client.JoinedGuild += g =>
{
_ = 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;
};
_client.GuildUnavailable += g =>
{
_ = 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;
};
_client.LeftGuild += g =>
{
_ = 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;
};
}
private void InitializeChannelCount()
{
var guilds = _client.Guilds;
textChannels = guilds.Sum(static g => g.Channels.Count(static cx => cx is ITextChannel));
voiceChannels = guilds.Sum(static g => g.Channels.Count(static cx => cx is IVoiceChannel));
}
public async Task OnReadyAsync()
{
InitializeChannelCount();
using var timer = new PeriodicTimer(TimeSpan.FromHours(1));
do
{
if (string.IsNullOrWhiteSpace(_creds.BotListToken))
continue;
try
{
using var http = _httpFactory.CreateClient();
using var content = new FormUrlEncodedContent(new Dictionary<string, string>
{
{ "shard_count", _creds.TotalShards.ToString() },
{ "shard_id", _client.ShardId.ToString() },
{ "server_count", _client.Guilds.Count().ToString() }
});
content.Headers.Clear();
content.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
http.DefaultRequestHeaders.Add("Authorization", _creds.BotListToken);
using var res = await http.PostAsync(
new Uri($"https://discordbots.org/api/bots/{_client.CurrentUser.Id}/stats"),
content);
}
catch (Exception ex)
{
Log.Error(ex, "Error in botlist post");
}
} while (await timer.WaitForNextTickAsync());
}
public TimeSpan GetUptime()
=> DateTime.UtcNow - _started;
public string GetUptimeString(string separator = ", ")
{
var time = GetUptime();
return time.Humanize(3, maxUnit: TimeUnit.Day, minUnit: TimeUnit.Minute);
}
public double GetPrivateMemoryMegabytes()
{
_currentProcess.Refresh();
return _currentProcess.PrivateMemorySize64 / 1.Megabytes().Bytes;
}
}