tytd-mobile/TYTD.Common/Class1.cs

1047 lines
27 KiB
C#
Raw Permalink Normal View History

2022-10-04 10:44:09 +00:00
namespace Tesses.YouTubeDownloader.Droid;
using Tesses.YouTubeDownloader;
using Tesses.YouTubeDownloader.Server;
using Tesses.WebServer;
using Tesses.WebServer.Swagme;
using Android.Content;
using Android.Net;
using Android.Database;
using Android.OS;
using Tesses.YouTubeDownloader.SFTP;
using Renci.SshNet;
using System.Net;
using Android.Preferences;
using AndroidX.Preference;
using Android.Runtime;
using Java.Interop;
public class TYTDPreferences : PreferenceDataStore
{
public override bool GetBoolean(string? key, bool defValue)
{
if(key == TYTDCommon.TYTD_SERVER_ACCESSABLE)
{
return TYTDCommon.ServerAccessable;
}
if(key == TYTDCommon.TYTD_NO_EXTERNAL_INFO_THUMB)
{
//no scanning server for info or thumb
return TYTDCommon.NoExtenalInfoThumbnail;
}
if(key == TYTDCommon.TYTD_CACHE_THUMBNAILS_ON_START)
{
return TYTDCommon.CacheThumbnailsFromServersOnStartup;
}
if(key == TYTDCommon.TYTD_CACHE_INFO_ON_START)
{
return TYTDCommon.CacheInfoFromServersOnStartup;
}
if(key == TYTDCommon.TYTD_CACHE_LAZY)
{
return TYTDCommon.CacheLazy;
}
if(key == TYTDCommon.TYTD_FETCH_THUMB_YOUTUBE)
{
return TYTDCommon.FetchThumbYouTube;
}
return defValue;
}
public override float GetFloat(string? key, float defValue)
{
return defValue;
}
public override int GetInt(string? key, int defValue)
{
if(key == TYTDCommon.TYTD_SERVER_PORT)
{
return TYTDCommon.ServerPort;
}
return defValue;
}
public override long GetLong(string? key, long defValue)
{
return defValue;
}
public override string? GetString(string? key, string? defValue)
{
if(key == TYTDCommon.TYTD_SERVER_PORT)
{
return TYTDCommon.ServerPort.ToString();
}
if(key == TYTDCommon.TYTD_TAG)
{
return TYTDCommon.Tag;
}
return defValue;
}
public override ICollection<string>? GetStringSet(string? key, ICollection<string>? defValues)
{
return defValues;
}
public override void PutBoolean(string? key, bool value)
{
if(key == TYTDCommon.TYTD_SERVER_ACCESSABLE)
{
TYTDCommon.ServerAccessable=value;
}
if(key == TYTDCommon.TYTD_NO_EXTERNAL_INFO_THUMB)
{
//no scanning server for info or thumb
TYTDCommon.NoExtenalInfoThumbnail = value;
}
if(key == TYTDCommon.TYTD_CACHE_THUMBNAILS_ON_START)
{
TYTDCommon.CacheThumbnailsFromServersOnStartup=value;
}
if(key == TYTDCommon.TYTD_CACHE_INFO_ON_START)
{
TYTDCommon.CacheInfoFromServersOnStartup=value;
}
if(key == TYTDCommon.TYTD_CACHE_LAZY)
{
TYTDCommon.CacheLazy=value;
}
if(key == TYTDCommon.TYTD_FETCH_THUMB_YOUTUBE)
{
TYTDCommon.FetchThumbYouTube=value;
}
}
public override void PutFloat(string? key, float value)
{
}
public override void PutInt(string? key, int value)
{
if(key == TYTDCommon.TYTD_SERVER_PORT)
{
if(value <= ushort.MaxValue)
{
TYTDCommon.ServerPort=(ushort)value;
}
}
}
public override void PutLong(string? key, long value)
{
base.PutLong(key, value);
}
public override void PutString(string? key, string? value)
{
if(key == TYTDCommon.TYTD_SERVER_PORT)
{
ushort value2;
if(ushort.TryParse(value,out value2))
{
TYTDCommon.ServerPort=value2;
}
}
if(key == TYTDCommon.TYTD_TAG)
{
if(!string.IsNullOrWhiteSpace(value)){
TYTDCommon.Tag = value;
}else{
TYTDCommon.Tag="UnknownPC";
}
}
}
public override void PutStringSet(string? key, ICollection<string>? values)
{
}
}
public static class CastExtensions
{
public static async Task CopyThumbnailsFromYouTubeAsync(this IStorage storage,string id)
{
if(id.Length == 11)
{
storage.CreateDirectoryIfNotExist($"Thumbnails/{id}");
await storage.CopyThumbnailFromYouTubeAsync(id,"default");
await storage.CopyThumbnailFromYouTubeAsync(id,"hqdefault");
await storage.CopyThumbnailFromYouTubeAsync(id,"maxresdefault");
await storage.CopyThumbnailFromYouTubeAsync(id,"mqdefault");
await storage.CopyThumbnailFromYouTubeAsync(id,"sddefault");
}
}
private static async Task CopyThumbnailFromYouTubeAsync(this IStorage storage,string id,string thumbnail)
{
string name=$"Thumbnails/{id}/{thumbnail}.jpg";
if(!storage.FileExists(name))
{
try{
using(var src=await storage.HttpClient.GetStreamAsync($"https://i.ytimg.com/vi/{id}/{thumbnail}.jpg")){
using(var dest=await storage.CreateAsync(name))
{
await src.CopyToAsync(dest);
}
}}catch(Exception ex)
{
_=ex;
}
}
}
private static async Task CopyThumbnailAsync(this ITYTDBase baseCtl,string id,string thumbnail,IStorage storage)
{
string name=$"Thumbnails/{id}/{thumbnail}.jpg";
if(!storage.FileExists(name) && baseCtl.FileExists(name))
{
using(var src=await baseCtl.OpenReadAsync(name)){
using(var dest=await storage.CreateAsync(name))
{
await src.CopyToAsync(dest);
}
}
}
}
public static async Task CopyThumbnailsAsync(this ITYTDBase baseCtl,string id,IStorage storage)
{
storage.CreateDirectoryIfNotExist($"Thumbnails/{id}");
await baseCtl.CopyThumbnailAsync(id,"default",storage);
await baseCtl.CopyThumbnailAsync(id,"hqdefault",storage);
await baseCtl.CopyThumbnailAsync(id,"maxresdefault",storage);
await baseCtl.CopyThumbnailAsync(id,"mqdefault",storage);
await baseCtl.CopyThumbnailAsync(id,"sddefault",storage);
await baseCtl.CopyThumbnailAsync(id,"900x900",storage);
}
public static async Task CastIfAsync<T1,T2>(this T1? src,Func<T2,Task> cb) where T2 : class
{
var type = src as T2;
if(type != null && cb != null)
{
await cb(type);
}
}
public static void CastIf<T1,T2>(this T1? src,Action<T2> cb) where T2 : class
{
var type = src as T2;
if(type != null && cb != null)
{
cb(type);
}
}
}
public static class TYTDCommon
{
#region PREFENCES
public static string Tag {
get{
if(ctx==null) return "UnknownPC";
var res=ctx.GetSharedPreferences(TYTD_CONFIG,FileCreationMode.Private);
if(res != null)
{
var res2=res.GetString(TYTD_TAG,"UnknownPC");
if(!string.IsNullOrWhiteSpace(res2))
{
return res2;
}
}
return "";
}
set{
if(ctx==null) return;
var res=ctx.GetSharedPreferences(TYTD_CONFIG,FileCreationMode.Private);
if(res != null)
{
var res2=res.Edit();
if(res2 != null)
{
res2.PutString(TYTD_TAG,value);
if(res2.Commit())
{
Restart();
}
}
}
}
}
public static bool ServerAccessable
{
get{
if(ctx==null) return false;
var res=ctx.GetSharedPreferences(TYTD_CONFIG,FileCreationMode.Private);
if(res != null)
{
var res2=res.GetBoolean(TYTD_SERVER_ACCESSABLE,false);
return res2;
}
return false;
}
set{
if(ctx==null) return;
var res=ctx.GetSharedPreferences(TYTD_CONFIG,FileCreationMode.Private);
if(res != null)
{
var res2=res.Edit();
if(res2 != null)
{
res2.PutBoolean(TYTD_SERVER_ACCESSABLE,value);
if(res2.Commit())
{
Restart();
}
}
}
}
}
public static bool CacheLazy
{
get{
if(ctx==null) return false;
var res=ctx.GetSharedPreferences(TYTD_CONFIG,FileCreationMode.Private);
if(res != null)
{
var res2=res.GetBoolean(TYTD_CACHE_LAZY,false);
return res2;
}
return false;
}
set{
if(ctx==null) return;
var res=ctx.GetSharedPreferences(TYTD_CONFIG,FileCreationMode.Private);
if(res != null)
{
var res2=res.Edit();
if(res2 != null)
{
res2.PutBoolean(TYTD_CACHE_LAZY,value);
res2.Apply();
}
}
}
}
public static bool CacheThumbnailsFromServersOnStartup
{
get{
if(ctx==null) return false;
var res=ctx.GetSharedPreferences(TYTD_CONFIG,FileCreationMode.Private);
if(res != null)
{
var res2=res.GetBoolean(TYTD_CACHE_THUMBNAILS_ON_START,false);
return res2;
}
return false;
}
set{
if(ctx==null) return;
var res=ctx.GetSharedPreferences(TYTD_CONFIG,FileCreationMode.Private);
if(res != null)
{
var res2=res.Edit();
if(res2 != null)
{
res2.PutBoolean(TYTD_CACHE_THUMBNAILS_ON_START,value);
res2.Apply();
}
}
}
}
public static bool CacheInfoFromServersOnStartup
{
get{
if(ctx==null) return false;
var res=ctx.GetSharedPreferences(TYTD_CONFIG,FileCreationMode.Private);
if(res != null)
{
var res2=res.GetBoolean(TYTD_CACHE_INFO_ON_START,false);
return res2;
}
return false;
}
set{
if(ctx==null) return;
var res=ctx.GetSharedPreferences(TYTD_CONFIG,FileCreationMode.Private);
if(res != null)
{
var res2=res.Edit();
if(res2 != null)
{
res2.PutBoolean(TYTD_CACHE_INFO_ON_START,value);
res2.Apply();
}
}
}
}
public static bool NoExtenalInfoThumbnail
{
get{
if(ctx==null) return false;
var res=ctx.GetSharedPreferences(TYTD_CONFIG,FileCreationMode.Private);
if(res != null)
{
var res2=res.GetBoolean(TYTD_NO_EXTERNAL_INFO_THUMB,false);
return res2;
}
return false;
}
set{
if(ctx==null) return;
var res=ctx.GetSharedPreferences(TYTD_CONFIG,FileCreationMode.Private);
if(res != null)
{
var res2=res.Edit();
if(res2 != null)
{
res2.PutBoolean(TYTD_NO_EXTERNAL_INFO_THUMB,value);
res2.Apply();
}
}
}
}
public static bool FetchThumbYouTube
{
get{
if(ctx==null) return false;
var res=ctx.GetSharedPreferences(TYTD_CONFIG,FileCreationMode.Private);
if(res != null)
{
var res2=res.GetBoolean(TYTD_FETCH_THUMB_YOUTUBE,false);
return res2;
}
return false;
}
set{
if(ctx==null) return;
var res=ctx.GetSharedPreferences(TYTD_CONFIG,FileCreationMode.Private);
if(res != null)
{
var res2=res.Edit();
if(res2 != null)
{
res2.PutBoolean(TYTD_FETCH_THUMB_YOUTUBE,value);
res2.Apply();
}
}
}
}
public static ushort ServerPort
{
get{
if(ctx==null) return 3252;
var res=ctx.GetSharedPreferences(TYTD_CONFIG,FileCreationMode.Private);
if(res != null)
{
var res2=res.GetInt(TYTD_SERVER_PORT,3252);
if(res2 < 1025 || res2 > ushort.MaxValue)
return 1025;
return (ushort)res2;
}
return 3252;
}
set{
if(ctx==null) return;
var res=ctx.GetSharedPreferences(TYTD_CONFIG,FileCreationMode.Private);
if(res != null)
{
var res2=res.Edit();
if(res2 != null)
{
res2.PutInt(TYTD_SERVER_PORT,value);
if(res2.Commit())
{
Restart();
}
}
}
}
}
public static string AppDownloadLocation
{
get{
if(ctx==null) return "";
var res=ctx.GetSharedPreferences(TYTD_CONFIG,FileCreationMode.Private);
if(res != null)
{
var res2=res.GetString(TYTD_DOWNLOAD_LOCATION,"");
if(!string.IsNullOrWhiteSpace(res2))
{
return res2;
}
}
return "";
}
set{
if(ctx==null) return;
var res=ctx.GetSharedPreferences(TYTD_CONFIG,FileCreationMode.Private);
if(res != null)
{
var res2=res.Edit();
if(res2 != null)
{
res2.PutString(TYTD_DOWNLOAD_LOCATION,value);
if(res2.Commit())
{
Restart();
}
}
}
}
}
public static string AppStorageLocation
{
get{
if(ctx==null) return "";
var res=ctx.GetSharedPreferences(TYTD_CONFIG,FileCreationMode.Private);
if(res != null)
{
var res2=res.GetString(TYTD_STORE_LOCATION,"");
if(!string.IsNullOrWhiteSpace(res2))
{
return res2;
}
}
return "";
}
set{
if(ctx==null) return;
var res=ctx.GetSharedPreferences(TYTD_CONFIG,FileCreationMode.Private);
if(res != null)
{
var res2=res.Edit();
if(res2 != null)
{
res2.PutString(TYTD_STORE_LOCATION,value);
if(res2.Commit())
{
Restart();
}
}
}
}
}
#endregion
#region CONSTANTS
public const string TYTD_CONFIG="tytdConfig";
public const string TYTD_TAG = "tytdTag";
public const string TYTD_STORE_LOCATION = "tytdStorageLocation";
public const string TYTD_DOWNLOAD_LOCATION = "tytdDownloadLocation";
public const string TYTD_SERVER_ACCESSABLE = "tytdServerAccessable";
public const string TYTD_SERVER_PORT= "tytdServerPort";
public const string TYTD_NO_EXTERNAL_INFO_THUMB= "tytdNoExternalInfoThumb";
public const string TYTD_CACHE_THUMBNAILS_ON_START="tytdCacheThumbnailsOnStart";
public const string TYTD_CACHE_INFO_ON_START = "tytdCacheInfoOnStart";
public const string TYTD_FETCH_THUMB_YOUTUBE = "tytdFetchThumbYouTube";
public const string TYTD_CACHE_LAZY="tytdCacheLazy";
#endregion
#region PRIVATE_FIELDS
private static string data_dir_internal="";
private static CancellationTokenSource? src=null;
private static Context? ctx=null;
private static CancellationToken token=default(CancellationToken);
private static string server_url_file="";
private static List<PrivateKeyFile> privateKeys=new List<PrivateKeyFile>();
private static Dictionary<string,ITYTDBase> svrs=new Dictionary<string, ITYTDBase>();
#endregion
#region PUBLIC_PROPERTIES
public static Type? MainActivity {get;set;}
public static Type? SettingsActivity {get;set;}
public static ITYTDBase? TYTD {get;private set;}
public static Context? Context {get{return ctx;}}
public static ITYTDBase? LocalStorage {get;private set;}
public static bool HasContext {get{return ctx != null;}}
#endregion
#region PUBLIC_METHODS
public static Dictionary<string,string> GetServers()
{
Dictionary<string,string> servers=new Dictionary<string, string>();
if(File.Exists(server_url_file)){
var lines=File.ReadAllLines(server_url_file);
foreach(var line in lines)
{
string[] item=line.Split(':',2,StringSplitOptions.RemoveEmptyEntries);
if(item.Length ==2)
{
servers.Add(item[0],item[1]);
}
}
}
return servers;
}
public static void SaveServers(Dictionary<string,string> servers)
{
List<string> servers_list=new List<string>();
foreach(var svr in servers)
{
servers_list.Add($"{svr.Key.Replace(":","").Replace("\n","").Replace("\r","")}:{svr.Value.Replace("\n","").Replace("\r","")}");
}
File.WriteAllLines(server_url_file,servers_list);
}
public static async Task<byte[]> GetBestThumbnailArrayAsync(string id,string thumbRes)
{
string thumb = $"Thumbnails/{id}/{thumbRes}.jpg";
if(LocalStorage!= null && LocalStorage.FileExists(thumb)) return await LocalStorage.ReadAllBytesAsync(thumb);
if(TYTD != null && TYTD.FileExists(thumb)) {
var bytes=await TYTD.ReadAllBytesAsync(thumb);
if(CacheLazy && LocalStorage != null)
{
await LocalStorage.CastIfAsync<ITYTDBase,IStorage>(async(e)=>{
using(var f = await e.CreateAsync(thumb))
{
await f.WriteAsync(bytes,0,bytes.Length);
}
});
}
return bytes;
}
return Convert.FromBase64String("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");
}
public static byte[] GetBestThumbnailArray(string id,string thumbRes)
{
return GetBestThumbnailArrayAsync(id,thumbRes).Result;
}
public static async IAsyncEnumerable<SavedVideo> EnumerateVideos()
{
if(NoExtenalInfoThumbnail)
{
if(LocalStorage == null) yield break;
await foreach(var item in LocalStorage.GetVideosAsync())
{
if(FetchThumbYouTube)
{
await LocalStorage.CastIfAsync<ITYTDBase,IStorage>(async(e)=>{
await e.CopyThumbnailsFromYouTubeAsync(item.Id);
});
}
yield return await Task.FromResult(item);
}
}else{
if(TYTD != null){
await foreach(var item in TYTD.GetVideosAsync())
{
if(CacheLazy && LocalStorage != null && !LocalStorage.VideoInfoExists(item.Id))
{
await LocalStorage.CastIfAsync<ITYTDBase,IStorage>(async(e)=>{
await e.WriteVideoInfoAsync(item);
});
}
yield return await Task.FromResult(item);
}
}else{
if(LocalStorage == null) yield break;
await foreach(var item in LocalStorage.GetVideosAsync())
{
if(FetchThumbYouTube || CacheLazy)
{
await LocalStorage.CastIfAsync<ITYTDBase,IStorage>(async(e)=>{
await e.CopyThumbnailsFromYouTubeAsync(item.Id);
});
}
yield return await Task.FromResult(item);
}
}
}
}
public static void StartBootCache<T>(Func<T> startCacheCb,Action<T> stopCacheCb)
{
if(CacheThumbnailsFromServersOnStartup || CacheInfoFromServersOnStartup)
{
T t = startCacheCb();
Thread thd=new Thread(async()=>{
if(LocalStorage != null ){
foreach(var server in GetServers())
{
try{
var tytddb = getTYTDBase(server.Value,Path.Combine(data_dir_internal,"working"),privateKeys);
await foreach(var item in tytddb.GetVideoIdsAsync())
{
if(!LocalStorage.VideoInfoExists(item) && CacheInfoFromServersOnStartup)
{
await LocalStorage.CastIfAsync<ITYTDBase,IStorage>(async (e)=>{
await e.WriteVideoInfoAsync(await tytddb.GetVideoInfoAsync(item));
});
}
if(CacheThumbnailsFromServersOnStartup)
{
await LocalStorage.CastIfAsync<ITYTDBase,IStorage>(async (e)=>{
await tytddb.CopyThumbnailsAsync(item,e);
});
}
}
await foreach(var item in tytddb.GetPlaylistIdsAsync())
{
if(!LocalStorage.PlaylistInfoExists(item) && CacheInfoFromServersOnStartup)
{
await LocalStorage.CastIfAsync<ITYTDBase,IStorage>(async (e)=>{
await e.WritePlaylistInfoAsync(await tytddb.GetPlaylistInfoAsync(item));
});
}
if(LocalStorage.PlaylistInfoExists(item))
{
var pl=await LocalStorage.GetPlaylistInfoAsync(item);
foreach(var id in pl.Videos)
{
if(!LocalStorage.VideoInfoExists(id) && tytddb.VideoInfoExists(id) && CacheInfoFromServersOnStartup)
{
await LocalStorage.CastIfAsync<ITYTDBase,IStorage>(async (e)=>{
await e.WriteVideoInfoAsync(await tytddb.GetVideoInfoAsync(id));
});
}
if(CacheThumbnailsFromServersOnStartup)
{
await LocalStorage.CastIfAsync<ITYTDBase,IStorage>(async (e)=>{
await tytddb.CopyThumbnailsAsync(id,e);
});
}
}
}
}
await foreach(var channel in tytddb.GetChannelIdsAsync())
{
if(!LocalStorage.ChannelInfoExists(channel) && CacheInfoFromServersOnStartup)
{
await LocalStorage.CastIfAsync<ITYTDBase,IStorage>(async (e)=>{
await e.WriteChannelInfoAsync(await tytddb.GetChannelInfoAsync(channel));
});
}
if(CacheThumbnailsFromServersOnStartup)
{
await LocalStorage.CastIfAsync<ITYTDBase,IStorage>(async (e)=>{
await tytddb.CopyThumbnailsAsync(channel,e);
});
}
}
}catch(Exception ex)
{
_=ex;
}
}
}
stopCacheCb(t);
});
thd.Start();
}
}
public static List<(string Label,string Path)> GetStorageDevices()
{
List<(string Label,string Path)> paths=new List<(string Label, string Path)>();
if(ctx != null){
var dirs=ctx.GetExternalFilesDirs(null);
if(dirs != null)
foreach(var item in dirs)
{
string path=item.ToString();
if(path.StartsWith("/storage/emulated/"))
{
paths.Add(("Internal Storage",path));
}else{
if(path.StartsWith("/storage/"))
{
string[] path0=path.Split('/',3,StringSplitOptions.RemoveEmptyEntries);
if(path0.Length >= 2)
{
paths.Add((path0[1],path));
}else{
paths.Add((path,path));
}
}else{
paths.Add((path,path));
}
}
}
}
return paths;
}
public static void Close()
{
if(src != null)
{
src.Cancel();
src=null;
}
}
public static void Restart()
{
if(ctx != null)
reInit(ctx);
}
public static void Init(Android.Content.Context ctx)
{
if(!HasContext)
{
reInit(ctx);
}
}
#endregion
#region PRIVATE_METHODS
private static void reInit(Android.Content.Context ctx)
{
Close();
src=new CancellationTokenSource();
var dir=ctx.GetExternalFilesDir(null);
var token = src.Token;
if(dir == null) return;
TYTDCommon.ctx=ctx;
TYTDCommon.token = token;
data_dir_internal=dir.ToString();
server_url_file = Path.Combine(data_dir_internal,"servers.txt");
string applocationInternal = Path.Combine(data_dir_internal, "working");
string privKeyDir = Path.Combine(data_dir_internal,"privkeys");
Directory.CreateDirectory(privKeyDir);
foreach(var priv in Directory.GetFiles(privKeyDir))
{
privateKeys.Add(new PrivateKeyFile(priv));
}
Directory.CreateDirectory(applocationInternal);
System.Environment.CurrentDirectory = applocationInternal;
string appStorageLocation = AppStorageLocation;
string appDownloadLocation = AppDownloadLocation;
TYTDStorage.SetTYTDTag(Tag);
MountableServer svr=new MountableServer(new StaticServer(Path.Combine(data_dir_internal,"site")));
svr.Mount("/serveradmin/",getServerApi(data_dir_internal));
LocalStorage=getTYTDBase("",applocationInternal,privateKeys);
var storage=getTYTDBase(appStorageLocation,applocationInternal,privateKeys);
var downloader = getTYTDBase(appDownloadLocation,applocationInternal,privateKeys);
ITYTDBase baseCtl=storage;
if(storage != downloader)
{
var proxy = new TYTDDownloaderStorageProxy();
proxy.Storage = storage;
downloader.CastIf<ITYTDBase,IDownloader>((dl)=>{
proxy.Downloader = dl;
});
baseCtl=proxy;
}
TYTD=baseCtl;
TYTDServer server=new TYTDServer(baseCtl);
server.RootServer.Server = svr;
var svrCtl = baseCtl as IStorage;
if(svrCtl != null){
ExtensionLoader.Loader loader=new ExtensionLoader.Loader(svrCtl);
loader.SetServer(server);
}
HttpServerListener listener = new HttpServerListener(new IPEndPoint(ServerAccessable ? IPAddress.Any : IPAddress.Loopback,ServerPort),server.InnerServer);
listener.ListenAsync(token).Wait(0);
SetupChannels();
Intent intent=new Intent(ctx,typeof(TYTDServerService));
ctx.StartForegroundService(intent);
}
private static void SetupChannels()
{
if (Build.VERSION.SdkInt < BuildVersionCodes.O || ctx == null)
{
// Notification channels are new in API 26 (and not a part of the
// support library). There is no need to create a notification
// channel on older versions of Android.
return;
}
NotificationChannel serverChannel = new NotificationChannel(TYTDServerService.SERVER_CHANNEL_ID, "TYTD Server", NotificationImportance.Default);
NotificationManager? manager = (NotificationManager?)ctx.GetSystemService(Context.NotificationService);
if (manager != null)
{
manager.CreateNotificationChannel(serverChannel);
}
}
private static IServer getServerApi(string appDir)
{
StaticServer ssvr=new StaticServer(Path.Combine(appDir,"adminpanel"));
MountableServer svr=new MountableServer(ssvr);
SwagmeServer swagme = new SwagmeServer();
svr.Mount("/api/",swagme);
return svr;
}
private static ITYTDBase getTYTDBase(string url,string internalUrl,IEnumerable<PrivateKeyFile> privKeys)
{
if(!string.IsNullOrWhiteSpace(url)){
if(url.StartsWith('/'))
{
//file
if(svrs.ContainsKey(url)) return svrs[url];
var item=new TYTDPathDirectory(url);
item.CreateDirectories();
item.StartLoop(token);
svrs.Add(url,item);
return item;
}else{
System.Uri uri = new(url);
if(uri.Scheme == "http" || uri.Scheme == "https")
{
if(svrs.ContainsKey(url)) return svrs[url];
var item = new TYTDClient(url);
svrs.Add(url,item);
return item;
}
if(uri.Scheme == "sftp")
{
//sftp
//we need to get username password
string username = "root";
string? password = null;
string userInfo=uri.UserInfo;
if(!string.IsNullOrWhiteSpace(userInfo))
{
string[] userInfoSplit = userInfo.Split(':',2,StringSplitOptions.RemoveEmptyEntries);
if(userInfoSplit.Length == 2)
{
//username:password
username = userInfoSplit[0];
password = userInfoSplit[1];
}else if(userInfoSplit.Length == 1)
{
//username only
username = userInfoSplit[0];
}
}
if(string.IsNullOrWhiteSpace(password))
{
try{
var item= new SSHFS(url,username,privKeys.ToArray());
item.CreateDirectories();
item.StartLoop(token);
svrs.Add(url,item);
return item;
}catch(Exception ex)
{
_=ex;
}
}else{
try{
var item= new SSHFS(url,username,password);
item.CreateDirectories();
item.StartLoop(token);
svrs.Add(url,item);
return item;
}catch(Exception ex)
{
_=ex;
}
}
//SSHFS ssh=new SSHFS(url,);
}
}
}
if(svrs.ContainsKey(internalUrl)) return svrs[internalUrl];
var item2= new TYTDPathDirectory(internalUrl);
item2.CreateDirectories();
item2.StartLoop(token);
svrs.Add(internalUrl,item2);
return item2;
}
#endregion
}