mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-19 06:43:51 +02:00
Add support for prints
This commit is contained in:
@@ -4,6 +4,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NLog;
|
||||
@@ -172,6 +173,18 @@ namespace VRCX
|
||||
// If not JSON metadata, return early so we're not throwing/catching pointless exceptions
|
||||
if (!metadataString.StartsWith("{"))
|
||||
{
|
||||
// parse VRC prints
|
||||
var xmlIndex = metadataString.IndexOf("<x:xmpmeta");
|
||||
if (xmlIndex != -1)
|
||||
{
|
||||
var xmlString = metadataString.Substring(xmlIndex);
|
||||
// everything after index
|
||||
var result = ParseVRCPrint(xmlString.Substring(xmlIndex - 7));
|
||||
result.SourceFile = path;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
logger.ConditionalDebug("Screenshot file '{0}' has unknown non-JSON metadata:\n{1}\n", path, metadataString);
|
||||
return ScreenshotMetadata.JustError(path, "File has unknown non-JSON metadata.");
|
||||
}
|
||||
@@ -193,6 +206,44 @@ namespace VRCX
|
||||
return ScreenshotMetadata.JustError(path, "Failed to parse screenshot metadata JSON. Check logs.");
|
||||
}
|
||||
}
|
||||
|
||||
public static ScreenshotMetadata ParseVRCPrint(string xmlString)
|
||||
{
|
||||
var doc = new XmlDocument();
|
||||
doc.LoadXml(xmlString);
|
||||
var root = doc.DocumentElement;
|
||||
var nsManager = new XmlNamespaceManager(doc.NameTable);
|
||||
nsManager.AddNamespace("x", "adobe:ns:meta/");
|
||||
nsManager.AddNamespace("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
|
||||
nsManager.AddNamespace("xmp", "http://ns.adobe.com/xap/1.0/");
|
||||
nsManager.AddNamespace("tiff", "http://ns.adobe.com/tiff/1.0/");
|
||||
nsManager.AddNamespace("dc", "http://purl.org/dc/elements/1.1/");
|
||||
nsManager.AddNamespace("vrc", "http://ns.vrchat.com/vrc/1.0/");
|
||||
var creatorTool = root.SelectSingleNode("//xmp:CreatorTool", nsManager)?.InnerText;
|
||||
var authorId = root.SelectSingleNode("//xmp:Author", nsManager)?.InnerText;
|
||||
var dateTime = root.SelectSingleNode("//tiff:DateTime", nsManager)?.InnerText;
|
||||
var note = root.SelectSingleNode("//dc:title/rdf:Alt/rdf:li", nsManager)?.InnerText;
|
||||
var worldId = root.SelectSingleNode("//vrc:World", nsManager)?.InnerText;
|
||||
|
||||
return new ScreenshotMetadata
|
||||
{
|
||||
Application = creatorTool,
|
||||
Version = 1,
|
||||
Author = new ScreenshotMetadata.AuthorDetail
|
||||
{
|
||||
Id = authorId,
|
||||
DisplayName = null
|
||||
},
|
||||
World = new ScreenshotMetadata.WorldDetail
|
||||
{
|
||||
Id = worldId,
|
||||
InstanceId = worldId,
|
||||
Name = null
|
||||
},
|
||||
Timestamp = DateTime.TryParse(dateTime, out var dt) ? dt : null,
|
||||
Note = note
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a text description into a PNG file at the specified path.
|
||||
|
||||
@@ -44,6 +44,13 @@ namespace VRCX
|
||||
/// </summary>
|
||||
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||
public Vector3? Pos { get; set; }
|
||||
|
||||
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||
public DateTime? Timestamp { get; set; }
|
||||
|
||||
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string? Note { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Any error that occurred while parsing the file. This being true implies nothing else is set.
|
||||
|
||||
@@ -256,7 +256,6 @@ namespace VRCX
|
||||
if (options.TryGetValue("postData", out object postDataObject))
|
||||
{
|
||||
var jsonPostData = (JObject)JsonConvert.DeserializeObject((string)postDataObject);
|
||||
Dictionary<string, string> postData = new Dictionary<string, string>();
|
||||
string formDataTemplate = "--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}\r\n";
|
||||
if (jsonPostData != null)
|
||||
{
|
||||
@@ -294,6 +293,65 @@ namespace VRCX
|
||||
await requestStream.WriteAsync(endBytes, 0, endBytes.Length);
|
||||
requestStream.Close();
|
||||
}
|
||||
|
||||
private static async Task PrintImageUpload(HttpWebRequest request, IDictionary<string, object> options)
|
||||
{
|
||||
if (ProxySet)
|
||||
request.Proxy = Proxy;
|
||||
|
||||
request.AutomaticDecompression = DecompressionMethods.All;
|
||||
request.Method = "POST";
|
||||
var boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
|
||||
request.ContentType = "multipart/form-data; boundary=" + boundary;
|
||||
var requestStream = request.GetRequestStream();
|
||||
// var requestStream = new MemoryStream();
|
||||
var imageData = options["imageData"] as string;
|
||||
var fileToUpload = Convert.FromBase64String(imageData);
|
||||
const string fileFormKey = "image";
|
||||
const string fileName = "image";
|
||||
const string fileMimeType = "image/png";
|
||||
var fileSize = fileToUpload.Length;
|
||||
const string headerTemplate = "--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\"\r\nContent-Type: {3}\r\nContent-Length: {4}\r\n";
|
||||
var header = string.Format(headerTemplate, boundary, fileFormKey, fileName, fileMimeType, fileSize);
|
||||
var headerBytes = Encoding.UTF8.GetBytes(header);
|
||||
await requestStream.WriteAsync(headerBytes);
|
||||
using (var fileStream = new MemoryStream(fileToUpload))
|
||||
{
|
||||
var buffer = new byte[1024];
|
||||
int bytesRead;
|
||||
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
|
||||
{
|
||||
await requestStream.WriteAsync(buffer.AsMemory(0, bytesRead));
|
||||
}
|
||||
fileStream.Close();
|
||||
}
|
||||
var newlineBytes = Encoding.UTF8.GetBytes("\r\n");
|
||||
await requestStream.WriteAsync(newlineBytes);
|
||||
const string textContentType = "text/plain; charset=utf-8";
|
||||
const string formDataTemplate = "--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\nContent-Type: {2}\r\nContent-Length: {3}\r\n{4}\r\n";
|
||||
if (options.TryGetValue("postData", out var postDataObject))
|
||||
{
|
||||
var jsonPostData = JsonConvert.DeserializeObject<Dictionary<string, string>>(postDataObject.ToString());
|
||||
if (jsonPostData != null)
|
||||
{
|
||||
foreach (var (key, value) in jsonPostData)
|
||||
{
|
||||
var section = string.Format(formDataTemplate, boundary, key, textContentType, value.Length, value);
|
||||
var sectionBytes = Encoding.UTF8.GetBytes(section);
|
||||
await requestStream.WriteAsync(sectionBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
var endBytes = Encoding.UTF8.GetBytes("--" + boundary + "--");
|
||||
await requestStream.WriteAsync(endBytes);
|
||||
// test file
|
||||
// var newFileStream = new FileStream(@"D:\WindowsFiles\Desktop\test", FileMode.Create, FileAccess.Write);
|
||||
// requestStream.WriteTo(newFileStream);
|
||||
// newFileStream.Close();
|
||||
|
||||
requestStream.Close();
|
||||
// throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#pragma warning disable CS4014
|
||||
|
||||
@@ -364,6 +422,11 @@ namespace VRCX
|
||||
{
|
||||
await LegacyImageUpload(request, options);
|
||||
}
|
||||
|
||||
if (options.TryGetValue("uploadImagePrint", out _))
|
||||
{
|
||||
await PrintImageUpload(request, options);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user