using System; using System.Collections.Generic; using System.Threading.Tasks; using Tesses.YouTubeDownloader; using Tesses.WebServer; using System.Reflection; using System.IO; using System.Text; using System.Net; using Tesses.YouTubeDownloader.Server; namespace Tesses.YouTubeDownloader.ExtensionLoader { public class Loader : IExtensionContext { internal class IndexServer : Tesses.WebServer.Server { public IndexServer(List exts) { Extensions=exts; } List Extensions; public override async Task GetAsync(ServerContext ctx) { StringBuilder builder=new StringBuilder("Extensions

Extensions

"); foreach(var ext in Extensions) { builder.Append($"{WebUtility.HtmlEncode(ext.Name)}
"); } builder.Append(""); await ctx.SendTextAsync(builder.ToString()); } } List extensions = new List(); public List Extensions => extensions; TYTDStorage Storage; MountableServer Server; string dir; /// /// Constructor /// /// Storage for TYTD /// where to look for extensions public Loader(TYTDStorage storage,string lookInDir="config/apidll") { Directory.CreateDirectory(lookInDir); dir=lookInDir; Server= new MountableServer(new IndexServer(Extensions)); Storage = storage; } private (IExtension Extension,IServer Server) LoadExtension(string dllPath) { //Assembly.Load() Assembly assembly= Assembly.LoadFrom(dllPath); foreach(var cls in assembly.GetTypes()) { if(typeof(Extension).IsAssignableFrom(cls)) { var ext=(Extension)Activator.CreateInstance(cls); ext.name=Path.GetFileNameWithoutExtension(dllPath); ChangeableServer server=new ChangeableServer(); ext.Server=server; ext.Storage=Storage; ext.OnStart(); return (ext,server); } } return (null,null); } /// /// Load Extensions /// public void LoadExtensions() { foreach(var extdir in Directory.GetDirectories(dir)) { string extname = Path.GetFileName(extdir); string dll = Path.Combine(extdir,$"{extname}.dll"); if(File.Exists(dll)) { var (ext,server) =LoadExtension(dll); if(ext != null && server !=null) { Extensions.Add(ext); Server.Mount($"/{WebUtility.UrlEncode(ext.Name)}",server); } } } } /// /// Set server to TYTDServer.ExtensionServer /// Will set Storage.ExtensionContext /// /// TYTD server public void SetServer(TYTDServer server) { server.ExtensionsServer.Server = Server; var storage=Storage; if(storage !=null) { storage.ExtensionContext=this; } } } public abstract class Extension : IExtension { /// /// If You Have A WebPage You Want for Extension /// Set Server.Server to your server /// /// public ChangeableServer Server {get; internal set;} /// /// Abstract storage for Downloader /// Use relative paths please /// /// public TYTDStorage Storage {get; internal set;} /// /// Get extension storage dir use "Storage" to actually access files /// The path config/apistore/{Name} is created if it doesnt exist /// /// relative and absolute paths are treated the same use / for spliting paths /// a path for file public string ExtensionStorage(string path) { Storage.CreateDirectoryIfNotExist($"config/apistore/{Name}"); return $"config/apistore/{Name}/{path.TrimStart('/')}"; } /// /// Called when extension starts /// public abstract void OnStart(); internal string name; /// /// Name, defaults to dll folder name * (the dll is loaded based on foldername) /// /// public virtual string Name {get {return name;}} /// /// Called when extension needs to end /// public virtual void OnEnd() { } /// /// Called when Video On Downloader Finishes /// /// Info about Video /// Video Resolution public virtual async Task VideoFinished(SavedVideo video, Resolution resolution) { await Task.FromResult(true); } /// /// Called when downloader writes some data /// /// Info about Video /// Video Percent 0 -> 1 (might overflow so clamp it if you need to) /// public virtual async Task VideoProgress(SavedVideo video, double progress) { await Task.FromResult(true); } /// /// Called when Video On Downloader Starts /// /// Info about Video /// Video Resolution /// Video File Length (can be 0 if resolution==Resolution.Mux) public virtual async Task VideoStarted(SavedVideo video, Resolution resolution, long length) { await Task.FromResult(true); } } }