.qs command added
This commit is contained in:
		@@ -182,6 +182,44 @@ namespace NadekoBot.Modules.Music
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [NadekoCommand, Usage, Description, Aliases]
 | 
				
			||||||
 | 
					        [RequireContext(ContextType.Guild)]
 | 
				
			||||||
 | 
					        public async Task QueueSearch([Remainder] string query)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var videos = (await _google.GetVideoInfosByKeywordAsync(query, 5))
 | 
				
			||||||
 | 
					                .ToArray();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!videos.Any())
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                await ReplyErrorLocalized("song_not_found").ConfigureAwait(false);
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var msg = await Context.Channel.SendConfirmAsync(string.Join("\n", videos.Select((x, i) => $"`{i + 1}.`\n\t{Format.Bold(x.Name)}\n\t{x.Url}")));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            try
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                var input = await GetUserInputAsync(Context.User.Id, Context.Channel.Id);
 | 
				
			||||||
 | 
					                if (input == null
 | 
				
			||||||
 | 
					                    || !int.TryParse(input, out var index)
 | 
				
			||||||
 | 
					                    || (index -= 1) < 0
 | 
				
			||||||
 | 
					                    || index >= videos.Length)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    try { await msg.DeleteAsync().ConfigureAwait(false); } catch { }
 | 
				
			||||||
 | 
					                    return;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                query = videos[index].Url;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                await Queue(query).ConfigureAwait(false);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            finally
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                try { await msg.DeleteAsync().ConfigureAwait(false); } catch { }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [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)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,8 @@ using NadekoBot.Services;
 | 
				
			|||||||
using NLog;
 | 
					using NLog;
 | 
				
			||||||
using System.Globalization;
 | 
					using System.Globalization;
 | 
				
			||||||
using System.Threading.Tasks;
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using Discord.WebSocket;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace NadekoBot.Modules
 | 
					namespace NadekoBot.Modules
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -84,6 +86,44 @@ namespace NadekoBot.Modules
 | 
				
			|||||||
            var text = GetText(textKey, replacements);
 | 
					            var text = GetText(textKey, replacements);
 | 
				
			||||||
            return Context.Channel.SendConfirmAsync(Context.User.Mention + " " + text);
 | 
					            return Context.Channel.SendConfirmAsync(Context.User.Mention + " " + text);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // todo maybe make this generic and use
 | 
				
			||||||
 | 
					        // TypeConverter typeConverter = TypeDescriptor.GetConverter(propType);
 | 
				
			||||||
 | 
					        public async Task<string> GetUserInputAsync(ulong userId, ulong channelId)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var userInputTask = new TaskCompletionSource<string>();
 | 
				
			||||||
 | 
					            var dsc = (DiscordShardedClient)Context.Client;
 | 
				
			||||||
 | 
					            try
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                dsc.MessageReceived += MessageReceived;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if ((await Task.WhenAny(userInputTask.Task, Task.Delay(10000))) != userInputTask.Task)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    return null;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return await userInputTask.Task;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            finally
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                dsc.MessageReceived -= MessageReceived;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Task MessageReceived(SocketMessage arg)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (!(arg is SocketUserMessage userMsg) ||
 | 
				
			||||||
 | 
					                    !(userMsg.Channel is ITextChannel chan) ||
 | 
				
			||||||
 | 
					                    userMsg.Author.Id != userId ||
 | 
				
			||||||
 | 
					                    userMsg.Channel.Id != channelId)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    return Task.CompletedTask;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                userInputTask.SetResult(arg.Content);
 | 
				
			||||||
 | 
					                userMsg.DeleteAfter(1);
 | 
				
			||||||
 | 
					                return Task.CompletedTask;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract class NadekoSubmodule : NadekoTopLevelModule
 | 
					    public abstract class NadekoSubmodule : NadekoTopLevelModule
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -89,7 +89,7 @@ namespace NadekoBot.Modules.Searches
 | 
				
			|||||||
        public async Task Youtube([Remainder] string query = null)
 | 
					        public async Task Youtube([Remainder] string query = null)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (!await ValidateQuery(Context.Channel, query).ConfigureAwait(false)) return;
 | 
					            if (!await ValidateQuery(Context.Channel, query).ConfigureAwait(false)) return;
 | 
				
			||||||
            var result = (await _google.GetVideosByKeywordsAsync(query, 1)).FirstOrDefault();
 | 
					            var result = (await _google.GetVideoLinksByKeywordAsync(query, 1)).FirstOrDefault();
 | 
				
			||||||
            if (string.IsNullOrWhiteSpace(result))
 | 
					            if (string.IsNullOrWhiteSpace(result))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                await ReplyErrorLocalized("no_results").ConfigureAwait(false);
 | 
					                await ReplyErrorLocalized("no_results").ConfigureAwait(false);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1512,6 +1512,15 @@
 | 
				
			|||||||
  <data name="queue_usage" xml:space="preserve">
 | 
					  <data name="queue_usage" xml:space="preserve">
 | 
				
			||||||
    <value>`{0}q Dream Of Venice`</value>
 | 
					    <value>`{0}q Dream Of Venice`</value>
 | 
				
			||||||
  </data>
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="queuesearch_cmd" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>queuesearch qs yqs</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="queuesearch_desc" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>Search for top 5 youtube song result using keywords, and type the index of the song to play that song. Bot will join your voice channel. **You must be in a voice channel**.</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="queuesearch_usage" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>`{0}qs Dream Of Venice`</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
  <data name="soundcloudqueue_cmd" xml:space="preserve">
 | 
					  <data name="soundcloudqueue_cmd" xml:space="preserve">
 | 
				
			||||||
    <value>soundcloudqueue sq</value>
 | 
					    <value>soundcloudqueue sq</value>
 | 
				
			||||||
  </data>
 | 
					  </data>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,7 +9,8 @@ namespace NadekoBot.Services
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        IEnumerable<string> Languages { get; }
 | 
					        IEnumerable<string> Languages { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Task<IEnumerable<string>> GetVideosByKeywordsAsync(string keywords, int count = 1);
 | 
					        Task<IEnumerable<string>> GetVideoLinksByKeywordAsync(string keywords, int count = 1);
 | 
				
			||||||
 | 
					        Task<IEnumerable<(string Name, string Id, string Url)>> GetVideoInfosByKeywordAsync(string keywords, int count = 1);
 | 
				
			||||||
        Task<IEnumerable<string>> GetPlaylistIdsByKeywordsAsync(string keywords, int count = 1);
 | 
					        Task<IEnumerable<string>> GetPlaylistIdsByKeywordsAsync(string keywords, int count = 1);
 | 
				
			||||||
        Task<IEnumerable<string>> GetRelatedVideosAsync(string url, int count = 1);
 | 
					        Task<IEnumerable<string>> GetRelatedVideosAsync(string url, int count = 1);
 | 
				
			||||||
        Task<IEnumerable<string>> GetPlaylistTracksAsync(string playlistId, int count = 50);
 | 
					        Task<IEnumerable<string>> GetPlaylistTracksAsync(string playlistId, int count = 50);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,6 +12,7 @@ using Google.Apis.Customsearch.v1;
 | 
				
			|||||||
using System.Net.Http;
 | 
					using System.Net.Http;
 | 
				
			||||||
using System.Net;
 | 
					using System.Net;
 | 
				
			||||||
using Newtonsoft.Json.Linq;
 | 
					using Newtonsoft.Json.Linq;
 | 
				
			||||||
 | 
					using NadekoBot.Extensions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace NadekoBot.Services.Impl
 | 
					namespace NadekoBot.Services.Impl
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -86,7 +87,7 @@ namespace NadekoBot.Services.Impl
 | 
				
			|||||||
            return (await query.ExecuteAsync()).Items.Select(i => "http://www.youtube.com/watch?v=" + i.Id.VideoId);
 | 
					            return (await query.ExecuteAsync()).Items.Select(i => "http://www.youtube.com/watch?v=" + i.Id.VideoId);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public async Task<IEnumerable<string>> GetVideosByKeywordsAsync(string keywords, int count = 1)
 | 
					        public async Task<IEnumerable<string>> GetVideoLinksByKeywordAsync(string keywords, int count = 1)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (string.IsNullOrWhiteSpace(keywords))
 | 
					            if (string.IsNullOrWhiteSpace(keywords))
 | 
				
			||||||
                throw new ArgumentNullException(nameof(keywords));
 | 
					                throw new ArgumentNullException(nameof(keywords));
 | 
				
			||||||
@@ -111,6 +112,21 @@ namespace NadekoBot.Services.Impl
 | 
				
			|||||||
            return (await query.ExecuteAsync()).Items.Select(i => "http://www.youtube.com/watch?v=" + i.Id.VideoId);
 | 
					            return (await query.ExecuteAsync()).Items.Select(i => "http://www.youtube.com/watch?v=" + i.Id.VideoId);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public async Task<IEnumerable<(string Name, string Id, string Url)>> GetVideoInfosByKeywordAsync(string keywords, int count = 1)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (string.IsNullOrWhiteSpace(keywords))
 | 
				
			||||||
 | 
					                throw new ArgumentNullException(nameof(keywords));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (count <= 0)
 | 
				
			||||||
 | 
					                throw new ArgumentOutOfRangeException(nameof(count));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var query = yt.Search.List("snippet");
 | 
				
			||||||
 | 
					            query.MaxResults = count;
 | 
				
			||||||
 | 
					            query.Q = keywords;
 | 
				
			||||||
 | 
					            query.Type = "video";
 | 
				
			||||||
 | 
					            return (await query.ExecuteAsync()).Items.Select(i => (i.Snippet.Title.TrimTo(50), i.Id.VideoId, "http://www.youtube.com/watch?v=" + i.Id.VideoId));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public async Task<string> ShortenUrl(string url)
 | 
					        public async Task<string> ShortenUrl(string url)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (string.IsNullOrWhiteSpace(url))
 | 
					            if (string.IsNullOrWhiteSpace(url))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -304,7 +304,7 @@ namespace NadekoBot.Services.Music
 | 
				
			|||||||
                    { TotalTime = TimeSpan.FromMilliseconds(svideo.Duration) };
 | 
					                    { TotalTime = TimeSpan.FromMilliseconds(svideo.Duration) };
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                var link = (await _google.GetVideosByKeywordsAsync(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.");
 | 
					                    throw new OperationCanceledException("Not a valid youtube query.");
 | 
				
			||||||
                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);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,7 +23,7 @@ namespace NadekoBot.Services.Utility
 | 
				
			|||||||
        private readonly SemaphoreSlim claimLockJustInCase = new SemaphoreSlim(1, 1);
 | 
					        private readonly SemaphoreSlim claimLockJustInCase = new SemaphoreSlim(1, 1);
 | 
				
			||||||
        private readonly Logger _log;
 | 
					        private readonly Logger _log;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public readonly TimeSpan Interval = TimeSpan.FromHours(1);
 | 
					        public readonly TimeSpan Interval = TimeSpan.FromMinutes(15);
 | 
				
			||||||
        private IBotCredentials _creds;
 | 
					        private IBotCredentials _creds;
 | 
				
			||||||
        private readonly DbService _db;
 | 
					        private readonly DbService _db;
 | 
				
			||||||
        private readonly CurrencyService _currency;
 | 
					        private readonly CurrencyService _currency;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user