Added example
This commit is contained in:
parent
229443fb86
commit
e60820a763
|
@ -142,4 +142,5 @@ Tesses.YouTubeDownloader.Net6/PreMuxed/
|
||||||
Tesses.YouTubeDownloader.Net6/config/
|
Tesses.YouTubeDownloader.Net6/config/
|
||||||
Tesses.YouTubeDownloader.Net6/Playlist/
|
Tesses.YouTubeDownloader.Net6/Playlist/
|
||||||
Tesses.YouTubeDownloader.Net6/Channel/
|
Tesses.YouTubeDownloader.Net6/Channel/
|
||||||
|
Tesses.YouTubeDownloader.Net6/Subscriptions/
|
||||||
push
|
push
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
# Tesses.YouTubeDownloader (2022)
|
# Tesses.YouTubeDownloader (2022)
|
||||||
|
|
||||||
|
Tesses.YouTubeDownloader.ExampleExtension uses [Return YouTube Dislikes](https://returnyoutubedislike.com/)
|
||||||
|
|
||||||
|
[How To Find Videos (When Downloaded)](docs/HowToFindVideos.md)
|
||||||
|
<br>
|
||||||
[Server Endpoints](docs/Server.md)
|
[Server Endpoints](docs/Server.md)
|
||||||
<br>
|
<br>
|
||||||
[Classes and Enums](docs/JsonAndEnum.md)
|
[Classes and Enums](docs/JsonAndEnum.md)
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
using System;
|
||||||
|
using Tesses.YouTubeDownloader.ExtensionLoader;
|
||||||
|
using Tesses.WebServer;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Tesses.YouTubeDownloader.ExampleExtension
|
||||||
|
{
|
||||||
|
public class ExampleExtensionClass : Extension
|
||||||
|
{
|
||||||
|
string efn;
|
||||||
|
public bool Enabled {get {return Storage.FileExists(efn);} set{
|
||||||
|
if(value)
|
||||||
|
{
|
||||||
|
if(!Storage.FileExists(efn))
|
||||||
|
{
|
||||||
|
Storage.WriteAllTextAsync(efn,"enabled").Wait();
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if(Storage.FileExists(efn))
|
||||||
|
{
|
||||||
|
Storage.DeleteFile(efn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
public bool FirstLoad()
|
||||||
|
{
|
||||||
|
string init=this.ExtensionStorage("init");
|
||||||
|
bool first = !this.Storage.FileExists(init);
|
||||||
|
if(first)
|
||||||
|
{
|
||||||
|
this.Storage.WriteAllTextAsync(init,"loaded").Wait();
|
||||||
|
}
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
public override void OnStart()
|
||||||
|
{
|
||||||
|
if(FirstLoad())
|
||||||
|
{
|
||||||
|
Enabled=true;
|
||||||
|
}
|
||||||
|
this.Storage.BeforeSaveInfo += BeforeSaveInfo;
|
||||||
|
efn=this.ExtensionStorage("enabled");
|
||||||
|
RouteServer svr=new RouteServer();
|
||||||
|
svr.Add("/",Index);
|
||||||
|
svr.Add("/setting.cgi",Setting);
|
||||||
|
}
|
||||||
|
public async Task Index(ServerContext ctx)
|
||||||
|
{
|
||||||
|
string enabledStr = Enabled ? " checked" : "";
|
||||||
|
string index=$"<!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>Return YouTube Dislikes Addon for TYTD</title></head><body><h1>Return YouTube Dislikes Addon for TYTD</h1><form action=\"./setting.cgi\" method=\"GET\"><label for=\"enabled\">Enabled: </label><input type=\"checkbox\" name=\"enabled\" id=\"enabled\" {enabledStr}><br><input type=\"submit\" value=\"Save\"></form>This extension uses <a href=\"//returnyoutubedislike.com\">Return YouTube Dislikes</a></body></html>";
|
||||||
|
await ctx.SendTextAsync(index);
|
||||||
|
}
|
||||||
|
public async Task Setting(ServerContext ctx)
|
||||||
|
{
|
||||||
|
Enabled=ctx.QueryParams.ContainsKey("enabled");
|
||||||
|
|
||||||
|
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"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
public override string Name => "returnyoutubedislike.com";
|
||||||
|
private async void BeforeSaveInfo(object sender, BeforeSaveInfoEventArgs e)
|
||||||
|
{
|
||||||
|
if(Enabled)
|
||||||
|
e.VideoInfo.Dislikes=JsonConvert.DeserializeObject<Dislike>(await this.Storage.HttpClient.GetStringAsync($"https://returnyoutubedislikeapi.com/votes?videoId={e.VideoInfo.Id}")).dislikes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Dislike
|
||||||
|
{
|
||||||
|
public long dislikes {get;set;}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Tesses.YouTubeDownloader.ExtensionLoader\Tesses.YouTubeDownloader.ExtensionLoader.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -10,11 +10,13 @@ namespace Tesses.YouTubeDownloader.Net6
|
||||||
TYTDCurrentDirectory currentDirectory=new TYTDCurrentDirectory(new HttpClient());
|
TYTDCurrentDirectory currentDirectory=new TYTDCurrentDirectory(new HttpClient());
|
||||||
TYTDServer server=new TYTDServer(currentDirectory);
|
TYTDServer server=new TYTDServer(currentDirectory);
|
||||||
server.RootServer.Server=new StaticServer("WebSite");
|
server.RootServer.Server=new StaticServer("WebSite");
|
||||||
HttpServerListener listener=new HttpServerListener(new System.Net.IPEndPoint(System.Net.IPAddress.Any,42440),server.InnerServer);
|
currentDirectory.CanDownload=false;
|
||||||
|
HttpServerListener listener=new HttpServerListener(new System.Net.IPEndPoint(System.Net.IPAddress.Any,3252),server.InnerServer);
|
||||||
currentDirectory.StartLoop();
|
currentDirectory.StartLoop();
|
||||||
TYTDStorage.FFmpeg ="/usr/bin/ffmpeg";
|
TYTDStorage.FFmpeg ="/usr/bin/ffmpeg";
|
||||||
Console.WriteLine("Almost Ready to Listen");
|
Console.WriteLine("Almost Ready to Listen");
|
||||||
await listener.ListenAsync(CancellationToken.None);
|
await listener.ListenAsync(CancellationToken.None);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -30,17 +30,17 @@ namespace Tesses.YouTubeDownloader
|
||||||
}
|
}
|
||||||
Resolution Resolution;
|
Resolution Resolution;
|
||||||
UserName name1;
|
UserName name1;
|
||||||
ChannelId Id;
|
ChannelId? Id; //made me nullable
|
||||||
|
|
||||||
public async Task<SavedChannel> GetChannel(TYTDStorage storage)
|
public async Task<SavedChannel> GetChannel(TYTDStorage storage)
|
||||||
{
|
{
|
||||||
SavedChannel channel;
|
SavedChannel channel;
|
||||||
if(Id !=null)
|
if(Id.HasValue) //dont check for if(Id != null) hince I was looking for several minutes for the bug
|
||||||
{
|
{
|
||||||
string path=$"Channel/{Id}.json";
|
string path=$"Channel/{Id.Value}.json";
|
||||||
if(await storage.Continue(path))
|
if(await storage.Continue(path))
|
||||||
{
|
{
|
||||||
channel=await DownloadThumbnails(storage,await storage.YoutubeClient.Channels.GetAsync(Id));
|
channel=await DownloadThumbnails(storage,await storage.YoutubeClient.Channels.GetAsync(Id.Value));
|
||||||
//channel=new SavedChannel(i);
|
//channel=new SavedChannel(i);
|
||||||
await storage.WriteAllTextAsync(path,JsonConvert.SerializeObject(channel));
|
await storage.WriteAllTextAsync(path,JsonConvert.SerializeObject(channel));
|
||||||
return channel;
|
return channel;
|
||||||
|
@ -49,8 +49,9 @@ namespace Tesses.YouTubeDownloader
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
channel=await DownloadThumbnails(storage, await storage.YoutubeClient.Channels.GetByUserAsync(name1));
|
var c=await storage.YoutubeClient.Channels.GetByUserAsync(name1);
|
||||||
string path=$"Channel/{Id}.json";
|
channel=await DownloadThumbnails(storage,c);
|
||||||
|
string path=$"Channel/{c.Id.Value}.json";
|
||||||
if(await storage.Continue(path))
|
if(await storage.Continue(path))
|
||||||
{
|
{
|
||||||
await storage.WriteAllTextAsync(path,JsonConvert.SerializeObject(channel));
|
await storage.WriteAllTextAsync(path,JsonConvert.SerializeObject(channel));
|
||||||
|
|
|
@ -130,7 +130,7 @@ namespace Tesses.YouTubeDownloader
|
||||||
}
|
}
|
||||||
public async Task SaveSubscription(Subscription sub)
|
public async Task SaveSubscription(Subscription sub)
|
||||||
{
|
{
|
||||||
await WriteAllTextAsync($"Subscriptions/{sub.Id}",JsonConvert.SerializeObject(sub));
|
await WriteAllTextAsync($"Subscriptions/{sub.Id}.json",JsonConvert.SerializeObject(sub));
|
||||||
}
|
}
|
||||||
public async Task SubscribeAsync(UserName name,ChannelBellInfo bellInfo=ChannelBellInfo.NotifyAndDownload)
|
public async Task SubscribeAsync(UserName name,ChannelBellInfo bellInfo=ChannelBellInfo.NotifyAndDownload)
|
||||||
{
|
{
|
||||||
|
|
|
@ -115,6 +115,8 @@ namespace Tesses.YouTubeDownloader
|
||||||
}
|
}
|
||||||
public void CreateDirectories()
|
public void CreateDirectories()
|
||||||
{
|
{
|
||||||
|
CreateDirectoryIfNotExist("Channel");
|
||||||
|
CreateDirectoryIfNotExist("Playlist");
|
||||||
CreateDirectoryIfNotExist("Subscriptions");
|
CreateDirectoryIfNotExist("Subscriptions");
|
||||||
CreateDirectoryIfNotExist("VideoOnly");
|
CreateDirectoryIfNotExist("VideoOnly");
|
||||||
CreateDirectoryIfNotExist("AudioOnly");
|
CreateDirectoryIfNotExist("AudioOnly");
|
||||||
|
@ -122,6 +124,8 @@ namespace Tesses.YouTubeDownloader
|
||||||
CreateDirectoryIfNotExist("PreMuxed");
|
CreateDirectoryIfNotExist("PreMuxed");
|
||||||
CreateDirectoryIfNotExist("Info");
|
CreateDirectoryIfNotExist("Info");
|
||||||
CreateDirectoryIfNotExist("Thumbnails");
|
CreateDirectoryIfNotExist("Thumbnails");
|
||||||
|
CreateDirectoryIfNotExist("config");
|
||||||
|
CreateDirectoryIfNotExist("config/logs");
|
||||||
}
|
}
|
||||||
public void StartLoop(CancellationToken token = default(CancellationToken))
|
public void StartLoop(CancellationToken token = default(CancellationToken))
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
<PackageId>Tesses.YouTubeDownloader</PackageId>
|
<PackageId>Tesses.YouTubeDownloader</PackageId>
|
||||||
<Author>Mike Nolan</Author>
|
<Author>Mike Nolan</Author>
|
||||||
<Company>Tesses</Company>
|
<Company>Tesses</Company>
|
||||||
<Version>1.0.3.1</Version>
|
<Version>1.0.3.3</Version>
|
||||||
<AssemblyVersion>1.0.3.1</AssemblyVersion>
|
<AssemblyVersion>1.0.3.3</AssemblyVersion>
|
||||||
<FileVersion>1.0.3.1</FileVersion>
|
<FileVersion>1.0.3.3</FileVersion>
|
||||||
<Description>A YouTube Downloader</Description>
|
<Description>A YouTube Downloader</Description>
|
||||||
<PackageLicenseExpression>LGPL-3.0-only</PackageLicenseExpression>
|
<PackageLicenseExpression>LGPL-3.0-only</PackageLicenseExpression>
|
||||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Configuration
|
# Configuration
|
||||||
This is Json Object (With these Key/Value Pairs)
|
This is Json Object (With these Key/Value Pairs)<br>
|
||||||
File path is config/tytdprop.json
|
File path is config/tytdprop.json
|
||||||
| Name | Description | Type |
|
| Name | Description | Type |
|
||||||
| ------- | ----------------- | ----- |
|
| ------- | ----------------- | ----- |
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
# How to find videos
|
||||||
|
|
||||||
|
| Name | Url | Url with filename in content-disposition | Path |
|
||||||
|
| ------- | ------- | ---------- | ----- |
|
||||||
|
| Mux | http://localhost:3252/api/Storage/File/Mux/{Id}.mkv | http://localhost:3252/api/Storage/VideoRes/0/{Id} | Mux/{Id}.mkv |
|
||||||
|
| PreMuxed | http://localhost:3252/api/Storage/File/PreMuxed/{Id}.{Container} | http://localhost:3252/api/Storage/VideoRes/1/{Id} | PreMuxed/{Id}.{Container} |
|
||||||
|
| AudioOnly | http://localhost:3252/api/Storage/File/AudioOnly/{Id}.{Container} | http://localhost:3252/api/Storage/VideoRes/2/{Id} | AudioOnly/{Id}.{Container} |
|
||||||
|
|
|
||||||
|
| VideoOnly | http://localhost:3252/api/Storage/File/VideoOnly/{Id}.{Container} | http://localhost:3252/api/Storage/VideoRes/3/{Id} | VideoOnly/{Id}.{Container} |
|
||||||
|
|
|
||||||
|
|
||||||
|
# What you should see before this
|
||||||
|
[StreamInfo](StreamInfo.md) (this is required to get {Container})<br>
|
||||||
|
[Resolution](Resolution.md) (this is recomended so you know what the resolution numbers mean)
|
|
@ -9,4 +9,5 @@
|
||||||
| Configure | App Configuration | Class | [View](Configure.md) |
|
| Configure | App Configuration | Class | [View](Configure.md) |
|
||||||
| QueueList | Video Queue | List of Class | [View](QueueList.md) |
|
| QueueList | Video Queue | List of Class | [View](QueueList.md) |
|
||||||
| Bell | Bell Setting (simular to on YouTube) | Enum | [View](Bell.md) |
|
| Bell | Bell Setting (simular to on YouTube) | Enum | [View](Bell.md) |
|
||||||
| Resolution | Video Resolution | Enum | [View](Resolution.md) |
|
| Resolution | Video Resolution | Enum | [View](Resolution.md) |
|
||||||
|
| StreamInfo | Video Stream Info | Class | [View](StreamInfo.md) |
|
|
@ -4,6 +4,7 @@ This is an Enum
|
||||||
|
|
||||||
| Name | Number| Used to be |
|
| Name | Number| Used to be |
|
||||||
| ---- | ---- | -----|
|
| ---- | ---- | -----|
|
||||||
|
| NoDownload | -1 | N/A (Endpoints with Only in them) |
|
||||||
| Mux | 0 | Converted |
|
| Mux | 0 | Converted |
|
||||||
| PreMuxed | 1 | NotConverted |
|
| PreMuxed | 1 | NotConverted |
|
||||||
| AudioOnly | 2 | Audio |
|
| AudioOnly | 2 | Audio |
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Saved Channel
|
# Saved Channel
|
||||||
This is Json Object (With these Key/Value Pairs)
|
This is Json Object (With these Key/Value Pairs)<br>
|
||||||
File Path is Channel/{Id}.json
|
File Path is Channel/{Id}.json
|
||||||
| Name | Description | Type |
|
| Name | Description | Type |
|
||||||
|--------|-------|------|
|
|--------|-------|------|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Saved Playlist
|
# Saved Playlist
|
||||||
This is Json Object (With these Key/Value Pairs)
|
This is Json Object (With these Key/Value Pairs)<br>
|
||||||
File Path is Playlist/{Id}.json
|
File Path is Playlist/{Id}.json
|
||||||
| Name | Description | Type |
|
| Name | Description | Type |
|
||||||
|--------|-------|------|
|
|--------|-------|------|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Saved Video
|
# Saved Video
|
||||||
This is Json Object (With these Key/Value Pairs)
|
This is Json Object (With these Key/Value Pairs)<br>
|
||||||
File Path is Info/{Id}.json
|
File Path is Info/{Id}.json
|
||||||
| Name | Description | Type |
|
| Name | Description | Type |
|
||||||
|--------|-------|------|
|
|--------|-------|------|
|
||||||
|
|
|
@ -17,4 +17,9 @@ Get Requests
|
||||||
| http://localhost:3252/api/v2/subscribe?id={UserName}&conf=NotifyAndDownload | Subscribe to YouTuber (UserName), See [Bell](Bell.md) for conf queryparm |
|
| http://localhost:3252/api/v2/subscribe?id={UserName}&conf=NotifyAndDownload | Subscribe to YouTuber (UserName), See [Bell](Bell.md) for conf queryparm |
|
||||||
| http://localhost:3252/api/v2/resubscribe?id={ChannelId}&conf=Download | Change Bell for YouTuber, See [Bell](Bell.md) for conf queryparm |
|
| http://localhost:3252/api/v2/resubscribe?id={ChannelId}&conf=Download | Change Bell for YouTuber, See [Bell](Bell.md) for conf queryparm |
|
||||||
| http://localhost:3252/api/v2/unsubscribe?id={ChannelId} | Unsubscribe from YouTuber |
|
| http://localhost:3252/api/v2/unsubscribe?id={ChannelId} | Unsubscribe from YouTuber |
|
||||||
| http://localhost:3252/api/v2/subscriptions | Get Subscriptions, Is a json array of [Subscription](Subscription.md) |
|
| http://localhost:3252/api/v2/subscriptions | Get Subscriptions, Is a json array of [Subscription](Subscription.md) |
|
||||||
|
| http://localhost:3252/api/Storage/File/{File_Path} | Get File from TYTDStorage |
|
||||||
|
| http://localhost:3252/api/Storage/FileExists/{File_Path} | Does file exist, returns "true" or "false" as response (Not Json just that text) |
|
||||||
|
| http://localhost:3252/api/Storage/DirectoryExists/{Directory_Path} | Does directory exist, returns "true" or "false" as response (Not Json just that text) |
|
||||||
|
| http://localhost:3252/api/Storage/GetFiles/{File_Path} | Get list of files json array of filenames, not full path |
|
||||||
|
| http://localhost:3252/api/Storage/GetDirectories/{Directory_Path} | Get list of directorys json array of directory names, not full path |
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
# Video Streams Info
|
||||||
|
This is Json Object (With these Key/Value Pairs)<br>
|
||||||
|
File Path is StreamInfo/{Id}.json<br>
|
||||||
|
This is required to get extension for all resolutions except "Mux" which uses mkv<br>
|
||||||
|
these extensions are not prepended with .<br>
|
||||||
|
hince all of the resolutions use the same class use [this](StreamInfo2.md) for json structure for all three with type "Object"
|
||||||
|
| Name | Description | Type |
|
||||||
|
|--------|-------|------|
|
||||||
|
| Expires | When the url's expire (6 hours after adding video) ex 2022-05-07T01:48:23.982827-05:00 | DateTime(String) |
|
||||||
|
| VideoOnly | This stream go into "VideoOnly" folder, no audio | Object |
|
||||||
|
| Audio | This stream go into "AudioOnly" folder, no video | Object |
|
||||||
|
| Muxed | This stream go into "PreMuxed" folder, both video and audio (no conversion required) | Object |
|
|
@ -0,0 +1,10 @@
|
||||||
|
# Video Streams Info
|
||||||
|
This is Json Object (With these Key/Value Pairs)<br>
|
||||||
|
See [this](StreamInfo.md) if you havent already
|
||||||
|
|
||||||
|
| Name | Description | Type |
|
||||||
|
|--------|-------|------|
|
||||||
|
| | When the url's expire (6 hours after adding video) ex 2022-05-07T01:48:23.982827-05:00 | DateTime(String) |
|
||||||
|
| VideoOnly | This stream go into "VideoOnly" folder, no audio | Object |
|
||||||
|
| Audio | This stream go into "AudioOnly" folder, no video | Object |
|
||||||
|
| Muxed | This stream go into "PreMuxed" folder, both video and audio (no conversion required) | Object |
|
Loading…
Reference in New Issue