public async Task Skip() { var guild = Context.Guild; var user = Context.Message.Author; var queue = Queues.GetOrCreateService(guild.Id); if (!IsInVoiceChannel(Context.Guild, Context.Message.Author)) { await ReplyAsync("You are not in any channel!"); return; } SocketVoiceChannel channel = FindVoiceChannel(guild, user); if (!channel.Users.Any(x => x.Id == Context.Client.CurrentUser.Id)) { await ReplyAsync("You are not in the same channel as me!"); return; } int requests = queue.RequestSkip(user.Id, channel); int usercount = channel.Users.Count(x => !x.IsBot); float part = (float)requests / usercount; await base.ReplyAsync($"Skip requested ({requests} of {usercount}, {(int)Math.Round(part * 100)}%). " + $"{(int)Math.Round(Config.MinSkipQuota * 100)}% needed."); if (part > Config.MinSkipQuota) { queue.Skip(); await ReplyAsync("Skipping current song."); } }
public async Task Join() { var queue = Queues.GetOrCreateService(Context.Guild.Id); if (!queue.HasEntries()) { await ReplyAsync("The queue is empty!"); return; } SocketGuild guild = Context.Guild; if (!IsInVoiceChannel(guild, Context.Message.Author)) { await ReplyAsync("You are not in a channel!"); return; } SocketVoiceChannel channel = FindVoiceChannel(guild, Context.Message.Author); if (channel.Users.Any(x => x.Id == Context.Client.CurrentUser.Id)) { await ReplyAsync("I'm already in your channel!"); return; } await JoinAndPlay(queue, channel); }
public async Task Play([Remainder, Summary("The query or the URL of the youtube video.")] string urlOrQuery) { SocketGuild guild = Context.Guild; QueueService queue = Queues.GetOrCreateService(guild.Id); string youtubeLink; string title = null; // Query, select first video found, works for links too. // If param looks like a valid Uri, don't search for title similarities. var result = Search(urlOrQuery, 1, Uri.IsWellFormedUriString(urlOrQuery, UriKind.Absolute) ? (Func <VideoInformation, int>)(x => (x.Url == urlOrQuery) ? 0 : 1) : null)[0]; youtubeLink = result.Url; title = result.Title; Enqueue(youtubeLink, title, guild.Id); await ReplyAsync(Enqueued(title)); if (IsInVoiceChannel(guild, Context.Message.Author) && !IAmInVoiceChannel(FindVoiceChannel(guild, Context.Message.Author))) { await JoinAndPlay(queue, FindVoiceChannel(guild, Context.Message.Author)); } else if (!queue.IsPlaying) { PlayQueue(queue, AudioClients.GetClient(guild.Id)); } }
public async Task Remove([Summary("The index of the song to remove.")] int index) { var queue = Queues.GetOrCreateService(Context.Guild.Id); if (queue.TryRemove(index - 1, Context.Message.Author, out string reasonOrTitle)) { await ReplyAsync($"Removed {reasonOrTitle}."); } else { await ReplyAsync($"Failed to remove song at index {index}. Reason: {reasonOrTitle}"); } }
public async Task ShowQueue() { var queue = Queues.GetOrCreateService(Context.Guild.Id); var queueList = queue.GetQueue(); List <string> responseLines = new List <string>(); for (int i = 0; i < queueList.Length; i++) { responseLines.Add($"{i + 1}.: {queueList[i].Title} (added by " + $"{Context.Guild.Users.FirstOrDefault(x => x.Id == queueList[i].OriginatorId)?.Username ?? queueList[i].OriginatorId.ToString()})"); } await ReplyAsync(string.Join("\n", "Current Queue:", string.Join("\n", responseLines))); }
private void Enqueue(string youtubeLink, string title, ulong guildId) { QueueEntry entry = null; if (Cache.TryGetCachedFile(youtubeLink, out MusicFile musicFile)) { entry = QueueEntry.FromMusicFile(musicFile, Context.Message.Author.Id); } else { entry = new QueueEntry(youtubeLink, Context.Message.Author.Id, title, filePath: Path.Combine(Config.FileCachePath, title.RemovePathForbiddenChars()), alreadyDownloaded: false, onDownloadFinished: x => { Cache.AddToCache(youtubeLink, entry, Config.CachePersistTime); }); } Queues.GetOrCreateService(guildId).Add(entry); }
public async Task Search([Remainder, Summary("The search query")] string query) { SocketGuild guild = Context.Guild; QueueService queue = Queues.GetOrCreateService(guild.Id); List <VideoInformation> results = Search(query, Config.MaxSearchResults); var lines = new List <string>(); for (int i = 0; i < results.Count; i++) { lines.Add($"{i + 1}. {results[i].Title}"); } string response = string.Join("\n", lines); var sentMessage = await ReplyAsync(response); using (var waiter = new AutoResetEvent(false)) { // define title reference for later use string title = ""; Task handler(Cacheable <IUserMessage, ulong> message, IMessageChannel channel, SocketReaction reaction) { if (message.Id != sentMessage.Id || reaction.UserId != Context.Message.Author.Id || (!Constants.Keycaps.Contains(reaction.Emote.Name) && Constants.EmojiX != reaction.Emote.Name)) { return(Task.CompletedTask); } if (Constants.EmojiX == reaction.Emote.Name) { title = "Nothing"; waiter.Set(); return(Task.CompletedTask); } for (int i = 0; i < Constants.Keycaps.Length; i++) { if (Constants.Keycaps[i + 1] == reaction.Emote.Name) { Console.WriteLine("i: {0}, Title: {1}", i, results[i].Title); Enqueue(results[i].Url, results[i].Title, Context.Guild.Id); title = results[i].Title; waiter.Set(); return(Task.CompletedTask); } } return(Task.CompletedTask); } for (int i = 1; i <= Math.Min(results.Count, 10); i++) { await sentMessage.AddReactionAsync(new Emoji(Constants.Keycaps[i])); } await sentMessage.AddReactionAsync(new Emoji(Constants.EmojiX)); Context.Client.ReactionAdded += handler; waiter.WaitOne(); Context.Client.ReactionAdded -= handler; await sentMessage.RemoveAllReactionsAsync(); await sentMessage.ModifyAsync(msgProp => msgProp.Content = Enqueued(title)); if (IsInVoiceChannel(guild, Context.Message.Author) && !IAmInVoiceChannel(FindVoiceChannel(guild, Context.Message.Author))) { await JoinAndPlay(queue, FindVoiceChannel(guild, Context.Message.Author)); } else if (!queue.IsPlaying) { PlayQueue(queue, AudioClients.GetClient(guild.Id)); } } }