2016-08-21 22:37:39 +00:00
using Discord.Commands ;
using NadekoBot.Modules.Music.Classes ;
using System.Collections.Concurrent ;
using Discord.WebSocket ;
using NadekoBot.Services ;
using System.IO ;
using Discord ;
using System.Threading.Tasks ;
using NadekoBot.Attributes ;
using System ;
using System.Linq ;
using NadekoBot.Extensions ;
using System.Net.Http ;
using Newtonsoft.Json.Linq ;
using System.Collections.Generic ;
2016-10-01 03:49:05 +00:00
using NadekoBot.Services.Database.Models ;
2016-12-14 19:29:01 +00:00
using System.Text.RegularExpressions ;
2016-12-21 12:14:24 +00:00
using System.Threading ;
2016-08-21 22:37:39 +00:00
namespace NadekoBot.Modules.Music
{
2016-12-17 00:16:14 +00:00
[NadekoModule("Music", "!!")]
[DontAutoLoad]
2016-08-21 22:47:06 +00:00
public partial class Music : DiscordModule
2016-08-21 22:37:39 +00:00
{
2016-12-08 17:46:08 +00:00
public static ConcurrentDictionary < ulong , MusicPlayer > MusicPlayers { get ; } = new ConcurrentDictionary < ulong , MusicPlayer > ( ) ;
2016-08-21 22:37:39 +00:00
public const string MusicDataPath = "data/musicdata" ;
2017-01-01 12:57:38 +00:00
static Music ( )
2016-08-21 22:37:39 +00:00
{
//it can fail if its currenctly opened or doesn't exist. Either way i don't care
try { Directory . Delete ( MusicDataPath , true ) ; } catch { }
2016-12-21 12:14:24 +00:00
NadekoBot . Client . UserVoiceStateUpdated + = Client_UserVoiceStateUpdated ;
2016-08-21 22:37:39 +00:00
Directory . CreateDirectory ( MusicDataPath ) ;
}
2016-12-21 12:14:24 +00:00
2017-01-01 12:57:38 +00:00
private static async void Client_UserVoiceStateUpdated ( SocketUser iusr , SocketVoiceState oldState , SocketVoiceState newState )
2016-12-14 19:48:44 +00:00
{
2016-12-17 00:16:14 +00:00
var usr = iusr as SocketGuildUser ;
2016-12-14 19:48:44 +00:00
if ( usr = = null | |
oldState . VoiceChannel = = newState . VoiceChannel )
2016-12-16 19:45:46 +00:00
return ;
2016-12-14 19:48:44 +00:00
MusicPlayer player ;
if ( ! MusicPlayers . TryGetValue ( usr . Guild . Id , out player ) )
2016-12-16 19:45:46 +00:00
return ;
2016-12-31 12:21:18 +00:00
try
{
var users = await player . PlaybackVoiceChannel . GetUsersAsync ( ) . Flatten ( ) . ConfigureAwait ( false ) ;
if ( ( player . PlaybackVoiceChannel = = newState . VoiceChannel & & //if joined first, and player paused, unpause
player . Paused & &
users . Count ( ) = = 2 ) | | // keep in mind bot is in the channel (+1)
( player . PlaybackVoiceChannel = = oldState . VoiceChannel & & // if left last, and player unpaused, pause
! player . Paused & &
users . Count ( ) = = 1 ) )
{
player . TogglePause ( ) ;
}
}
2017-01-01 12:57:38 +00:00
catch { }
2016-12-14 19:48:44 +00:00
}
2016-08-21 22:37:39 +00:00
2016-10-05 03:09:44 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-08-21 22:37:39 +00:00
[RequireContext(ContextType.Guild)]
2016-12-16 19:45:46 +00:00
public Task Next ( int skipCount = 1 )
2016-08-21 22:37:39 +00:00
{
2016-10-28 12:08:02 +00:00
if ( skipCount < 1 )
return Task . CompletedTask ;
2016-08-21 22:37:39 +00:00
MusicPlayer musicPlayer ;
2016-12-17 00:16:14 +00:00
if ( ! MusicPlayers . TryGetValue ( Context . Guild . Id , out musicPlayer ) ) return Task . CompletedTask ;
2016-12-16 18:43:57 +00:00
if ( musicPlayer . PlaybackVoiceChannel = = ( ( IGuildUser ) Context . User ) . VoiceChannel )
2016-10-28 12:08:02 +00:00
{
while ( - - skipCount > 0 )
{
musicPlayer . RemoveSongAt ( 0 ) ;
}
2016-08-21 22:37:39 +00:00
musicPlayer . Next ( ) ;
2016-10-28 12:08:02 +00:00
}
2016-09-10 19:40:25 +00:00
return Task . CompletedTask ;
2016-08-21 22:37:39 +00:00
}
2016-10-05 03:09:44 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-08-21 22:37:39 +00:00
[RequireContext(ContextType.Guild)]
2016-12-16 18:43:57 +00:00
public Task Stop ( )
2016-08-21 22:37:39 +00:00
{
MusicPlayer musicPlayer ;
2016-12-17 00:16:14 +00:00
if ( ! MusicPlayers . TryGetValue ( Context . Guild . Id , out musicPlayer ) ) return Task . CompletedTask ;
2016-12-16 18:43:57 +00:00
if ( ( ( IGuildUser ) Context . User ) . VoiceChannel = = musicPlayer . PlaybackVoiceChannel )
2016-08-21 22:37:39 +00:00
{
musicPlayer . Autoplay = false ;
musicPlayer . Stop ( ) ;
}
2016-09-10 19:40:25 +00:00
return Task . CompletedTask ;
2016-08-21 22:37:39 +00:00
}
2016-10-05 03:09:44 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-08-21 22:37:39 +00:00
[RequireContext(ContextType.Guild)]
2016-12-31 10:55:12 +00:00
public async Task Destroy ( )
2016-08-21 22:37:39 +00:00
{
2017-01-04 12:23:30 +00:00
//await Context.Channel.SendErrorAsync("This command is temporarily disabled.").ConfigureAwait(false);
2016-12-22 03:49:33 +00:00
2017-01-04 12:23:30 +00:00
MusicPlayer musicPlayer ;
if ( ! MusicPlayers . TryGetValue ( Context . Guild . Id , out musicPlayer ) ) return ;
if ( ( ( IGuildUser ) Context . User ) . VoiceChannel = = musicPlayer . PlaybackVoiceChannel )
if ( MusicPlayers . TryRemove ( Context . Guild . Id , out musicPlayer ) )
2016-10-15 23:37:29 +00:00
musicPlayer . Destroy ( ) ;
2017-01-04 12:23:30 +00:00
2016-08-21 22:37:39 +00:00
}
2016-10-05 03:09:44 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-08-21 22:37:39 +00:00
[RequireContext(ContextType.Guild)]
2016-12-16 18:43:57 +00:00
public Task Pause ( )
2016-08-21 22:37:39 +00:00
{
MusicPlayer musicPlayer ;
2016-12-17 00:16:14 +00:00
if ( ! MusicPlayers . TryGetValue ( Context . Guild . Id , out musicPlayer ) ) return Task . CompletedTask ;
2016-12-16 18:43:57 +00:00
if ( ( ( IGuildUser ) Context . User ) . VoiceChannel ! = musicPlayer . PlaybackVoiceChannel )
2016-12-15 15:51:09 +00:00
return Task . CompletedTask ;
2016-08-21 22:37:39 +00:00
musicPlayer . TogglePause ( ) ;
2016-12-15 15:51:09 +00:00
return Task . CompletedTask ;
2016-08-21 22:37:39 +00:00
}
2016-12-25 05:39:04 +00:00
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
2016-12-31 10:55:12 +00:00
public async Task Fairplay ( )
2016-12-25 05:39:04 +00:00
{
2016-12-31 10:55:12 +00:00
var channel = ( ITextChannel ) Context . Channel ;
2016-12-25 05:39:04 +00:00
MusicPlayer musicPlayer ;
if ( ! MusicPlayers . TryGetValue ( channel . Guild . Id , out musicPlayer ) ) return ;
2016-12-31 12:21:18 +00:00
if ( ( ( IGuildUser ) Context . User ) . VoiceChannel ! = musicPlayer . PlaybackVoiceChannel )
2016-12-25 05:39:04 +00:00
return ;
var val = musicPlayer . FairPlay = ! musicPlayer . FairPlay ;
await channel . SendConfirmAsync ( "Fair play " + ( val ? "enabled" : "disabled" ) + "." ) . ConfigureAwait ( false ) ;
}
2016-10-05 03:09:44 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-08-21 22:37:39 +00:00
[RequireContext(ContextType.Guild)]
2016-12-16 19:45:46 +00:00
public async Task Queue ( [ Remainder ] string query )
2016-08-21 22:37:39 +00:00
{
2016-12-17 00:16:14 +00:00
await QueueSong ( ( ( IGuildUser ) Context . User ) , ( ITextChannel ) Context . Channel , ( ( IGuildUser ) Context . User ) . VoiceChannel , query ) . ConfigureAwait ( false ) ;
2016-12-17 04:09:04 +00:00
if ( ( await Context . Guild . GetCurrentUserAsync ( ) ) . GetPermissions ( ( IGuildChannel ) Context . Channel ) . ManageMessages )
2016-08-21 22:37:39 +00:00
{
2016-12-31 10:55:12 +00:00
Context . Message . DeleteAfter ( 10 ) ;
2016-08-21 22:37:39 +00:00
}
}
2016-10-05 03:09:44 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-08-21 22:37:39 +00:00
[RequireContext(ContextType.Guild)]
2016-12-16 19:45:46 +00:00
public async Task SoundCloudQueue ( [ Remainder ] string query )
2016-08-21 22:37:39 +00:00
{
2016-12-17 00:16:14 +00:00
await QueueSong ( ( ( IGuildUser ) Context . User ) , ( ITextChannel ) Context . Channel , ( ( IGuildUser ) Context . User ) . VoiceChannel , query , musicType : MusicType . Soundcloud ) . ConfigureAwait ( false ) ;
2016-12-17 04:09:04 +00:00
if ( ( await Context . Guild . GetCurrentUserAsync ( ) ) . GetPermissions ( ( IGuildChannel ) Context . Channel ) . ManageMessages )
2016-08-21 22:37:39 +00:00
{
2016-12-31 12:21:18 +00:00
Context . Message . DeleteAfter ( 10 ) ;
2016-08-21 22:37:39 +00:00
}
}
2016-10-05 03:09:44 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-08-21 22:37:39 +00:00
[RequireContext(ContextType.Guild)]
2016-12-16 19:45:46 +00:00
public async Task ListQueue ( int page = 1 )
2016-08-21 22:37:39 +00:00
{
2016-12-21 12:14:24 +00:00
2016-08-21 22:37:39 +00:00
MusicPlayer musicPlayer ;
2016-12-17 00:16:14 +00:00
if ( ! MusicPlayers . TryGetValue ( Context . Guild . Id , out musicPlayer ) )
2016-08-21 22:37:39 +00:00
{
2016-12-17 00:16:14 +00:00
await Context . Channel . SendErrorAsync ( "🎵 No active music player." ) . ConfigureAwait ( false ) ;
2016-08-21 22:37:39 +00:00
return ;
}
if ( page < = 0 )
return ;
var currentSong = musicPlayer . CurrentSong ;
if ( currentSong = = null )
2016-10-19 10:40:43 +00:00
{
2016-12-31 12:21:18 +00:00
await Context . Channel . SendErrorAsync ( "🎵 No active music player." ) . ConfigureAwait ( false ) ;
2016-12-21 11:59:25 +00:00
return ;
2016-10-19 10:40:43 +00:00
}
2016-12-22 03:49:33 +00:00
try { await musicPlayer . UpdateSongDurationsAsync ( ) . ConfigureAwait ( false ) ; } catch { }
2016-12-21 11:59:25 +00:00
2016-12-22 03:49:33 +00:00
const int itemsPerPage = 10 ;
2016-08-21 22:37:39 +00:00
int startAt = itemsPerPage * ( page - 1 ) ;
2016-12-22 03:49:33 +00:00
var number = 0 + startAt ;
2016-12-27 14:18:12 +00:00
var total = musicPlayer . TotalPlaytime ;
var maxPlaytime = musicPlayer . MaxPlaytimeSeconds ;
2016-12-22 03:49:33 +00:00
var embed = new EmbedBuilder ( )
2016-12-22 04:32:34 +00:00
. WithAuthor ( eab = > eab . WithName ( $"Player Queue - Page {page}" )
2016-12-22 03:49:33 +00:00
. WithMusicIcon ( ) )
. WithDescription ( string . Join ( "\n" , musicPlayer . Playlist
. Skip ( startAt )
. Take ( 10 )
. Select ( v = > $"`{++number}.` {v.PrettyFullName}" ) ) )
2016-12-27 14:18:12 +00:00
. WithFooter ( ef = > ef . WithText ( $"{musicPlayer.PrettyVolume} | {musicPlayer.Playlist.Count} " +
$"{(" tracks ".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {total.Minutes}m {total.Seconds}s | " +
2016-12-31 12:21:18 +00:00
( musicPlayer . FairPlay ? "✔️ fairplay" : "✖️ fairplay" ) + $" | " + ( maxPlaytime = = 0 ? "unlimited" : $"{maxPlaytime}s limit" ) ) )
2016-12-22 03:49:33 +00:00
. WithOkColor ( ) ;
2016-08-21 22:37:39 +00:00
if ( musicPlayer . RepeatSong )
2016-12-22 03:49:33 +00:00
{
embed . WithTitle ( $"🔂 Repeating Song: {currentSong.SongInfo.Title} | {currentSong.PrettyFullTime}" ) ;
}
2016-08-21 22:37:39 +00:00
else if ( musicPlayer . RepeatPlaylist )
2016-12-22 03:49:33 +00:00
{
embed . WithTitle ( "🔁 Repeating Playlist" ) ;
}
2016-08-21 22:37:39 +00:00
if ( musicPlayer . MaxQueueSize ! = 0 & & musicPlayer . Playlist . Count > = musicPlayer . MaxQueueSize )
2016-12-22 03:49:33 +00:00
{
embed . WithTitle ( "🎵 Song queue is full!" ) ;
}
2016-12-31 12:21:18 +00:00
await Context . Channel . EmbedAsync ( embed ) . ConfigureAwait ( false ) ;
2016-08-21 22:37:39 +00:00
}
2016-10-05 03:09:44 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-08-21 22:37:39 +00:00
[RequireContext(ContextType.Guild)]
2016-12-16 18:43:57 +00:00
public async Task NowPlaying ( )
2016-08-21 22:37:39 +00:00
{
MusicPlayer musicPlayer ;
2016-12-17 00:16:14 +00:00
if ( ! MusicPlayers . TryGetValue ( Context . Guild . Id , out musicPlayer ) )
2016-08-21 22:37:39 +00:00
return ;
var currentSong = musicPlayer . CurrentSong ;
if ( currentSong = = null )
return ;
2016-12-22 22:29:25 +00:00
try { await musicPlayer . UpdateSongDurationsAsync ( ) . ConfigureAwait ( false ) ; } catch { }
2016-10-19 10:40:43 +00:00
2016-12-27 13:32:58 +00:00
var embed = new EmbedBuilder ( ) . WithOkColor ( )
. WithAuthor ( eab = > eab . WithName ( "Now Playing" ) . WithMusicIcon ( ) )
. WithDescription ( currentSong . PrettyName )
2016-12-31 12:21:18 +00:00
. WithThumbnailUrl ( currentSong . Thumbnail )
2016-12-27 14:18:12 +00:00
. WithFooter ( ef = > ef . WithText ( musicPlayer . PrettyVolume + " | " + currentSong . PrettyFullTime + $" | {currentSong.PrettyProvider} | {currentSong.QueuerName}" ) ) ;
2016-12-27 13:32:58 +00:00
2016-12-31 12:21:18 +00:00
await Context . Channel . EmbedAsync ( embed ) . ConfigureAwait ( false ) ;
2016-08-21 22:37:39 +00:00
}
2016-10-05 03:09:44 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-08-21 22:37:39 +00:00
[RequireContext(ContextType.Guild)]
2016-12-16 19:45:46 +00:00
public async Task Volume ( int val )
2016-08-21 22:37:39 +00:00
{
MusicPlayer musicPlayer ;
2016-12-17 00:16:14 +00:00
if ( ! MusicPlayers . TryGetValue ( Context . Guild . Id , out musicPlayer ) )
2016-08-21 22:37:39 +00:00
return ;
2016-12-16 18:43:57 +00:00
if ( ( ( IGuildUser ) Context . User ) . VoiceChannel ! = musicPlayer . PlaybackVoiceChannel )
2016-08-21 22:37:39 +00:00
return ;
if ( val < 0 )
return ;
var volume = musicPlayer . SetVolume ( val ) ;
2016-12-17 00:16:14 +00:00
await Context . Channel . SendConfirmAsync ( $"🎵 Volume set to {volume}%" ) . ConfigureAwait ( false ) ;
2016-08-21 22:37:39 +00:00
}
2016-08-30 01:22:15 +00:00
2016-10-05 03:09:44 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-08-30 01:22:15 +00:00
[RequireContext(ContextType.Guild)]
2016-12-16 19:45:46 +00:00
public async Task Defvol ( [ Remainder ] int val )
2016-08-30 01:22:15 +00:00
{
2016-12-21 12:14:24 +00:00
2016-08-30 01:22:15 +00:00
if ( val < 0 | | val > 100 )
{
2016-12-17 00:16:14 +00:00
await Context . Channel . SendErrorAsync ( "Volume number invalid. Must be between 0 and 100" ) . ConfigureAwait ( false ) ;
2016-08-30 01:22:15 +00:00
return ;
}
using ( var uow = DbHandler . UnitOfWork ( ) )
{
2016-12-17 00:16:14 +00:00
uow . GuildConfigs . For ( Context . Guild . Id , set = > set ) . DefaultMusicVolume = val / 100.0f ;
2016-08-30 01:22:15 +00:00
uow . Complete ( ) ;
}
2016-12-17 00:16:14 +00:00
await Context . Channel . SendConfirmAsync ( $"🎵 Default volume set to {val}%" ) . ConfigureAwait ( false ) ;
2016-08-30 01:22:15 +00:00
}
2016-08-21 22:37:39 +00:00
2016-10-05 03:09:44 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-08-21 22:37:39 +00:00
[RequireContext(ContextType.Guild)]
2016-12-16 18:43:57 +00:00
public async Task ShufflePlaylist ( )
2016-08-21 22:37:39 +00:00
{
2016-12-21 12:14:24 +00:00
2016-08-21 22:37:39 +00:00
MusicPlayer musicPlayer ;
2016-12-17 00:16:14 +00:00
if ( ! MusicPlayers . TryGetValue ( Context . Guild . Id , out musicPlayer ) )
2016-08-21 22:37:39 +00:00
return ;
2016-12-16 18:43:57 +00:00
if ( ( ( IGuildUser ) Context . User ) . VoiceChannel ! = musicPlayer . PlaybackVoiceChannel )
2016-08-21 22:37:39 +00:00
return ;
if ( musicPlayer . Playlist . Count < 2 )
{
2016-12-17 00:16:14 +00:00
await Context . Channel . SendErrorAsync ( "💢 Not enough songs in order to perform the shuffle." ) . ConfigureAwait ( false ) ;
2016-08-21 22:37:39 +00:00
return ;
}
musicPlayer . Shuffle ( ) ;
2016-12-17 00:16:14 +00:00
await Context . Channel . SendConfirmAsync ( "🎵 Songs shuffled." ) . ConfigureAwait ( false ) ;
2016-08-21 22:37:39 +00:00
}
2016-10-05 03:09:44 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-08-21 22:37:39 +00:00
[RequireContext(ContextType.Guild)]
2016-12-16 19:45:46 +00:00
public async Task Playlist ( [ Remainder ] string playlist )
2016-08-21 22:37:39 +00:00
{
2016-12-21 12:14:24 +00:00
2016-08-21 22:37:39 +00:00
var arg = playlist ;
if ( string . IsNullOrWhiteSpace ( arg ) )
return ;
2016-12-17 00:16:14 +00:00
if ( ( ( IGuildUser ) Context . User ) . VoiceChannel ? . Guild ! = Context . Guild )
2016-08-21 22:37:39 +00:00
{
2016-12-17 00:16:14 +00:00
await Context . Channel . SendErrorAsync ( "💢 You need to be in a **voice channel** on this server.\n If you are already in a voice (ITextChannel)Context.Channel, try rejoining it." ) . ConfigureAwait ( false ) ;
2016-08-21 22:37:39 +00:00
return ;
}
2016-12-08 17:46:08 +00:00
var plId = ( await NadekoBot . Google . GetPlaylistIdsByKeywordsAsync ( arg ) . ConfigureAwait ( false ) ) . FirstOrDefault ( ) ;
2016-08-21 22:37:39 +00:00
if ( plId = = null )
{
2016-12-17 00:16:14 +00:00
await Context . Channel . SendErrorAsync ( "No search results for that query." ) ;
2016-08-21 22:37:39 +00:00
return ;
}
2016-12-08 17:46:08 +00:00
var ids = await NadekoBot . Google . GetPlaylistTracksAsync ( plId , 500 ) . ConfigureAwait ( false ) ;
2016-08-21 22:37:39 +00:00
if ( ! ids . Any ( ) )
{
2016-12-17 00:16:14 +00:00
await Context . Channel . SendErrorAsync ( $"🎵 Failed to find any songs." ) . ConfigureAwait ( false ) ;
2016-08-21 22:37:39 +00:00
return ;
}
2016-12-24 01:45:51 +00:00
var count = ids . Count ( ) ;
2016-12-21 11:59:25 +00:00
2016-12-31 12:21:18 +00:00
var msg = await Context . Channel . SendMessageAsync ( $"🎵 Attempting to queue **{count}** songs" . SnPl ( count ) + "..." ) . ConfigureAwait ( false ) ;
2016-12-27 00:35:46 +00:00
2016-12-21 12:14:24 +00:00
var cancelSource = new CancellationTokenSource ( ) ;
2016-12-31 12:21:18 +00:00
var gusr = ( IGuildUser ) Context . User ;
2016-12-27 00:35:46 +00:00
while ( ids . Any ( ) & & ! cancelSource . IsCancellationRequested )
2016-08-21 22:37:39 +00:00
{
2016-12-24 01:45:51 +00:00
var tasks = Task . WhenAll ( ids . Take ( 5 ) . Select ( async id = >
2016-08-21 22:37:39 +00:00
{
2016-12-24 01:45:51 +00:00
if ( cancelSource . Token . IsCancellationRequested )
2016-12-27 00:35:46 +00:00
return ;
try
{
2016-12-31 12:21:18 +00:00
await QueueSong ( gusr , ( ITextChannel ) Context . Channel , gusr . VoiceChannel , id , true ) . ConfigureAwait ( false ) ;
2016-12-27 00:35:46 +00:00
}
catch ( SongNotFoundException ) { }
catch { try { cancelSource . Cancel ( ) ; } catch { } }
} ) ) ;
2016-12-21 12:14:24 +00:00
2016-12-27 00:35:46 +00:00
await Task . WhenAny ( tasks , Task . Delay ( Timeout . Infinite , cancelSource . Token ) ) ;
ids = ids . Skip ( 5 ) ;
}
2016-12-21 12:14:24 +00:00
2016-12-14 19:29:01 +00:00
await msg . ModifyAsync ( m = > m . Content = "✅ Playlist queue complete." ) . ConfigureAwait ( false ) ;
2016-08-21 22:37:39 +00:00
}
2016-10-05 03:09:44 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-08-21 22:37:39 +00:00
[RequireContext(ContextType.Guild)]
2016-12-16 19:45:46 +00:00
public async Task SoundCloudPl ( [ Remainder ] string pl )
2016-08-21 22:37:39 +00:00
{
2016-12-21 12:14:24 +00:00
2016-08-21 22:37:39 +00:00
pl = pl ? . Trim ( ) ;
if ( string . IsNullOrWhiteSpace ( pl ) )
return ;
using ( var http = new HttpClient ( ) )
{
var scvids = JObject . Parse ( await http . GetStringAsync ( $"http://api.soundcloud.com/resolve?url={pl}&client_id={NadekoBot.Credentials.SoundCloudClientId}" ) . ConfigureAwait ( false ) ) [ "tracks" ] . ToObject < SoundCloudVideo [ ] > ( ) ;
2016-12-17 00:16:14 +00:00
await QueueSong ( ( ( IGuildUser ) Context . User ) , ( ITextChannel ) Context . Channel , ( ( IGuildUser ) Context . User ) . VoiceChannel , scvids [ 0 ] . TrackLink ) . ConfigureAwait ( false ) ;
2016-08-21 22:37:39 +00:00
MusicPlayer mp ;
2016-12-17 00:16:14 +00:00
if ( ! MusicPlayers . TryGetValue ( Context . Guild . Id , out mp ) )
2016-08-21 22:37:39 +00:00
return ;
foreach ( var svideo in scvids . Skip ( 1 ) )
{
try
{
mp . AddSong ( new Song ( new Classes . SongInfo
{
Title = svideo . FullName ,
Provider = "SoundCloud" ,
Uri = svideo . StreamLink ,
ProviderType = MusicType . Normal ,
Query = svideo . TrackLink ,
2016-12-16 18:43:57 +00:00
} ) , ( ( IGuildUser ) Context . User ) . Username ) ;
2016-08-21 22:37:39 +00:00
}
catch ( PlaylistFullException ) { break ; }
}
}
}
2016-10-05 03:09:44 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-08-21 22:37:39 +00:00
[RequireContext(ContextType.Guild)]
2016-09-30 02:20:09 +00:00
[OwnerOnly]
2016-12-16 19:45:46 +00:00
public async Task LocalPl ( [ Remainder ] string directory )
2016-08-21 22:37:39 +00:00
{
2016-12-21 12:14:24 +00:00
2016-08-21 22:37:39 +00:00
var arg = directory ;
if ( string . IsNullOrWhiteSpace ( arg ) )
return ;
try
{
2016-10-19 06:53:09 +00:00
var dir = new DirectoryInfo ( arg ) ;
var fileEnum = dir . GetFiles ( "*" , SearchOption . AllDirectories )
2016-08-21 22:37:39 +00:00
. Where ( x = > ! x . Attributes . HasFlag ( FileAttributes . Hidden | FileAttributes . System ) ) ;
2016-12-31 12:21:18 +00:00
var gusr = ( IGuildUser ) Context . User ;
2016-08-21 22:37:39 +00:00
foreach ( var file in fileEnum )
{
try
{
2016-12-17 00:16:14 +00:00
await QueueSong ( ( ( IGuildUser ) Context . User ) , ( ITextChannel ) Context . Channel , ( ( IGuildUser ) Context . User ) . VoiceChannel , file . FullName , true , MusicType . Local ) . ConfigureAwait ( false ) ;
2016-08-21 22:37:39 +00:00
}
catch ( PlaylistFullException )
{
break ;
}
catch { }
}
2016-12-17 00:16:14 +00:00
await Context . Channel . SendConfirmAsync ( "🎵 Directory queue complete." ) . ConfigureAwait ( false ) ;
2016-08-21 22:37:39 +00:00
}
catch { }
}
2016-10-05 03:09:44 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-08-21 22:37:39 +00:00
[RequireContext(ContextType.Guild)]
2016-12-16 19:45:46 +00:00
public async Task Radio ( string radio_link )
2016-08-21 22:37:39 +00:00
{
2016-12-21 12:14:24 +00:00
2016-12-17 00:16:14 +00:00
if ( ( ( IGuildUser ) Context . User ) . VoiceChannel ? . Guild ! = Context . Guild )
2016-08-21 22:37:39 +00:00
{
2016-12-17 00:16:14 +00:00
await Context . Channel . SendErrorAsync ( "💢 You need to be in a voice channel on this server.\n If you are already in a voice (ITextChannel)Context.Channel, try rejoining it." ) . ConfigureAwait ( false ) ;
2016-08-21 22:37:39 +00:00
return ;
}
2016-12-17 00:16:14 +00:00
await QueueSong ( ( ( IGuildUser ) Context . User ) , ( ITextChannel ) Context . Channel , ( ( IGuildUser ) Context . User ) . VoiceChannel , radio_link , musicType : MusicType . Radio ) . ConfigureAwait ( false ) ;
2016-12-17 04:09:04 +00:00
if ( ( await Context . Guild . GetCurrentUserAsync ( ) ) . GetPermissions ( ( IGuildChannel ) Context . Channel ) . ManageMessages )
2016-08-21 22:37:39 +00:00
{
2016-12-31 10:55:12 +00:00
Context . Message . DeleteAfter ( 10 ) ;
2016-08-21 22:37:39 +00:00
}
}
2016-10-05 03:09:44 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-08-21 22:37:39 +00:00
[RequireContext(ContextType.Guild)]
2016-09-30 02:20:09 +00:00
[OwnerOnly]
2016-12-16 19:45:46 +00:00
public async Task Local ( [ Remainder ] string path )
2016-08-21 22:37:39 +00:00
{
2016-12-21 12:14:24 +00:00
2016-08-21 22:37:39 +00:00
var arg = path ;
if ( string . IsNullOrWhiteSpace ( arg ) )
return ;
2016-12-17 00:16:14 +00:00
await QueueSong ( ( ( IGuildUser ) Context . User ) , ( ITextChannel ) Context . Channel , ( ( IGuildUser ) Context . User ) . VoiceChannel , path , musicType : MusicType . Local ) . ConfigureAwait ( false ) ;
2016-08-21 22:37:39 +00:00
}
2016-10-05 03:09:44 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-08-21 22:37:39 +00:00
[RequireContext(ContextType.Guild)]
2016-12-16 18:43:57 +00:00
public async Task Move ( )
2016-08-21 22:37:39 +00:00
{
2016-12-21 12:14:24 +00:00
2016-08-21 22:37:39 +00:00
MusicPlayer musicPlayer ;
2016-12-16 18:43:57 +00:00
var voiceChannel = ( ( IGuildUser ) Context . User ) . VoiceChannel ;
2016-12-17 00:16:14 +00:00
if ( voiceChannel = = null | | voiceChannel . Guild ! = Context . Guild | | ! MusicPlayers . TryGetValue ( Context . Guild . Id , out musicPlayer ) )
2016-08-21 22:37:39 +00:00
return ;
2016-09-10 19:40:25 +00:00
await musicPlayer . MoveToVoiceChannel ( voiceChannel ) ;
2016-08-21 22:37:39 +00:00
}
2016-10-05 03:09:44 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-08-21 22:37:39 +00:00
[RequireContext(ContextType.Guild)]
2016-10-19 08:10:57 +00:00
[Priority(0)]
2016-12-16 19:45:46 +00:00
public async Task Remove ( int num )
2016-08-21 22:37:39 +00:00
{
MusicPlayer musicPlayer ;
2016-12-17 00:16:14 +00:00
if ( ! MusicPlayers . TryGetValue ( Context . Guild . Id , out musicPlayer ) )
2016-08-21 22:37:39 +00:00
return ;
2016-12-16 18:43:57 +00:00
if ( ( ( IGuildUser ) Context . User ) . VoiceChannel ! = musicPlayer . PlaybackVoiceChannel )
2016-08-21 22:37:39 +00:00
return ;
2017-01-03 15:02:02 +00:00
2017-01-03 14:46:16 +00:00
musicPlayer . SongRemoved + = async ( song ) = >
{
try
{
var embed = new EmbedBuilder ( )
. WithAuthor ( eab = > eab . WithName ( "Removed song #" + num ) . WithMusicIcon ( ) )
. WithDescription ( song . PrettyName )
. WithFooter ( ef = > ef . WithText ( song . PrettyInfo ) )
. WithErrorColor ( ) ;
2016-12-22 04:32:34 +00:00
2017-01-03 14:46:16 +00:00
await Context . Channel . EmbedAsync ( embed ) . ConfigureAwait ( false ) ;
}
catch { }
} ;
musicPlayer . RemoveSongAt ( num - 1 ) ;
2016-08-21 22:37:39 +00:00
}
2016-09-03 13:04:07 +00:00
2016-10-05 03:09:44 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-08-21 22:37:39 +00:00
[RequireContext(ContextType.Guild)]
2016-10-19 08:10:57 +00:00
[Priority(1)]
2016-12-16 19:45:46 +00:00
public async Task Remove ( string all )
2016-08-21 22:37:39 +00:00
{
2016-12-21 12:14:24 +00:00
2016-08-21 22:37:39 +00:00
if ( all . Trim ( ) . ToUpperInvariant ( ) ! = "ALL" )
return ;
MusicPlayer musicPlayer ;
2016-12-17 00:16:14 +00:00
if ( ! MusicPlayers . TryGetValue ( Context . Guild . Id , out musicPlayer ) ) return ;
2016-08-21 22:37:39 +00:00
musicPlayer . ClearQueue ( ) ;
2016-12-17 00:16:14 +00:00
await Context . Channel . SendConfirmAsync ( $"🎵 Queue cleared!" ) . ConfigureAwait ( false ) ;
2016-08-21 22:37:39 +00:00
return ;
}
2016-10-05 03:09:44 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-08-21 22:37:39 +00:00
[RequireContext(ContextType.Guild)]
2016-12-16 19:45:46 +00:00
public async Task MoveSong ( [ Remainder ] string fromto )
2016-08-21 22:37:39 +00:00
{
2016-12-17 00:16:14 +00:00
2016-08-21 22:37:39 +00:00
MusicPlayer musicPlayer ;
2016-12-17 00:16:14 +00:00
if ( ! MusicPlayers . TryGetValue ( Context . Guild . Id , out musicPlayer ) )
2016-08-21 22:37:39 +00:00
{
return ;
}
fromto = fromto ? . Trim ( ) ;
var fromtoArr = fromto . Split ( '>' ) ;
int n1 ;
int n2 ;
var playlist = musicPlayer . Playlist as List < Song > ? ? musicPlayer . Playlist . ToList ( ) ;
if ( fromtoArr . Length ! = 2 | | ! int . TryParse ( fromtoArr [ 0 ] , out n1 ) | |
! int . TryParse ( fromtoArr [ 1 ] , out n2 ) | | n1 < 1 | | n2 < 1 | | n1 = = n2 | |
n1 > playlist . Count | | n2 > playlist . Count )
{
2016-12-17 00:16:14 +00:00
await Context . Channel . SendErrorAsync ( "Invalid input." ) . ConfigureAwait ( false ) ;
2016-08-21 22:37:39 +00:00
return ;
}
var s = playlist [ n1 - 1 ] ;
playlist . Insert ( n2 - 1 , s ) ;
var nn1 = n2 < n1 ? n1 : n1 - 1 ;
playlist . RemoveAt ( nn1 ) ;
2016-12-31 12:21:18 +00:00
var embed = new EmbedBuilder ( )
. WithTitle ( $"{s.SongInfo.Title.TrimTo(70)}" )
. WithUrl ( $"{s.SongInfo.Query}" )
. WithAuthor ( eab = > eab . WithName ( "Song Moved" ) . WithIconUrl ( "https://cdn.discordapp.com/attachments/155726317222887425/258605269972549642/music1.png" ) )
. AddField ( fb = > fb . WithName ( "**From Position**" ) . WithValue ( $"#{n1}" ) . WithIsInline ( true ) )
. AddField ( fb = > fb . WithName ( "**To Position**" ) . WithValue ( $"#{n2}" ) . WithIsInline ( true ) )
. WithColor ( NadekoBot . OkColor ) ;
await Context . Channel . EmbedAsync ( embed ) . ConfigureAwait ( false ) ;
2016-08-21 22:37:39 +00:00
2016-12-14 19:29:01 +00:00
//await channel.SendConfirmAsync($"🎵Moved {s.PrettyName} `from #{n1} to #{n2}`").ConfigureAwait(false);
2016-08-21 22:37:39 +00:00
}
2016-10-05 03:09:44 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-08-21 22:37:39 +00:00
[RequireContext(ContextType.Guild)]
2016-12-16 19:45:46 +00:00
public async Task SetMaxQueue ( uint size )
2016-08-21 22:37:39 +00:00
{
MusicPlayer musicPlayer ;
2016-12-17 00:16:14 +00:00
if ( ! MusicPlayers . TryGetValue ( Context . Guild . Id , out musicPlayer ) )
2016-08-21 22:37:39 +00:00
return ;
2016-12-31 12:21:18 +00:00
2016-08-21 22:37:39 +00:00
musicPlayer . MaxQueueSize = size ;
2016-12-17 00:16:14 +00:00
await Context . Channel . SendConfirmAsync ( $"🎵 Max queue set to {(size == 0 ? (" unlimited ") : size + " tracks ")}." ) ;
2016-08-21 22:37:39 +00:00
}
2016-10-05 03:09:44 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-08-21 22:37:39 +00:00
[RequireContext(ContextType.Guild)]
2016-12-31 10:55:12 +00:00
public async Task SetMaxPlaytime ( uint seconds )
2016-12-27 13:32:58 +00:00
{
2016-12-27 14:18:12 +00:00
if ( seconds < 15 & & seconds ! = 0 )
2016-12-27 13:32:58 +00:00
return ;
2016-12-31 10:55:12 +00:00
var channel = ( ITextChannel ) Context . Channel ;
2016-12-27 13:32:58 +00:00
MusicPlayer musicPlayer ;
if ( ! MusicPlayers . TryGetValue ( channel . Guild . Id , out musicPlayer ) )
return ;
musicPlayer . MaxPlaytimeSeconds = seconds ;
2016-12-31 12:21:18 +00:00
if ( seconds = = 0 )
2016-12-27 13:32:58 +00:00
await channel . SendConfirmAsync ( $"🎵 Max playtime has no limit now." ) ;
else
await channel . SendConfirmAsync ( $"🎵 Max playtime set to {seconds} seconds." ) ;
}
2016-10-05 03:09:44 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-08-21 22:37:39 +00:00
[RequireContext(ContextType.Guild)]
2017-01-01 12:26:17 +00:00
public async Task ReptCurSong ( )
2016-08-21 22:37:39 +00:00
{
2016-12-21 12:14:24 +00:00
2016-08-21 22:37:39 +00:00
MusicPlayer musicPlayer ;
2016-12-17 00:16:14 +00:00
if ( ! MusicPlayers . TryGetValue ( Context . Guild . Id , out musicPlayer ) )
2016-08-21 22:37:39 +00:00
return ;
var currentSong = musicPlayer . CurrentSong ;
if ( currentSong = = null )
return ;
var currentValue = musicPlayer . ToggleRepeatSong ( ) ;
2016-12-22 03:49:33 +00:00
if ( currentValue )
2016-12-31 12:21:18 +00:00
await Context . Channel . EmbedAsync ( new EmbedBuilder ( )
2016-12-22 03:49:33 +00:00
. WithOkColor ( )
. WithAuthor ( eab = > eab . WithMusicIcon ( ) . WithName ( "🔂 Repeating track" ) )
2016-12-24 19:49:29 +00:00
. WithDescription ( currentSong . PrettyName )
2016-12-31 10:55:12 +00:00
. WithFooter ( ef = > ef . WithText ( currentSong . PrettyInfo ) ) ) . ConfigureAwait ( false ) ;
2016-12-22 03:49:33 +00:00
else
2016-12-31 10:55:12 +00:00
await Context . Channel . SendConfirmAsync ( $"🔂 Current track repeat stopped." )
2016-08-21 22:37:39 +00:00
. ConfigureAwait ( false ) ;
}
2016-10-05 03:09:44 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-08-21 22:37:39 +00:00
[RequireContext(ContextType.Guild)]
2016-12-16 18:43:57 +00:00
public async Task RepeatPl ( )
2016-08-21 22:37:39 +00:00
{
2016-12-21 12:14:24 +00:00
2016-08-21 22:37:39 +00:00
MusicPlayer musicPlayer ;
2016-12-17 00:16:14 +00:00
if ( ! MusicPlayers . TryGetValue ( Context . Guild . Id , out musicPlayer ) )
2016-08-21 22:37:39 +00:00
return ;
var currentValue = musicPlayer . ToggleRepeatPlaylist ( ) ;
2016-12-17 00:16:14 +00:00
await Context . Channel . SendConfirmAsync ( $"🔁 Repeat playlist {(currentValue ? " * * enabled * * . " : " * * disabled * * . ")}" ) . ConfigureAwait ( false ) ;
2016-08-21 22:37:39 +00:00
}
2016-10-05 03:09:44 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-10-01 03:49:05 +00:00
[RequireContext(ContextType.Guild)]
2016-12-16 19:45:46 +00:00
public async Task Save ( [ Remainder ] string name )
2016-10-01 03:49:05 +00:00
{
2016-12-21 12:14:24 +00:00
2016-10-01 03:49:05 +00:00
MusicPlayer musicPlayer ;
2016-12-17 00:16:14 +00:00
if ( ! MusicPlayers . TryGetValue ( Context . Guild . Id , out musicPlayer ) )
2016-10-01 03:49:05 +00:00
return ;
2016-08-21 22:37:39 +00:00
2016-10-01 03:49:05 +00:00
var curSong = musicPlayer . CurrentSong ;
var songs = musicPlayer . Playlist . Append ( curSong )
2016-12-21 12:14:24 +00:00
. Select ( s = > new PlaylistSong ( )
{
2016-10-01 03:49:05 +00:00
Provider = s . SongInfo . Provider ,
ProviderType = s . SongInfo . ProviderType ,
Title = s . SongInfo . Title ,
Uri = s . SongInfo . Uri ,
Query = s . SongInfo . Query ,
} ) . ToList ( ) ;
2016-08-21 22:37:39 +00:00
2016-10-01 03:49:05 +00:00
MusicPlaylist playlist ;
using ( var uow = DbHandler . UnitOfWork ( ) )
{
playlist = new MusicPlaylist
{
Name = name ,
2016-12-16 18:43:57 +00:00
Author = Context . User . Username ,
AuthorId = Context . User . Id ,
2016-10-01 03:49:05 +00:00
Songs = songs ,
} ;
uow . MusicPlaylists . Add ( playlist ) ;
await uow . CompleteAsync ( ) . ConfigureAwait ( false ) ;
}
2016-08-21 22:37:39 +00:00
2016-12-17 00:16:14 +00:00
await Context . Channel . SendConfirmAsync ( ( $"🎵 Saved playlist as **{name}**, ID: {playlist.Id}." ) ) . ConfigureAwait ( false ) ;
2016-10-01 03:49:05 +00:00
}
2016-08-21 22:37:39 +00:00
2016-10-05 03:09:44 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-10-01 03:49:05 +00:00
[RequireContext(ContextType.Guild)]
2016-12-16 19:45:46 +00:00
public async Task Load ( [ Remainder ] int id )
2016-10-01 03:49:05 +00:00
{
MusicPlaylist mpl ;
using ( var uow = DbHandler . UnitOfWork ( ) )
{
mpl = uow . MusicPlaylists . GetWithSongs ( id ) ;
}
if ( mpl = = null )
{
2016-12-17 00:16:14 +00:00
await Context . Channel . SendErrorAsync ( "Can't find playlist with that ID." ) . ConfigureAwait ( false ) ;
2016-10-01 03:49:05 +00:00
return ;
}
2016-10-05 05:01:19 +00:00
IUserMessage msg = null ;
2016-12-17 00:16:14 +00:00
try { msg = await Context . Channel . SendMessageAsync ( $"🎶 Attempting to load **{mpl.Songs.Count}** songs..." ) . ConfigureAwait ( false ) ; } catch ( Exception ex ) { _log . Warn ( ex ) ; }
2016-10-01 03:49:05 +00:00
foreach ( var item in mpl . Songs )
{
2016-12-16 18:43:57 +00:00
var usr = ( IGuildUser ) Context . User ;
2016-10-01 03:49:05 +00:00
try
{
2016-12-17 00:16:14 +00:00
await QueueSong ( usr , ( ITextChannel ) Context . Channel , usr . VoiceChannel , item . Query , true , item . ProviderType ) . ConfigureAwait ( false ) ;
2016-10-01 03:49:05 +00:00
}
2016-11-14 23:07:36 +00:00
catch ( SongNotFoundException ) { }
2016-10-01 03:49:05 +00:00
catch { break ; }
}
2016-10-05 05:01:19 +00:00
if ( msg ! = null )
2016-12-14 19:29:01 +00:00
await msg . ModifyAsync ( m = > m . Content = $"✅ Done loading playlist **{mpl.Name}**." ) . ConfigureAwait ( false ) ;
2016-10-01 03:49:05 +00:00
}
2016-10-05 03:09:44 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-10-01 03:49:05 +00:00
[RequireContext(ContextType.Guild)]
2016-12-16 19:45:46 +00:00
public async Task Playlists ( [ Remainder ] int num = 1 )
2016-10-01 03:49:05 +00:00
{
2016-12-21 12:14:24 +00:00
2016-10-01 03:49:05 +00:00
if ( num < = 0 )
return ;
List < MusicPlaylist > playlists ;
using ( var uow = DbHandler . UnitOfWork ( ) )
{
playlists = uow . MusicPlaylists . GetPlaylistsOnPage ( num ) ;
}
2016-12-22 03:49:33 +00:00
var embed = new EmbedBuilder ( )
. WithAuthor ( eab = > eab . WithName ( $"Page {num} of Saved Playlists" ) . WithMusicIcon ( ) )
2016-12-24 19:49:29 +00:00
. WithDescription ( string . Join ( "\n" , playlists . Select ( r = > $"`#{r.Id}` - **{r.Name}** by *{r.Author}* ({r.Songs.Count} songs)" ) ) )
2016-12-22 03:49:33 +00:00
. WithOkColor ( ) ;
2016-12-31 10:55:12 +00:00
await Context . Channel . EmbedAsync ( embed ) . ConfigureAwait ( false ) ;
2016-10-01 03:49:05 +00:00
}
2016-08-21 22:37:39 +00:00
2016-10-01 03:49:05 +00:00
//todo only author or owner
2016-10-05 03:09:44 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-10-01 17:35:11 +00:00
[RequireContext(ContextType.Guild)]
2016-12-16 19:45:46 +00:00
public async Task DeletePlaylist ( [ Remainder ] int id )
2016-10-01 17:35:11 +00:00
{
2016-12-21 12:14:24 +00:00
2016-08-21 22:37:39 +00:00
2016-10-01 17:35:11 +00:00
bool success = false ;
MusicPlaylist pl = null ;
2016-10-02 01:00:03 +00:00
try
2016-10-01 17:35:11 +00:00
{
2016-10-02 01:00:03 +00:00
using ( var uow = DbHandler . UnitOfWork ( ) )
2016-10-01 17:35:11 +00:00
{
2016-10-02 01:00:03 +00:00
pl = uow . MusicPlaylists . Get ( id ) ;
if ( pl ! = null )
2016-10-01 17:35:11 +00:00
{
2016-12-16 18:43:57 +00:00
if ( NadekoBot . Credentials . IsOwner ( Context . User ) | | pl . AuthorId = = Context . User . Id )
2016-10-02 01:00:03 +00:00
{
uow . MusicPlaylists . Remove ( pl ) ;
await uow . CompleteAsync ( ) . ConfigureAwait ( false ) ;
success = true ;
}
else
success = false ;
2016-10-01 17:35:11 +00:00
}
}
2016-10-02 01:00:03 +00:00
if ( ! success )
2016-12-17 00:16:14 +00:00
await Context . Channel . SendErrorAsync ( "Failed to delete that playlist. It either doesn't exist, or you are not its author." ) . ConfigureAwait ( false ) ;
2016-10-02 01:00:03 +00:00
else
2016-12-17 00:16:14 +00:00
await Context . Channel . SendConfirmAsync ( "🗑 Playlist successfully **deleted**." ) . ConfigureAwait ( false ) ;
2016-10-02 01:00:03 +00:00
}
catch ( Exception ex )
{
Console . WriteLine ( ex ) ;
}
2016-10-01 17:35:11 +00:00
}
2016-08-21 22:37:39 +00:00
2016-10-05 03:09:44 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-08-21 22:37:39 +00:00
[RequireContext(ContextType.Guild)]
2016-12-16 19:45:46 +00:00
public async Task Goto ( int time )
2016-08-21 22:37:39 +00:00
{
MusicPlayer musicPlayer ;
2016-12-17 00:16:14 +00:00
if ( ! MusicPlayers . TryGetValue ( Context . Guild . Id , out musicPlayer ) )
2016-08-21 22:37:39 +00:00
return ;
2016-12-16 18:43:57 +00:00
if ( ( ( IGuildUser ) Context . User ) . VoiceChannel ! = musicPlayer . PlaybackVoiceChannel )
2016-08-21 22:37:39 +00:00
return ;
if ( time < 0 )
return ;
var currentSong = musicPlayer . CurrentSong ;
if ( currentSong = = null )
return ;
//currentSong.PrintStatusMessage = false;
var gotoSong = currentSong . Clone ( ) ;
gotoSong . SkipTo = time ;
musicPlayer . AddSong ( gotoSong , 0 ) ;
musicPlayer . Next ( ) ;
var minutes = ( time / 60 ) . ToString ( ) ;
var seconds = ( time % 60 ) . ToString ( ) ;
if ( minutes . Length = = 1 )
minutes = "0" + minutes ;
if ( seconds . Length = = 1 )
seconds = "0" + seconds ;
2016-12-17 00:16:14 +00:00
await Context . Channel . SendConfirmAsync ( $"Skipped to `{minutes}:{seconds}`" ) . ConfigureAwait ( false ) ;
2016-08-21 22:37:39 +00:00
}
2016-10-05 03:09:44 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-08-21 22:37:39 +00:00
[RequireContext(ContextType.Guild)]
2017-01-01 12:26:17 +00:00
public async Task Autoplay ( )
2016-08-21 22:37:39 +00:00
{
MusicPlayer musicPlayer ;
2016-12-17 00:16:14 +00:00
if ( ! MusicPlayers . TryGetValue ( Context . Guild . Id , out musicPlayer ) )
2016-08-21 22:37:39 +00:00
return ;
if ( ! musicPlayer . ToggleAutoplay ( ) )
2016-12-17 00:16:14 +00:00
await Context . Channel . SendConfirmAsync ( "❌ Autoplay disabled." ) . ConfigureAwait ( false ) ;
2016-08-21 22:37:39 +00:00
else
2016-12-17 00:16:14 +00:00
await Context . Channel . SendConfirmAsync ( "✅ Autoplay enabled." ) . ConfigureAwait ( false ) ;
2016-08-21 22:37:39 +00:00
}
public static async Task QueueSong ( IGuildUser queuer , ITextChannel textCh , IVoiceChannel voiceCh , string query , bool silent = false , MusicType musicType = MusicType . Normal )
{
if ( voiceCh = = null | | voiceCh . Guild ! = textCh . Guild )
{
if ( ! silent )
2016-12-17 00:16:14 +00:00
await textCh . SendErrorAsync ( "💢 You need to be in a voice channel on this server.\n If you are already in a voice (ITextChannel)Context.Channel, try rejoining." ) . ConfigureAwait ( false ) ;
2016-08-21 22:37:39 +00:00
throw new ArgumentNullException ( nameof ( voiceCh ) ) ;
}
if ( string . IsNullOrWhiteSpace ( query ) | | query . Length < 3 )
throw new ArgumentException ( "💢 Invalid query for queue song." , nameof ( query ) ) ;
var musicPlayer = MusicPlayers . GetOrAdd ( textCh . Guild . Id , server = >
{
2016-08-26 01:25:55 +00:00
float vol = 1 ; // SpecificConfigurations.Default.Of(server.Id).DefaultMusicVolume;
2016-08-30 01:11:25 +00:00
using ( var uow = DbHandler . UnitOfWork ( ) )
{
2016-12-03 13:14:37 +00:00
vol = uow . GuildConfigs . For ( textCh . Guild . Id , set = > set ) . DefaultMusicVolume ;
2016-08-30 01:11:25 +00:00
}
2016-08-21 22:37:39 +00:00
var mp = new MusicPlayer ( voiceCh , vol ) ;
2016-08-28 02:33:09 +00:00
IUserMessage playingMessage = null ;
2016-12-31 12:21:18 +00:00
IUserMessage lastFinishedMessage = null ;
2016-08-21 22:37:39 +00:00
mp . OnCompleted + = async ( s , song ) = >
{
2016-12-22 03:49:33 +00:00
try
2016-08-21 22:37:39 +00:00
{
2016-12-31 12:21:18 +00:00
if ( lastFinishedMessage ! = null )
lastFinishedMessage . DeleteAfter ( 0 ) ;
2016-12-27 00:35:46 +00:00
2016-12-31 12:21:18 +00:00
lastFinishedMessage = await textCh . EmbedAsync ( new EmbedBuilder ( ) . WithOkColor ( )
2016-12-22 03:49:33 +00:00
. WithAuthor ( eab = > eab . WithName ( "Finished Song" ) . WithMusicIcon ( ) )
. WithDescription ( song . PrettyName )
2016-12-31 12:21:18 +00:00
. WithFooter ( ef = > ef . WithText ( song . PrettyInfo ) ) )
. ConfigureAwait ( false ) ;
2016-12-22 03:49:33 +00:00
if ( mp . Autoplay & & mp . Playlist . Count = = 0 & & song . SongInfo . Provider = = "YouTube" )
2016-08-21 22:37:39 +00:00
{
2016-12-31 12:21:18 +00:00
await QueueSong ( await queuer . Guild . GetCurrentUserAsync ( ) , textCh , voiceCh , ( await NadekoBot . Google . GetRelatedVideosAsync ( song . SongInfo . Query , 4 ) ) . ToList ( ) . Shuffle ( ) . FirstOrDefault ( ) , silent , musicType ) . ConfigureAwait ( false ) ;
2016-08-21 22:37:39 +00:00
}
}
2016-12-22 03:49:33 +00:00
catch { }
2016-08-21 22:37:39 +00:00
} ;
2016-12-27 00:35:46 +00:00
2016-12-22 03:49:33 +00:00
mp . OnStarted + = async ( player , song ) = >
2016-08-21 22:37:39 +00:00
{
2016-12-23 07:06:11 +00:00
try { await mp . UpdateSongDurationsAsync ( ) . ConfigureAwait ( false ) ; } catch { }
var sender = player as MusicPlayer ;
2016-12-23 03:50:49 +00:00
if ( sender = = null )
2016-12-27 00:35:46 +00:00
return ;
2016-12-22 04:32:34 +00:00
try
2016-08-21 22:37:39 +00:00
{
2016-12-22 04:32:34 +00:00
if ( playingMessage ! = null )
playingMessage . DeleteAfter ( 0 ) ;
playingMessage = await textCh . EmbedAsync ( new EmbedBuilder ( ) . WithOkColor ( )
. WithAuthor ( eab = > eab . WithName ( "Playing Song" ) . WithMusicIcon ( ) )
2016-12-24 19:49:29 +00:00
. WithDescription ( song . PrettyName )
2016-12-31 10:55:12 +00:00
. WithFooter ( ef = > ef . WithText ( song . PrettyInfo ) ) )
2016-12-22 04:32:34 +00:00
. ConfigureAwait ( false ) ;
2016-08-21 22:37:39 +00:00
}
2016-12-22 04:32:34 +00:00
catch { }
2016-08-21 22:37:39 +00:00
} ;
2016-12-31 12:21:18 +00:00
mp . OnPauseChanged + = async ( paused ) = >
{
try
{
if ( paused )
await textCh . SendConfirmAsync ( "🎵 Music playback **paused**." ) . ConfigureAwait ( false ) ;
else
await textCh . SendConfirmAsync ( "🎵 Music playback **resumed**." ) . ConfigureAwait ( false ) ;
}
catch { }
} ;
2016-08-21 22:37:39 +00:00
return mp ;
} ) ;
Song resolvedSong ;
try
{
musicPlayer . ThrowIfQueueFull ( ) ;
2016-12-22 03:49:33 +00:00
resolvedSong = await SongHandler . ResolveSong ( query , musicType ) . ConfigureAwait ( false ) ;
2016-08-21 22:37:39 +00:00
2016-11-14 23:07:36 +00:00
if ( resolvedSong = = null )
throw new SongNotFoundException ( ) ;
2016-08-21 22:37:39 +00:00
musicPlayer . AddSong ( resolvedSong , queuer . Username ) ;
}
catch ( PlaylistFullException )
{
2016-12-28 05:31:39 +00:00
try { await textCh . SendConfirmAsync ( $"🎵 Queue is full at **{musicPlayer.MaxQueueSize}/{musicPlayer.MaxQueueSize}**." ) ; } catch { }
2016-08-21 22:37:39 +00:00
throw ;
}
if ( ! silent )
{
2016-10-05 05:01:19 +00:00
try
2016-08-21 22:37:39 +00:00
{
2016-12-21 23:52:52 +00:00
//var queuedMessage = await textCh.SendConfirmAsync($"🎵 Queued **{resolvedSong.SongInfo.Title}** at `#{musicPlayer.Playlist.Count + 1}`").ConfigureAwait(false);
2016-12-22 03:49:33 +00:00
var queuedMessage = await textCh . EmbedAsync ( new EmbedBuilder ( ) . WithOkColor ( )
2016-12-27 16:06:53 +00:00
. WithAuthor ( eab = > eab . WithName ( "Queued Song #" + ( musicPlayer . Playlist . Count + 1 ) ) . WithMusicIcon ( ) )
. WithDescription ( $"{resolvedSong.PrettyName}\nQueue " )
2016-12-31 12:21:18 +00:00
. WithThumbnailUrl ( resolvedSong . Thumbnail )
2016-12-31 10:55:12 +00:00
. WithFooter ( ef = > ef . WithText ( resolvedSong . PrettyProvider ) ) )
2016-12-21 23:52:52 +00:00
. ConfigureAwait ( false ) ;
2016-12-22 04:32:34 +00:00
if ( queuedMessage ! = null )
queuedMessage . DeleteAfter ( 10 ) ;
2016-10-05 05:01:19 +00:00
}
catch { } // if queued message sending fails, don't attempt to delete it
2016-08-21 22:37:39 +00:00
}
}
}
2016-12-23 03:50:49 +00:00
}