136 lines
4.3 KiB
C#
136 lines
4.3 KiB
C#
|
using Lavalink4NET;
|
|||
|
using Lavalink4NET.Rest;
|
|||
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Linq;
|
|||
|
using System.Text;
|
|||
|
using System.Threading.Tasks;
|
|||
|
using System.Web;
|
|||
|
using TomatenMusic.Music.Entitites;
|
|||
|
using TomatenMusic.Services;
|
|||
|
using TomatenMusicCore.Music;
|
|||
|
using TomatenMusicCore.Music.Entities;
|
|||
|
|
|||
|
namespace TomatenMusic.Music
|
|||
|
{
|
|||
|
public class TrackProvider
|
|||
|
{
|
|||
|
public ISpotifyService _spotifyService { get; set; }
|
|||
|
public IAudioService _audioService { get; set; }
|
|||
|
public YoutubeService _youtubeService { get; set; }
|
|||
|
|
|||
|
public TrackProvider(ISpotifyService spotify, IAudioService audioService, YoutubeService youtubeService)
|
|||
|
{
|
|||
|
_audioService = audioService;
|
|||
|
_spotifyService = spotify;
|
|||
|
_youtubeService = youtubeService;
|
|||
|
}
|
|||
|
|
|||
|
public async Task<MusicActionResponse> SearchAsync(string query, bool withSearchResults = false)
|
|||
|
{
|
|||
|
|
|||
|
Uri uri;
|
|||
|
TrackLoadResponsePayload loadResult;
|
|||
|
bool isSearch = true;
|
|||
|
|
|||
|
if (query.StartsWith("https://open.spotify.com"))
|
|||
|
{
|
|||
|
return await _spotifyService.ConvertURL(query);
|
|||
|
}
|
|||
|
|
|||
|
if (Uri.TryCreate(query, UriKind.Absolute, out uri))
|
|||
|
{
|
|||
|
loadResult = await _audioService.LoadTracksAsync(uri.ToString());
|
|||
|
isSearch = false;
|
|||
|
}
|
|||
|
else
|
|||
|
loadResult = await _audioService.LoadTracksAsync(query, SearchMode.YouTube);
|
|||
|
|
|||
|
if (uri != null && uri.AbsolutePath.Contains("."))
|
|||
|
return await SearchAsync(uri);
|
|||
|
|
|||
|
if (loadResult.LoadType == TrackLoadType.LoadFailed) throw new ArgumentException("Track loading failed");
|
|||
|
|
|||
|
if (loadResult.LoadType == TrackLoadType.NoMatches) throw new FileNotFoundException("Query resulted in no Matches");
|
|||
|
|
|||
|
if (ParseTimestamp(query) != null)
|
|||
|
loadResult.Tracks[0] = loadResult.Tracks[0].WithPosition((TimeSpan)ParseTimestamp(query));
|
|||
|
|
|||
|
if (withSearchResults && loadResult.LoadType == TrackLoadType.SearchResult)
|
|||
|
{
|
|||
|
return new MusicActionResponse(tracks: await FullTrackContext.PopulateTracksAsync(new TrackList(loadResult.Tracks)));
|
|||
|
}
|
|||
|
|
|||
|
if (loadResult.LoadType == TrackLoadType.PlaylistLoaded && !isSearch)
|
|||
|
return new MusicActionResponse(
|
|||
|
playlist: await _youtubeService.PopulatePlaylistAsync(
|
|||
|
new YoutubePlaylist(loadResult.PlaylistInfo.Name, await FullTrackContext.PopulateTracksAsync(new TrackList(loadResult.Tracks)), ParseListId(query))));
|
|||
|
else
|
|||
|
return new MusicActionResponse(await FullTrackContext.PopulateAsync(new TomatenMusicTrack(loadResult.Tracks.First())));
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
public async Task<MusicActionResponse> SearchAsync(Uri fileUri)
|
|||
|
{
|
|||
|
|
|||
|
var loadResult = new TomatenMusicTrack(await _audioService.GetTrackAsync(fileUri.ToString()));
|
|||
|
loadResult.Context = new FullTrackContext
|
|||
|
{
|
|||
|
IsFile = true
|
|||
|
};
|
|||
|
|
|||
|
if (loadResult == null)
|
|||
|
throw new FileNotFoundException("The file was not found");
|
|||
|
|
|||
|
return new MusicActionResponse(loadResult);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
public string ParseListId(string url)
|
|||
|
{
|
|||
|
var uri = new Uri(url, UriKind.Absolute);
|
|||
|
|
|||
|
var query = HttpUtility.ParseQueryString(uri.Query);
|
|||
|
|
|||
|
var videoId = string.Empty;
|
|||
|
|
|||
|
if (query.AllKeys.Contains("list"))
|
|||
|
{
|
|||
|
videoId = query["list"];
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
videoId = uri.Segments.Last();
|
|||
|
}
|
|||
|
|
|||
|
return videoId;
|
|||
|
}
|
|||
|
|
|||
|
public TimeSpan? ParseTimestamp(string url)
|
|||
|
{
|
|||
|
Uri uri;
|
|||
|
try
|
|||
|
{
|
|||
|
uri = new Uri(url, UriKind.Absolute);
|
|||
|
}catch (UriFormatException)
|
|||
|
{
|
|||
|
return null;
|
|||
|
}
|
|||
|
|
|||
|
var query = HttpUtility.ParseQueryString(uri.Query);
|
|||
|
|
|||
|
int seconds;
|
|||
|
|
|||
|
if (query.AllKeys.Contains("t"))
|
|||
|
{
|
|||
|
seconds = int.Parse(query["t"]);
|
|||
|
}
|
|||
|
else
|
|||
|
return null;
|
|||
|
|
|||
|
return TimeSpan.FromSeconds(seconds);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|