using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Net; using System.Reflection; using System.Text; using System.Threading; using Newtonsoft.Json; using SimpleHttp; using TYTD.Server.Functions; using TYTD.Server.Models; namespace TYTD { public abstract class Api : IDisposable { public virtual bool OnHomePage(string path,HttpListenerRequest req,HttpListenerResponse resp,Dictionary args) { return false; } public virtual bool OnTemplatePage(string path,out string template_string) { template_string = ""; return false; } public bool CanProvideHomePage { get; protected set; } public virtual void OnStart() { Console.WriteLine("Extension Loaded"); } internal string storage; protected string StorageLocation { get { return storage; } } public virtual string Name { get { return Path.GetFileName(StorageLocation); } } private System.Timers.Timer t = null; protected void SetTimer(TimeSpan timespan) { if(t == null) { t = new System.Timers.Timer(); t.Elapsed += (sender, e) => { TimerElapsed(); }; } t.Interval = timespan.TotalMilliseconds; t.Start(); } public virtual void SetProgress(double progress) { } public virtual void OnEnd() { } public bool TimerEnabled { get { if (t != null) { return t.Enabled; } else { return false; } } set { if (t != null) { t.Enabled = value; } } } public virtual IEnumerable> GetUrls() { yield return new KeyValuePair("Home",$"api/Extensions/{Name}"); } protected virtual void TimerElapsed() { Console.WriteLine("Event Fired"); } public Api AddItem(string id) { Downloader.DownloadItem(id); return this; } internal void SendDLStart(object sender,DownloadStartEventArgs e) { if(DownloadStart != null) { DownloadStart.Invoke(sender, e); } } internal void SendDLInfoStart(object sender, DownloadInfoStartEventArgs e) { if (DownloadInfoStart != null) { DownloadInfoStart.Invoke(sender, e); } } internal void SendDLComplete(object sender, DownloadCompleteEventArgs e) { if (DownloadComplete != null) { DownloadComplete.Invoke(sender, e); } } public event EventHandler DownloadInfoStart; public event EventHandler DownloadStart; public event EventHandler DownloadComplete; public void Dispose() { if( t != null) { t.Dispose(); } OnEnd(); } } public class DownloadCompleteEventArgs : EventArgs { public bool RegularFile { get; set; } public SavedVideo Video { get; set; } } public class DownloadInfoStartEventArgs : EventArgs { public SavedVideo Video { get; set; } } public class DownloadStartEventArgs : EventArgs { public bool RegularFile { get; set; } public SavedVideo Video { get; set; } public bool Cancel { get; set; } } public class ApiHomePageInfo { public event EventHandler Changed; public ApiHomePageInfo() { HasHomePage = false; HomePage = null; } public ApiHomePageInfo(Api api) { HasHomePage = api != null; HomePage = api; } public void Change(Api api) { HasHomePage = api != null; HomePage = api; if(Changed != null) { Changed.Invoke(this, EventArgs.Empty); } } public bool HasHomePage { get; private set; } public Api HomePage { get; private set; } } public static class ApiLoader { public static void CopyDir(string src, string dest,bool canoverride=false) { Directory.CreateDirectory(dest); //Console.WriteLine($"Created directory {dest}"); ; foreach (var dir in Directory.EnumerateDirectories(src)) { CopyDir(dir, Path.Combine(dest, Path.GetFileName(dir))); } foreach (var file in Directory.EnumerateFiles(src)) { if(File.Exists(Path.Combine(dest, Path.GetFileName(file)))) { if(canoverride) { File.Delete(Path.Combine(dest, Path.GetFileName(file))); } else { continue; } } File.Copy(file, Path.Combine(dest, Path.GetFileName(file))); //Console.WriteLine($"Copied {file} -> {Path.Combine(dest, Path.GetFileName(file))}"); } //Console.WriteLine($"Copied directory {src} -> {dest}"); } public static void UninstallExtension(string name) { Directory.Delete($"config/apidll/{name}",true); Directory.Delete($"config/apistore/{name}", true); File.Delete($"config/apiicons/{name}.png"); } public static (ext_conf conf,string name) InstallExtension(string archive) { if(Directory.Exists($"{archive}_contents")) { Directory.Delete($"{archive}_contents", true); } ZipFile.ExtractToDirectory(archive, $"{archive}_contents"); //we need to read manifest json string manifest = $"{archive}_contents/manifest.json"; ext_conf conf = JsonConvert.DeserializeObject(File.ReadAllText(manifest)); string extName = Path.GetFileName(conf.binPath); Directory.CreateDirectory($"config/apidll/{extName}"); Directory.CreateDirectory($"config/apistore/{extName}"); Directory.CreateDirectory("config/apiicons"); File.Copy($"{archive}_contents/{conf.icon}", $"config/apiicons/{extName}.png"); string parDirOf = Path.GetDirectoryName($"{archive}_contents/{conf.binPath}"); CopyDir(parDirOf, $"config/apidll/{extName}", true); CopyDir($"{archive}_contents/files", $"config/apistore/{extName}", true); Directory.Delete($"{archive}_contents"); return (conf,extName); } static bool start_term=false; public static bool StartTermination { get { return start_term; } set { start_term = value; if (start_term) { _cancel.Cancel(); } } } public static bool Restart { get; set; } public static void StopApp() { Restart = false; StartTermination = true; } public static void RestartApp() { Restart = true; StartTermination = true; } public static string RenderFileOrDefault(string file,string defaultData,Dictionary arg) { return Templating.RenderString(ReadAllTextOrDefault(file, defaultData), arg); } public static string ReadAllTextOrDefault(string file,string defaultData) { if(_info.HasHomePage) { //starts with website so remove WebSite\ string path = file.Substring(7); string data; if(_info.HomePage.OnTemplatePage(path,out data)) { return data; } } if (File.Exists(file)) { return File.ReadAllText(file); } return defaultData; } public static string Page { get; private set; } internal static List apis = new List(); internal static void DownloadStarted(object sender,DownloadStartEventArgs evt) { foreach(var api in apis) { api.SendDLStart(sender, evt); } } internal static void DownloadComplete(object sender, DownloadCompleteEventArgs evt) { foreach (var api in apis) { api.SendDLComplete(sender, evt); } } internal static void SetProgress(double progress) { foreach (var api in apis) { api.SetProgress(progress); } } internal static void DownloadInfoStart(object sender, DownloadInfoStartEventArgs evt) { foreach (var api in apis) { api.SendDLInfoStart(sender, evt); } } public static void Dispose() { foreach(var api in apis) { api.Dispose(); } } public static void GenerateTr(Api api,StringBuilder b) { string data = ""; string root = Path.Combine(Environment.CurrentDirectory, "config"); string fallbackIcon = Path.Combine(root, "default_icon.png"); string icon = Path.Combine(root, "apiicons", api.Name + ".png"); string icon2 = File.Exists(icon) ? icon : fallbackIcon; if (File.Exists(icon2)) { data = Convert.ToBase64String(File.ReadAllBytes(icon2)); } b.Append($"

{api.Name}

\"{api.Name}\""); foreach (var link in api.GetUrls()) { b.Append($"{link.Key}
"); } b.Append(""); } internal static void Load(StringBuilder b,string dll,string confpath) { var asm=Assembly.LoadFrom(dll); foreach (var item in asm.GetTypes()) { if(typeof(Api).IsAssignableFrom(item)) { Api api = (Api)Activator.CreateInstance(item); api.storage = confpath; apis.Add(api); api.OnStart(); GenerateTr(api, b); } } } public static IEnumerable EnumerateExtensions() { return apis; } static CancellationTokenSource _cancel; private static ApiHomePageInfo _info; public static CancellationToken Init(ApiHomePageInfo info) { _cancel = new CancellationTokenSource(); _info = info; StringBuilder b = new StringBuilder(); string root = Path.Combine(Environment.CurrentDirectory,"config", "apidll"); string appconfroot = Path.Combine(Environment.CurrentDirectory,"config", "apistore"); foreach(var dir in Directory.GetDirectories(root)) { string name = Path.GetFileName(dir); string dllpath = Path.Combine(root, name, name + ".dll"); string confpath = Path.Combine(appconfroot, name); if(File.Exists(dllpath)) { Directory.CreateDirectory(confpath); Load(b,dllpath, confpath); } } Dictionary templating = new Dictionary(); templating.Add("Items", b.ToString()); string combined= "WebSite/extensions.html"; info.Changed += (sender, e) => { //it will change immediately string template = "Extensions

Extensions

{Items}
NameUrls
"; template = ReadAllTextOrDefault(combined, template); Page = Templating.RenderString(template, templating); }; return _cancel.Token; } } public class ext_conf { public string binPath { get; set; } public string name { get; set; } public string icon { get; set; } public string desc { get; set; } public bool hasHomePageOverride { get; set; } } }