initial
This commit is contained in:
@@ -0,0 +1,164 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Discord;
|
||||
using Discord.Audio;
|
||||
using Discord.WebSocket;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace KasinoBot
|
||||
{
|
||||
public class Music
|
||||
{
|
||||
private IAudioClient AudioClient { get; set; }
|
||||
private ISocketMessageChannel TextChannel { get; set; }
|
||||
private Queue<MusicInfo> Queue { get; }
|
||||
private Stream? CurrentMusicStream { get; set; }
|
||||
private Process? CurrentFFmpeg { get; set; }
|
||||
private AudioOutStream? CurrentOuAudio { get; set; }
|
||||
|
||||
public Music(SocketGuild guild, ISocketMessageChannel channel, IAudioClient audioClient)
|
||||
{
|
||||
Queue = new Queue<MusicInfo>();
|
||||
TextChannel = channel;
|
||||
AudioClient = audioClient;
|
||||
}
|
||||
|
||||
public async Task Play(string query, SocketUser user, SocketUserMessage message)
|
||||
{
|
||||
if (message.Channel != null)
|
||||
TextChannel = message.Channel;
|
||||
|
||||
MusicInfo musicInfo = new MusicInfo(query, user);
|
||||
//await message.AddReactionAsync(Emoji.Parse("👌"));
|
||||
await TextChannel.SendMessageAsync($"Enqueued **\"{musicInfo.Title}\"** *({musicInfo.Duration})*");
|
||||
|
||||
Queue.Enqueue(musicInfo);
|
||||
if (Queue.Count == 1)
|
||||
await PlayNextMusic();
|
||||
}
|
||||
|
||||
public async Task Stop()
|
||||
{
|
||||
Queue.Clear();
|
||||
if (CurrentMusicStream != null)
|
||||
CurrentMusicStream.Close();
|
||||
await Task.Delay(10);
|
||||
}
|
||||
|
||||
public async Task Skip()
|
||||
{
|
||||
Console.WriteLine("Skipping");
|
||||
if (CurrentMusicStream != null)
|
||||
CurrentMusicStream.Close();
|
||||
await Task.Delay(10);
|
||||
}
|
||||
|
||||
private async Task PlayNextMusic()
|
||||
{
|
||||
if (Queue.Count == 0)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
var musicInfo = Queue.Peek();
|
||||
|
||||
using (var input = AudioClient.CreatePCMStream(AudioApplication.Music))
|
||||
using (CurrentFFmpeg = CreateAudioStream(musicInfo.MediaURL))
|
||||
using (CurrentMusicStream = CurrentFFmpeg.StandardOutput.BaseStream)
|
||||
{
|
||||
try
|
||||
{
|
||||
await CurrentMusicStream.CopyToAsync(input);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Error CopyToAsync: " + ex.ToString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
Queue.Dequeue();
|
||||
await input.FlushAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
await TextChannel.SendMessageAsync($"Error: {e.Message}");
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
|
||||
await PlayNextMusic();
|
||||
}
|
||||
|
||||
private Process CreateAudioStream(string path)
|
||||
{
|
||||
var p = Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = "ffmpeg",
|
||||
Arguments = $"-hide_banner -loglevel panic -i \"{path}\" -ac 2 -f s16le -ar 48000 pipe:1",
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
});
|
||||
|
||||
if (p == null)
|
||||
throw new Exception("Could not start ffmpeg. Please make sure ffmpeg is available.");
|
||||
else if (p.HasExited)
|
||||
throw new Exception("ffmpeg exited with code " + p.ExitCode);
|
||||
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
public class MusicInfo
|
||||
{
|
||||
public string Query { get; }
|
||||
public SocketUser User { get; }
|
||||
public string Title { get; set; }
|
||||
public string Duration { get; set; }
|
||||
public string MediaURL { get; set; }
|
||||
public string YoutubeURL { get; set; }
|
||||
public MusicInfo(string query, SocketUser user)
|
||||
{
|
||||
Query = query;
|
||||
User = user;
|
||||
|
||||
var p = Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = "youtube-dl",
|
||||
Arguments = $"-f bestaudio --dump-json --default-search \"ytsearch\" -g \"{this.Query}\"",
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
});
|
||||
|
||||
if (p == null)
|
||||
throw new Exception("Could not start youtube-dl. Please make sure youtube-dl is available.");
|
||||
else if (p.HasExited)
|
||||
throw new Exception("youtube-dl exited with code " + p.ExitCode);
|
||||
|
||||
var output = p.StandardOutput.ReadToEnd();
|
||||
p.WaitForExit();
|
||||
|
||||
try
|
||||
{
|
||||
JToken json = JObject.Parse(output.Split('\n')[1]);
|
||||
if (json == null)
|
||||
throw new Exception("Could not parse youtube-dl output.");
|
||||
|
||||
int duration = int.Parse(json["duration"].ToString());
|
||||
this.MediaURL = output.Split('\n')[0];
|
||||
this.Title = json["title"].ToString();
|
||||
this.YoutubeURL = json["webpage_url"].ToString();
|
||||
this.Duration = $"{Math.Floor((float)duration / 60)}m {duration % 60}s";
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new Exception("Error parsing information from Youtube-DL: " + e.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user