Skip to content

Commit cdb5794

Browse files
committed
Diffs prolly working? Needs testing
1 parent 298a8e4 commit cdb5794

4 files changed

Lines changed: 270 additions & 10 deletions

File tree

QuestAppVersionSwitcher/Assets/html/diff/diff.html

Lines changed: 115 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,400italic,700,700italic' rel='stylesheet' type='text/css'>
88
</head>
99
<body>
10-
<h1>Diff creation</h1>
11-
<h3>A interface for creating diff patches of your games. Make sure you have made backups in QAVS of the 2 versions you want to diff. Change app in the <a href="/">main ui</a></h3>
10+
<h1>Diffs</h1>
11+
<h4>A interface for creating diff patches of your games. Make sure you have made backups in QAVS of the 2 versions you want to diff. Change app in the <a href="/">main ui</a></h4>
12+
<br>
13+
<h2>Diff creation</h2>
1214
Create a diff from
1315
<select id="fromList">
1416
<option value="test">1.36</option>
@@ -19,11 +21,118 @@ <h3>A interface for creating diff patches of your games. Make sure you have made
1921
</select>
2022
<br>
2123
<button onclick="CreateDiff()">Create diff</button>
24+
<div id="diffProgress"></div>
25+
<br>
26+
<br>
27+
<h2>Backup creation</h2>
28+
Create a Backup and populate it with apk and obb from your pc for creating diffs
29+
<input type="text" id="backupName" placeholder="Backup name">
30+
<br>
31+
<button onclick="CreateBackup()">Create empty Backup</button>
32+
<br>
33+
<div id="createProgress"></div>
34+
<br>
35+
<br>
36+
Selected Backup: <select id="backupList">
37+
<option value="test">1.28</option>
38+
</select>
39+
<br>
40+
<br>
41+
42+
<button onclick="UploadFile()">Upload file to selected backup</button>
43+
<div id="progress"></div>
44+
<h4>Files</h4>
45+
<table id="files">
46+
<tr>
47+
<th>File</th>
48+
<th>Size</th>
49+
</tr>
50+
</table>
2251
<script>
2352
function CreateDiff() {
2453
var from = document.getElementById("fromList").value;
2554
var to = document.getElementById("toList").value;
26-
55+
document.getElementById("diffProgress").innerText = "Creating, please wait a few minutes..."
56+
fetch(`/api/diff/create?package=${config.currentApp}&sourceBackup=${from}&targetBackup=${to}`, {
57+
method: "POST"
58+
}).then(res => {
59+
if (res.status === 200) {
60+
document.getElementById("diffProgress").innerText = "Diff created!"
61+
}
62+
})
63+
}
64+
65+
document.getElementById("backupList").onchange = () => {
66+
LoadFiles()
67+
}
68+
69+
function LoadFiles() {
70+
var backupName = document.getElementById("backupList").value
71+
fetch(`/api/backup/files?package=${config.currentApp}&name=${backupName}`).then(res => {
72+
if (res.status === 200) {
73+
res.json().then(files => {
74+
var table = `
75+
<tr>
76+
<th>File</th>
77+
<th>Size</th>
78+
</tr>
79+
`
80+
files.forEach(f => {
81+
table += `<tr><td><a href="/api/backup/getfile?package=${config.currentApp}&name=${backupName}&file=${f.path}">${f.path}</a></td><td>${f.sizeString}</td></tr>`
82+
})
83+
document.getElementById("files").innerHTML = table
84+
})
85+
}
86+
})
87+
}
88+
89+
var progress = document.getElementById("progress")
90+
91+
function CreateBackup() {
92+
var name = document.getElementById("backupName").value
93+
fetch(`/api/backup/create?package=${config.currentApp}&name=${name}`, {
94+
method: "POST"
95+
}).then(res => {
96+
if (res.status === 200) {
97+
document.getElementById("createProgress").innerText = "Backup created!"
98+
PopulateBackups()
99+
}
100+
})
101+
}
102+
function UploadFile() {
103+
var input = document.createElement("input")
104+
input.setAttribute("type", "file")
105+
106+
input.onchange = function (e) {
107+
if (!this.files[0]) {
108+
return;
109+
}
110+
111+
var reader = new FileReader();
112+
var fileName = this.files[0].name
113+
progress.innerText = "Reading file, please wait..."
114+
reader.onloadend = function () {
115+
var xhr = new XMLHttpRequest()
116+
xhr.upload.addEventListener("progress", function(evt) {
117+
if (evt.lengthComputable) {
118+
var percentComplete = evt.loaded / evt.total;
119+
percentComplete = parseInt(percentComplete * 100);
120+
progress.innerText = percentComplete + "%"
121+
122+
if (percentComplete === 100) {
123+
progress.innerText = "File uploaded!"
124+
LoadFiles()
125+
}
126+
127+
}
128+
}, false);
129+
xhr.open("POST", `/api/backup/upload?package=${config.currentApp}&name=${document.getElementById("backupList").value}&file=${fileName}`)
130+
xhr.send(reader.result)
131+
}
132+
reader.readAsArrayBuffer(this.files[0]);
133+
}
134+
135+
input.click()
27136
}
28137

29138
var config = {};
@@ -38,12 +147,15 @@ <h3>A interface for creating diff patches of your games. Make sure you have made
38147
let names = backups.backups.map(b => b.backupName)
39148
let fromList = document.getElementById("fromList")
40149
let toList = document.getElementById("toList")
150+
let backupList = document.getElementById("backupList")
41151
fromList.innerHTML = ""
42152
toList.innerHTML = ""
153+
backupList.innerHTML = ""
43154
names.forEach(n => {
44155
let option = `<option value=${n}>${n}</option>`
45156
fromList.innerHTML += option
46157
toList.innerHTML += option
158+
backupList.innerHTML += option
47159
})
48160
}))
49161
}))

QuestAppVersionSwitcher/DiffDowngrading/DiffCreator.cs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System.Collections.Generic;
22
using System.IO;
3+
using System.Linq;
34
using System.Text.Json;
5+
using ComputerUtils.Android.FileManaging;
46
using ComputerUtils.Android.Logging;
57
using QuestAppVersionSwitcher.Core;
68
using xdelta3.net;
@@ -16,25 +18,38 @@ public static DiffDowngradeEntry CreateDiff(string appId, string sourceBackup, s
1618
if (!sourceBackup.EndsWith(Path.DirectorySeparatorChar)) sourceBackup += Path.DirectorySeparatorChar;
1719
if (!targetBackup.EndsWith(Path.DirectorySeparatorChar)) targetBackup += Path.DirectorySeparatorChar;
1820
if (!outputDir.EndsWith(Path.DirectorySeparatorChar)) outputDir += Path.DirectorySeparatorChar;
21+
FileManager.CreateDirectoryIfNotExisting(outputDir);
1922

2023
Logger.Log("Creating diff");
21-
baseEntry.SV = BackupManager.GetBackupInfo(sourceBackup).gameVersion;
22-
baseEntry.TV = BackupManager.GetBackupInfo(targetBackup).gameVersion;
24+
baseEntry.SV = BackupManager.GetBackupInfo(sourceBackup, true).gameVersion;
25+
baseEntry.TV = BackupManager.GetBackupInfo(targetBackup, true).gameVersion;
2326
baseEntry.isXDelta3 = true;
2427

2528
// Create entries
2629
baseEntry.Set(CreateDiffOfFile(baseEntry, sourceBackup + "app.apk", targetBackup + "app.apk", outputDir));
2730
// add obbs and other files
28-
string[] sourceDirFiles = Directory.GetFiles(sourceBackup + "/obb/" + appId + "/");
29-
string[] targetDirFiles = Directory.GetFiles(targetBackup + "/obb/" + appId + "/");
30-
for(int i = 0; i < targetDirFiles.Length; i++)
31+
List<string> allSourceFiles = new List<string>();
32+
List<string> allTargetFiles = new List<string>();
33+
if (Directory.Exists(sourceBackup + "/obb/" + appId))
34+
{
35+
allSourceFiles = Directory.GetFiles(sourceBackup + "/obb/" + appId + "/").ToList();
36+
allSourceFiles.Insert(0, sourceBackup + "app.apk");
37+
}
38+
if (Directory.Exists(targetBackup + "/obb/" + appId))
39+
{
40+
allTargetFiles = Directory.GetFiles(targetBackup + "/obb/" + appId + "/").ToList();
41+
allTargetFiles.Insert(0, targetBackup + "app.apk");
42+
}
43+
for(int i = 1; i < allTargetFiles.Count; i++)
3144
{
3245
// generate one diff for every target backup obbs
33-
baseEntry.otherFiles.Add(CreateDiffOfFile(baseEntry, sourceDirFiles[i % sourceDirFiles.Length], targetDirFiles[i], outputDir));
46+
baseEntry.otherFiles.Add(CreateDiffOfFile(baseEntry, allSourceFiles[i % allSourceFiles.Count], allTargetFiles[i], outputDir));
3447
}
3548

3649
// The diff file is now created
50+
Logger.Log("Writing version.json file");
3751
File.WriteAllText(outputDir + "version.json", JsonSerializer.Serialize(baseEntry));
52+
Logger.Log("Finished creating diff");
3853
return baseEntry;
3954
}
4055

QuestAppVersionSwitcher/DiffDowngrading/DiffDowngradeEntry.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public string diffFilename
3636
}
3737

3838
public string outputFilename { get; set; } = "";
39-
public FileDiffDowngradeEntryType type = FileDiffDowngradeEntryType.Apk;
39+
public FileDiffDowngradeEntryType type { get; set; } = FileDiffDowngradeEntryType.Apk;
4040
public bool isXDelta3 { get; set; } = false;
4141
public long TargetByteSize { get; set; } = 0;
4242
public long DiffByteSize { get; set; } = 0;
@@ -50,6 +50,7 @@ public string diffFilename
5050
public void Set(FileDiffDowngradeEntry e)
5151
{
5252
this.sourceFilename = e.sourceFilename;
53+
this.diffFilename = e.diffFilename;
5354
this.outputFilename = e.outputFilename;
5455
this.type = e.type;
5556
this.isXDelta3 = e.isXDelta3;

QuestAppVersionSwitcher/WebServer.cs

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,137 @@ public void Start()
163163
clients.Remove(socket);
164164
};
165165
wsServer.StartServer(CoreService.coreVars.wsPort);
166+
server.AddRoute("POST", "/api/diff/create", request =>
167+
{
168+
if (request.queryString.Get("package") == null)
169+
{
170+
request.SendString(GenericResponse.GetResponse("package key needed", false), "application/json", 400);
171+
return true;
172+
}
173+
string package = request.queryString.Get("package");
174+
if (request.queryString.Get("sourceBackup") == null)
175+
{
176+
request.SendString(GenericResponse.GetResponse("sourceBackup key needed", false), "application/json", 400);
177+
return true;
178+
}
179+
string sourceBackup = CoreService.coreVars.QAVSBackupDir + package + Path.DirectorySeparatorChar + request.queryString.Get("sourceBackup") + Path.DirectorySeparatorChar;
180+
if (request.queryString.Get("targetBackup") == null)
181+
{
182+
request.SendString(GenericResponse.GetResponse("targetBackup key needed", false), "application/json", 400);
183+
return true;
184+
}
185+
string targetBackup = CoreService.coreVars.QAVSBackupDir + package + Path.DirectorySeparatorChar + request.queryString.Get("targetBackup") + Path.DirectorySeparatorChar;
186+
string outputDir = targetBackup + "diffs" + Path.DirectorySeparatorChar + request.queryString.Get("sourceBackup") +
187+
Path.DirectorySeparatorChar + DateTime.Now.Ticks + Path.DirectorySeparatorChar;
188+
DiffCreator.CreateDiff(package, sourceBackup, targetBackup, outputDir);
189+
request.SendString(GenericResponse.GetResponse("Created diff", true), "application/json");
190+
return true;
191+
});
192+
server.AddRoute("GET", "/api/backup/files", request =>
193+
{
194+
195+
if (request.queryString.Get("package") == null)
196+
{
197+
request.SendString(GenericResponse.GetResponse("package key needed", false), "application/json", 400);
198+
return true;
199+
}
200+
string package = request.queryString.Get("package");
201+
if (request.queryString.Get("name") == null)
202+
{
203+
request.SendString(GenericResponse.GetResponse("name key needed", false), "application/json", 400);
204+
return true;
205+
}
206+
string name = request.queryString.Get("name");
207+
string directory = CoreService.coreVars.QAVSBackupDir + package + "/" + name + "/";
208+
if (!Directory.Exists(directory))
209+
{
210+
request.SendString(GenericResponse.GetResponse("Backup does not exist", false), "application/json", 404);
211+
return true;
212+
}
213+
// get all files recursively
214+
request.SendString(JsonSerializer.Serialize(FileManager.GetAllFilesRecursively(directory)), "application/json");
215+
return true;
216+
});
217+
server.AddRoute("GET", "/api/backup/getfile", request =>
218+
{
219+
if (request.queryString.Get("package") == null)
220+
{
221+
request.SendString(GenericResponse.GetResponse("package key needed", false), "application/json", 400);
222+
return true;
223+
}
224+
string package = request.queryString.Get("package");
225+
if (request.queryString.Get("name") == null)
226+
{
227+
request.SendString(GenericResponse.GetResponse("name key needed", false), "application/json", 400);
228+
return true;
229+
}
230+
string name = request.queryString.Get("name");
231+
if (request.queryString.Get("file") == null)
232+
{
233+
request.SendString(GenericResponse.GetResponse("file key needed", false), "application/json", 400);
234+
return true;
235+
}
236+
string file = request.queryString.Get("file");
237+
string directory = CoreService.coreVars.QAVSBackupDir + package + "/" + name + "/";
238+
string createdFile = directory + file;
239+
if (!File.Exists(createdFile))
240+
{
241+
request.Send404();
242+
return true;
243+
}
244+
request.SendFileFS(createdFile, "application/octet-stream", 200, true, new Dictionary<string, string> {{"Content-Disposition", "attachment; filename=\"" + Path.GetFileName(file) + "\""}});
245+
return true;
246+
});
247+
server.AddRouteStreamOnly("POST", "/api/backup/upload", request =>
248+
{
249+
250+
if (request.queryString.Get("package") == null)
251+
{
252+
request.SendString(GenericResponse.GetResponse("package key needed", false), "application/json", 400);
253+
return true;
254+
}
255+
string package = request.queryString.Get("package");
256+
if (request.queryString.Get("name") == null)
257+
{
258+
request.SendString(GenericResponse.GetResponse("name key needed", false), "application/json", 400);
259+
return true;
260+
}
261+
string name = request.queryString.Get("name");
262+
if (request.queryString.Get("file") == null)
263+
{
264+
request.SendString(GenericResponse.GetResponse("file key needed", false), "application/json", 400);
265+
return true;
266+
}
267+
string file = request.queryString.Get("file");
268+
string directory = CoreService.coreVars.QAVSBackupDir + package + "/" + name + "/";
269+
string createdFile = directory + (file.ToLower().EndsWith(".apk") ? "app.apk" : "obb/" + package + "/" + file);
270+
FileManager.CreateDirectoryIfNotExisting(FileManager.GetParentDirIfExisting(createdFile));
271+
Stream fileStream = File.Create(createdFile);
272+
request.context.Request.InputStream.CopyTo(fileStream);
273+
fileStream.Close();
274+
request.SendString(GenericResponse.GetResponse("Created file at " + createdFile, true), "application/json");
275+
return true;
276+
});
277+
server.AddRoute("POST", "/api/backup/create", request =>
278+
{
279+
280+
if (request.queryString.Get("package") == null)
281+
{
282+
request.SendString(GenericResponse.GetResponse("package key needed", false), "application/json", 400);
283+
return true;
284+
}
285+
string package = request.queryString.Get("package");
286+
if (request.queryString.Get("name") == null)
287+
{
288+
request.SendString(GenericResponse.GetResponse("name key needed", false), "application/json", 400);
289+
return true;
290+
}
291+
string name = request.queryString.Get("name");
292+
string directory = CoreService.coreVars.QAVSBackupDir + package + "/" + name;
293+
Directory.CreateDirectory(directory);
294+
request.SendString(GenericResponse.GetResponse("Created backup", true), "application/json");
295+
return true;
296+
});
166297
server.AddRoute("GET", "/api/downgrade/usediff", request =>
167298
{
168299
request.SendString(UseDiffResponse.GetResponse(CoreService.coreVars.useDiffDowngrading || CoreService.coreVars.onlineDowngradeJson.useDiffDowngrade, true), "application/json");
@@ -564,6 +695,7 @@ public void Start()
564695
});
565696

566697
server.AddRouteFile("/", "html/index.html");
698+
server.AddRouteFile("/diff", "html/diff/diff.html");
567699
server.AddRouteFile("/scotlandforever.mp3", "html/scotlandforever.mp3");
568700
server.AddRouteFile("/setup", "html/setup.html");
569701
server.AddRouteFile("/flows/beat_saber_modding", "html/flows/beat_saber_modding.html");

0 commit comments

Comments
 (0)