public static int Execute(List <string> argumentsGiven) { if (!argumentsGiven.Contains("start")) { Console.WriteLine("Include \"start\" in the arguments to confirm execution!"); Console.WriteLine("Other arguments to enable specific file types:"); Console.WriteLine(" comptoe Tales Compressor files"); Console.WriteLine(" TXMdetect Try and autodetect Tales texture TXM/TXV pairs even if their file extensions are different"); Console.WriteLine(" DRpak Dangan Ronpa PAK files"); Console.WriteLine("Usage of these parameters could break unrelated files, be careful."); return(-1); } Queue <FileStruct> queue = new Queue <FileStruct>(); Console.WriteLine("Adding all files and folders recursively..."); EnqueueDirectoryRecursively(queue, System.Environment.CurrentDirectory); bool AllowComptoe = argumentsGiven.Contains("comptoe"); bool DetectTxmTxv = argumentsGiven.Contains("TXMdetect"); bool AllowDrPak = argumentsGiven.Contains("DRpak"); while (queue.Count > 0) { FileStruct fstr = queue.Dequeue(); Console.WriteLine(fstr.Filename); string f = System.IO.Path.GetFullPath(fstr.Filename); string prog, args; if (!System.IO.File.Exists(f)) { continue; } try { bool isMaybeVesperiaStyleTexture; isMaybeVesperiaStyleTexture = f.EndsWith(".TXV"); if (isMaybeVesperiaStyleTexture) { string txm = f.Substring(0, f.Length - 1) + "M"; string txv = f; Tales.Vesperia.Texture.Decode.Extract(txm, txv, f + ".ext"); } using (FileStream fs = new FileStream(f, FileMode.Open)) { long filesize = fs.Length; int firstbyte = fs.ReadByte(); int secondbyte = fs.ReadByte(); int thirdbyte = fs.ReadByte(); int fourthbyte = fs.ReadByte(); int fifthbyte = fs.ReadByte(); bool HasBeenProcessed = false; // maybe a comptoe file if (AllowComptoe) { if (firstbyte == 0x01 || firstbyte == 0x03) { uint maybefilesizeBigEndian = ((uint)secondbyte) << 24 | ((uint)thirdbyte) << 16 | ((uint)fourthbyte) << 8 | (uint)fifthbyte; uint maybefilesizeLitEndian = ((uint)fifthbyte) << 24 | ((uint)fourthbyte) << 16 | ((uint)thirdbyte) << 8 | (uint)secondbyte; if ((maybefilesizeBigEndian == filesize) || (maybefilesizeLitEndian + 9 == filesize)) { int b6 = fs.ReadByte(); int b7 = fs.ReadByte(); int b8 = fs.ReadByte(); int b9 = fs.ReadByte(); uint uncompressedfilesizeBigEndian = ((uint)b6) << 24 | ((uint)b7) << 16 | ((uint)b8) << 8 | (uint)b9; uint uncompressedfilesizeLitEndian = ((uint)b6) | ((uint)b7) << 8 | ((uint)b8) << 16 | ((uint)b9) << 24; fs.Close(); prog = "comptoe"; args = "-d \"" + f + "\" \"" + f + ".d\""; Console.WriteLine(); Console.WriteLine(prog + " " + args); try { if (ExternalProgramExecution.RunProgramSynchronous(prog, new string[] { "-d", f, f + ".d" }).StdOut.EndsWith("Success")) { queue.Enqueue(new FileStruct(f + ".d", fstr.Indirection)); FileInfo decInfo = new FileInfo(f + ".d"); if ((decInfo.Length == uncompressedfilesizeBigEndian) || (decInfo.Length == uncompressedfilesizeLitEndian)) { System.IO.File.Delete(f); HasBeenProcessed = true; } else { Console.WriteLine("Uncompressed comptoe Filesize does not match!"); } } else { Console.WriteLine("comptoe decompression failure"); } } catch (Exception ex) { Console.WriteLine("comptoe failure: " + ex.ToString()); } } else { Console.WriteLine(); Console.WriteLine(f); Console.WriteLine("Suspected comptoe, but compressed Filesize does not match!"); Console.WriteLine(); Console.WriteLine("Tales.Abyss.PKF.Split.SplitPkf " + f); fs.Close(); if (Tales.Abyss.PKF.Split.SplitPkf(System.IO.File.ReadAllBytes(f), f + ".ex")) { EnqueueDirectoryRecursively(queue, f + ".ex"); System.IO.File.Delete(f); HasBeenProcessed = true; } } } } if (firstbyte == (int)'T') { if (secondbyte == (int)'L' && thirdbyte == (int)'Z' && fourthbyte == (int)'C') { fs.Close(); List <string> tlzcargs = new List <string>(); tlzcargs.Add("-d"); tlzcargs.Add(f); tlzcargs.Add(f + ".dec"); Console.WriteLine(); Console.WriteLine("tlzc -d \"" + f + "\" \"" + f + ".dec\""); if (HyoutaTools.Tales.tlzc.tlzcmain.Execute(tlzcargs) == 0) { queue.Enqueue(new FileStruct(f + ".dec", fstr.Indirection)); System.IO.File.Delete(f); HasBeenProcessed = true; } } } if (firstbyte == (int)'F') { if (secondbyte == (int)'P' && thirdbyte == (int)'S' && fourthbyte == (int)'4') { fs.Close(); prog = "tovfps4e"; args = "\"" + f + "\""; Console.WriteLine(); Console.WriteLine(prog + " " + args); var fps4 = new Tales.Vesperia.FPS4.FPS4(f); fps4.Extract(f + ".ext"); fps4.Close(); EnqueueDirectoryRecursively(queue, f + ".ext"); System.IO.File.Delete(f); HasBeenProcessed = true; } if (secondbyte == (int)'P' && thirdbyte == (int)'S' && fourthbyte == (int)'2') { fs.Close(); Console.WriteLine(); Console.WriteLine("Tales.Abyss.FPS2.Extract " + f); List <string> argList = new List <string>(1); argList.Add(f); if (0 == Tales.Abyss.FPS2.Program.Execute(argList)) { EnqueueDirectoryRecursively(queue, f + ".ext"); System.IO.File.Delete(f); HasBeenProcessed = true; } } if (secondbyte == (int)'P' && thirdbyte == (int)'S' && fourthbyte == (int)'3') { fs.Close(); Console.WriteLine(); Console.WriteLine("Tales.Abyss.FPS3.Extract " + f); List <string> argList = new List <string>(1); argList.Add(f); if (0 == Tales.Abyss.FPS3.Program.Execute(argList)) { EnqueueDirectoryRecursively(queue, f + ".ext"); System.IO.File.Delete(f); HasBeenProcessed = true; } } } string fname = System.IO.Path.GetFileName(f); if (DetectTxmTxv && (firstbyte == 0x00 && secondbyte == 0x02 && thirdbyte == 0x00 && fourthbyte == 0x00 && !isMaybeVesperiaStyleTexture && !(fname.EndsWith(".TXM") || fname.EndsWith(".TXV"))) ) { FileStruct nextfile = queue.Peek(); fs.Close(); string txm = f + ".TXM"; string txv = f + ".TXV"; Console.WriteLine("ren " + f + " " + txm); Console.WriteLine("ren " + nextfile.Filename + " " + txv); System.IO.File.Move(f, txm); System.IO.File.Move(nextfile.Filename, txv); queue.Enqueue(new FileStruct(txv, fstr.Indirection)); HasBeenProcessed = true; } if (firstbyte == 0x4D) { if (secondbyte == 0x49 && thirdbyte == 0x47 && fourthbyte == 0x2E) { fs.Close(); Console.WriteLine(); Console.WriteLine("GimToPng " + f); List <string> converted = PSP.GIM.GimToPng.GimToPng.ConvertGimFileToPngFiles(f); if (converted != null && converted.Count > 0) { System.IO.File.Delete(f); HasBeenProcessed = true; } } } if (firstbyte == 'O' && secondbyte == 'M' && thirdbyte == 'G' && fourthbyte == 0x2E) { fs.Close(); f = RenameToWithExtension(f, ".gmo"); HasBeenProcessed = true; } if (firstbyte == 'L' && secondbyte == 'L' && thirdbyte == 'F' && fourthbyte == 'S') { fs.Close(); f = RenameToWithExtension(f, ".llfs"); HasBeenProcessed = true; } if (AllowDrPak) { if (f.ToLowerInvariant().EndsWith(".pak") || (secondbyte < 0x10 && thirdbyte == 0x00 && fourthbyte == 0x00)) { // could maybe possibly be a PAK file who knows bool drpaksuccess = false; try { fs.Position = 0; DanganRonpa.Pak.Program.Extract(fs, f + ".ex"); fs.Close(); drpaksuccess = true; } catch (Exception ex) { Console.WriteLine("Extracting " + f + " as DanganRonpa PAK file failed: " + ex.ToString()); } if (drpaksuccess) { EnqueueDirectoryRecursively(queue, f + ".ex"); System.IO.File.Delete(f); HasBeenProcessed = true; } } } if (firstbyte == 0x1F && secondbyte == 0x8B && thirdbyte == 0x08) { // gzip compressed file GZip.GZipHandler.Extract(fs, f + ".dec"); queue.Enqueue(new FileStruct(f + ".dec", fstr.Indirection)); fs.Close(); System.IO.File.Delete(f); HasBeenProcessed = true; } if (!HasBeenProcessed) { Console.WriteLine("Nothing found to process " + f + ", leaving alone."); } } } catch (FileNotFoundException) { } catch (Exception ex) { Console.WriteLine(ex.ToString()); } } return(0); }
public override async Task <ResultType> Run(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return(ResultType.Cancelled); } JobStatus = VideoJobStatus.Running; if ((VideoInfo as YoutubeVideoInfo) == null) { Status = "Retrieving video info..."; bool wantCookies = Notes != null && Notes.Contains("cookies"); var result = await Youtube.RetrieveVideo(VideoInfo.VideoId, VideoInfo.Username, wantCookies); switch (result.result) { case Youtube.RetrieveVideoResult.Success: VideoInfo = result.info; break; case Youtube.RetrieveVideoResult.ParseFailure: // this seems to happen randomly from time to time, just retry later return(ResultType.TemporarilyUnavailable); default: return(ResultType.Failure); } } string filenameWithoutExtension = "youtube_" + VideoInfo.Username + "_" + VideoInfo.VideoTimestamp.ToString("yyyy-MM-dd") + "_" + VideoInfo.VideoId; string filename = filenameWithoutExtension + ".mkv"; string tempFolder = Path.Combine(Util.TempFolderPath, filenameWithoutExtension); string tempFilepath = Path.Combine(tempFolder, filename); { if (!await Util.FileExists(tempFilepath)) { if (cancellationToken.IsCancellationRequested) { return(ResultType.Cancelled); } Directory.CreateDirectory(tempFolder); Status = "Running youtube-dl..."; await StallWrite(tempFilepath, 0, cancellationToken); // don't know expected filesize, so hope we have a sensible value in minimum free space if (cancellationToken.IsCancellationRequested) { return(ResultType.Cancelled); } List <string> args = new List <string>() { "-f", "bestvideo[height<=?1080]+bestaudio/best", "-o", tempFilepath, "--merge-output-format", "mkv", "--no-color", "--abort-on-error", "--abort-on-unavailable-fragment", "--no-sponsorblock", }; string limit = Util.YoutubeSpeedLimit; if (limit != "") { args.Add("--rate-limit"); args.Add(limit); } bool wantCookies = Notes != null && Notes.Contains("cookies"); if (wantCookies) { args.Add("--cookies"); args.Add(@"d:\cookies.txt"); } bool nokill = Notes != null && Notes.Contains("nokill"); args.Add("https://www.youtube.com/watch?v=" + VideoInfo.VideoId); var data = await ExternalProgramExecution.RunProgram( @"yt-dlp", args.ToArray(), youtubeSpeedWorkaround : !nokill, stdoutCallbacks : new System.Diagnostics.DataReceivedEventHandler[1] { (sender, received) => { if (!String.IsNullOrEmpty(received.Data)) { Status = received.Data; } } } ); } string finalFilename = GenerateOutputFilename(); string finalFilepath = Path.Combine(Util.TargetFolderPath, finalFilename); if (File.Exists(finalFilepath)) { throw new Exception("File exists: " + finalFilepath); } Status = "Waiting for free disk IO slot to move..."; try { await Util.ExpensiveDiskIOSemaphore.WaitAsync(cancellationToken); } catch (OperationCanceledException) { return(ResultType.Cancelled); } try { // sanity check Status = "Sanity check on downloaded video..."; TimeSpan actualVideoLength = (await FFMpegUtil.Probe(tempFilepath)).Duration; TimeSpan expectedVideoLength = VideoInfo.VideoLength; if (actualVideoLength.Subtract(expectedVideoLength).Duration() > TimeSpan.FromSeconds(5)) { // if difference is bigger than 5 seconds something is off, report Status = "Large time difference between expected (" + expectedVideoLength.ToString() + ") and actual (" + actualVideoLength.ToString() + "), stopping."; return(ResultType.Failure); } Status = "Moving..."; await Task.Run(() => Util.MoveFileOverwrite(tempFilepath, finalFilepath)); await Task.Run(() => Directory.Delete(tempFolder)); } finally { Util.ExpensiveDiskIOSemaphore.Release(); } } Status = "Done!"; JobStatus = VideoJobStatus.Finished; return(ResultType.Success); }