readded .sq and .lo and .lopl, also .lopl will now explicitly avoid files with .jpg and .png extension (usually album images)

This commit is contained in:
Master Kwoth 2017-07-02 19:00:25 +02:00
parent 728aeab809
commit 196f40e648
5 changed files with 301 additions and 294 deletions

View File

@ -12,6 +12,9 @@ using NadekoBot.Services.Database.Models;
using NadekoBot.Services.Music;
using NadekoBot.DataStructures;
using System.Collections.Concurrent;
using System.IO;
using System.Net.Http;
using Newtonsoft.Json.Linq;
namespace NadekoBot.Modules.Music
{
@ -36,6 +39,8 @@ namespace NadekoBot.Modules.Music
//_client.UserVoiceStateUpdated += Client_UserVoiceStateUpdated;
}
//todo when someone drags nadeko from one voice channel to another
//private Task Client_UserVoiceStateUpdated(SocketUser iusr, SocketVoiceState oldState, SocketVoiceState newState)
//{
// var usr = iusr as SocketGuildUser;
@ -84,6 +89,13 @@ namespace NadekoBot.Modules.Music
private async Task InternalQueue(MusicPlayer mp, SongInfo songInfo, bool silent)
{
if (songInfo == null)
{
if(!silent)
await ReplyErrorLocalized("song_not_found").ConfigureAwait(false);
return;
}
(bool Success, int Index) qData;
try
{
@ -137,6 +149,7 @@ namespace NadekoBot.Modules.Music
{
var mp = await _music.GetOrCreatePlayer(Context);
var songInfo = await _music.ResolveSong(query, Context.User.ToString());
try { await InternalQueue(mp, songInfo, false); } catch (QueueFullException) { return; }
if ((await Context.Guild.GetCurrentUserAsync()).GetPermissions((IGuildChannel)Context.Channel).ManageMessages)
@ -486,8 +499,7 @@ namespace NadekoBot.Modules.Music
try
{
await Task.Yield();
//todo fix for all
if (item.ProviderType == MusicType.Normal)
await Task.WhenAll(Task.Delay(1000), InternalQueue(mp, await _music.ResolveSong(item.Query, Context.User.ToString(), item.ProviderType), true)).ConfigureAwait(false);
}
catch (SongNotFoundException) { }
@ -524,17 +536,43 @@ namespace NadekoBot.Modules.Music
// }
//}
//[NadekoCommand, Usage, Description, Aliases]
//[RequireContext(ContextType.Guild)]
//public async Task SoundCloudQueue([Remainder] string query)
//{
// await _music.QueueSong(((IGuildUser)Context.User), (ITextChannel)Context.Channel, ((IGuildUser)Context.User).VoiceChannel, query, musicType: MusicType.Soundcloud).ConfigureAwait(false);
// if ((await Context.Guild.GetCurrentUserAsync()).GetPermissions((IGuildChannel)Context.Channel).ManageMessages)
// {
// Context.Message.DeleteAfter(10);
// }
//}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task SoundCloudQueue([Remainder] string query)
{
var mp = await _music.GetOrCreatePlayer(Context);
var song = await _music.ResolveSong(query, Context.User.ToString(), MusicType.Soundcloud);
await InternalQueue(mp, song, false).ConfigureAwait(false);
}
//todo test soundcloudpl
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task SoundCloudPl([Remainder] string pl)
{
pl = pl?.Trim();
if (string.IsNullOrWhiteSpace(pl))
return;
var mp = await _music.GetOrCreatePlayer(Context);
using (var http = new HttpClient())
{
var scvids = JObject.Parse(await http.GetStringAsync($"https://scapi.nadekobot.me/resolve?url={pl}").ConfigureAwait(false))["tracks"].ToObject<SoundCloudVideo[]>();
foreach (var svideo in scvids)
{
try
{
await InternalQueue(mp, await _music.SongInfoFromSVideo(svideo, Context.User.ToString()), true);
}
catch { break; }
}
}
}
//todo fix playlist sync stuff
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task NowPlaying()
@ -619,103 +657,59 @@ namespace NadekoBot.Modules.Music
// await msg.ModifyAsync(m => m.Content = "✅ " + Format.Bold(GetText("playlist_queue_complete"))).ConfigureAwait(false);
//}
//[NadekoCommand, Usage, Description, Aliases]
//[RequireContext(ContextType.Guild)]
//public async Task SoundCloudPl([Remainder] string pl)
//{
// pl = pl?.Trim();
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task Radio(string radioLink)
{
var mp = await _music.GetOrCreatePlayer(Context);
var song = await _music.ResolveSong(radioLink, Context.User.ToString(), MusicType.Radio);
await InternalQueue(mp, song, false).ConfigureAwait(false);
}
// if (string.IsNullOrWhiteSpace(pl))
// return;
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[OwnerOnly]
public async Task Local([Remainder] string path)
{
var mp = await _music.GetOrCreatePlayer(Context);
var song = await _music.ResolveSong(path, Context.User.ToString(), MusicType.Local);
await InternalQueue(mp, song, false).ConfigureAwait(false);
}
//todo test localpl
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[OwnerOnly]
public async Task LocalPl([Remainder] string dirPath)
{
if (string.IsNullOrWhiteSpace(dirPath))
return;
// using (var http = new HttpClient())
// {
// var scvids = JObject.Parse(await http.GetStringAsync($"https://scapi.nadekobot.me/resolve?url={pl}").ConfigureAwait(false))["tracks"].ToObject<SoundCloudVideo[]>();
// await _music.QueueSong(((IGuildUser)Context.User), (ITextChannel)Context.Channel, ((IGuildUser)Context.User).VoiceChannel, scvids[0].TrackLink).ConfigureAwait(false);
var mp = await _music.GetOrCreatePlayer(Context);
// MusicPlayer musicPlayer;
// if ((musicPlayer = _music.GetPlayer(Context.Guild.Id)) == null)
// return;
// foreach (var svideo in scvids.Skip(1))
// {
// try
// {
// musicPlayer.AddSong(new Song(new SongInfo
// {
// Title = svideo.FullName,
// Provider = "SoundCloud",
// Uri = await svideo.StreamLink(),
// ProviderType = MusicType.Normal,
// Query = svideo.TrackLink,
// }), ((IGuildUser)Context.User).Username);
// }
// catch (PlaylistFullException) { break; }
// }
// }
//}
//[NadekoCommand, Usage, Description, Aliases]
//[RequireContext(ContextType.Guild)]
//[OwnerOnly]
//public async Task LocalPl([Remainder] string directory)
//{
// var arg = directory;
// if (string.IsNullOrWhiteSpace(arg))
// return;
// var dir = new DirectoryInfo(arg);
// var fileEnum = dir.GetFiles("*", SearchOption.AllDirectories)
// .Where(x => !x.Attributes.HasFlag(FileAttributes.Hidden | FileAttributes.System));
// var gusr = (IGuildUser)Context.User;
// foreach (var file in fileEnum)
// {
// try
// {
// await _music.QueueSong(gusr, (ITextChannel)Context.Channel, gusr.VoiceChannel, file.FullName, true, MusicType.Local).ConfigureAwait(false);
// }
// catch (PlaylistFullException)
// {
// break;
// }
// catch
// {
// // ignored
// }
// }
// await ReplyConfirmLocalized("dir_queue_complete").ConfigureAwait(false);
//}
//[NadekoCommand, Usage, Description, Aliases]
//[RequireContext(ContextType.Guild)]
//public async Task Radio(string radioLink)
//{
// if (((IGuildUser)Context.User).VoiceChannel?.Guild != Context.Guild)
// {
// await ReplyErrorLocalized("must_be_in_voice").ConfigureAwait(false);
// return;
// }
// await _music.QueueSong(((IGuildUser)Context.User), (ITextChannel)Context.Channel, ((IGuildUser)Context.User).VoiceChannel, radioLink, musicType: MusicType.Radio).ConfigureAwait(false);
// if ((await Context.Guild.GetCurrentUserAsync()).GetPermissions((IGuildChannel)Context.Channel).ManageMessages)
// {
// Context.Message.DeleteAfter(10);
// }
//}
//[NadekoCommand, Usage, Description, Aliases]
//[RequireContext(ContextType.Guild)]
//[OwnerOnly]
//public async Task Local([Remainder] string path)
//{
// var arg = path;
// if (string.IsNullOrWhiteSpace(arg))
// return;
// await _music.QueueSong(((IGuildUser)Context.User), (ITextChannel)Context.Channel, ((IGuildUser)Context.User).VoiceChannel, path, musicType: MusicType.Local).ConfigureAwait(false);
//}
DirectoryInfo dir;
try { dir = new DirectoryInfo(dirPath); } catch { return; }
var fileEnum = dir.GetFiles("*", SearchOption.AllDirectories)
.Where(x => !x.Attributes.HasFlag(FileAttributes.Hidden | FileAttributes.System) && x.Extension != ".jpg" && x.Extension != ".png");
foreach (var file in fileEnum)
{
try
{
var song = await _music.ResolveSong(file.FullName, Context.User.ToString(), MusicType.Local);
await InternalQueue(mp, song, true).ConfigureAwait(false);
}
catch (QueueFullException)
{
break;
}
catch (Exception ex)
{
_log.Warn(ex);
break;
}
}
await ReplyConfirmLocalized("dir_queue_complete").ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
@ -776,8 +770,6 @@ namespace NadekoBot.Modules.Music
// await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
// //await channel.SendConfirmAsync($"🎵Moved {s.PrettyName} `from #{n1} to #{n2}`").ConfigureAwait(false);
//}
[NadekoCommand, Usage, Description, Aliases]

View File

@ -12,7 +12,7 @@
public enum MusicType
{
Radio,
Normal,
YouTube,
Local,
Soundcloud
}

View File

@ -115,10 +115,10 @@ namespace NadekoBot.Services.Music
// i don't want to spam connection attempts
continue;
}
var pcm = ac.CreatePCMStream(AudioApplication.Music, bufferMillis: 1000);
var pcm = ac.CreatePCMStream(AudioApplication.Music, bufferMillis: 200);
OnStarted?.Invoke(this, data.Song);
byte[] buffer = new byte[38400];
byte[] buffer = new byte[3840];
int bytesRead = 0;
try
{
@ -127,7 +127,7 @@ namespace NadekoBot.Services.Music
var vol = Volume;
if (vol != 1)
AdjustVolume(buffer, vol);
await Task.WhenAll(Task.Delay(10), pcm.WriteAsync(buffer, 0, bytesRead, cancelToken)).ConfigureAwait(false);
await pcm.WriteAsync(buffer, 0, bytesRead, cancelToken).ConfigureAwait(false);
await (pauseTaskSource?.Task ?? Task.CompletedTask);
}
@ -169,7 +169,7 @@ namespace NadekoBot.Services.Music
{
//if last song, and autoplay is enabled, and if it's a youtube song
// do autplay magix
if (Queue.Count - 1 == data.Index && Autoplay && data.Song?.Provider == "YouTube")
if (Queue.Count - 1 == data.Index && Autoplay && data.Song?.ProviderType == Database.Models.MusicType.YouTube)
{
try
{

View File

@ -11,6 +11,8 @@ using VideoLibrary;
using System.Collections.Generic;
using Discord.Commands;
using Discord.WebSocket;
using System.Text.RegularExpressions;
using System.Net.Http;
namespace NadekoBot.Services.Music
{
@ -156,24 +158,7 @@ namespace NadekoBot.Services.Music
// ignored
}
};
//mp.SongRemoved += async (song, index) =>
//{
// try
// {
// var embed = new EmbedBuilder()
// .WithAuthor(eab => eab.WithName(GetText("removed_song") + " #" + (index + 1)).WithMusicIcon())
// .WithDescription(song.PrettyName)
// .WithFooter(ef => ef.WithText(song.PrettyInfo))
// .WithErrorColor();
// await mp.OutputTextChannel.EmbedAsync(embed).ConfigureAwait(false);
// }
// catch
// {
// // ignored
// }
//};
return mp;
});
}
@ -192,27 +177,109 @@ namespace NadekoBot.Services.Music
if (!related.Any())
return;
var si = await ResolveSong(related[new NadekoRandom().Next(related.Length)], _client.CurrentUser.ToString(), MusicType.Normal);
var si = await ResolveSong(related[new NadekoRandom().Next(related.Length)], _client.CurrentUser.ToString(), MusicType.YouTube);
if (si == null)
throw new SongNotFoundException();
var mp = await GetOrCreatePlayer(txtCh.GuildId, vch, txtCh);
mp.Enqueue(si);
}
public async Task<SongInfo> ResolveSong(string query, string queuerName, MusicType musicType = MusicType.Normal)
public async Task<SongInfo> ResolveSong(string query, string queuerName, MusicType? musicType = null)
{
query.ThrowIfNull(nameof(query));
SongInfo sinfo;
sinfo = await ResolveYoutubeSong(query, queuerName).ConfigureAwait(false);
SongInfo sinfo = null;
switch (musicType)
{
case MusicType.YouTube:
sinfo = await ResolveYoutubeSong(query, queuerName);
break;
case MusicType.Radio:
try { sinfo = ResolveRadioSong(IsRadioLink(query) ? await HandleStreamContainers(query) : query, queuerName); } catch { };
break;
case MusicType.Local:
sinfo = ResolveLocalSong(query, queuerName);
break;
case MusicType.Soundcloud:
sinfo = await ResolveSoundCloudSong(query, queuerName);
break;
case null:
if (_sc.IsSoundCloudLink(query))
sinfo = await ResolveSoundCloudSong(query, queuerName);
else if (IsRadioLink(query))
sinfo = ResolveRadioSong(await HandleStreamContainers(query), queuerName);
else
try
{
sinfo = await ResolveYoutubeSong(query, queuerName);
}
catch
{
sinfo = null;
}
break;
}
return sinfo;
}
public async Task<SongInfo> ResolveSoundCloudSong(string query, string queuerName)
{
var svideo = !_sc.IsSoundCloudLink(query) ?
await _sc.GetVideoByQueryAsync(query).ConfigureAwait(false):
await _sc.ResolveVideoAsync(query).ConfigureAwait(false);
if (svideo == null)
return null;
return await SongInfoFromSVideo(svideo, queuerName);
}
public async Task<SongInfo> SongInfoFromSVideo(SoundCloudVideo svideo, string queuerName) =>
new SongInfo
{
Title = svideo.FullName,
Provider = "SoundCloud",
Uri = await svideo.StreamLink().ConfigureAwait(false),
ProviderType = MusicType.Soundcloud,
Query = svideo.TrackLink,
AlbumArt = svideo.artwork_url,
QueuerName = queuerName
};
public SongInfo ResolveLocalSong(string query, string queuerName)
{
return new SongInfo
{
Uri = "\"" + Path.GetFullPath(query) + "\"",
Title = Path.GetFileNameWithoutExtension(query),
Provider = "Local File",
ProviderType = MusicType.Local,
Query = query,
QueuerName = queuerName
};
}
public SongInfo ResolveRadioSong(string query, string queuerName)
{
return new SongInfo
{
Uri = query,
Title = query,
Provider = "Radio Stream",
ProviderType = MusicType.Radio,
Query = query,
QueuerName = queuerName
};
}
public async Task<SongInfo> ResolveYoutubeSong(string query, string queuerName)
{
var link = (await _google.GetVideoLinksByKeywordAsync(query).ConfigureAwait(false)).FirstOrDefault();
if (string.IsNullOrWhiteSpace(link))
throw new OperationCanceledException("Not a valid youtube query.");
{
_log.Info("No song found.");
return null;
}
var allVideos = await Task.Run(async () => { try { return await YouTube.Default.GetAllVideosAsync(link).ConfigureAwait(false); } catch { return Enumerable.Empty<YouTubeVideo>(); } }).ConfigureAwait(false);
var videos = allVideos.Where(v => v.AdaptiveKind == AdaptiveKind.Audio);
var video = videos
@ -221,7 +288,7 @@ namespace NadekoBot.Services.Music
.FirstOrDefault();
if (video == null) // do something with this error
throw new Exception("Could not load any video elements based on the query.");
_log.Info("Could not load any video elements based on the query.");
//var m = Regex.Match(query, @"\?t=(?<t>\d*)");
//int gotoTime = 0;
//if (m.Captures.Count > 0)
@ -232,171 +299,119 @@ namespace NadekoBot.Services.Music
Provider = "YouTube",
Uri = await video.GetUriAsync().ConfigureAwait(false),
Query = link,
ProviderType = MusicType.Normal,
ProviderType = MusicType.YouTube,
QueuerName = queuerName
};
return song;
}
private bool IsRadioLink(string query) =>
(query.StartsWith("http") ||
query.StartsWith("ww"))
&&
(query.Contains(".pls") ||
query.Contains(".m3u") ||
query.Contains(".asx") ||
query.Contains(".xspf"));
public async Task DestroyPlayer(ulong id)
{
if (MusicPlayers.TryRemove(id, out var mp))
await mp.Destroy();
}
// public async Task QueueSong(IGuildUser queuer, ITextChannel textCh, IVoiceChannel voiceCh, string query, bool silent = false, MusicType musicType = MusicType.Normal)
// {
// string GetText(string text, params object[] replacements) =>
// _strings.GetText(text, _localization.GetCultureInfo(textCh.Guild), "Music".ToLowerInvariant(), replacements);
private readonly Regex plsRegex = new Regex("File1=(?<url>.*?)\\n", RegexOptions.Compiled);
private readonly Regex m3uRegex = new Regex("(?<url>^[^#].*)", RegexOptions.Compiled | RegexOptions.Multiline);
private readonly Regex asxRegex = new Regex("<ref href=\"(?<url>.*?)\"", RegexOptions.Compiled);
private readonly Regex xspfRegex = new Regex("<location>(?<url>.*?)</location>", RegexOptions.Compiled);
//if (string.IsNullOrWhiteSpace(query) || query.Length< 3)
// throw new ArgumentException("Invalid song query.", nameof(query));
private async Task<string> HandleStreamContainers(string query)
{
string file = null;
try
{
using (var http = new HttpClient())
{
file = await http.GetStringAsync(query).ConfigureAwait(false);
}
}
catch
{
return query;
}
if (query.Contains(".pls"))
{
//File1=http://armitunes.com:8000/
//Regex.Match(query)
try
{
var m = plsRegex.Match(file);
var res = m.Groups["url"]?.ToString();
return res?.Trim();
}
catch
{
_log.Warn($"Failed reading .pls:\n{file}");
return null;
}
}
if (query.Contains(".m3u"))
{
/*
# This is a comment
C:\xxx4xx\xxxxxx3x\xx2xxxx\xx.mp3
C:\xxx5xx\x6xxxxxx\x7xxxxx\xx.mp3
*/
try
{
var m = m3uRegex.Match(file);
var res = m.Groups["url"]?.ToString();
return res?.Trim();
}
catch
{
_log.Warn($"Failed reading .m3u:\n{file}");
return null;
}
// var musicPlayer = GetOrCreatePlayer(textCh.Guild.Id, voiceCh, textCh);
// Song resolvedSong;
// try
// {
// musicPlayer.ThrowIfQueueFull();
// resolvedSong = await ResolveSong(query, musicType).ConfigureAwait(false);
}
if (query.Contains(".asx"))
{
//<ref href="http://armitunes.com:8000"/>
try
{
var m = asxRegex.Match(file);
var res = m.Groups["url"]?.ToString();
return res?.Trim();
}
catch
{
_log.Warn($"Failed reading .asx:\n{file}");
return null;
}
}
if (query.Contains(".xspf"))
{
/*
<?xml version="1.0" encoding="UTF-8"?>
<playlist version="1" xmlns="http://xspf.org/ns/0/">
<trackList>
<track><location>file:///mp3s/song_1.mp3</location></track>
*/
try
{
var m = xspfRegex.Match(file);
var res = m.Groups["url"]?.ToString();
return res?.Trim();
}
catch
{
_log.Warn($"Failed reading .xspf:\n{file}");
return null;
}
}
// if (resolvedSong == null)
// throw new SongNotFoundException();
// musicPlayer.AddSong(resolvedSong, queuer.Username);
// }
// catch (PlaylistFullException)
// {
// try
// {
// await textCh.SendConfirmAsync(GetText("queue_full", musicPlayer.MaxQueueSize));
// }
// catch
// {
// // ignored
// }
// throw;
// }
// if (!silent)
// {
// try
// {
// //var queuedMessage = await textCh.SendConfirmAsync($"🎵 Queued **{resolvedSong.SongInfo.Title}** at `#{musicPlayer.Playlist.Count + 1}`").ConfigureAwait(false);
// var queuedMessage = await textCh.EmbedAsync(new EmbedBuilder().WithOkColor()
// .WithAuthor(eab => eab.WithName(GetText("queued_song") + " #" + (musicPlayer.Playlist.Count + 1)).WithMusicIcon())
// .WithDescription($"{resolvedSong.PrettyName}\n{GetText("queue")} ")
// .WithThumbnailUrl(resolvedSong.Thumbnail)
// .WithFooter(ef => ef.WithText(resolvedSong.PrettyProvider)))
// .ConfigureAwait(false);
// queuedMessage?.DeleteAfter(10);
// }
// catch
// {
// // ignored
// } // if queued message sending fails, don't attempt to delete it
// }
// }
// private async Task<string> HandleStreamContainers(string query)
// {
// string file = null;
// try
// {
// using (var http = new HttpClient())
// {
// file = await http.GetStringAsync(query).ConfigureAwait(false);
// }
// }
// catch
// {
// return query;
// }
// if (query.Contains(".pls"))
// {
// //File1=http://armitunes.com:8000/
// //Regex.Match(query)
// try
// {
// var m = Regex.Match(file, "File1=(?<url>.*?)\\n");
// var res = m.Groups["url"]?.ToString();
// return res?.Trim();
// }
// catch
// {
// _log.Warn($"Failed reading .pls:\n{file}");
// return null;
// }
// }
// if (query.Contains(".m3u"))
// {
// /*
//# This is a comment
// C:\xxx4xx\xxxxxx3x\xx2xxxx\xx.mp3
// C:\xxx5xx\x6xxxxxx\x7xxxxx\xx.mp3
// */
// try
// {
// var m = Regex.Match(file, "(?<url>^[^#].*)", RegexOptions.Multiline);
// var res = m.Groups["url"]?.ToString();
// return res?.Trim();
// }
// catch
// {
// _log.Warn($"Failed reading .m3u:\n{file}");
// return null;
// }
// }
// if (query.Contains(".asx"))
// {
// //<ref href="http://armitunes.com:8000"/>
// try
// {
// var m = Regex.Match(file, "<ref href=\"(?<url>.*?)\"");
// var res = m.Groups["url"]?.ToString();
// return res?.Trim();
// }
// catch
// {
// _log.Warn($"Failed reading .asx:\n{file}");
// return null;
// }
// }
// if (query.Contains(".xspf"))
// {
// /*
// <?xml version="1.0" encoding="UTF-8"?>
// <playlist version="1" xmlns="http://xspf.org/ns/0/">
// <trackList>
// <track><location>file:///mp3s/song_1.mp3</location></track>
// */
// try
// {
// var m = Regex.Match(file, "<location>(?<url>.*?)</location>");
// var res = m.Groups["url"]?.ToString();
// return res?.Trim();
// }
// catch
// {
// _log.Warn($"Failed reading .xspf:\n{file}");
// return null;
// }
// }
// return query;
// }
// private bool IsRadioLink(string query) =>
// (query.StartsWith("http") ||
// query.StartsWith("ww"))
// &&
// (query.Contains(".pls") ||
// query.Contains(".m3u") ||
// query.Contains(".asx") ||
// query.Contains(".xspf"));
return query;
}
}
}

View File

@ -47,7 +47,7 @@ namespace NadekoBot.Services.Music
{
switch (ProviderType)
{
case MusicType.Normal:
case MusicType.YouTube:
return Query;
case MusicType.Soundcloud:
return Query;
@ -60,6 +60,7 @@ namespace NadekoBot.Services.Music
}
}
}
private string videoId = null;
private readonly Regex videoIdRegex = new Regex("<=v=[a-zA-Z0-9-]+(?=&)|(?<=[0-9])[^&\n]+|(?<=v=)[^&\n]+", RegexOptions.Compiled);
public string Thumbnail
{
@ -69,9 +70,8 @@ namespace NadekoBot.Services.Music
{
case MusicType.Radio:
return "https://cdn.discordapp.com/attachments/155726317222887425/261850925063340032/1482522097_radio.png"; //test links
case MusicType.Normal:
//todo have videoid in songinfo from the start
var videoId = videoIdRegex.Match(Query);
case MusicType.YouTube:
videoId = videoId ?? videoIdRegex.Match(Query)?.ToString();
return $"https://img.youtube.com/vi/{ videoId }/0.jpg";
case MusicType.Local:
return "https://cdn.discordapp.com/attachments/155726317222887425/261850914783100928/1482522077_music.png"; //test links