2022-07-06 22:59:50 +00:00
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
using System;
|
2022-08-28 21:40:34 +00:00
|
|
|
|
using YoutubeExplode.Videos;
|
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
|
|
2022-07-06 22:59:50 +00:00
|
|
|
|
namespace Tesses.YouTubeDownloader.Tools.Common
|
|
|
|
|
{
|
|
|
|
|
public static class SymlinkGenerator
|
|
|
|
|
{
|
|
|
|
|
[DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
|
|
|
|
|
static extern bool CreateHardLink(string lpFileName, string lpExistingFileName, IntPtr lpSecurityAttributes);
|
|
|
|
|
private static void createHardLink(string destPath,string srcPath)
|
|
|
|
|
{if(RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
|
|
|
|
{
|
|
|
|
|
CreateHardLink(destPath,srcPath,IntPtr.Zero);
|
|
|
|
|
}else{
|
|
|
|
|
using(var p=new Process())
|
|
|
|
|
{
|
2022-08-28 21:40:34 +00:00
|
|
|
|
p.StartInfo.UseShellExecute=false;
|
|
|
|
|
p.StartInfo.WorkingDirectory="/";
|
2022-07-06 22:59:50 +00:00
|
|
|
|
p.StartInfo.FileName = "ln";
|
|
|
|
|
p.StartInfo.ArgumentList.Add(srcPath);
|
|
|
|
|
p.StartInfo.ArgumentList.Add(destPath);
|
|
|
|
|
|
|
|
|
|
if(p.Start()){ p.WaitForExit();}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public static async Task GenerateHardLinks(TYTDStorage storage,string dest="GoodFileNames",Resolution res=Resolution.PreMuxed,bool verbose=false)
|
|
|
|
|
{
|
|
|
|
|
Directory.CreateDirectory(dest);
|
2022-08-28 21:40:34 +00:00
|
|
|
|
await foreach(var item in storage.GetVideosAsync())
|
2022-07-06 22:59:50 +00:00
|
|
|
|
{
|
2022-08-28 21:40:34 +00:00
|
|
|
|
try{
|
|
|
|
|
var v=await BestStreams.GetPathResolution(storage,item,res);
|
|
|
|
|
if(storage.FileExists(v))
|
2022-07-06 22:59:50 +00:00
|
|
|
|
{
|
2022-08-28 21:40:34 +00:00
|
|
|
|
|
|
|
|
|
var (path,delete)= await storage.GetRealUrlOrPathAsync(v);
|
2022-07-06 22:59:50 +00:00
|
|
|
|
string? ext=Path.GetExtension(path);
|
|
|
|
|
|
|
|
|
|
string defaultExt = res == Resolution.Mux ? ".mkv" : ".mp4";
|
|
|
|
|
if(string.IsNullOrWhiteSpace(ext))
|
|
|
|
|
{
|
|
|
|
|
ext=defaultExt;
|
|
|
|
|
}
|
|
|
|
|
string destPathMkv=Path.Combine(dest,$"{item.Title.GetSafeFileName()}-{item.Id}{defaultExt}");
|
|
|
|
|
string destPath=Path.Combine(dest,$"{item.Title.GetSafeFileName()}-{item.Id}{ext}");
|
|
|
|
|
|
|
|
|
|
if(File.Exists(destPathMkv) && destPathMkv != destPath)
|
|
|
|
|
{
|
|
|
|
|
File.Delete(destPathMkv);
|
|
|
|
|
createHardLink(destPath,path);
|
|
|
|
|
if(verbose)
|
|
|
|
|
Console.WriteLine($"Changed: {item.Title} {defaultExt} -> {ext}");
|
|
|
|
|
}
|
|
|
|
|
if(!File.Exists(destPath))
|
|
|
|
|
{
|
|
|
|
|
createHardLink(destPath,path);
|
|
|
|
|
if(verbose)
|
|
|
|
|
Console.WriteLine(item.Title);
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-08-28 21:40:34 +00:00
|
|
|
|
}catch(Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine($"ERROR: {item.Id}");
|
|
|
|
|
Console.WriteLine(ex.ToString());
|
|
|
|
|
}
|
2022-07-06 22:59:50 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
2022-08-28 21:40:34 +00:00
|
|
|
|
public static async Task<bool> VideoExistsAsync(ITYTDBase b,SavedVideo id)
|
|
|
|
|
{
|
|
|
|
|
var res=await BestStreams.GetPathResolution(b,id,Resolution.PreMuxed);
|
|
|
|
|
if(b.FileExists(res)) return true;
|
|
|
|
|
await BestStreams.GetPathResolution(b,id,Resolution.Mux);
|
|
|
|
|
if(b.FileExists(res)) return true;
|
|
|
|
|
await BestStreams.GetPathResolution(b,id,Resolution.VideoOnly);
|
|
|
|
|
if(b.FileExists(res)) return true;
|
|
|
|
|
await BestStreams.GetPathResolution(b,id,Resolution.AudioOnly);
|
|
|
|
|
if(b.FileExists(res)) return true;
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
public static async Task GenerateMeta(List<string> items,TYTDStorage storage,string dest="GoodInfos",bool verbose=false)
|
|
|
|
|
{
|
|
|
|
|
items.Add("Videos");
|
|
|
|
|
if(verbose)
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine("[Generating Meta]");
|
|
|
|
|
}
|
|
|
|
|
Directory.CreateDirectory(dest);
|
|
|
|
|
await foreach(var item in storage.GetVideosAsync())
|
|
|
|
|
{
|
|
|
|
|
if(await VideoExistsAsync(storage,item))
|
|
|
|
|
{
|
|
|
|
|
string destPathJson=Path.Combine(dest,$"{item.Title.GetSafeFileName()}-{item.Id}.json");
|
|
|
|
|
string destPathText=Path.Combine(dest,$"{item.Title.GetSafeFileName()}-{item.Id}.txt");
|
|
|
|
|
if(!File.Exists(destPathJson))
|
|
|
|
|
File.WriteAllText(destPathJson,JsonConvert.SerializeObject(item,Formatting.Indented));
|
|
|
|
|
if(!File.Exists(destPathText)){ using(var f=new StreamWriter(destPathText))
|
|
|
|
|
{
|
|
|
|
|
f.WriteLine($"Title: {item.Title}");
|
|
|
|
|
f.WriteLine($"Id: {item.Id}");
|
|
|
|
|
f.WriteLine($"AuthorTitle: {item.AuthorTitle}");
|
|
|
|
|
f.WriteLine($"AuthorChannelId: {item.AuthorChannelId}");
|
|
|
|
|
f.WriteLine($"Tags: {string.Join(", ",item.Keywords)}");
|
|
|
|
|
|
|
|
|
|
f.WriteLine($"Views: {item.Views}");
|
|
|
|
|
f.WriteLine($"Likes: {item.Likes}");
|
|
|
|
|
f.WriteLine($"Dislikes: {item.Dislikes}");
|
|
|
|
|
|
|
|
|
|
f.WriteLine($"Duration: {item.Duration.ToString()}");
|
|
|
|
|
f.WriteLine($"Upload Date: {item.UploadDate}");
|
|
|
|
|
f.WriteLine($"Add Date: {item.AddDate.ToShortDateString()}");
|
|
|
|
|
|
|
|
|
|
f.WriteLine($"DownloadFrom: {item.DownloadFrom}");
|
|
|
|
|
f.WriteLine($"Legacy Video: {item.LegacyVideo}");
|
|
|
|
|
f.WriteLine($"Downloader Tag: {item.TYTDTag}");
|
|
|
|
|
f.WriteLine($"Video Frozen: {item.VideoFrozen}");
|
|
|
|
|
|
|
|
|
|
f.WriteLine("Description:");
|
|
|
|
|
f.WriteLine($"{item.Description}");
|
|
|
|
|
}}
|
|
|
|
|
items.Add($"{item.Title}-{item.Id}");
|
|
|
|
|
if(verbose)
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine($"[META] {item.Title}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-07-06 22:59:50 +00:00
|
|
|
|
public static async Task GenerateSymlinks(TYTDBase storage,string dest="GoodFileNames",Resolution res=Resolution.PreMuxed,bool verbose=false)
|
|
|
|
|
{
|
|
|
|
|
Directory.CreateDirectory(dest);
|
|
|
|
|
await foreach(var item in storage.GetVideosAsync())
|
|
|
|
|
{
|
2022-08-28 21:40:34 +00:00
|
|
|
|
var v=await BestStreams.GetPathResolution(storage,item,res);
|
|
|
|
|
if(storage.FileExists(v))
|
2022-07-06 22:59:50 +00:00
|
|
|
|
{
|
2022-08-28 21:40:34 +00:00
|
|
|
|
var (path,delete)= await storage.GetRealUrlOrPathAsync(v);
|
2022-07-06 22:59:50 +00:00
|
|
|
|
string? ext=Path.GetExtension(path);
|
|
|
|
|
|
|
|
|
|
string defaultExt = res == Resolution.Mux ? ".mkv" : ".mp4";
|
|
|
|
|
if(string.IsNullOrWhiteSpace(ext))
|
|
|
|
|
{
|
|
|
|
|
ext=defaultExt;
|
|
|
|
|
}
|
|
|
|
|
string destPathMkv=Path.Combine(dest,$"{item.Title.GetSafeFileName()}-{item.Id}{defaultExt}");
|
|
|
|
|
string destPath=Path.Combine(dest,$"{item.Title.GetSafeFileName()}-{item.Id}{ext}");
|
|
|
|
|
|
|
|
|
|
if(File.Exists(destPathMkv) && destPathMkv != destPath)
|
|
|
|
|
{
|
|
|
|
|
File.Delete(destPathMkv);
|
|
|
|
|
File.CreateSymbolicLink(destPath,path);
|
|
|
|
|
if(verbose)
|
|
|
|
|
Console.WriteLine($"Changed: {item.Title} {defaultExt} -> {ext}");
|
|
|
|
|
}
|
|
|
|
|
if(!File.Exists(destPath))
|
|
|
|
|
{
|
|
|
|
|
File.CreateSymbolicLink(destPath,path);
|
|
|
|
|
if(verbose)
|
|
|
|
|
Console.WriteLine(item.Title);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|