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:
parent
728aeab809
commit
196f40e648
@ -12,6 +12,9 @@ using NadekoBot.Services.Database.Models;
|
|||||||
using NadekoBot.Services.Music;
|
using NadekoBot.Services.Music;
|
||||||
using NadekoBot.DataStructures;
|
using NadekoBot.DataStructures;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net.Http;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Music
|
namespace NadekoBot.Modules.Music
|
||||||
{
|
{
|
||||||
@ -36,6 +39,8 @@ namespace NadekoBot.Modules.Music
|
|||||||
//_client.UserVoiceStateUpdated += Client_UserVoiceStateUpdated;
|
//_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)
|
//private Task Client_UserVoiceStateUpdated(SocketUser iusr, SocketVoiceState oldState, SocketVoiceState newState)
|
||||||
//{
|
//{
|
||||||
// var usr = iusr as SocketGuildUser;
|
// var usr = iusr as SocketGuildUser;
|
||||||
@ -84,6 +89,13 @@ namespace NadekoBot.Modules.Music
|
|||||||
|
|
||||||
private async Task InternalQueue(MusicPlayer mp, SongInfo songInfo, bool silent)
|
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;
|
(bool Success, int Index) qData;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -137,6 +149,7 @@ namespace NadekoBot.Modules.Music
|
|||||||
{
|
{
|
||||||
var mp = await _music.GetOrCreatePlayer(Context);
|
var mp = await _music.GetOrCreatePlayer(Context);
|
||||||
var songInfo = await _music.ResolveSong(query, Context.User.ToString());
|
var songInfo = await _music.ResolveSong(query, Context.User.ToString());
|
||||||
|
|
||||||
try { await InternalQueue(mp, songInfo, false); } catch (QueueFullException) { return; }
|
try { await InternalQueue(mp, songInfo, false); } catch (QueueFullException) { return; }
|
||||||
|
|
||||||
if ((await Context.Guild.GetCurrentUserAsync()).GetPermissions((IGuildChannel)Context.Channel).ManageMessages)
|
if ((await Context.Guild.GetCurrentUserAsync()).GetPermissions((IGuildChannel)Context.Channel).ManageMessages)
|
||||||
@ -486,9 +499,8 @@ namespace NadekoBot.Modules.Music
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
await Task.Yield();
|
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);
|
||||||
await Task.WhenAll(Task.Delay(1000), InternalQueue(mp, await _music.ResolveSong(item.Query, Context.User.ToString(), item.ProviderType), true)).ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
catch (SongNotFoundException) { }
|
catch (SongNotFoundException) { }
|
||||||
catch { break; }
|
catch { break; }
|
||||||
@ -524,17 +536,43 @@ namespace NadekoBot.Modules.Music
|
|||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
//[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
//public async Task SoundCloudQueue([Remainder] string query)
|
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);
|
var mp = await _music.GetOrCreatePlayer(Context);
|
||||||
// if ((await Context.Guild.GetCurrentUserAsync()).GetPermissions((IGuildChannel)Context.Channel).ManageMessages)
|
var song = await _music.ResolveSong(query, Context.User.ToString(), MusicType.Soundcloud);
|
||||||
// {
|
await InternalQueue(mp, song, false).ConfigureAwait(false);
|
||||||
// Context.Message.DeleteAfter(10);
|
}
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
//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]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task NowPlaying()
|
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);
|
// 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))
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
// return;
|
[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 mp = await _music.GetOrCreatePlayer(Context);
|
||||||
// {
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
// MusicPlayer musicPlayer;
|
DirectoryInfo dir;
|
||||||
// if ((musicPlayer = _music.GetPlayer(Context.Guild.Id)) == null)
|
try { dir = new DirectoryInfo(dirPath); } catch { return; }
|
||||||
// return;
|
var fileEnum = dir.GetFiles("*", SearchOption.AllDirectories)
|
||||||
|
.Where(x => !x.Attributes.HasFlag(FileAttributes.Hidden | FileAttributes.System) && x.Extension != ".jpg" && x.Extension != ".png");
|
||||||
// foreach (var svideo in scvids.Skip(1))
|
foreach (var file in fileEnum)
|
||||||
// {
|
{
|
||||||
// try
|
try
|
||||||
// {
|
{
|
||||||
// musicPlayer.AddSong(new Song(new SongInfo
|
var song = await _music.ResolveSong(file.FullName, Context.User.ToString(), MusicType.Local);
|
||||||
// {
|
await InternalQueue(mp, song, true).ConfigureAwait(false);
|
||||||
// Title = svideo.FullName,
|
}
|
||||||
// Provider = "SoundCloud",
|
catch (QueueFullException)
|
||||||
// Uri = await svideo.StreamLink(),
|
{
|
||||||
// ProviderType = MusicType.Normal,
|
break;
|
||||||
// Query = svideo.TrackLink,
|
}
|
||||||
// }), ((IGuildUser)Context.User).Username);
|
catch (Exception ex)
|
||||||
// }
|
{
|
||||||
// catch (PlaylistFullException) { break; }
|
_log.Warn(ex);
|
||||||
// }
|
break;
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
|
await ReplyConfirmLocalized("dir_queue_complete").ConfigureAwait(false);
|
||||||
//[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);
|
|
||||||
|
|
||||||
//}
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
@ -776,8 +770,6 @@ namespace NadekoBot.Modules.Music
|
|||||||
// await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
|
// await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
|
||||||
|
|
||||||
// //await channel.SendConfirmAsync($"🎵Moved {s.PrettyName} `from #{n1} to #{n2}`").ConfigureAwait(false);
|
// //await channel.SendConfirmAsync($"🎵Moved {s.PrettyName} `from #{n1} to #{n2}`").ConfigureAwait(false);
|
||||||
|
|
||||||
|
|
||||||
//}
|
//}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
public enum MusicType
|
public enum MusicType
|
||||||
{
|
{
|
||||||
Radio,
|
Radio,
|
||||||
Normal,
|
YouTube,
|
||||||
Local,
|
Local,
|
||||||
Soundcloud
|
Soundcloud
|
||||||
}
|
}
|
||||||
|
@ -115,10 +115,10 @@ namespace NadekoBot.Services.Music
|
|||||||
// i don't want to spam connection attempts
|
// i don't want to spam connection attempts
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var pcm = ac.CreatePCMStream(AudioApplication.Music, bufferMillis: 1000);
|
var pcm = ac.CreatePCMStream(AudioApplication.Music, bufferMillis: 200);
|
||||||
OnStarted?.Invoke(this, data.Song);
|
OnStarted?.Invoke(this, data.Song);
|
||||||
|
|
||||||
byte[] buffer = new byte[38400];
|
byte[] buffer = new byte[3840];
|
||||||
int bytesRead = 0;
|
int bytesRead = 0;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -127,7 +127,7 @@ namespace NadekoBot.Services.Music
|
|||||||
var vol = Volume;
|
var vol = Volume;
|
||||||
if (vol != 1)
|
if (vol != 1)
|
||||||
AdjustVolume(buffer, vol);
|
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);
|
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
|
//if last song, and autoplay is enabled, and if it's a youtube song
|
||||||
// do autplay magix
|
// 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
|
try
|
||||||
{
|
{
|
||||||
|
@ -11,6 +11,8 @@ using VideoLibrary;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Net.Http;
|
||||||
|
|
||||||
namespace NadekoBot.Services.Music
|
namespace NadekoBot.Services.Music
|
||||||
{
|
{
|
||||||
@ -156,24 +158,7 @@ namespace NadekoBot.Services.Music
|
|||||||
// ignored
|
// 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;
|
return mp;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -192,27 +177,109 @@ namespace NadekoBot.Services.Music
|
|||||||
if (!related.Any())
|
if (!related.Any())
|
||||||
return;
|
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);
|
var mp = await GetOrCreatePlayer(txtCh.GuildId, vch, txtCh);
|
||||||
mp.Enqueue(si);
|
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));
|
query.ThrowIfNull(nameof(query));
|
||||||
|
|
||||||
SongInfo sinfo;
|
SongInfo sinfo = null;
|
||||||
|
switch (musicType)
|
||||||
sinfo = await ResolveYoutubeSong(query, queuerName).ConfigureAwait(false);
|
{
|
||||||
|
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;
|
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)
|
public async Task<SongInfo> ResolveYoutubeSong(string query, string queuerName)
|
||||||
{
|
{
|
||||||
var link = (await _google.GetVideoLinksByKeywordAsync(query).ConfigureAwait(false)).FirstOrDefault();
|
var link = (await _google.GetVideoLinksByKeywordAsync(query).ConfigureAwait(false)).FirstOrDefault();
|
||||||
if (string.IsNullOrWhiteSpace(link))
|
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 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 videos = allVideos.Where(v => v.AdaptiveKind == AdaptiveKind.Audio);
|
||||||
var video = videos
|
var video = videos
|
||||||
@ -221,7 +288,7 @@ namespace NadekoBot.Services.Music
|
|||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
|
|
||||||
if (video == null) // do something with this error
|
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*)");
|
//var m = Regex.Match(query, @"\?t=(?<t>\d*)");
|
||||||
//int gotoTime = 0;
|
//int gotoTime = 0;
|
||||||
//if (m.Captures.Count > 0)
|
//if (m.Captures.Count > 0)
|
||||||
@ -232,171 +299,119 @@ namespace NadekoBot.Services.Music
|
|||||||
Provider = "YouTube",
|
Provider = "YouTube",
|
||||||
Uri = await video.GetUriAsync().ConfigureAwait(false),
|
Uri = await video.GetUriAsync().ConfigureAwait(false),
|
||||||
Query = link,
|
Query = link,
|
||||||
ProviderType = MusicType.Normal,
|
ProviderType = MusicType.YouTube,
|
||||||
QueuerName = queuerName
|
QueuerName = queuerName
|
||||||
};
|
};
|
||||||
return song;
|
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)
|
public async Task DestroyPlayer(ulong id)
|
||||||
{
|
{
|
||||||
if (MusicPlayers.TryRemove(id, out var mp))
|
if (MusicPlayers.TryRemove(id, out var mp))
|
||||||
await mp.Destroy();
|
await mp.Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
// public async Task QueueSong(IGuildUser queuer, ITextChannel textCh, IVoiceChannel voiceCh, string query, bool silent = false, MusicType musicType = MusicType.Normal)
|
private readonly Regex plsRegex = new Regex("File1=(?<url>.*?)\\n", RegexOptions.Compiled);
|
||||||
// {
|
private readonly Regex m3uRegex = new Regex("(?<url>^[^#].*)", RegexOptions.Compiled | RegexOptions.Multiline);
|
||||||
// string GetText(string text, params object[] replacements) =>
|
private readonly Regex asxRegex = new Regex("<ref href=\"(?<url>.*?)\"", RegexOptions.Compiled);
|
||||||
// _strings.GetText(text, _localization.GetCultureInfo(textCh.Guild), "Music".ToLowerInvariant(), replacements);
|
private readonly Regex xspfRegex = new Regex("<location>(?<url>.*?)</location>", RegexOptions.Compiled);
|
||||||
|
|
||||||
//if (string.IsNullOrWhiteSpace(query) || query.Length< 3)
|
private async Task<string> HandleStreamContainers(string query)
|
||||||
// throw new ArgumentException("Invalid song query.", nameof(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;
|
if (query.Contains(".asx"))
|
||||||
// try
|
{
|
||||||
// {
|
//<ref href="http://armitunes.com:8000"/>
|
||||||
// musicPlayer.ThrowIfQueueFull();
|
try
|
||||||
// resolvedSong = await ResolveSong(query, musicType).ConfigureAwait(false);
|
{
|
||||||
|
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)
|
return query;
|
||||||
// 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"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -47,7 +47,7 @@ namespace NadekoBot.Services.Music
|
|||||||
{
|
{
|
||||||
switch (ProviderType)
|
switch (ProviderType)
|
||||||
{
|
{
|
||||||
case MusicType.Normal:
|
case MusicType.YouTube:
|
||||||
return Query;
|
return Query;
|
||||||
case MusicType.Soundcloud:
|
case MusicType.Soundcloud:
|
||||||
return Query;
|
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);
|
private readonly Regex videoIdRegex = new Regex("<=v=[a-zA-Z0-9-]+(?=&)|(?<=[0-9])[^&\n]+|(?<=v=)[^&\n]+", RegexOptions.Compiled);
|
||||||
public string Thumbnail
|
public string Thumbnail
|
||||||
{
|
{
|
||||||
@ -69,9 +70,8 @@ namespace NadekoBot.Services.Music
|
|||||||
{
|
{
|
||||||
case MusicType.Radio:
|
case MusicType.Radio:
|
||||||
return "https://cdn.discordapp.com/attachments/155726317222887425/261850925063340032/1482522097_radio.png"; //test links
|
return "https://cdn.discordapp.com/attachments/155726317222887425/261850925063340032/1482522097_radio.png"; //test links
|
||||||
case MusicType.Normal:
|
case MusicType.YouTube:
|
||||||
//todo have videoid in songinfo from the start
|
videoId = videoId ?? videoIdRegex.Match(Query)?.ToString();
|
||||||
var videoId = videoIdRegex.Match(Query);
|
|
||||||
return $"https://img.youtube.com/vi/{ videoId }/0.jpg";
|
return $"https://img.youtube.com/vi/{ videoId }/0.jpg";
|
||||||
case MusicType.Local:
|
case MusicType.Local:
|
||||||
return "https://cdn.discordapp.com/attachments/155726317222887425/261850914783100928/1482522077_music.png"; //test links
|
return "https://cdn.discordapp.com/attachments/155726317222887425/261850914783100928/1482522077_music.png"; //test links
|
||||||
|
Loading…
Reference in New Issue
Block a user