2022-04-06 16:41:29 +00:00
using System ;
using System.Collections.Generic ;
using System.Threading.Tasks ;
using Newtonsoft.Json ;
using Tesses.WebServer ;
using System.Net ;
using YoutubeExplode.Videos ;
using System.Linq ;
using System.IO ;
using System.Text ;
2022-04-10 00:18:45 +00:00
using YoutubeExplode.Playlists ;
using YoutubeExplode.Channels ;
2022-07-13 13:59:23 +00:00
using Tesses.Extensions ;
using YoutubeExplode.Videos.Streams ;
namespace Tesses.Extensions
{
public static class Extensions
{
public static string Substring ( this string value , string str )
{
return value . Substring ( str . Length ) ;
}
2022-08-28 21:40:34 +00:00
public static async Task RedirectBackAsync ( this ServerContext ctx )
{
await ctx . SendTextAsync ( "<script>history.back()</script>\n" ) ;
}
2022-07-13 13:59:23 +00:00
}
}
2022-04-06 16:41:29 +00:00
namespace Tesses.YouTubeDownloader.Server
{
2022-09-01 05:51:49 +00:00
using Tesses.YouTubeDownloader ;
public class Progress
{
public long Length { get ; set ; }
public double Percent { get ; set ; }
public SavedVideo Video { get ; set ; }
public bool StartEvent { get ; set ; }
public bool StopEvent { get ; set ; }
}
2022-07-13 13:59:23 +00:00
internal static class B64
{
public static string Base64UrlEncodes ( string arg )
{
return Base64UrlEncode ( System . Text . Encoding . UTF8 . GetBytes ( arg ) ) ;
}
public static string Base64Encode ( byte [ ] arg )
{
return Convert . ToBase64String ( arg ) ;
}
public static byte [ ] Base64Decode ( string arg )
{
return Convert . FromBase64String ( arg ) ;
}
public static string Base64Encodes ( string arg )
{
return Base64Encode ( System . Text . Encoding . UTF8 . GetBytes ( arg ) ) ;
}
public static string Base64UrlEncode ( byte [ ] arg )
{
string s = Convert . ToBase64String ( arg ) ; // Regular base64 encoder
s = s . Split ( '=' ) [ 0 ] ; // Remove any trailing '='s
s = s . Replace ( '+' , '-' ) ; // 62nd char of encoding
s = s . Replace ( '/' , '_' ) ; // 63rd char of encoding
return s ;
}
public static string Base64Decodes ( string arg )
{
return System . Text . Encoding . UTF8 . GetString ( Base64Decode ( arg ) ) ;
}
public static string Base64UrlDecodes ( string arg )
{
return System . Text . Encoding . UTF8 . GetString ( Base64UrlDecode ( arg ) ) ;
}
public static byte [ ] Base64UrlDecode ( string arg )
{
string s = arg ;
s = s . Replace ( '-' , '+' ) ; // 62nd char of encoding
s = s . Replace ( '_' , '/' ) ; // 63rd char of encoding
switch ( s . Length % 4 ) // Pad with trailing '='s
{
case 0 : break ; // No pad chars in this case
case 2 : s + = "==" ; break ; // Two pad chars
case 3 : s + = "=" ; break ; // One pad char
default : throw new System . Exception (
"Illegal base64url string!" ) ;
}
return Convert . FromBase64String ( s ) ; // Standard base64 decoder
}
}
2022-04-06 16:41:29 +00:00
internal class ApiV1Server : Tesses . WebServer . Server
{
IDownloader downloader1 ;
public ApiV1Server ( IDownloader dl )
{
downloader1 = dl ;
}
public override async Task GetAsync ( ServerContext ctx )
{
string path = ctx . UrlAndQuery ;
2022-07-06 22:59:50 +00:00
if ( path . StartsWith ( "/AddPlaylistRes/" ) )
{ string id_res = path . Substring ( 16 ) ;
string [ ] id_res_split = id_res . Split ( new char [ ] { '/' } , 2 , StringSplitOptions . RemoveEmptyEntries ) ;
if ( id_res_split . Length = = 2 )
{
int num ;
if ( int . TryParse ( id_res_split [ 0 ] , out num ) )
{
if ( num < 0 ) num = 1 ;
if ( num > 3 ) num = 1 ;
await downloader1 . AddPlaylistAsync ( id_res_split [ 1 ] , ( Resolution ) num ) ;
}
}
}
if ( path . StartsWith ( "/AddChannelRes/" ) )
{ string id_res = path . Substring ( 15 ) ;
string [ ] id_res_split = id_res . Split ( new char [ ] { '/' } , 2 , StringSplitOptions . RemoveEmptyEntries ) ;
if ( id_res_split . Length = = 2 )
{
int num ;
if ( int . TryParse ( id_res_split [ 0 ] , out num ) )
{
if ( num < 0 ) num = 1 ;
if ( num > 3 ) num = 1 ;
await downloader1 . AddChannelAsync ( id_res_split [ 1 ] , ( Resolution ) num ) ;
}
}
}
if ( path . StartsWith ( "/AddChannel/" ) )
{
await downloader1 . AddChannelAsync ( path . Substring ( 12 ) , Resolution . PreMuxed ) ;
}
if ( path . StartsWith ( "/AddPlaylist/" ) )
{
await downloader1 . AddPlaylistAsync ( path . Substring ( 13 ) , Resolution . PreMuxed ) ;
}
if ( path . StartsWith ( "/AddVideoRes/" ) )
{ string id_res = path . Substring ( 13 ) ;
string [ ] id_res_split = id_res . Split ( new char [ ] { '/' } , 2 , StringSplitOptions . RemoveEmptyEntries ) ;
if ( id_res_split . Length = = 2 )
{
int num ;
if ( int . TryParse ( id_res_split [ 0 ] , out num ) )
{
if ( num < 0 ) num = 1 ;
if ( num > 3 ) num = 1 ;
await downloader1 . AddVideoAsync ( id_res_split [ 1 ] , ( Resolution ) num ) ;
}
}
}
if ( path . StartsWith ( "/AddVideo/" ) )
{
//string id_res=path.Substring(12);
//string[] id_res_split = id_res.Split(new char[] {'/'},2,StringSplitOptions.RemoveEmptyEntries);
//if(id_res_split.Length ==2)
//{
await downloader1 . AddVideoAsync ( path . Substring ( 10 ) , Resolution . PreMuxed ) ;
// }
// await ctx.SendTextAsync(
// $"<html><head><titleYou Will Be Redirected in 5 Sec</title><meta http-equiv=\"Refresh\" content=\"5; url='../'\" /></head><body><h1>You Will Be Redirected in 5 Sec</h1></body></html>\n"
//);
2022-08-28 21:40:34 +00:00
2022-07-06 22:59:50 +00:00
}
2022-04-06 16:41:29 +00:00
if ( path . StartsWith ( "/AddItemRes/" ) )
{
string id_res = path . Substring ( 12 ) ;
string [ ] id_res_split = id_res . Split ( new char [ ] { '/' } , 2 , StringSplitOptions . RemoveEmptyEntries ) ;
if ( id_res_split . Length = = 2 )
{
int num ;
if ( int . TryParse ( id_res_split [ 0 ] , out num ) )
{
if ( num < 0 ) num = 1 ;
if ( num > 3 ) num = 1 ;
await downloader1 . AddItemAsync ( id_res_split [ 1 ] , ( Resolution ) num ) ;
}
}
// await ctx.SendTextAsync(
// $"<html><head><titleYou Will Be Redirected in 5 Sec</title><meta http-equiv=\"Refresh\" content=\"5; url='../'\" /></head><body><h1>You Will Be Redirected in 5 Sec</h1></body></html>\n"
//);
2022-07-06 22:59:50 +00:00
2022-04-06 16:41:29 +00:00
}
if ( path . StartsWith ( "/AddItem/" ) )
{
//string id_res=path.Substring(12);
//string[] id_res_split = id_res.Split(new char[] {'/'},2,StringSplitOptions.RemoveEmptyEntries);
//if(id_res_split.Length ==2)
//{
await downloader1 . AddItemAsync ( path . Substring ( 9 ) , Resolution . PreMuxed ) ;
// }
// await ctx.SendTextAsync(
// $"<html><head><titleYou Will Be Redirected in 5 Sec</title><meta http-equiv=\"Refresh\" content=\"5; url='../'\" /></head><body><h1>You Will Be Redirected in 5 Sec</h1></body></html>\n"
//);
2022-07-06 22:59:50 +00:00
}
if ( path . StartsWith ( "/AddUserRes/" ) )
{
string id_res = path . Substring ( 12 ) ;
string [ ] id_res_split = id_res . Split ( new char [ ] { '/' } , 2 , StringSplitOptions . RemoveEmptyEntries ) ;
if ( id_res_split . Length = = 2 )
{
int num ;
if ( int . TryParse ( id_res_split [ 0 ] , out num ) )
{
if ( num < 0 ) num = 1 ;
if ( num > 3 ) num = 1 ;
await downloader1 . AddUserAsync ( id_res_split [ 1 ] , ( Resolution ) num ) ;
}
}
// await ctx.SendTextAsync(
// $"<html><head><titleYou Will Be Redirected in 5 Sec</title><meta http-equiv=\"Refresh\" content=\"5; url='../'\" /></head><body><h1>You Will Be Redirected in 5 Sec</h1></body></html>\n"
//);
}
if ( path . StartsWith ( "/AddUser/" ) )
{
//string id_res=path.Substring(12);
//string[] id_res_split = id_res.Split(new char[] {'/'},2,StringSplitOptions.RemoveEmptyEntries);
//if(id_res_split.Length ==2)
//{
await downloader1 . AddUserAsync ( path . Substring ( 9 ) , Resolution . PreMuxed ) ;
// }
// await ctx.SendTextAsync(
// $"<html><head><titleYou Will Be Redirected in 5 Sec</title><meta http-equiv=\"Refresh\" content=\"5; url='../'\" /></head><body><h1>You Will Be Redirected in 5 Sec</h1></body></html>\n"
//);
2022-04-06 16:41:29 +00:00
}
2022-07-06 22:59:50 +00:00
if ( path . StartsWith ( "/AddFile/" ) )
{
//string id_res=path.Substring(12);
//string[] id_res_split = id_res.Split(new char[] {'/'},2,StringSplitOptions.RemoveEmptyEntries);
//if(id_res_split.Length ==2)
//{
await downloader1 . AddFileAsync ( path . Substring ( 9 ) ) ;
// }
// await ctx.SendTextAsync(
// $"<html><head><titleYou Will Be Redirected in 5 Sec</title><meta http-equiv=\"Refresh\" content=\"5; url='../'\" /></head><body><h1>You Will Be Redirected in 5 Sec</h1></body></html>\n"
//);
}
2022-08-28 21:40:34 +00:00
await ctx . RedirectBackAsync ( ) ;
2022-04-06 16:41:29 +00:00
}
}
internal class ApiStorage : Tesses . WebServer . Server
{
2022-06-14 18:21:36 +00:00
ITYTDBase baseCtl ;
public ApiStorage ( ITYTDBase baseCtl )
2022-04-06 16:41:29 +00:00
{
this . baseCtl = baseCtl ;
}
public static System . Net . Mime . ContentDisposition GetVideoContentDisposition ( string name )
{
var cd = new System . Net . Mime . ContentDisposition ( ) ;
string filename = GetVideoName ( name ) ;
cd . FileName = filename ;
2022-06-24 23:02:51 +00:00
cd . DispositionType = System . Net . Mime . DispositionTypeNames . Inline ;
2022-04-06 16:41:29 +00:00
return cd ;
}
public static string GetVideoName ( string name )
{
string asAscii = Encoding . ASCII . GetString (
Encoding . Convert (
Encoding . UTF8 ,
Encoding . GetEncoding (
Encoding . ASCII . EncodingName ,
new EncoderReplacementFallback ( string . Empty ) ,
new DecoderExceptionFallback ( )
) ,
Encoding . UTF8 . GetBytes ( name )
)
) ;
return asAscii ;
}
2022-04-10 00:18:45 +00:00
2022-04-06 16:41:29 +00:00
public override async Task GetAsync ( ServerContext ctx )
{
string path = ctx . UrlAndQuery ;
2022-04-10 00:18:45 +00:00
/ * if ( path . StartsWith ( "/File/NotConverted/" ) )
2022-04-06 16:41:29 +00:00
{
2022-04-10 00:18:45 +00:00
// redirect to new
// /File/NotConverted/xxxxxxxxxxx.mp4
string idmp4 = WebUtility . UrlDecode ( path . Substring ( 19 ) ) ;
if ( idmp4 . Length = = 15 )
{
string id = Path . GetFileNameWithoutExtension ( idmp4 ) ;
string path2 = $"Info/{id}.json" ;
if ( ! await baseCtl . FileExistsAsync ( path2 ) )
{
await NotFoundServer . ServerNull . GetAsync ( ctx ) ;
return ;
} var data = await baseCtl . ReadAllTextAsync ( path2 ) ;
var data2 = JsonConvert . DeserializeObject < SavedVideo > ( data ) ;
var loc = await BestStreams . GetPathResolution ( baseCtl , data2 , Resolution . PreMuxed ) ;
if ( ! await baseCtl . FileExistsAsync ( loc ) )
{
await NotFoundServer . ServerNull . GetAsync ( ctx ) ;
return ;
}
using ( var s = await baseCtl . OpenReadAsyncWithLength ( loc ) )
{
await ctx . SendStreamAsync ( s , HeyRed . Mime . MimeTypesMap . GetMimeType ( loc ) ) ;
}
}
}
else if ( path . StartsWith ( "/File/Converted/" ) )
{
// redirect to new
// /File/NotConverted/xxxxxxxxxxx.mp4
string idmp4 = WebUtility . UrlDecode ( path . Substring ( 16 ) ) ;
if ( idmp4 . Length = = 15 )
{
string id = Path . GetFileNameWithoutExtension ( idmp4 ) ;
string path2 = $"Info/{id}.json" ;
if ( ! await baseCtl . FileExistsAsync ( path2 ) )
{
await NotFoundServer . ServerNull . GetAsync ( ctx ) ;
return ;
} var data = await baseCtl . ReadAllTextAsync ( path2 ) ;
var data2 = JsonConvert . DeserializeObject < SavedVideo > ( data ) ;
var loc = await BestStreams . GetPathResolution ( baseCtl , data2 , Resolution . Mux ) ;
if ( ! await baseCtl . FileExistsAsync ( loc ) )
{
await NotFoundServer . ServerNull . GetAsync ( ctx ) ;
return ;
}
using ( var s = await baseCtl . OpenReadAsyncWithLength ( loc ) )
{
await ctx . SendStreamAsync ( s , HeyRed . Mime . MimeTypesMap . GetMimeType ( loc ) ) ;
}
}
}
else if ( path . StartsWith ( "/File/Audio/" ) )
{
// redirect to new
// /File/NotConverted/xxxxxxxxxxx.mp4
string idmp4 = WebUtility . UrlDecode ( path . Substring ( 12 ) ) ;
if ( idmp4 . Length = = 15 )
{
string id = Path . GetFileNameWithoutExtension ( idmp4 ) ;
string path2 = $"Info/{id}.json" ;
if ( ! await baseCtl . FileExistsAsync ( path2 ) )
{
await NotFoundServer . ServerNull . GetAsync ( ctx ) ;
return ;
} var data = await baseCtl . ReadAllTextAsync ( path2 ) ;
var data2 = JsonConvert . DeserializeObject < SavedVideo > ( data ) ;
var loc = await BestStreams . GetPathResolution ( baseCtl , data2 , Resolution . AudioOnly ) ;
if ( ! await baseCtl . FileExistsAsync ( loc ) )
{
await NotFoundServer . ServerNull . GetAsync ( ctx ) ;
return ;
}
using ( var s = await baseCtl . OpenReadAsyncWithLength ( loc ) )
{
await ctx . SendStreamAsync ( s , HeyRed . Mime . MimeTypesMap . GetMimeType ( loc ) ) ;
}
}
}
else if ( path . StartsWith ( "/File/Info/" ) )
{
string idjson = WebUtility . UrlDecode ( path . Substring ( 11 ) ) ;
string path2 = $"Info/{idjson}" ;
if ( ! await baseCtl . FileExistsAsync ( path2 ) )
{
await NotFoundServer . ServerNull . GetAsync ( ctx ) ;
return ;
}
var data = await baseCtl . ReadAllTextAsync ( path2 ) ;
var data2 = JsonConvert . DeserializeObject < SavedVideo > ( data ) ;
await ctx . SendJsonAsync ( data2 . ToLegacy ( ) ) ;
}
2022-07-13 13:59:23 +00:00
else * /
if ( path . StartsWith ( "/File/FileInfo/" ) )
{
string file = Path . GetFileNameWithoutExtension ( WebUtility . UrlDecode ( path . Substring ( "/File/FileInfo/" ) ) ) ;
string url = B64 . Base64UrlDecodes ( file ) ;
if ( baseCtl . DownloadExists ( url ) )
{
var obj = await baseCtl . GetDownloadInfoAsync ( url ) ;
await ctx . SendJsonAsync ( obj ) ;
} else {
ctx . StatusCode = 404 ;
ctx . NetworkStream . Close ( ) ;
}
}
else if ( path . StartsWith ( "/File/Info/" ) )
{
string file = Path . GetFileNameWithoutExtension ( WebUtility . UrlDecode ( path . Substring ( "/File/Info/" ) ) ) ;
VideoId ? id = VideoId . TryParse ( file ) ;
if ( id . HasValue & & baseCtl . VideoInfoExists ( id . Value ) )
{
var obj = await baseCtl . GetVideoInfoAsync ( id . Value ) ;
await ctx . SendJsonAsync ( obj ) ;
} else {
ctx . StatusCode = 404 ;
ctx . NetworkStream . Close ( ) ;
}
} else if ( path . StartsWith ( "/File/Playlist/" ) )
{
string file = Path . GetFileNameWithoutExtension ( WebUtility . UrlDecode ( path . Substring ( "/File/Playlist/" ) ) ) ;
PlaylistId ? id = PlaylistId . TryParse ( file ) ;
if ( id . HasValue & & baseCtl . PlaylistInfoExists ( id . Value ) )
{
var obj = await baseCtl . GetPlaylistInfoAsync ( id . Value ) ;
await ctx . SendJsonAsync ( obj ) ;
} else {
ctx . StatusCode = 404 ;
ctx . NetworkStream . Close ( ) ;
}
} else if ( path . StartsWith ( "/File/Channel/" ) )
{
string file = Path . GetFileNameWithoutExtension ( WebUtility . UrlDecode ( path . Substring ( "/File/Channel/" ) ) ) ;
ChannelId ? id = ChannelId . TryParse ( file ) ;
if ( id . HasValue & & baseCtl . ChannelInfoExists ( id . Value ) )
{
var obj = await baseCtl . GetChannelInfoAsync ( id . Value ) ;
await ctx . SendJsonAsync ( obj ) ;
} else {
ctx . StatusCode = 404 ;
ctx . NetworkStream . Close ( ) ;
}
} else if ( path . StartsWith ( "/File/StreamInfo/" ) )
{
string file = Path . GetFileNameWithoutExtension ( WebUtility . UrlDecode ( path . Substring ( "/File/Info/" ) ) ) ;
VideoId ? id = VideoId . TryParse ( file ) ;
if ( id . HasValue & & baseCtl . BestStreamInfoExists ( id . Value ) )
{
var obj = await baseCtl . GetBestStreamInfoAsync ( id . Value ) ;
await ctx . SendJsonAsync ( obj ) ;
} else {
ctx . StatusCode = 404 ;
ctx . NetworkStream . Close ( ) ;
}
}
else if ( path . StartsWith ( "/File/" ) )
2022-04-10 00:18:45 +00:00
{
string file = WebUtility . UrlDecode ( path . Substring ( 6 ) ) ;
if ( ! await baseCtl . FileExistsAsync ( file ) )
{
await NotFoundServer . ServerNull . GetAsync ( ctx ) ;
return ;
}
2022-06-24 23:02:51 +00:00
using ( var s = await baseCtl . OpenReadAsync ( file ) )
2022-04-10 00:18:45 +00:00
{
await ctx . SendStreamAsync ( s ) ;
}
} / * else if ( path . StartsWith ( "/File-v2/" ) )
{
string file = WebUtility . UrlDecode ( path . Substring ( 9 ) ) ;
if ( ! await baseCtl . FileExistsAsync ( file ) )
{
await NotFoundServer . ServerNull . GetAsync ( ctx ) ;
return ;
}
using ( var s = await baseCtl . OpenReadAsyncWithLength ( file ) )
2022-04-06 16:41:29 +00:00
{
await ctx . SendStreamAsync ( s ) ;
}
2022-04-10 00:18:45 +00:00
} * /
2022-07-13 13:59:23 +00:00
else if ( path . StartsWith ( "/GetFiles/FileInfo" ) | | path . StartsWith ( "/GetFiles/FileInfo/" ) )
{
List < string > urls = new List < string > ( ) ;
await foreach ( var url in baseCtl . GetDownloadUrlsAsync ( ) )
{
urls . Add ( $"{B64.Base64UrlEncodes(url)}.json" ) ;
}
await ctx . SendJsonAsync ( urls ) ;
}
else if ( path . StartsWith ( "/GetFiles/Info" ) | | path . StartsWith ( "/GetFiles/Info/" ) | | path . StartsWith ( "/GetFiles/StreamInfo" ) | | path . StartsWith ( "/GetFiles/StreamInfo/" ) )
{
bool containsStrmInfo = path . Contains ( "StreamInfo" ) ;
List < string > items = new List < string > ( ) ;
await foreach ( var vid in baseCtl . GetVideoIdsAsync ( ) )
{
var vid2 = VideoId . TryParse ( vid ) ;
if ( ! containsStrmInfo | | ( vid2 . HasValue & & baseCtl . BestStreamInfoExists ( vid2 . Value ) ) ) {
items . Add ( $"{vid}.json" ) ;
}
}
await ctx . SendJsonAsync ( items ) ;
} else if ( path . StartsWith ( "/GetFiles/Playlist" ) | | path . StartsWith ( "/GetFiles/Playlist/" ) )
{
List < string > items = new List < string > ( ) ;
await foreach ( var vid in baseCtl . GetPlaylistIdsAsync ( ) )
{
items . Add ( $"{vid}.json" ) ;
}
await ctx . SendJsonAsync ( items ) ;
} else if ( path . StartsWith ( "/GetFiles/Channel" ) | | path . StartsWith ( "/GetFiles/Channel/" ) )
{
List < string > items = new List < string > ( ) ;
await foreach ( var vid in baseCtl . GetChannelIdsAsync ( ) )
{
items . Add ( $"{vid}.json" ) ;
}
await ctx . SendJsonAsync ( items ) ;
}
2022-04-10 00:18:45 +00:00
else if ( path . StartsWith ( "/GetFiles/" ) )
2022-04-06 16:41:29 +00:00
{
await ctx . SendJsonAsync ( baseCtl . EnumerateFiles ( WebUtility . UrlDecode ( path . Substring ( 10 ) ) ) . ToList ( ) ) ;
2022-07-13 13:59:23 +00:00
}
else if ( path . StartsWith ( "/GetDirectories/" ) )
2022-04-06 16:41:29 +00:00
{
await ctx . SendJsonAsync ( baseCtl . EnumerateDirectories ( WebUtility . UrlDecode ( path . Substring ( 16 ) ) ) . ToList ( ) ) ;
2022-07-13 13:59:23 +00:00
}
else if ( path . StartsWith ( "/FileExists/StreamInfo/" ) )
{
string file = Path . GetFileNameWithoutExtension ( WebUtility . UrlDecode ( path . Substring ( "/FileExists/StreamInfo/" ) ) ) ;
VideoId ? id = VideoId . TryParse ( file ) ;
if ( id . HasValue & & baseCtl . BestStreamInfoExists ( id . Value ) )
{
await ctx . SendTextAsync ( "true" , "text/plain" ) ;
} else {
await ctx . SendTextAsync ( "false" , "text/plain" ) ;
}
}
else if ( path . StartsWith ( "/FileExists/FileInfo/" ) )
{
string file = Path . GetFileNameWithoutExtension ( WebUtility . UrlDecode ( path . Substring ( "/FileExists/StreamInfo/" ) ) ) ;
string url = B64 . Base64Decodes ( file ) ;
if ( baseCtl . DownloadExists ( url ) )
{
await ctx . SendTextAsync ( "true" , "text/plain" ) ;
} else {
await ctx . SendTextAsync ( "false" , "text/plain" ) ;
}
}
else if ( path . StartsWith ( "/FileExists/Info/" ) )
{
string file = Path . GetFileNameWithoutExtension ( WebUtility . UrlDecode ( path . Substring ( "/FileExists/Info/" ) ) ) ;
VideoId ? id = VideoId . TryParse ( file ) ;
if ( id . HasValue & & baseCtl . VideoInfoExists ( id . Value ) )
{
await ctx . SendTextAsync ( "true" , "text/plain" ) ;
} else {
await ctx . SendTextAsync ( "false" , "text/plain" ) ;
}
} else if ( path . StartsWith ( "/FileExists/Playlist/" ) )
{
string file = Path . GetFileNameWithoutExtension ( WebUtility . UrlDecode ( path . Substring ( "/FileExists/Playlist/" ) ) ) ;
PlaylistId ? id = PlaylistId . TryParse ( file ) ;
if ( id . HasValue & & baseCtl . PlaylistInfoExists ( id . Value ) )
{
await ctx . SendTextAsync ( "true" , "text/plain" ) ;
} else {
await ctx . SendTextAsync ( "false" , "text/plain" ) ;
}
} else if ( path . StartsWith ( "/FileExists/Channel/" ) )
2022-04-10 00:18:45 +00:00
{
2022-07-13 13:59:23 +00:00
string file = Path . GetFileNameWithoutExtension ( WebUtility . UrlDecode ( path . Substring ( "/FileExists/Channel/" ) ) ) ;
ChannelId ? id = ChannelId . TryParse ( file ) ;
if ( id . HasValue & & baseCtl . ChannelInfoExists ( id . Value ) )
{
await ctx . SendTextAsync ( "true" , "text/plain" ) ;
} else {
await ctx . SendTextAsync ( "false" , "text/plain" ) ;
}
2022-04-10 00:18:45 +00:00
}
else if ( path . StartsWith ( "/FileExists/" ) )
2022-04-06 16:41:29 +00:00
{
await ctx . SendTextAsync ( baseCtl . FileExists ( WebUtility . UrlDecode ( path . Substring ( 12 ) ) ) ? "true" : "false" , "text/plain" ) ;
} else if ( path . StartsWith ( "/DirectoryExists/" ) )
{
await ctx . SendTextAsync ( baseCtl . DirectoryExists ( WebUtility . UrlDecode ( path . Substring ( 17 ) ) ) ? "true" : "false" , "text/plain" ) ;
2022-07-13 13:59:23 +00:00
} else if ( path . StartsWith ( "/Download/" ) )
{
string url = path . Substring ( "/Download/" ) ;
if ( baseCtl . DownloadExists ( url ) & & baseCtl . DownloadFileExists ( url ) )
{
var v = await baseCtl . GetDownloadInfoAsync ( url ) ;
string header = GetVideoContentDisposition ( v . Title ) . ToString ( ) ;
ctx . ResponseHeaders . Add ( "Content-Disposition" , header ) ;
using ( var strm = await baseCtl . OpenReadAsync ( baseCtl . GetDownloadFile ( url ) ) )
{
await ctx . SendStreamAsync ( strm , HeyRed . Mime . MimeTypesMap . GetMimeType ( v . Title ) ) ;
}
}
}
else if ( path . StartsWith ( "/Video/" ) )
2022-04-06 16:41:29 +00:00
{
string id = path . Substring ( 7 ) ;
VideoId ? id1 = VideoId . TryParse ( id ) ;
if ( id1 . HasValue ) {
2022-07-13 13:59:23 +00:00
if ( baseCtl . VideoInfoExists ( id1 . Value ) )
2022-04-06 16:41:29 +00:00
{
//Console.WriteLine("Id exists");
SavedVideo v = await baseCtl . GetVideoInfoAsync ( id1 . Value ) ;
string path0 = await BestStreams . GetPathResolution ( baseCtl , v , Resolution . PreMuxed ) ;
if ( ! string . IsNullOrWhiteSpace ( path0 ) )
{
//Console.WriteLine("F is not null");
2022-04-10 00:18:45 +00:00
string filename = $"{v.Title}-{Path.GetFileName(path0)}" ;
2022-04-06 16:41:29 +00:00
string header = GetVideoContentDisposition ( filename ) . ToString ( ) ;
ctx . ResponseHeaders . Add ( "Content-Disposition" , header ) ;
using ( var strm = await baseCtl . OpenReadAsync ( path0 ) )
{
await ctx . SendStreamAsync ( strm , HeyRed . Mime . MimeTypesMap . GetMimeType ( filename ) ) ;
}
}
}
}
2022-07-13 13:59:23 +00:00
}
else if ( path . StartsWith ( "/VideoRes/" ) )
2022-04-06 16:41:29 +00:00
{
string id_res = path . Substring ( 10 ) ;
string [ ] id_res_split = id_res . Split ( new char [ ] { '/' } , 2 , StringSplitOptions . RemoveEmptyEntries ) ;
if ( id_res_split . Length = = 2 )
{
int num ;
if ( int . TryParse ( id_res_split [ 0 ] , out num ) )
{
if ( num < 0 ) num = 1 ;
if ( num > 3 ) num = 1 ;
VideoId ? id1 = VideoId . TryParse ( id_res_split [ 1 ] ) ;
if ( id1 . HasValue ) {
2022-07-13 13:59:23 +00:00
if ( baseCtl . VideoInfoExists ( id1 . Value ) )
2022-04-06 16:41:29 +00:00
{
//Console.WriteLine("Id exists");
SavedVideo v = await baseCtl . GetVideoInfoAsync ( id1 . Value ) ;
string path0 = await BestStreams . GetPathResolution ( baseCtl , v , ( Resolution ) num ) ;
if ( ! string . IsNullOrWhiteSpace ( path0 ) )
{
//Console.WriteLine("F is not null");
2022-04-10 00:18:45 +00:00
string filename = $"{v.Title}-{Path.GetFileName(path0)}" ;
2022-04-06 16:41:29 +00:00
string header = GetVideoContentDisposition ( filename ) . ToString ( ) ;
ctx . ResponseHeaders . Add ( "Content-Disposition" , header ) ;
using ( var strm = await baseCtl . OpenReadAsync ( path0 ) )
{
await ctx . SendStreamAsync ( strm , HeyRed . Mime . MimeTypesMap . GetMimeType ( filename ) ) ;
}
}
}
}
}
}
}
2022-07-13 13:59:23 +00:00
else if ( path . StartsWith ( "/Watch/" ) )
{
string id = path . Substring ( 7 ) ;
VideoId ? id1 = VideoId . TryParse ( id ) ;
if ( id1 . HasValue ) {
int i = 0 ;
alt :
if ( i > = 10 )
{
ctx . StatusCode = 500 ;
return ;
}
if ( baseCtl . VideoInfoExists ( id1 . Value ) )
{
//Console.WriteLine("Id exists");
SavedVideo v = await baseCtl . GetVideoInfoAsync ( id1 . Value ) ;
var res = await BestStreamInfo . GetBestStreams ( baseCtl , id1 . Value ) ;
string path0 = await BestStreams . GetPathResolution ( baseCtl , v , Resolution . PreMuxed ) ;
if ( ! string . IsNullOrWhiteSpace ( path0 ) & & baseCtl . VideoInfoExists ( id1 . Value ) )
{
//Console.WriteLine("F is not null");
string filename = $"{v.Title}-{Path.GetFileName(path0)}" ;
string header = GetVideoContentDisposition ( filename ) . ToString ( ) ;
ctx . ResponseHeaders . Add ( "Content-Disposition" , header ) ;
using ( var strm = await baseCtl . OpenReadAsync ( path0 ) )
{
await ctx . SendStreamAsync ( strm , HeyRed . Mime . MimeTypesMap . GetMimeType ( filename ) ) ;
}
} else {
//stream to browser
string url = res . MuxedStreamInfo . Url ;
var b = baseCtl as TYTDStorage ;
if ( b ! = null )
{
string filename = $"{v.Title}-{Path.GetFileName(path0)}" ;
string header = GetVideoContentDisposition ( filename ) . ToString ( ) ;
ctx . ResponseHeaders . Add ( "Content-Disposition" , header ) ;
using ( var strm = await b . YoutubeClient . Videos . Streams . GetAsync ( res . MuxedStreamInfo ) )
{
await ctx . SendStreamAsync ( strm , HeyRed . Mime . MimeTypesMap . GetMimeType ( filename ) ) ;
}
} else {
ctx . StatusCode = 500 ;
return ;
}
}
} else {
var b = baseCtl as TYTDStorage ;
if ( b ! = null )
{
var videoInfo = await b . YoutubeClient . Videos . GetAsync ( id1 . Value ) ;
await b . WriteVideoInfoAsync ( new SavedVideo ( videoInfo ) ) ;
} else {
ctx . StatusCode = 500 ;
return ;
}
i + + ;
goto alt ;
}
}
}
else if ( path . StartsWith ( "/WatchRes/" ) )
{
string id_res = path . Substring ( 10 ) ;
string [ ] id_res_split = id_res . Split ( new char [ ] { '/' } , 2 , StringSplitOptions . RemoveEmptyEntries ) ;
if ( id_res_split . Length = = 2 )
{
int num ;
if ( int . TryParse ( id_res_split [ 0 ] , out num ) )
{
if ( num < 0 ) num = 1 ;
if ( num > 3 ) num = 1 ;
VideoId ? id1 = VideoId . TryParse ( id_res_split [ 1 ] ) ;
if ( id1 . HasValue ) {
int i = 0 ;
alt :
if ( i > = 10 )
{
ctx . StatusCode = 500 ;
return ;
}
if ( baseCtl . VideoInfoExists ( id1 . Value ) )
{
//Console.WriteLine("Id exists");
SavedVideo v = await baseCtl . GetVideoInfoAsync ( id1 . Value ) ;
var res = await BestStreamInfo . GetBestStreams ( baseCtl , id1 . Value ) ;
string path0 = await BestStreams . GetPathResolution ( baseCtl , v , ( Resolution ) num ) ;
if ( ! string . IsNullOrWhiteSpace ( path0 ) & & baseCtl . VideoInfoExists ( id1 . Value ) )
{
//Console.WriteLine("F is not null");
string filename = $"{v.Title}-{Path.GetFileName(path0)}" ;
string header = GetVideoContentDisposition ( filename ) . ToString ( ) ;
ctx . ResponseHeaders . Add ( "Content-Disposition" , header ) ;
using ( var strm = await baseCtl . OpenReadAsync ( path0 ) )
{
await ctx . SendStreamAsync ( strm , HeyRed . Mime . MimeTypesMap . GetMimeType ( filename ) ) ;
}
} else {
//stream to browser
var b = baseCtl as TYTDStorage ;
if ( b ! = null )
{
string filename = $"{v.Title}-{Path.GetFileName(path0)}" ;
string header = GetVideoContentDisposition ( filename ) . ToString ( ) ;
ctx . ResponseHeaders . Add ( "Content-Disposition" , header ) ;
IStreamInfo info = res . MuxedStreamInfo ;
if ( num = = 2 )
{
info = res . AudioOnlyStreamInfo ;
} else if ( num = = 3 ) {
info = res . VideoOnlyStreamInfo ;
}
using ( var strm = await b . YoutubeClient . Videos . Streams . GetAsync ( info ) )
{
await ctx . SendStreamAsync ( strm , HeyRed . Mime . MimeTypesMap . GetMimeType ( filename ) ) ;
}
} else {
ctx . StatusCode = 500 ;
return ;
}
}
} else {
var b = baseCtl as TYTDStorage ;
if ( b ! = null )
{
var videoInfo = await b . YoutubeClient . Videos . GetAsync ( id1 . Value ) ;
await b . WriteVideoInfoAsync ( new SavedVideo ( videoInfo ) ) ;
} else {
ctx . StatusCode = 500 ;
return ;
}
i + + ;
goto alt ;
}
}
}
}
}
2022-04-06 16:41:29 +00:00
else {
await NotFoundServer . ServerNull . GetAsync ( ctx ) ;
}
}
}
internal class ApiV2Server : RouteServer
{
IDownloader Downloader ;
public ApiV2Server ( IDownloader downloader )
{
this . Downloader = downloader ;
2022-09-01 05:51:49 +00:00
AddBoth ( "/event" , Event ) ;
2022-08-28 21:40:34 +00:00
AddBoth ( "/CancelDownload" , Cancel ) ;
2022-07-13 13:59:23 +00:00
AddBoth ( "/Search" , Search ) ;
2022-06-24 23:02:51 +00:00
AddBoth ( "/AddItem" , AddItem ) ;
AddBoth ( "/AddChannel" , AddChannel ) ;
AddBoth ( "/AddUser" , AddUser ) ;
AddBoth ( "/AddPlaylist" , AddPlaylist ) ;
AddBoth ( "/AddVideo" , AddVideo ) ;
2022-07-06 22:59:50 +00:00
AddBoth ( "/AddFile" , AddFile ) ;
2022-06-24 23:02:51 +00:00
AddBoth ( "/Progress" , ProgressFunc ) ;
AddBoth ( "/QueueList" , QueueList ) ;
AddBoth ( "/subscribe" , Subscribe ) ;
AddBoth ( "/resubscribe" , Resubscribe ) ;
AddBoth ( "/unsubscribe" , Unsubscribe ) ;
AddBoth ( "/subscriptions" , Subscriptions ) ;
AddBoth ( "/Subscribe" , Subscribe ) ;
AddBoth ( "/Resubscribe" , Resubscribe ) ;
AddBoth ( "/Unsubscribe" , Unsubscribe ) ;
AddBoth ( "/Subscriptions" , Subscriptions ) ;
AddBoth ( "/AddToList" , AddToList ) ;
AddBoth ( "/DeleteFromList" , DeleteFromList ) ;
Add ( "/ReplaceList" , ReplaceList , "POST" ) ;
AddBoth ( "/DeleteList" , DeleteList ) ;
AddBoth ( "/SetResolutionInList" , SetResolutionInList ) ;
2022-07-13 13:59:23 +00:00
Add ( "/export/everything.json" , Everything_Export , "GET" ) ;
Add ( "/export/videos.json" , VideosExport , "GET" ) ;
Add ( "/export/playlists.json" , PlaylistsExport , "GET" ) ;
Add ( "/export/channels.json" , ChannelsExport , "GET" ) ;
Add ( "/export/filedownloads.json" , FilesExport , "GET" ) ;
Add ( "/export/subscriptions.json" , SubscriptionsExport , "GET" ) ;
Add ( "/export/personal_lists.json" , PersonalListsExport , "GET" ) ;
2022-05-09 22:00:19 +00:00
2022-06-24 23:02:51 +00:00
/ *
public async Task AddToPersonalPlaylistAsync ( string name , IEnumerable < ( VideoId Id , Resolution Resolution ) > items )
{
throw new NotImplementedException ( ) ;
}
public async Task ReplacePersonalPlaylistAsync ( string name , IEnumerable < ( VideoId Id , Resolution Resolution ) > items )
{
throw new NotImplementedException ( ) ;
}
public async Task RemoveItemFromPersonalPlaylistAsync ( string name , VideoId id )
{
throw new NotImplementedException ( ) ;
}
public async Task SetResolutionForItemInPersonalPlaylistAsync ( string name , VideoId id , Resolution resolution )
{
throw new NotImplementedException ( ) ;
} * /
}
2022-09-01 05:51:49 +00:00
public async Task Event ( ServerContext ctx )
{
IStorage storage = Downloader as IStorage ;
if ( storage ! = null ) {
var _p = Downloader . GetProgress ( ) ;
long len = _p . Length ;
bool first = true ;
SendEvents evts = new SendEvents ( ) ;
storage . VideoStarted + = ( sender , e ) = >
{
len = e . EstimatedLength ;
Progress p = new Progress ( ) ;
p . StartEvent = true ;
p . StopEvent = false ;
p . Length = e . EstimatedLength ;
p . Percent = 0 ;
p . Video = e . VideoInfo ;
evts . SendEvent ( p ) ;
} ;
storage . VideoProgress + = ( sender , e ) = > {
Progress p = new Progress ( ) ;
p . StartEvent = false ;
p . StopEvent = false ;
p . Length = len ;
p . Percent = e . Progress ;
if ( first )
p . Video = e . VideoInfo ;
first = false ;
evts . SendEvent ( p ) ;
} ;
storage . VideoFinished + = ( sender , e ) = > {
Progress p = new Progress ( ) ;
p . StartEvent = false ;
p . StopEvent = true ;
p . Length = len ;
p . Percent = 1 ;
p . Video = e . VideoInfo ;
evts . SendEvent ( p ) ;
} ;
ctx . ServerSentEvents ( evts ) ;
} else {
await ctx . SendTextAsync ( "Error no IStorage" ) ;
}
}
2022-08-28 21:40:34 +00:00
private async Task Cancel ( ServerContext ctx )
{
bool restart = false ;
string restartString = "false" ;
if ( ctx . QueryParams . TryGetFirst ( "restart" , out restartString ) )
{
if ( ! bool . TryParse ( restartString , out restart ) )
{
restart = false ;
}
}
Downloader . CancelDownload ( restart ) ;
await ctx . RedirectBackAsync ( ) ;
}
2022-07-13 13:59:23 +00:00
private async Task Search ( ServerContext ctx )
{
var dl = Downloader as IStorage ;
string q ;
if ( ctx . QueryParams . TryGetFirst ( "q" , out q ) )
{
bool getInfoBool = false ;
string getInfo ;
if ( ctx . QueryParams . TryGetFirst ( "getinfo" , out getInfo ) )
{
if ( ! bool . TryParse ( getInfo , out getInfoBool ) ) getInfoBool = false ;
}
List < SearchResult > results = new List < SearchResult > ( ) ;
await foreach ( var vid in dl . SearchYouTubeAsync ( q , getInfoBool ) )
{
results . Add ( vid ) ;
}
if ( getInfoBool )
{
dl . WaitTillMediaContentQueueEmpty ( ) ;
}
await ctx . SendJsonAsync ( results ) ;
}
}
2022-06-24 23:02:51 +00:00
private void AddBoth ( string url , HttpActionAsync action )
{
Add ( url , action ) ;
Add ( url , async ( evt ) = > {
evt . ParseBody ( ) ;
await action ( evt ) ;
} , "POST" ) ;
}
public async Task DeleteList ( ServerContext ctx )
{
//this is for personal playlists
string name ;
if ( ctx . QueryParams . TryGetFirst ( "name" , out name ) ) {
Downloader . DeletePersonalPlaylist ( name ) ;
//Downloader.AddToPersonalPlaylistAsync(name);
}
2022-08-28 21:40:34 +00:00
await ctx . RedirectBackAsync ( ) ;
2022-06-24 23:02:51 +00:00
}
public async Task ReplaceList ( ServerContext ctx )
{
//this is for personal playlists
string name ;
if ( ctx . QueryParams . TryGetFirst ( "name" , out name ) ) {
string jsonData ;
List < ListContentItem > itemList ;
if ( ctx . QueryParams . TryGetFirst ( "data" , out jsonData ) )
{
itemList = JsonConvert . DeserializeObject < List < ListContentItem > > ( jsonData ) ;
await Downloader . ReplacePersonalPlaylistAsync ( name , itemList ) ;
}
//Downloader.AddToPersonalPlaylistAsync(name);
}
2022-08-28 21:40:34 +00:00
await ctx . RedirectBackAsync ( ) ;
2022-06-24 23:02:51 +00:00
}
2022-07-13 13:59:23 +00:00
public async Task Everything_Export ( ServerContext ctx )
{
var storage = Downloader as TYTDStorage ;
if ( storage ! = null )
{
if ( storage . GetLoggerProperties ( ) . AllowExport )
{
TYTDExporter exporter = new TYTDExporter ( storage ) ;
var res = await exporter . ExportEverythingAsync ( ) ;
await ctx . SendJsonAsync ( res ) ;
} else {
ctx . StatusCode = 403 ;
await ctx . SendTextAsync ( "<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"UTF-8\"><meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>Can't Export, Access Denied</title></head><body><h1>Can't Export, Access Denied</h1><p>Call the TYTD adminstrator if you are not the administrator to edit the following</p><hr><p>In file: <i><b>config/tytdprop.json</b></i>, unless overriden in code<br>Change <font color=\"#ce9178\">"AllowExport"</font>:<font color=\"#569cd6\">false</font> with <font color=\"#ce9178\">"AllowExport"</font>:<font color=\"#569cd6\">true</font></p></body></html>" ) ;
}
}
}
public async Task VideosExport ( ServerContext ctx )
{
var storage = Downloader as TYTDStorage ;
if ( storage ! = null )
{
if ( storage . GetLoggerProperties ( ) . AllowExport )
{
TYTDExporter exporter = new TYTDExporter ( storage ) ;
var res = await exporter . ExportVideosAsync ( ) ;
await ctx . SendJsonAsync ( res ) ;
} else {
ctx . StatusCode = 403 ;
await ctx . SendTextAsync ( "<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"UTF-8\"><meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>Can't Export, Access Denied</title></head><body><h1>Can't Export, Access Denied</h1><p>Call the TYTD adminstrator if you are not the administrator to edit the following</p><hr><p>In file: <i><b>config/tytdprop.json</b></i>, unless overriden in code<br>Change <font color=\"#ce9178\">"AllowExport"</font>:<font color=\"#569cd6\">false</font> with <font color=\"#ce9178\">"AllowExport"</font>:<font color=\"#569cd6\">true</font></p></body></html>" ) ;
}
}
}
public async Task PlaylistsExport ( ServerContext ctx )
{
var storage = Downloader as TYTDStorage ;
if ( storage ! = null )
{
if ( storage . GetLoggerProperties ( ) . AllowExport )
{
TYTDExporter exporter = new TYTDExporter ( storage ) ;
var res = await exporter . ExportPlaylistsAsync ( ) ;
await ctx . SendJsonAsync ( res ) ;
} else {
ctx . StatusCode = 403 ;
await ctx . SendTextAsync ( "<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"UTF-8\"><meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>Can't Export, Access Denied</title></head><body><h1>Can't Export, Access Denied</h1><p>Call the TYTD adminstrator if you are not the administrator to edit the following</p><hr><p>In file: <i><b>config/tytdprop.json</b></i>, unless overriden in code<br>Change <font color=\"#ce9178\">"AllowExport"</font>:<font color=\"#569cd6\">false</font> with <font color=\"#ce9178\">"AllowExport"</font>:<font color=\"#569cd6\">true</font></p></body></html>" ) ;
}
}
}
public async Task ChannelsExport ( ServerContext ctx )
{
var storage = Downloader as TYTDStorage ;
if ( storage ! = null )
{
if ( storage . GetLoggerProperties ( ) . AllowExport )
{
TYTDExporter exporter = new TYTDExporter ( storage ) ;
var res = await exporter . ExportChannelsAsync ( ) ;
await ctx . SendJsonAsync ( res ) ;
} else {
ctx . StatusCode = 403 ;
await ctx . SendTextAsync ( "<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"UTF-8\"><meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>Can't Export, Access Denied</title></head><body><h1>Can't Export, Access Denied</h1><p>Call the TYTD adminstrator if you are not the administrator to edit the following</p><hr><p>In file: <i><b>config/tytdprop.json</b></i>, unless overriden in code<br>Change <font color=\"#ce9178\">"AllowExport"</font>:<font color=\"#569cd6\">false</font> with <font color=\"#ce9178\">"AllowExport"</font>:<font color=\"#569cd6\">true</font></p></body></html>" ) ;
}
}
}
public async Task FilesExport ( ServerContext ctx )
{
var storage = Downloader as TYTDStorage ;
if ( storage ! = null )
{
if ( storage . GetLoggerProperties ( ) . AllowExport )
{
TYTDExporter exporter = new TYTDExporter ( storage ) ;
var res = await exporter . ExportDownloadsAsync ( ) ;
await ctx . SendJsonAsync ( res ) ;
} else {
ctx . StatusCode = 403 ;
await ctx . SendTextAsync ( "<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"UTF-8\"><meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>Can't Export, Access Denied</title></head><body><h1>Can't Export, Access Denied</h1><p>Call the TYTD adminstrator if you are not the administrator to edit the following</p><hr><p>In file: <i><b>config/tytdprop.json</b></i>, unless overriden in code<br>Change <font color=\"#ce9178\">"AllowExport"</font>:<font color=\"#569cd6\">false</font> with <font color=\"#ce9178\">"AllowExport"</font>:<font color=\"#569cd6\">true</font></p></body></html>" ) ;
}
}
}
public async Task SubscriptionsExport ( ServerContext ctx )
{
var storage = Downloader as TYTDStorage ;
if ( storage ! = null )
{
if ( storage . GetLoggerProperties ( ) . AllowExport )
{
TYTDExporter exporter = new TYTDExporter ( storage ) ;
var res = await exporter . ExportSubscriptionsAsync ( ) ;
await ctx . SendJsonAsync ( res ) ;
} else {
ctx . StatusCode = 403 ;
await ctx . SendTextAsync ( "<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"UTF-8\"><meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>Can't Export, Access Denied</title></head><body><h1>Can't Export, Access Denied</h1><p>Call the TYTD adminstrator if you are not the administrator to edit the following</p><hr><p>In file: <i><b>config/tytdprop.json</b></i>, unless overriden in code<br>Change <font color=\"#ce9178\">"AllowExport"</font>:<font color=\"#569cd6\">false</font> with <font color=\"#ce9178\">"AllowExport"</font>:<font color=\"#569cd6\">true</font></p></body></html>" ) ;
}
}
}
public async Task PersonalListsExport ( ServerContext ctx )
{
var storage = Downloader as TYTDStorage ;
if ( storage ! = null )
{
if ( storage . GetLoggerProperties ( ) . AllowExport )
{
TYTDExporter exporter = new TYTDExporter ( storage ) ;
var res = await exporter . ExportPersonalPlaylistsAsync ( ) ;
await ctx . SendJsonAsync ( res ) ;
} else {
ctx . StatusCode = 403 ;
await ctx . SendTextAsync ( "<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"UTF-8\"><meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>Can't Export, Access Denied</title></head><body><h1>Can't Export, Access Denied</h1><p>Call the TYTD adminstrator if you are not the administrator to edit the following</p><hr><p>In file: <i><b>config/tytdprop.json</b></i>, unless overriden in code<br>Change <font color=\"#ce9178\">"AllowExport"</font>:<font color=\"#569cd6\">false</font> with <font color=\"#ce9178\">"AllowExport"</font>:<font color=\"#569cd6\">true</font></p></body></html>" ) ;
}
}
}
2022-06-24 23:02:51 +00:00
public async Task AddToList ( ServerContext ctx )
{
//this is for personal playlists
string name ;
if ( ctx . QueryParams . TryGetFirst ( "name" , out name ) ) {
string jsonData ;
List < ListContentItem > itemList ;
if ( ctx . Method = = "POST" & & ctx . QueryParams . TryGetFirst ( "data" , out jsonData ) )
{
itemList = JsonConvert . DeserializeObject < List < ListContentItem > > ( jsonData ) ;
} else {
itemList = new List < ListContentItem > ( ) ;
string id ;
if ( ctx . QueryParams . TryGetFirst ( "v" , out id ) )
{
Resolution resolution = Resolution . PreMuxed ;
string res ;
if ( ctx . QueryParams . TryGetFirst ( "res" , out res ) )
{
if ( ! Enum . TryParse < Resolution > ( res , out resolution ) )
{
resolution = Resolution . PreMuxed ;
}
}
VideoId ? id1 = VideoId . TryParse ( id ) ;
if ( id1 . HasValue )
{
itemList . Add ( new ListContentItem ( id1 , resolution ) ) ;
}
}
}
await Downloader . AddToPersonalPlaylistAsync ( name , itemList ) ;
//Downloader.AddToPersonalPlaylistAsync(name);
}
2022-08-28 21:40:34 +00:00
await ctx . RedirectBackAsync ( ) ;
2022-06-24 23:02:51 +00:00
}
public async Task DeleteFromList ( ServerContext ctx )
{
//this is for personal playlists
string name ;
if ( ctx . QueryParams . TryGetFirst ( "name" , out name ) ) {
string id ;
if ( ctx . QueryParams . TryGetFirst ( "v" , out id ) )
{
VideoId ? id1 = VideoId . TryParse ( id ) ;
if ( id1 . HasValue )
{
await Downloader . RemoveItemFromPersonalPlaylistAsync ( name , id1 . Value ) ;
}
}
}
2022-08-28 21:40:34 +00:00
await ctx . RedirectBackAsync ( ) ;
2022-06-24 23:02:51 +00:00
}
public async Task SetResolutionInList ( ServerContext ctx )
{
//this is for personal playlists
string name ;
if ( ctx . QueryParams . TryGetFirst ( "name" , out name ) ) {
string id ;
if ( ctx . QueryParams . TryGetFirst ( "v" , out id ) )
{
Resolution resolution = Resolution . PreMuxed ;
string res ;
if ( ctx . QueryParams . TryGetFirst ( "res" , out res ) )
{
if ( ! Enum . TryParse < Resolution > ( res , out resolution ) )
{
resolution = Resolution . PreMuxed ;
}
}
VideoId ? id1 = VideoId . TryParse ( id ) ;
if ( id1 . HasValue )
{
await Downloader . SetResolutionForItemInPersonalPlaylistAsync ( name , id1 . Value , resolution ) ;
}
}
}
2022-08-28 21:40:34 +00:00
await ctx . RedirectBackAsync ( ) ;
2022-05-10 12:57:52 +00:00
}
public async Task Subscriptions ( ServerContext ctx )
{
2022-06-14 18:21:36 +00:00
IStorage storage = Downloader as IStorage ;
2022-05-10 12:57:52 +00:00
if ( storage ! = null )
{
var sub = storage . GetLoadedSubscriptions ( ) ;
await ctx . SendJsonAsync ( sub ) ;
}
2022-08-28 21:40:34 +00:00
await ctx . RedirectBackAsync ( ) ;
2022-05-09 22:00:19 +00:00
}
public async Task Resubscribe ( ServerContext ctx )
{
2022-06-14 18:21:36 +00:00
IStorage storage = Downloader as IStorage ;
2022-05-09 22:00:19 +00:00
if ( storage ! = null )
{
string id ;
if ( ctx . QueryParams . TryGetFirst ( "id" , out id ) )
{
string confstr ;
ChannelBellInfo conf = ChannelBellInfo . NotifyAndDownload ;
if ( ctx . QueryParams . TryGetFirst ( "conf" , out confstr ) )
{
if ( ! Enum . TryParse < ChannelBellInfo > ( confstr , out conf ) )
{
conf = ChannelBellInfo . NotifyAndDownload ;
}
}
2022-06-24 23:02:51 +00:00
ChannelId ? cid = ChannelId . TryParse ( id ) ;
2022-05-09 22:00:19 +00:00
if ( cid . HasValue )
{
2022-05-10 12:57:52 +00:00
await storage . ResubscribeAsync ( cid . Value , conf ) ;
2022-05-09 22:00:19 +00:00
}
}
}
2022-08-28 21:40:34 +00:00
await ctx . RedirectBackAsync ( ) ;
2022-05-09 22:00:19 +00:00
}
2022-05-10 12:57:52 +00:00
public async Task Unsubscribe ( ServerContext ctx )
{
2022-06-14 18:21:36 +00:00
IStorage storage = Downloader as IStorage ;
2022-05-10 12:57:52 +00:00
if ( storage ! = null )
{
string id ;
if ( ctx . QueryParams . TryGetFirst ( "id" , out id ) )
{
2022-06-24 23:02:51 +00:00
ChannelId ? cid = ChannelId . TryParse ( id ) ;
2022-05-10 12:57:52 +00:00
if ( cid . HasValue )
{
storage . Unsubscribe ( cid . Value ) ;
}
}
}
2022-08-28 21:40:34 +00:00
await ctx . RedirectBackAsync ( ) ;
}
2022-05-09 22:00:19 +00:00
public async Task Subscribe ( ServerContext ctx )
{
2022-06-14 18:21:36 +00:00
IStorage storage = Downloader as IStorage ;
2022-05-09 22:00:19 +00:00
if ( storage ! = null )
{
string id ;
if ( ctx . QueryParams . TryGetFirst ( "id" , out id ) )
{
string getinfostr ;
bool getinfo = true ;
if ( ctx . QueryParams . TryGetFirst ( "getinfo" , out getinfostr ) )
{
if ( getinfostr = = "false" )
{
getinfo = false ;
}
}
string confstr ;
ChannelBellInfo conf = ChannelBellInfo . NotifyAndDownload ;
if ( ctx . QueryParams . TryGetFirst ( "conf" , out confstr ) )
{
if ( ! Enum . TryParse < ChannelBellInfo > ( confstr , out conf ) )
{
conf = ChannelBellInfo . NotifyAndDownload ;
}
}
2022-06-24 23:02:51 +00:00
ChannelId ? cid = ChannelId . TryParse ( id ) ;
2022-05-09 22:00:19 +00:00
if ( cid . HasValue )
{
2022-05-10 12:57:52 +00:00
await storage . SubscribeAsync ( cid . Value , getinfo , conf ) ;
2022-05-09 22:00:19 +00:00
} else {
2022-06-24 23:02:51 +00:00
UserName ? uname = UserName . TryParse ( id ) ;
2022-05-10 12:57:52 +00:00
await storage . SubscribeAsync ( uname . Value , conf ) ;
2022-05-09 22:00:19 +00:00
}
}
}
2022-08-28 21:40:34 +00:00
await ctx . RedirectBackAsync ( ) ;
2022-04-06 16:41:29 +00:00
}
2022-05-09 22:00:19 +00:00
2022-04-06 16:41:29 +00:00
public async Task QueueList ( ServerContext ctx )
{
await ctx . SendJsonAsync ( Downloader . GetQueueList ( ) ) ;
}
public async Task ProgressFunc ( ServerContext ctx )
{
await ctx . SendJsonAsync ( Downloader . GetProgress ( ) ) ;
2022-07-06 22:59:50 +00:00
}
public async Task AddFile ( ServerContext ctx )
{
string url ;
string downloadStr ;
bool download = true ;
if ( ctx . QueryParams . TryGetFirst ( "url" , out url ) )
{
if ( ctx . QueryParams . TryGetFirst ( "download" , out downloadStr ) )
{
bool dl ;
if ( bool . TryParse ( downloadStr , out dl ) )
{
download = dl ;
}
}
await Downloader . AddFileAsync ( url , download ) ;
2022-08-28 21:40:34 +00:00
await ctx . RedirectBackAsync ( ) ;
2022-07-06 22:59:50 +00:00
}
2022-04-06 16:41:29 +00:00
}
2022-04-10 00:18:45 +00:00
public async Task AddVideo ( ServerContext ctx )
2022-04-06 16:41:29 +00:00
{
string id ;
2022-06-16 11:12:27 +00:00
2022-04-06 16:41:29 +00:00
if ( ctx . QueryParams . TryGetFirst ( "v" , out id ) )
{
2022-06-24 23:02:51 +00:00
2022-04-06 16:41:29 +00:00
Resolution resolution = Resolution . PreMuxed ;
string res ;
if ( ctx . QueryParams . TryGetFirst ( "res" , out res ) )
{
if ( ! Enum . TryParse < Resolution > ( res , out resolution ) )
{
resolution = Resolution . PreMuxed ;
}
}
VideoId ? id1 = VideoId . TryParse ( id ) ;
if ( id1 . HasValue )
2022-06-15 12:59:36 +00:00
{
2022-04-10 00:18:45 +00:00
await Downloader . AddVideoAsync ( id1 . Value , resolution ) ;
}
}
2022-08-28 21:40:34 +00:00
await ctx . RedirectBackAsync ( ) ;
2022-04-10 00:18:45 +00:00
}
2022-08-28 21:40:34 +00:00
public async Task AddItem ( ServerContext ctx )
2022-04-10 00:18:45 +00:00
{
string id ;
if ( ctx . QueryParams . TryGetFirst ( "v" , out id ) )
{
Resolution resolution = Resolution . PreMuxed ;
string res ;
if ( ctx . QueryParams . TryGetFirst ( "res" , out res ) )
{
if ( ! Enum . TryParse < Resolution > ( res , out resolution ) )
{
resolution = Resolution . PreMuxed ;
}
}
await Downloader . AddItemAsync ( id , resolution ) ;
}
2022-08-28 21:40:34 +00:00
await ctx . RedirectBackAsync ( ) ;
2022-04-10 00:18:45 +00:00
}
2022-08-28 21:40:34 +00:00
public async Task AddUser ( ServerContext ctx )
2022-04-10 00:18:45 +00:00
{
string id ;
2022-05-09 22:00:19 +00:00
if ( ctx . QueryParams . TryGetFirst ( "id" , out id ) )
2022-04-10 00:18:45 +00:00
{
Resolution resolution = Resolution . PreMuxed ;
string res ;
if ( ctx . QueryParams . TryGetFirst ( "res" , out res ) )
{
if ( ! Enum . TryParse < Resolution > ( res , out resolution ) )
{
resolution = Resolution . PreMuxed ;
}
}
UserName ? id1 = UserName . TryParse ( id ) ;
if ( id1 . HasValue )
{
await Downloader . AddUserAsync ( id1 . Value , resolution ) ;
}
}
2022-08-28 21:40:34 +00:00
await ctx . RedirectBackAsync ( ) ;
2022-04-10 00:18:45 +00:00
}
2022-08-28 21:40:34 +00:00
public async Task AddChannel ( ServerContext ctx )
2022-04-10 00:18:45 +00:00
{
string id ;
2022-05-09 22:00:19 +00:00
if ( ctx . QueryParams . TryGetFirst ( "id" , out id ) )
2022-04-10 00:18:45 +00:00
{
Resolution resolution = Resolution . PreMuxed ;
string res ;
if ( ctx . QueryParams . TryGetFirst ( "res" , out res ) )
{
if ( ! Enum . TryParse < Resolution > ( res , out resolution ) )
{
resolution = Resolution . PreMuxed ;
}
}
ChannelId ? id1 = ChannelId . TryParse ( id ) ;
if ( id1 . HasValue )
{
await Downloader . AddChannelAsync ( id1 . Value , resolution ) ;
}
}
2022-08-28 21:40:34 +00:00
await ctx . RedirectBackAsync ( ) ;
2022-04-10 00:18:45 +00:00
}
public async Task AddPlaylist ( ServerContext ctx )
{
string id ;
2022-05-09 22:00:19 +00:00
if ( ctx . QueryParams . TryGetFirst ( "id" , out id ) )
2022-04-10 00:18:45 +00:00
{
Resolution resolution = Resolution . PreMuxed ;
string res ;
if ( ctx . QueryParams . TryGetFirst ( "res" , out res ) )
{
if ( ! Enum . TryParse < Resolution > ( res , out resolution ) )
{
resolution = Resolution . PreMuxed ;
}
}
PlaylistId ? id1 = PlaylistId . TryParse ( id ) ;
if ( id1 . HasValue )
{
await Downloader . AddPlaylistAsync ( id1 . Value , resolution ) ;
2022-04-06 16:41:29 +00:00
}
}
2022-08-28 21:40:34 +00:00
await ctx . RedirectBackAsync ( ) ;
2022-04-06 16:41:29 +00:00
}
2022-04-10 00:18:45 +00:00
2022-04-06 16:41:29 +00:00
}
public class TYTDServer
{
/// <summary>
/// Constructor
/// </summary>
/// <param name="baseCtl">TYTD context</param>
2022-06-14 18:21:36 +00:00
public TYTDServer ( ITYTDBase baseCtl )
2022-04-06 16:41:29 +00:00
{
ExtensionsServer = new ChangeableServer ( ) ;
RootServer = new ChangeableServer ( ) ;
MountableServer mountableServer = new MountableServer ( RootServer ) ;
IDownloader downloader = baseCtl as IDownloader ;
if ( downloader ! = null )
{
mountableServer . Mount ( "/api/" , new ApiV1Server ( downloader ) ) ;
mountableServer . Mount ( "/api/v2/" , new ApiV2Server ( downloader ) ) ;
}
mountableServer . Mount ( "/api/v2/Extensions/" , ExtensionsServer ) ;
mountableServer . Mount ( "/api/Storage/" , new ApiStorage ( baseCtl ) ) ;
InnerServer = mountableServer ;
}
/// <summary>
/// To provide to tesses.webserver
/// </summary>
public IServer InnerServer { get ; private set ; }
/// <summary>
/// Set by Nuget Package Tesses.YouTubeDownloader.ExtensionLoader
/// </summary>
public ChangeableServer ExtensionsServer { get ; private set ; }
/// <summary>
/// An optional static website (recomendeded)
/// </summary>
public ChangeableServer RootServer { get ; private set ; }
}
}