fixed music up a lot, caching stats every 5 seconds.
This commit is contained in:
parent
0c8934f12f
commit
805c592fff
@ -14,7 +14,7 @@ namespace NadekoBot.Classes.Music {
|
|||||||
public List<StreamRequest> SongQueue = new List<StreamRequest>();
|
public List<StreamRequest> SongQueue = new List<StreamRequest>();
|
||||||
public StreamRequest CurrentSong;
|
public StreamRequest CurrentSong;
|
||||||
|
|
||||||
public bool IsPaused { get; internal set; }
|
public bool IsPaused { get; internal set; } = false;
|
||||||
public IAudioClient VoiceClient;
|
public IAudioClient VoiceClient;
|
||||||
|
|
||||||
private readonly object _voiceLock = new object();
|
private readonly object _voiceLock = new object();
|
||||||
@ -23,13 +23,16 @@ namespace NadekoBot.Classes.Music {
|
|||||||
Task.Run(async () => {
|
Task.Run(async () => {
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
|
lock (_voiceLock) {
|
||||||
if (CurrentSong == null) {
|
if (CurrentSong == null) {
|
||||||
if (SongQueue.Count > 0)
|
if (SongQueue.Count > 0)
|
||||||
LoadNextSong();
|
LoadNextSong();
|
||||||
|
|
||||||
} else if (CurrentSong.State == StreamState.Completed) {
|
} else if (CurrentSong.State == StreamState.Completed || NextSong) {
|
||||||
|
NextSong = false;
|
||||||
LoadNextSong();
|
LoadNextSong();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Console.WriteLine("Bug in music task run. " + e);
|
Console.WriteLine("Bug in music task run. " + e);
|
||||||
}
|
}
|
||||||
@ -43,38 +46,50 @@ namespace NadekoBot.Classes.Music {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void LoadNextSong() {
|
public void LoadNextSong() {
|
||||||
Console.WriteLine("Loading next song.");
|
|
||||||
lock (_voiceLock) {
|
lock (_voiceLock) {
|
||||||
if (SongQueue.Count == 0) {
|
CurrentSong?.Stop();
|
||||||
CurrentSong = null;
|
CurrentSong = null;
|
||||||
return;
|
if (SongQueue.Count == 0) return;
|
||||||
}
|
|
||||||
CurrentSong = SongQueue[0];
|
CurrentSong = SongQueue[0];
|
||||||
SongQueue.RemoveAt(0);
|
SongQueue.RemoveAt(0);
|
||||||
}
|
}
|
||||||
CurrentSong.Start();
|
|
||||||
|
|
||||||
Console.WriteLine("Starting next song.");
|
try {
|
||||||
|
CurrentSong?.Start();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Console.WriteLine($"Starting failed: {ex}");
|
||||||
|
CurrentSong?.Stop();
|
||||||
|
CurrentSong = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void RemoveAllSongs() {
|
internal void Stop() {
|
||||||
lock (_voiceLock) {
|
lock (_voiceLock) {
|
||||||
foreach (var kvp in SongQueue) {
|
foreach (var kvp in SongQueue) {
|
||||||
if(kvp != null)
|
if(kvp != null)
|
||||||
kvp.Cancel();
|
kvp.Cancel();
|
||||||
}
|
}
|
||||||
SongQueue.Clear();
|
SongQueue.Clear();
|
||||||
|
LoadNextSong();
|
||||||
VoiceClient.Disconnect();
|
VoiceClient.Disconnect();
|
||||||
VoiceClient = null;
|
VoiceClient = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal StreamRequest CreateStreamRequest(CommandEventArgs e, string query, Channel voiceChannel) {
|
internal StreamRequest CreateStreamRequest(CommandEventArgs e, string query, Channel voiceChannel) {
|
||||||
|
if (VoiceChannel == null)
|
||||||
|
throw new ArgumentNullException("Please join a voicechannel.");
|
||||||
|
StreamRequest sr = null;
|
||||||
lock (_voiceLock) {
|
lock (_voiceLock) {
|
||||||
if (VoiceClient == null)
|
if (VoiceClient == null) {
|
||||||
VoiceClient = NadekoBot.client.Audio().Join(VoiceChannel).Result;
|
VoiceClient = NadekoBot.client.Audio().Join(VoiceChannel).Result;
|
||||||
return new StreamRequest(e, query, VoiceClient);
|
}
|
||||||
}
|
sr = new StreamRequest(e, query, this);
|
||||||
}
|
SongQueue.Add(sr);
|
||||||
|
}
|
||||||
|
return sr;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool TogglePause() => IsPaused = !IsPaused;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,31 +29,36 @@ namespace NadekoBot.Classes.Music {
|
|||||||
public User User { get; }
|
public User User { get; }
|
||||||
public string Query { get; }
|
public string Query { get; }
|
||||||
|
|
||||||
|
|
||||||
public string Title { get; internal set; } = String.Empty;
|
public string Title { get; internal set; } = String.Empty;
|
||||||
public IAudioClient VoiceClient { get; private set; }
|
public IAudioClient VoiceClient { get; private set; }
|
||||||
|
|
||||||
private MusicStreamer musicStreamer = null;
|
private MusicStreamer musicStreamer = null;
|
||||||
public StreamState State => musicStreamer?.State ?? StreamState.Resolving;
|
public StreamState State => musicStreamer?.State ?? privateState;
|
||||||
|
private StreamState privateState = StreamState.Resolving;
|
||||||
|
|
||||||
public StreamRequest(CommandEventArgs e, string query, IAudioClient voiceClient) {
|
public bool IsPaused => MusicControls.IsPaused;
|
||||||
|
|
||||||
|
private MusicControls MusicControls;
|
||||||
|
|
||||||
|
public StreamRequest(CommandEventArgs e, string query, MusicControls mc) {
|
||||||
if (e == null)
|
if (e == null)
|
||||||
throw new ArgumentNullException(nameof(e));
|
throw new ArgumentNullException(nameof(e));
|
||||||
if (query == null)
|
if (query == null)
|
||||||
throw new ArgumentNullException(nameof(query));
|
throw new ArgumentNullException(nameof(query));
|
||||||
if (voiceClient == null)
|
if (mc.VoiceClient == null)
|
||||||
throw new NullReferenceException($"{nameof(voiceClient)} is null, bot didn't join any server.");
|
throw new NullReferenceException($"{nameof(mc.VoiceClient)} is null, bot didn't join any server.");
|
||||||
|
this.MusicControls = mc;
|
||||||
this.VoiceClient = voiceClient;
|
this.VoiceClient = mc.VoiceClient;
|
||||||
this.Server = e.Server;
|
this.Server = e.Server;
|
||||||
this.Query = query;
|
this.Query = query;
|
||||||
ResolveStreamLink();
|
Task.Run(() => ResolveStreamLink());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task ResolveStreamLink() =>
|
private void ResolveStreamLink() {
|
||||||
Task.Run(() => {
|
VideoInfo video = null;
|
||||||
|
try {
|
||||||
Console.WriteLine("Resolving video link");
|
Console.WriteLine("Resolving video link");
|
||||||
var video = DownloadUrlResolver.GetDownloadUrls(Searches.FindYoutubeUrlByKeywords(Query))
|
video = DownloadUrlResolver.GetDownloadUrls(Searches.FindYoutubeUrlByKeywords(Query))
|
||||||
.Where(v => v.AdaptiveType == AdaptiveType.Audio)
|
.Where(v => v.AdaptiveType == AdaptiveType.Audio)
|
||||||
.OrderByDescending(v => v.AudioBitrate).FirstOrDefault();
|
.OrderByDescending(v => v.AudioBitrate).FirstOrDefault();
|
||||||
|
|
||||||
@ -61,18 +66,19 @@ namespace NadekoBot.Classes.Music {
|
|||||||
throw new Exception("Could not load any video elements based on the query.");
|
throw new Exception("Could not load any video elements based on the query.");
|
||||||
|
|
||||||
Title = video.Title;
|
Title = video.Title;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
privateState = StreamState.Completed;
|
||||||
|
Console.WriteLine($"Failed resolving the link.{ex.Message}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
musicStreamer = new MusicStreamer(this, video.DownloadUrl, Channel);
|
musicStreamer = new MusicStreamer(this, video.DownloadUrl, Channel);
|
||||||
if (OnQueued != null)
|
if (OnQueued != null)
|
||||||
OnQueued();
|
OnQueued();
|
||||||
});
|
}
|
||||||
|
|
||||||
internal string PrintStats() => musicStreamer?.Stats();
|
internal string PrintStats() => musicStreamer?.Stats();
|
||||||
|
|
||||||
internal void Pause() {
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Action OnQueued = null;
|
public Action OnQueued = null;
|
||||||
public Action OnBuffering = null;
|
public Action OnBuffering = null;
|
||||||
public Action OnStarted = null;
|
public Action OnStarted = null;
|
||||||
@ -84,24 +90,28 @@ namespace NadekoBot.Classes.Music {
|
|||||||
musicStreamer?.Cancel();
|
musicStreamer?.Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void Stop() {
|
||||||
|
musicStreamer?.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
internal Task Start() =>
|
internal Task Start() =>
|
||||||
Task.Run(async () => {
|
Task.Run(async () => {
|
||||||
Console.WriteLine("Start called.");
|
Console.WriteLine("Start called.");
|
||||||
|
|
||||||
int attemptsLeft = 7;
|
int attemptsLeft = 4;
|
||||||
//wait for up to 7 seconds to resolve a link
|
//wait for up to 4 seconds to resolve a link
|
||||||
while (State == StreamState.Resolving) {
|
while (State == StreamState.Resolving) {
|
||||||
await Task.Delay(1000);
|
await Task.Delay(1000);
|
||||||
Console.WriteLine("Resolving...");
|
Console.WriteLine("Resolving...");
|
||||||
if (--attemptsLeft == 0) {
|
if (--attemptsLeft == 0) {
|
||||||
Console.WriteLine("Resolving timed out.");
|
throw new TimeoutException("Resolving timed out.");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await musicStreamer.StartPlayback();
|
await musicStreamer.StartPlayback();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Console.WriteLine("Error in start playback." + ex);
|
Console.WriteLine("Error in start playback." + ex.Message);
|
||||||
|
privateState = StreamState.Completed;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -113,6 +123,7 @@ namespace NadekoBot.Classes.Music {
|
|||||||
public StreamState State { get; internal set; }
|
public StreamState State { get; internal set; }
|
||||||
public string Url { get; }
|
public string Url { get; }
|
||||||
private bool IsCanceled { get; set; }
|
private bool IsCanceled { get; set; }
|
||||||
|
public bool IsPaused => parent.IsPaused;
|
||||||
|
|
||||||
StreamRequest parent;
|
StreamRequest parent;
|
||||||
private readonly object _bufferLock = new object();
|
private readonly object _bufferLock = new object();
|
||||||
@ -152,12 +163,21 @@ namespace NadekoBot.Classes.Music {
|
|||||||
while (true) {
|
while (true) {
|
||||||
|
|
||||||
while (buffer.writePos - buffer.readPos > 5.MB() && State != StreamState.Completed) {
|
while (buffer.writePos - buffer.readPos > 5.MB() && State != StreamState.Completed) {
|
||||||
if (bufferCancelSource.Token.CanBeCanceled && !bufferCancelSource.IsCancellationRequested) {
|
if (!bufferCancelSource.IsCancellationRequested) {
|
||||||
bufferCancelSource.Cancel();
|
|
||||||
Console.WriteLine("Canceling buffer token");
|
Console.WriteLine("Canceling buffer token");
|
||||||
|
Task.Run(() => bufferCancelSource.Cancel());
|
||||||
}
|
}
|
||||||
|
|
||||||
await Task.Delay(1000);
|
await Task.Delay(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (State == StreamState.Completed) {
|
||||||
|
try {
|
||||||
|
p.CancelOutputRead();
|
||||||
|
p.Close();
|
||||||
|
} catch (Exception) { }
|
||||||
|
Console.WriteLine("Buffering canceled, stream is completed.");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer.readPos > 5.MiB()) { // if buffer is over 5 MiB, create new one
|
if (buffer.readPos > 5.MiB()) { // if buffer is over 5 MiB, create new one
|
||||||
@ -177,15 +197,6 @@ namespace NadekoBot.Classes.Music {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (State == StreamState.Completed) {
|
|
||||||
try {
|
|
||||||
p.CancelOutputRead();
|
|
||||||
p.Close();
|
|
||||||
} catch (Exception) { }
|
|
||||||
Console.WriteLine("Buffering canceled, stream is completed.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf = new byte[1024];
|
var buf = new byte[1024];
|
||||||
int read = 0;
|
int read = 0;
|
||||||
read = await p.StandardOutput.BaseStream.ReadAsync(buf, 0, 1024);
|
read = await p.StandardOutput.BaseStream.ReadAsync(buf, 0, 1024);
|
||||||
@ -212,6 +223,7 @@ namespace NadekoBot.Classes.Music {
|
|||||||
|
|
||||||
internal async Task StartPlayback() {
|
internal async Task StartPlayback() {
|
||||||
Console.WriteLine("Starting playback.");
|
Console.WriteLine("Starting playback.");
|
||||||
|
if (State == StreamState.Playing) return;
|
||||||
State = StreamState.Playing;
|
State = StreamState.Playing;
|
||||||
if (parent.OnBuffering != null)
|
if (parent.OnBuffering != null)
|
||||||
parent.OnBuffering();
|
parent.OnBuffering();
|
||||||
@ -253,22 +265,28 @@ namespace NadekoBot.Classes.Music {
|
|||||||
} else
|
} else
|
||||||
attempt = 0;
|
attempt = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (State == StreamState.Completed) {
|
if (State == StreamState.Completed) {
|
||||||
Console.WriteLine("Canceled");
|
Console.WriteLine("Canceled");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
parent.VoiceClient.Send(voiceBuffer, 0, voiceBuffer.Length);
|
parent.VoiceClient.Send(voiceBuffer, 0, voiceBuffer.Length);
|
||||||
|
|
||||||
|
while (IsPaused) {
|
||||||
|
await Task.Delay(50);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
parent.VoiceClient.Wait();
|
parent.VoiceClient.Wait();
|
||||||
StopPlayback();
|
Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Cancel() {
|
internal void Cancel() {
|
||||||
IsCanceled = true;
|
IsCanceled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void StopPlayback() {
|
internal void Stop() {
|
||||||
Console.WriteLine("Stopping playback");
|
Console.WriteLine("Stopping playback");
|
||||||
if (State != StreamState.Completed) {
|
if (State != StreamState.Completed) {
|
||||||
State = StreamState.Completed;
|
State = StreamState.Completed;
|
||||||
|
@ -13,34 +13,20 @@ namespace NadekoBot.Modules {
|
|||||||
|
|
||||||
public static ConcurrentDictionary<Server, MusicControls> musicPlayers = new ConcurrentDictionary<Server, MusicControls>();
|
public static ConcurrentDictionary<Server, MusicControls> musicPlayers = new ConcurrentDictionary<Server, MusicControls>();
|
||||||
|
|
||||||
internal static void CleanMusicPlayers() {
|
|
||||||
foreach (var mp in musicPlayers
|
|
||||||
.Where(kvp => kvp.Value.CurrentSong == null
|
|
||||||
&& kvp.Value.SongQueue.Count == 0)) {
|
|
||||||
var val = mp.Value;
|
|
||||||
(musicPlayers as System.Collections.IDictionary).Remove(mp.Key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static string GetMusicStats() {
|
internal static string GetMusicStats() {
|
||||||
var servers = 0;
|
var servers = 0;
|
||||||
var queued = 0;
|
var queued = 0;
|
||||||
musicPlayers.ForEach(kvp => {
|
var stats = musicPlayers.Where(kvp => kvp.Value?.SongQueue.Count > 0 || kvp.Value?.CurrentSong != null);
|
||||||
var mp = kvp.Value;
|
|
||||||
if (mp.SongQueue.Count > 0 || mp.CurrentSong != null)
|
|
||||||
queued += mp.SongQueue.Count + 1;
|
|
||||||
servers++;
|
|
||||||
});
|
|
||||||
|
|
||||||
return $"Playing {queued} songs across {servers} servers.";
|
return $"Playing {stats.Count()} songs, {stats.Sum(kvp => kvp.Value?.SongQueue?.Count ?? 0)} queued.";
|
||||||
}
|
}
|
||||||
|
|
||||||
public Music() : base() {
|
public Music() : base() {
|
||||||
Timer cleaner = new Timer();
|
/*Timer cleaner = new Timer();
|
||||||
cleaner.Elapsed += (s, e) => System.Threading.Tasks.Task.Run(() => CleanMusicPlayers());
|
cleaner.Elapsed += (s, e) => System.Threading.Tasks.Task.Run(() => CleanMusicPlayers());
|
||||||
cleaner.Interval = 10000;
|
cleaner.Interval = 10000;
|
||||||
cleaner.Start();
|
cleaner.Start();
|
||||||
/*
|
|
||||||
Timer statPrinter = new Timer();
|
Timer statPrinter = new Timer();
|
||||||
NadekoBot.client.Connected += (s, e) => {
|
NadekoBot.client.Connected += (s, e) => {
|
||||||
if (statPrinter.Enabled) return;
|
if (statPrinter.Enabled) return;
|
||||||
@ -62,8 +48,8 @@ namespace NadekoBot.Modules {
|
|||||||
.Alias("next")
|
.Alias("next")
|
||||||
.Description("Goes to the next song in the queue.")
|
.Description("Goes to the next song in the queue.")
|
||||||
.Do(e => {
|
.Do(e => {
|
||||||
if (musicPlayers.ContainsKey(e.Server) == false || (musicPlayers[e.Server]?.CurrentSong) == null) return;
|
if (musicPlayers.ContainsKey(e.Server) == false) return;
|
||||||
musicPlayers[e.Server].CurrentSong.Cancel();
|
musicPlayers[e.Server].LoadNextSong();
|
||||||
});
|
});
|
||||||
|
|
||||||
cgb.CreateCommand("s")
|
cgb.CreateCommand("s")
|
||||||
@ -72,10 +58,9 @@ namespace NadekoBot.Modules {
|
|||||||
.Do(e => {
|
.Do(e => {
|
||||||
if (musicPlayers.ContainsKey(e.Server) == false) return;
|
if (musicPlayers.ContainsKey(e.Server) == false) return;
|
||||||
var player = musicPlayers[e.Server];
|
var player = musicPlayers[e.Server];
|
||||||
player.RemoveAllSongs();
|
player.Stop();
|
||||||
if (player.CurrentSong != null) {
|
MusicControls throwAwayValue;
|
||||||
player.CurrentSong.Cancel();
|
musicPlayers.TryRemove(e.Server, out throwAwayValue);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
cgb.CreateCommand("p")
|
cgb.CreateCommand("p")
|
||||||
@ -83,14 +68,10 @@ namespace NadekoBot.Modules {
|
|||||||
.Description("Pauses the song")
|
.Description("Pauses the song")
|
||||||
.Do(async e => {
|
.Do(async e => {
|
||||||
if (musicPlayers.ContainsKey(e.Server) == false) return;
|
if (musicPlayers.ContainsKey(e.Server) == false) return;
|
||||||
await e.Send("This feature is coming tomorrow.");
|
if (musicPlayers[e.Server].TogglePause())
|
||||||
/*
|
await e.Send("Music player paused.");
|
||||||
if (musicPlayers[e.Server].Pause())
|
|
||||||
if (musicPlayers[e.Server].IsPaused)
|
|
||||||
await e.Send("Music player Paused");
|
|
||||||
else
|
else
|
||||||
await e.Send("Music player unpaused.");
|
await e.Send("Music player unpaused.");
|
||||||
*/
|
|
||||||
});
|
});
|
||||||
|
|
||||||
cgb.CreateCommand("q")
|
cgb.CreateCommand("q")
|
||||||
@ -99,16 +80,21 @@ namespace NadekoBot.Modules {
|
|||||||
.Parameter("query", ParameterType.Unparsed)
|
.Parameter("query", ParameterType.Unparsed)
|
||||||
.Do(async e => {
|
.Do(async e => {
|
||||||
if (musicPlayers.ContainsKey(e.Server) == false)
|
if (musicPlayers.ContainsKey(e.Server) == false)
|
||||||
if (musicPlayers.Count > 25) {
|
if (!musicPlayers.TryAdd(e.Server, new MusicControls(e.User.VoiceChannel))) {
|
||||||
await e.Send($"{e.User.Mention}, playlist supports up to 25 songs. If you think this is not enough, contact the owner.:warning:");
|
await e.Send("Failed to create a music player for this server");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
(musicPlayers as System.Collections.IDictionary).Add(e.Server, new MusicControls(e.User.VoiceChannel));
|
|
||||||
|
|
||||||
var player = musicPlayers[e.Server];
|
var player = musicPlayers[e.Server];
|
||||||
|
|
||||||
|
if (player.SongQueue.Count > 25) {
|
||||||
|
await e.Send("Music player supports up to 25 songs atm. Contant the owner if you think this is not enough :warning:");
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var sr = player.CreateStreamRequest(e, e.GetArg("query"), player.VoiceChannel);
|
var sr = player.CreateStreamRequest(e, e.GetArg("query"), player.VoiceChannel);
|
||||||
|
if (sr == null)
|
||||||
|
throw new NullReferenceException("StreamRequest is null.");
|
||||||
Message msg = null;
|
Message msg = null;
|
||||||
sr.OnQueued += async () => {
|
sr.OnQueued += async () => {
|
||||||
msg = await e.Send($":musical_note:**Queued** {sr.Title}");
|
msg = await e.Send($":musical_note:**Queued** {sr.Title}");
|
||||||
@ -126,12 +112,9 @@ namespace NadekoBot.Modules {
|
|||||||
if (msg != null)
|
if (msg != null)
|
||||||
msg = await e.Send($":musical_note:**Buffering the song**...{sr.Title}");
|
msg = await e.Send($":musical_note:**Buffering the song**...{sr.Title}");
|
||||||
};
|
};
|
||||||
lock (player.SongQueue) {
|
|
||||||
player.SongQueue.Add(sr);
|
|
||||||
}
|
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
await e.Send($"Error. :anger:\n{ex.Message}");
|
await e.Send($":anger: {ex.Message}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -110,10 +110,13 @@ namespace NadekoBot {
|
|||||||
if (loadTrello)
|
if (loadTrello)
|
||||||
modules.Add(new Trello(), "Trello", ModuleFilter.None);
|
modules.Add(new Trello(), "Trello", ModuleFilter.None);
|
||||||
|
|
||||||
|
//start the timer for stats
|
||||||
|
_statsSW.Start();
|
||||||
//run the bot
|
//run the bot
|
||||||
client.ExecuteAndWait(async () => {
|
client.ExecuteAndWait(async () => {
|
||||||
await client.Connect(c.Username, c.Password);
|
await client.Connect(c.Username, c.Password);
|
||||||
|
|
||||||
|
LoadStats();
|
||||||
Console.WriteLine("-----------------");
|
Console.WriteLine("-----------------");
|
||||||
Console.WriteLine(GetStats());
|
Console.WriteLine(GetStats());
|
||||||
Console.WriteLine("-----------------");
|
Console.WriteLine("-----------------");
|
||||||
@ -127,8 +130,17 @@ namespace NadekoBot {
|
|||||||
Console.WriteLine("Exiting...");
|
Console.WriteLine("Exiting...");
|
||||||
Console.ReadKey();
|
Console.ReadKey();
|
||||||
}
|
}
|
||||||
|
private static string _statsCache = "";
|
||||||
public static string GetStats() =>
|
private static Stopwatch _statsSW = new Stopwatch();
|
||||||
|
public static string GetStats() {
|
||||||
|
if (_statsSW.ElapsedTicks > 5) {
|
||||||
|
LoadStats();
|
||||||
|
_statsSW.Restart();
|
||||||
|
}
|
||||||
|
return _statsCache;
|
||||||
|
}
|
||||||
|
private static void LoadStats() {
|
||||||
|
_statsCache =
|
||||||
"Author: Kwoth" +
|
"Author: Kwoth" +
|
||||||
$"\nDiscord.Net version: {DiscordConfig.LibVersion}" +
|
$"\nDiscord.Net version: {DiscordConfig.LibVersion}" +
|
||||||
$"\nRuntime: {client.GetRuntime()}" +
|
$"\nRuntime: {client.GetRuntime()}" +
|
||||||
@ -141,6 +153,7 @@ namespace NadekoBot {
|
|||||||
$"\nUsers: {client.Servers.SelectMany(x => x.Users.Select(y => y.Id)).Count()} ({client.Servers.SelectMany(x => x.Users.Select(y => y.Id)).Distinct().Count()} unique) ({client.Servers.SelectMany(x => x.Users.Where(y => y.Status != UserStatus.Offline).Select(y => y.Id)).Distinct().Count()} online)" +
|
$"\nUsers: {client.Servers.SelectMany(x => x.Users.Select(y => y.Id)).Count()} ({client.Servers.SelectMany(x => x.Users.Select(y => y.Id)).Distinct().Count()} unique) ({client.Servers.SelectMany(x => x.Users.Where(y => y.Status != UserStatus.Offline).Select(y => y.Id)).Distinct().Count()} online)" +
|
||||||
$"\nHeap: {Math.Round(GC.GetTotalMemory(true) / (1024.0 * 1024.0), 2).ToString()}MB" +
|
$"\nHeap: {Math.Round(GC.GetTotalMemory(true) / (1024.0 * 1024.0), 2).ToString()}MB" +
|
||||||
$"\nCommands Ran this session: {commandsRan}";
|
$"\nCommands Ran this session: {commandsRan}";
|
||||||
|
}
|
||||||
|
|
||||||
public static string GetUptimeString() {
|
public static string GetUptimeString() {
|
||||||
var time = (DateTime.Now - Process.GetCurrentProcess().StartTime);
|
var time = (DateTime.Now - Process.GetCurrentProcess().StartTime);
|
||||||
|
Loading…
Reference in New Issue
Block a user