new api, new music code
This commit is contained in:
parent
9e870cfc87
commit
f0277b1ba8
@ -26,9 +26,9 @@ namespace NadekoBot.Modules {
|
||||
public static IAudioClient Voice;
|
||||
public static Channel VoiceChannel;
|
||||
public static bool Pause = false;
|
||||
public static List<YouTubeVideo> SongQueue = new List<YouTubeVideo>();
|
||||
public static List<StreamRequest> SongQueue = new List<StreamRequest>();
|
||||
|
||||
public static YouTubeVideo CurrentSong;
|
||||
public static StreamRequest CurrentSong;
|
||||
|
||||
public static bool Exit {
|
||||
get { return exit; }
|
||||
@ -49,6 +49,16 @@ namespace NadekoBot.Modules {
|
||||
|
||||
public override void Install(ModuleManager manager) {
|
||||
var client = NadekoBot.client;
|
||||
|
||||
Task.Run(async () => {
|
||||
while (true) {
|
||||
if (CurrentSong == null || CurrentSong.State == StreamTaskState.Completed) {
|
||||
await LoadNextSong();
|
||||
} else
|
||||
await Task.Delay(200);
|
||||
}
|
||||
});
|
||||
|
||||
manager.CreateCommands("!m", cgb => {
|
||||
//queue all more complex commands
|
||||
commands.ForEach(cmd => cmd.Init(cgb));
|
||||
@ -57,8 +67,11 @@ namespace NadekoBot.Modules {
|
||||
.Alias("next")
|
||||
.Description("Goes to the next song in the queue.")
|
||||
.Do(e => {
|
||||
if (Voice != null && Exit == false) {
|
||||
NextSong = true;
|
||||
if (CurrentSong == null) return;
|
||||
CurrentSong.Cancel();
|
||||
CurrentSong = SongQueue.Take(1).FirstOrDefault();
|
||||
if (CurrentSong != null) {
|
||||
CurrentSong.Start();
|
||||
}
|
||||
});
|
||||
|
||||
@ -66,50 +79,35 @@ namespace NadekoBot.Modules {
|
||||
.Alias("stop")
|
||||
.Description("Completely stops the music and unbinds the bot from the channel.")
|
||||
.Do(e => {
|
||||
if (Voice != null && Exit == false) {
|
||||
Exit = true;
|
||||
SongQueue = new List<YouTubeVideo>();
|
||||
SongQueue.Clear();
|
||||
if (CurrentSong != null) {
|
||||
CurrentSong.Cancel();
|
||||
CurrentSong = null;
|
||||
}
|
||||
});
|
||||
|
||||
cgb.CreateCommand("p")
|
||||
.Alias("pause")
|
||||
.Description("Pauses the song")
|
||||
.Do(async e => {
|
||||
if (Voice != null && Exit == false && CurrentSong != null) {
|
||||
Pause = !Pause;
|
||||
if (Pause) {
|
||||
await e.Send("Pausing. Run the command again to resume.");
|
||||
} else {
|
||||
await e.Send("Resuming...");
|
||||
}
|
||||
}
|
||||
/*if (CurrentSong != null) {
|
||||
CurrentSong.
|
||||
}*/
|
||||
await e.Send("Not yet implemented.");
|
||||
});
|
||||
|
||||
cgb.CreateCommand("q")
|
||||
.Alias("yq")
|
||||
.Description("Queue a song using a multi/single word name.\n**Usage**: `!m q Dream Of Venice`")
|
||||
.Parameter("Query", ParameterType.Unparsed)
|
||||
.Do(async e => {
|
||||
var youtube = YouTube.Default;
|
||||
var video = youtube.GetAllVideos(Searches.FindYoutubeUrlByKeywords(e.Args[0]))
|
||||
.Where(v => v.AdaptiveKind == AdaptiveKind.Audio)
|
||||
.OrderByDescending(v => v.AudioBitrate).FirstOrDefault();
|
||||
|
||||
if (video?.Uri != "" && video.Uri != null) {
|
||||
SongQueue.Add(video);
|
||||
await e.Send("**Queued** " + video.FullName);
|
||||
} else {
|
||||
await e.Send("Failed to load that song.");
|
||||
}
|
||||
.Do(e => {
|
||||
SongQueue.Add(new StreamRequest(NadekoBot.client, e, e.GetArg("Query")));
|
||||
});
|
||||
|
||||
cgb.CreateCommand("lq")
|
||||
.Alias("ls").Alias("lp")
|
||||
.Description("Lists up to 10 currently queued songs.")
|
||||
.Do(async e => {
|
||||
await e.Send(SongQueue.Count + " videos currently queued.");
|
||||
await e.Send(string.Join("\n", SongQueue.Select(v => v.FullName).Take(10)));
|
||||
await e.Send(":musical_note: " + SongQueue.Count + " videos currently queued.");
|
||||
await e.Send(string.Join("\n", SongQueue.Select(v => v.Title).Take(10)));
|
||||
});
|
||||
|
||||
cgb.CreateCommand("sh")
|
||||
@ -121,88 +119,21 @@ namespace NadekoBot.Modules {
|
||||
}
|
||||
|
||||
SongQueue.Shuffle();
|
||||
await e.Send("Songs shuffled!");
|
||||
});
|
||||
|
||||
cgb.CreateCommand("radio")
|
||||
.Alias("music")
|
||||
.Description("Binds to a voice and text channel in order to play music.")
|
||||
.Parameter("ChannelName", ParameterType.Unparsed)
|
||||
.Do(async e => {
|
||||
if (Voice != null) return;
|
||||
VoiceChannel = e.Server.FindChannels(e.GetArg("ChannelName").Trim(), ChannelType.Voice).FirstOrDefault();
|
||||
Voice = await client.Audio().Join(VoiceChannel);
|
||||
Exit = false;
|
||||
NextSong = false;
|
||||
Pause = false;
|
||||
try {
|
||||
while (true) {
|
||||
if (Exit) break;
|
||||
if (SongQueue.Count == 0 || Pause) { Thread.Sleep(100); continue; }
|
||||
if (!LoadNextSong()) break;
|
||||
|
||||
await Task.Run(async () => {
|
||||
if (Exit) {
|
||||
Voice = null;
|
||||
Exit = false;
|
||||
await e.Send("Exiting...");
|
||||
return;
|
||||
}
|
||||
|
||||
var streamer = new AudioStreamer(Music.CurrentSong.Uri);
|
||||
streamer.Start();
|
||||
while (streamer.BytesSentToTranscoder < 100 * 0x1000 || streamer.NetworkDone)
|
||||
await Task.Delay(500);
|
||||
|
||||
int blockSize = 1920 * client.Audio().Config.Channels;
|
||||
byte[] buffer = new byte[blockSize];
|
||||
|
||||
var msg = await e.Send("Playing " + Music.CurrentSong.FullName + " [00:00]");
|
||||
int counter = 0;
|
||||
int byteCount;
|
||||
|
||||
while ((byteCount = streamer.PCMOutput.Read(buffer, 0, blockSize)) > 0) {
|
||||
Voice.Send(buffer, byteCount);
|
||||
counter += blockSize;
|
||||
if (NextSong) {
|
||||
NextSong = false;
|
||||
break;
|
||||
}
|
||||
if (Exit) {
|
||||
Exit = false;
|
||||
return;
|
||||
}
|
||||
while (Pause) Thread.Sleep(100);
|
||||
}
|
||||
});
|
||||
}
|
||||
Voice.Wait();
|
||||
} catch (Exception ex) { Console.WriteLine(ex.ToString()); }
|
||||
await Voice.Disconnect();
|
||||
Voice = null;
|
||||
VoiceChannel = null;
|
||||
await e.Send(":musical_note: Songs shuffled!");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private Stream GetAudioFileStream(string file) {
|
||||
Process p = Process.Start(new ProcessStartInfo() {
|
||||
FileName = "ffmpeg",
|
||||
Arguments = "-i \"" + Uri.EscapeUriString(file) + "\" -f s16le -ar 48000 -af volume=1 -ac 2 pipe:1 ",
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true
|
||||
});
|
||||
return p.StandardOutput.BaseStream;
|
||||
}
|
||||
|
||||
private bool LoadNextSong() {
|
||||
private async Task LoadNextSong() {
|
||||
if (SongQueue.Count == 0) {
|
||||
CurrentSong = null;
|
||||
return false;
|
||||
await Task.Delay(200);
|
||||
return;
|
||||
}
|
||||
CurrentSong = SongQueue[0];
|
||||
SongQueue.RemoveAt(0);
|
||||
return true;
|
||||
CurrentSong.Start();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -238,7 +169,7 @@ namespace NadekoBot.Modules {
|
||||
public StreamTaskState State => streamTask?.State ?? StreamTaskState.Queued;
|
||||
|
||||
|
||||
public StreamRequest(DiscordClient client, MessageEventArgs e, string text) {
|
||||
public StreamRequest(DiscordClient client, CommandEventArgs e, string text) {
|
||||
this.client = client;
|
||||
Server = e.Server;
|
||||
Channel = e.Channel;
|
||||
@ -257,59 +188,29 @@ namespace NadekoBot.Modules {
|
||||
}
|
||||
|
||||
void ResolveLink() {
|
||||
var url = RequestText;
|
||||
var query = RequestText;
|
||||
try {
|
||||
var video = YouTube.Default.GetAllVideos(Searches.FindYoutubeUrlByKeywords(query))
|
||||
.Where(v => v.AdaptiveKind == AdaptiveKind.Audio)
|
||||
.OrderByDescending(v => v.AudioBitrate).FirstOrDefault();
|
||||
|
||||
if (url.IndexOf("soundcloud", StringComparison.OrdinalIgnoreCase) != -1) {
|
||||
var track = Services.SoundcloudService.GetTrackStreamUrl(url, out Title, out StreamUrl);
|
||||
Length = TimeSpan.FromMilliseconds(track.Duration);
|
||||
Title = track.Title;
|
||||
FileName = Uri.EscapeUriString(Title) + ".mp3";
|
||||
|
||||
StartBuffering();
|
||||
linkResolved = true;
|
||||
} else if (url.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) != -1 || url.IndexOf("youtu.be", StringComparison.OrdinalIgnoreCase) != -1) {
|
||||
try {
|
||||
var infos = DownloadUrlResolver
|
||||
.GetDownloadUrls(url.Trim())
|
||||
.Where(i => i.AudioType != AudioType.Unknown)
|
||||
.ToArray();
|
||||
|
||||
if (infos.Length == 0)
|
||||
throw new Exception("Could not load any video elements");
|
||||
|
||||
var info = infos
|
||||
.GroupBy(x => x.AudioBitrate) // Create groups for audio bitrates
|
||||
.OrderByDescending(x => x.Key) // Group with max bitrate first
|
||||
.Take(1) // Only take one group
|
||||
.SelectMany(x => x) // Unpack group container again
|
||||
.OrderBy(x => x.Resolution) // take vid with smallest resolution
|
||||
.First(); // First one
|
||||
|
||||
StreamUrl = info.DownloadUrl;
|
||||
Title = info.Title;
|
||||
FileName = Uri.EscapeUriString(Title) + ".mp4";
|
||||
|
||||
StartBuffering();
|
||||
linkResolved = true;
|
||||
} catch (Exception) {
|
||||
// Send a message to the guy that queued that
|
||||
Channel.SendMessage(":warning: " + User.Mention + " Cannot load youtube url: `This video is not available in your country` or the url is corrupted somehow...");
|
||||
Console.WriteLine("Cannot parse youtube url: " + url);
|
||||
Cancel();
|
||||
}
|
||||
} else {
|
||||
// Is it a direct link oO ??
|
||||
var format = validFormats.FirstOrDefault(f => url.EndsWith(f));
|
||||
if (format == null) {
|
||||
Console.WriteLine("Direct link: \"" + url + "\" does not end with a valid extension");
|
||||
return;
|
||||
}
|
||||
|
||||
StreamUrl = url;
|
||||
Title = url;
|
||||
if (video == null)
|
||||
throw new Exception("Could not load any video elements"); // First one
|
||||
|
||||
StreamUrl = video.Uri;
|
||||
Title = video.Title;
|
||||
var fileName = Title.Replace("\\","_").Replace("/","_");
|
||||
Path.GetInvalidPathChars().ForEach(c => { fileName = fileName.Replace(c, '_'); });
|
||||
FileName = fileName;
|
||||
|
||||
StartBuffering();
|
||||
linkResolved = true;
|
||||
Channel.Send(":musical_note: **Queued** " + video.FullName);
|
||||
} catch (Exception) {
|
||||
// Send a message to the guy that queued that
|
||||
Channel.SendMessage(":warning: " + User.Mention + " Cannot load youtube url: `This video is not available in your country` or the url is corrupted somehow...");
|
||||
Console.WriteLine("Cannot parse youtube url: " + query);
|
||||
Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@ -319,7 +220,6 @@ namespace NadekoBot.Modules {
|
||||
var fullPath = Path.Combine(folder, FileName);
|
||||
|
||||
FileStream fileStream;
|
||||
FileStream readStream;
|
||||
try {
|
||||
if (File.Exists(fullPath) && new FileInfo(fullPath).Length > 1024 * 2) {
|
||||
NetworkDone = true;
|
||||
@ -338,13 +238,9 @@ namespace NadekoBot.Modules {
|
||||
Console.WriteLine("Exception while creating or opening stream buffers: " + ex);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Task.Run(() => {
|
||||
AutoResetDelay fileLengthCheckDelay = new AutoResetDelay(500);
|
||||
int byteCounter = 0;
|
||||
bool fileLengthDetermined = false;
|
||||
|
||||
try {
|
||||
var webClient = new WebClient();
|
||||
@ -362,7 +258,7 @@ namespace NadekoBot.Modules {
|
||||
TotalSourceBytes += read;
|
||||
fileStream.Write(buffer, 0, read);
|
||||
|
||||
if (TotalSourceBytes > 1024 * 2 && Length.TotalSeconds < 0.1 && fileLengthCheckDelay.IsReady) {
|
||||
if (TotalSourceBytes > 1024 * 2 && Length.TotalSeconds < 0.1) {
|
||||
Length = GetFileLength(fullPath);
|
||||
}
|
||||
}
|
||||
@ -382,9 +278,6 @@ namespace NadekoBot.Modules {
|
||||
|
||||
Stopwatch resolveTimer = Stopwatch.StartNew();
|
||||
|
||||
if (!linkResolved || bufferingStream == null)
|
||||
Channel.SendMessage($":musical_note: Resolving link...\r\n:warning: `Keep in mind that other people can 'steal' the bot by just starting a stream command in their own server...`\r\n");
|
||||
|
||||
while (resolveTimer.ElapsedMilliseconds < 8000) {
|
||||
if (bufferingStream != null)
|
||||
break;
|
||||
@ -425,21 +318,6 @@ namespace NadekoBot.Modules {
|
||||
return client.Servers.SelectMany(s => s.VoiceChannels).FirstOrDefault(c => c.Users.Any(u => u.Id == user.Id));
|
||||
}
|
||||
|
||||
public string GetFormattedTitle() {
|
||||
if (Length.TotalSeconds < double.Epsilon)
|
||||
Length = GetFileLength(FileName);
|
||||
|
||||
if (Title != DefaultTitle)
|
||||
return $"**{Title.Replace('*', '°')}** *({Length.ToString()})*";
|
||||
|
||||
// put into <> when it contains a domain
|
||||
if (StreamUrl == null)
|
||||
return "<" + RequestText + ">";
|
||||
if (StreamUrl.Contains("http:") || StreamUrl.Contains("https:"))
|
||||
return "<" + StreamUrl.Trim() + ">";
|
||||
return StreamUrl;
|
||||
}
|
||||
|
||||
public static TimeSpan GetFileLength(string fileName) {
|
||||
try {
|
||||
var startInfo = new ProcessStartInfo("ffprobe", $"-i \"{fileName}\" -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1");
|
||||
@ -540,7 +418,7 @@ namespace NadekoBot.Modules {
|
||||
|
||||
// How much data is in the final output buffer?
|
||||
// We dont want to transcode too much in advance
|
||||
if (available > 0 && availableRingSpace < 1) {
|
||||
if (available > 0) {
|
||||
int read = await sourceStream.ReadAsync(buffer, 0, (int)Math.Min(available, buffer.LongLength), cancellationToken);
|
||||
if (read > 0) {
|
||||
// Write to transcoder
|
||||
@ -630,4 +508,115 @@ namespace NadekoBot.Modules {
|
||||
}
|
||||
}
|
||||
}
|
||||
class StreamTask {
|
||||
readonly DiscordClient client;
|
||||
readonly StreamRequest streamRequest;
|
||||
readonly Stream bufferingStream;
|
||||
|
||||
CancellationTokenSource tokenSource;
|
||||
Task audioTask;
|
||||
|
||||
public StreamTaskState State { get; private set; }
|
||||
|
||||
public StreamTask(DiscordClient client, StreamRequest streamRequest, Stream bufferingStream) {
|
||||
this.streamRequest = streamRequest;
|
||||
this.bufferingStream = bufferingStream;
|
||||
this.client = client;
|
||||
|
||||
State = StreamTaskState.Queued;
|
||||
}
|
||||
|
||||
public void StartStreaming() {
|
||||
if (State != StreamTaskState.Queued)
|
||||
return;
|
||||
|
||||
State = StreamTaskState.Playing;
|
||||
tokenSource = new CancellationTokenSource();
|
||||
audioTask = Task.Run(StreamFunc, tokenSource.Token);
|
||||
}
|
||||
|
||||
public void CancelStreaming() {
|
||||
if (State != StreamTaskState.Queued && State != StreamTaskState.Playing)
|
||||
return;
|
||||
|
||||
tokenSource?.Cancel(false);
|
||||
audioTask?.Wait();
|
||||
State = StreamTaskState.Completed;
|
||||
}
|
||||
|
||||
async Task StreamFunc() {
|
||||
CancellationToken cancellationToken = tokenSource.Token;
|
||||
IAudioClient voiceClient = null;
|
||||
TranscodingTask streamer = null;
|
||||
try {
|
||||
uint byteCounter = 0;
|
||||
|
||||
// Download and read audio from the url
|
||||
streamer = new TranscodingTask(streamRequest, bufferingStream);
|
||||
streamer.Start();
|
||||
|
||||
// Wait until we have at least a few kb transcoded or network stream done
|
||||
while (true) {
|
||||
if (streamRequest.NetworkDone) {
|
||||
await Task.Delay(600);
|
||||
break;
|
||||
}
|
||||
if (streamer.ReadyBytesLeft > 5 * 1024)
|
||||
break;
|
||||
await Task.Delay(200);
|
||||
}
|
||||
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
return;
|
||||
|
||||
// Start streaming to voice
|
||||
await streamRequest.Channel.SendMessage($":musical_note: Playing {streamRequest.Title}");
|
||||
|
||||
var audioService = client.Audio();
|
||||
voiceClient = await audioService.Join(streamRequest.VoiceChannel);
|
||||
|
||||
int blockSize = 1920 * audioService.Config.Channels;
|
||||
byte[] voiceBuffer = new byte[blockSize];
|
||||
var ringBuffer = streamer.PCMOutput;
|
||||
|
||||
Stopwatch timeout = Stopwatch.StartNew();
|
||||
while (true) {
|
||||
var readCount = ringBuffer.Read(voiceBuffer, 0, voiceBuffer.Length);
|
||||
|
||||
if (readCount == 0) {
|
||||
if (timeout.ElapsedMilliseconds > 1500) {
|
||||
Console.WriteLine("Audio stream timed out. Disconnecting.");
|
||||
break;
|
||||
}
|
||||
|
||||
await Task.Delay(200);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
return;
|
||||
|
||||
timeout.Restart();
|
||||
|
||||
byteCounter += (uint)voiceBuffer.Length;
|
||||
voiceClient.Send(voiceBuffer, 0, voiceBuffer.Length);
|
||||
}
|
||||
|
||||
streamer.Cancel();
|
||||
|
||||
voiceClient.Wait();
|
||||
} catch (Exception ex) {
|
||||
await streamRequest.Channel.SendMessage($":musical_note: {streamRequest.User.Mention} Something went wrong, please report this. :angry: :anger:");
|
||||
Console.WriteLine("Exception while playing music: " + ex);
|
||||
} finally {
|
||||
if (voiceClient != null) {
|
||||
State = StreamTaskState.Completed;
|
||||
streamer?.Cancel();
|
||||
await voiceClient.Disconnect();
|
||||
await Task.Delay(500);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -88,17 +88,17 @@ namespace NadekoBot
|
||||
}));
|
||||
|
||||
//install modules
|
||||
modules.Install(new Administration(), "Administration", FilterType.Unrestricted);
|
||||
modules.Install(new Conversations(), "Conversations", FilterType.Unrestricted);
|
||||
modules.Install(new Gambling(), "Gambling", FilterType.Unrestricted);
|
||||
modules.Install(new Games(), "Games", FilterType.Unrestricted);
|
||||
modules.Install(new Music(), "Music", FilterType.Unrestricted);
|
||||
modules.Install(new Searches(), "Searches", FilterType.Unrestricted);
|
||||
modules.Add(new Administration(), "Administration", ModuleFilter.None);
|
||||
modules.Add(new Conversations(), "Conversations", ModuleFilter.None);
|
||||
modules.Add(new Gambling(), "Gambling", ModuleFilter.None);
|
||||
modules.Add(new Games(), "Games", ModuleFilter.None);
|
||||
modules.Add(new Music(), "Music", ModuleFilter.None);
|
||||
modules.Add(new Searches(), "Searches", ModuleFilter.None);
|
||||
if(trelloLoaded)
|
||||
modules.Install(new Trello(), "Trello", FilterType.Unrestricted);
|
||||
modules.Add(new Trello(), "Trello", ModuleFilter.None);
|
||||
|
||||
//run the bot
|
||||
client.Run(async () =>
|
||||
client.ExecuteAndWait(async () =>
|
||||
{
|
||||
await client.Connect(c.Username, c.Password);
|
||||
Console.WriteLine("Connected!");
|
||||
|
@ -68,6 +68,26 @@
|
||||
<HintPath>..\packages\VideoLibrary.1.3.1\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\libvideo.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Manatee.Json, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c267f67a39449c62, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Manatee.Json.3.2.1\lib\net45\Manatee.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Manatee.StateMachine, Version=0.0.0.0, Culture=neutral, PublicKeyToken=15909d91027a225e, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Manatee.StateMachine.1.1.2\lib\net45\Manatee.StateMachine.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Manatee.Trello, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Manatee.Trello.1.8.2\lib\net45\Manatee.Trello.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Manatee.Trello.ManateeJson, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Manatee.Trello.ManateeJson.1.4.0\lib\net45\Manatee.Trello.ManateeJson.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Manatee.Trello.WebApi, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Manatee.Trello.WebApi.1.0.1\lib\net45\Manatee.Trello.WebApi.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.8.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
@ -91,6 +111,14 @@
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Net.Http.Formatting, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.Http, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
@ -122,6 +150,7 @@
|
||||
<Compile Include="Modules\Games.cs" />
|
||||
<Compile Include="Modules\Music.cs" />
|
||||
<Compile Include="Modules\Searches.cs" />
|
||||
<Compile Include="Modules\Trello.cs" />
|
||||
<Compile Include="NadekoBot.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="StatsCollector.cs" />
|
||||
|
@ -26,7 +26,7 @@ namespace NadekoBot
|
||||
{
|
||||
this._service = service;
|
||||
|
||||
_service.RanCommand += StatsCollector_RanCommand;
|
||||
_service.CommandExecuted += StatsCollector_RanCommand;
|
||||
//NadekoBot.client.MessageReceived += Client_MessageReceived;
|
||||
|
||||
StartCollecting();
|
||||
|
Loading…
Reference in New Issue
Block a user