From 81bf43b55863342293ba60220f7076750a270007 Mon Sep 17 00:00:00 2001 From: Syping Date: Sun, 26 Oct 2025 02:45:47 +0100 Subject: [PATCH] impl. create command --- Program.cs | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 117 insertions(+), 1 deletion(-) diff --git a/Program.cs b/Program.cs index 6599b3e..3b901f1 100644 --- a/Program.cs +++ b/Program.cs @@ -6,11 +6,98 @@ internal static class Program { private static void Main(String[] args) { RootCommand rootCommand = new("ragephoto-cli Application") { - GetCommand, SetCommand + CreateCommand, GetCommand, SetCommand }; rootCommand.Parse(args).Invoke(); } + private static void Create(FileInfo photoFile, String format, String jpegFile, String? title) { + try { + using Photo photo = new(); + + photo.Format = format.ToLowerInvariant() switch { + "gta5" => PhotoFormat.GTA5, + "rdr2" => PhotoFormat.RDR2, + _ => throw new ArgumentException("Invalid format", nameof(format)) + }; + + if (jpegFile == String.Empty) { + photo.Jpeg = Properties.Resources.EmptyJpeg; + } + else if (jpegFile != null) { + using MemoryStream jpegStream = new(); + using Stream input = jpegFile == "-" ? Console.OpenStandardInput() : File.OpenRead(jpegFile); + input.CopyTo(jpegStream); + photo.Jpeg = jpegStream.ToArray(); + } + + Byte[] buffer = new Byte[4]; + Random.Shared.NextBytes(buffer); + UInt32 photoUid = BitConverter.ToUInt32(buffer, 0); + + if (photo.Format == PhotoFormat.GTA5) { + DateTimeOffset photoTime = DateTimeOffset.FromUnixTimeSeconds(Random.Shared.Next(1356998400, 1388534399)); + photo.SetHeader("PHOTO - 10/26/25 02:28:08", 0x2F99E5D9, 0x00000000); + photo.Json = "{\"loc\":{\"x\":0,\"y\":0,\"z\":0}," + + "\"area\":\"SANAND\",\"street\":0,\"nm\":\"\",\"rds\":\"\"," + + "\"scr\":1,\"sid\":\"0x0\",\"crewid\":0,\"mid\":\"\"," + + "\"mode\":\"FREEMODE\",\"meme\":false,\"mug\":false," + + $"\"uid\":{photoUid}," + "\"time\":{" + + $"\"hour\":{photoTime.Hour}," + + $"\"minute\":{photoTime.Minute}," + + $"\"second\":{photoTime.Second}," + + $"\"day\":{photoTime.Day}," + + $"\"month\":{photoTime.Month}," + + $"\"year\":{photoTime.Year}" + "}," + + $"\"creat\":{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}," + + "\"slf\":true,\"drctr\":false,\"rsedtr\":false,\"cv\":true," + + $"\"sign\":{photo.Sign}" + + "}"; + } + else { + DateTimeOffset photoTime = DateTimeOffset.FromUnixTimeSeconds(Random.Shared.NextInt64(-2208988801, -2240524800)); + photo.SetHeader("PHOTO - 10/26/25 02:31:34", 0xB76BFD68, 0xACEF57D2); + photo.Json = "{\"loc\":{\"x\":0,\"y\":0,\"z\":0}," + + "\"regionname\":0,\"districtname\":0,\"statename\":0,\"nm\":\"\"," + + "\"sid\":\"0x0\",\"crewid\":0,\"mid\":\"\",\"mode\":\"SP\"," + + "\"meme\":false,\"mug\":false," + + $"\"uid\":{photoUid}," + "\"time\":{" + + $"\"hour\":{photoTime.Hour}," + + $"\"minute\":{photoTime.Minute}," + + $"\"second\":{photoTime.Second}," + + $"\"day\":{photoTime.Day}," + + $"\"month\":{photoTime.Month}," + + $"\"year\":{photoTime.Year}" + "}," + + $"\"creat\":{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}," + + "\"slf\":false,\"drctr\":false,\"rsedtr\":false,\"inphotomode\":true," + + "\"advanced\":false," + + "\"width\":1920," + + "\"height\":1080," + + $"\"size\":{photo.JpegSize}," + + $"\"sign\":{photo.Sign}" + + "}"; + } + + photo.Title = title ?? "Custom Photo"; + + String tempFile = Path.GetTempFileName(); + photo.SaveFile(tempFile); + File.Move(tempFile, photoFile.FullName, true); + } + catch (RagePhotoException exception) { + Console.Error.WriteLine(exception.Message); + Environment.Exit(exception.Photo != null ? (Int32)exception.Error + 2 : -1); + } + catch (ArgumentException exception) { + Console.Error.WriteLine(exception.Message); + Environment.Exit(1); + } + catch (Exception exception) { + Console.Error.WriteLine(exception.Message); + Environment.Exit(-1); + } + } + private static void Get(FileInfo photoFile, String dataType, String outputFile) { try { using Photo photo = new(); @@ -140,6 +227,35 @@ internal static class Program { } } + private static Command CreateCommand { + get { + Argument photoArgument = new("photo") { + Description = "Photo File" + }; + Argument formatArgument = new("format") { + Description = "Photo Format", + }; + formatArgument.CompletionSources.Add(_ => [ + new("gta5"), + new("rdr2")]); + Argument jpegArgument = new("jpeg") { + Description = "JPEG File", + }; + Argument titleArgument = new("title") { + Description = "Photo Title", + }; + Command createCommand = new("create", "Create Photo") { + photoArgument, formatArgument, jpegArgument, titleArgument + }; + createCommand.SetAction(result => Create( + result.GetRequiredValue(photoArgument), + result.GetRequiredValue(formatArgument), + result.GetRequiredValue(jpegArgument), + result.GetValue(titleArgument))); + return createCommand; + } + } + private static Command GetCommand { get { Argument photoArgument = new("photo") {