localization
This commit is contained in:
parent
8f81d1fa44
commit
6c3bd958e4
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
.idea
|
15
index.html
15
index.html
@ -1,20 +1,17 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<script src="https://rawcdn.githack.com/Stuk/jszip/master/dist/jszip.js"></script>
|
<script src="jszip.min.js"></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
|
||||||
<script src="loader.js"></script>
|
<script src="loader.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h3>Patch sif file in the browser</h3>
|
<h3>SIF1服务器修补程序</h3>
|
||||||
<br>
|
<br>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Select input file:</legend>
|
服务器 URL:<input id="serverurl" type="text" value="https://sif.zhushenwudi.top" autocomplete="off"><br><br>
|
||||||
<p>If no file is selected, it will be downloaded automatically (recommended).</p>
|
|
||||||
<input type="file" id="sifgamefile">
|
|
||||||
<br><br>
|
|
||||||
Server URL: <input id="serverurl" type="text" value="http://localhost:51376" autocomplete="off"><br><br>
|
|
||||||
<input type="radio" id="apk" name="format" value="apk" onchange="clickstuff(event)" checked><label for="apk">Android</label>
|
<input type="radio" id="apk" name="format" value="apk" onchange="clickstuff(event)" checked><label for="apk">Android</label>
|
||||||
<input type="radio" id="ipa" name="format" value="ipa" onchange="clickstuff(event)"><label for="ipa">iOS</label>
|
<input type="radio" id="ipa" name="format" value="ipa" onchange="clickstuff(event)"><label for="ipa">iOS</label>
|
||||||
<div id="patches">
|
<div id="patches">
|
||||||
@ -23,7 +20,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<br><br><br>
|
<br><br><br>
|
||||||
<button onclick="load(event)">Patch</button>
|
<button onclick="load(event)">开始修补</button>
|
||||||
<script>
|
<script>
|
||||||
function clickstuff(e) {
|
function clickstuff(e) {
|
||||||
if (document.getElementById("apk").checked) {
|
if (document.getElementById("apk").checked) {
|
||||||
@ -47,7 +44,7 @@
|
|||||||
patches[i].checked = patch.ios ? document.getElementById(patch.id + "-ios").checked : false;
|
patches[i].checked = patch.ios ? document.getElementById(patch.id + "-ios").checked : false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
init_honoka(document.getElementById("sifgamefile").files[0], android, document.getElementById("serverurl").value, patches);
|
init_honoka(android, document.getElementById("serverurl").value, patches);
|
||||||
}
|
}
|
||||||
(async () => {
|
(async () => {
|
||||||
patches = JSON.parse(await (await fetch("patches.json")).text());
|
patches = JSON.parse(await (await fetch("patches.json")).text());
|
||||||
|
13
jszip.min.js
vendored
Normal file
13
jszip.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
65
loader.js
65
loader.js
@ -3,20 +3,43 @@ function update_status(status) {
|
|||||||
document.getElementById("status").innerText = status;
|
document.getElementById("status").innerText = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function patch(file, android, newDomain, patches) {
|
async function downloadFile(url) {
|
||||||
|
const response = await fetch(url);
|
||||||
|
const contentLength = response.headers.get('Content-Length');
|
||||||
|
const total = parseInt(contentLength, 10);
|
||||||
|
let loaded = 0;
|
||||||
|
|
||||||
|
const reader = response.body.getReader();
|
||||||
|
const chunks = [];
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
const { done, value } = await reader.read();
|
||||||
|
if (done) break;
|
||||||
|
|
||||||
|
chunks.push(value);
|
||||||
|
loaded += value.length;
|
||||||
|
|
||||||
|
// 计算并显示下载进度
|
||||||
|
const progress = (loaded / total) * 100;
|
||||||
|
update_status(`下载中... ${progress.toFixed(2)}%`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将所有块合并为一个 Blob
|
||||||
|
return new Blob(chunks);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function patch(android, newDomain, patches) {
|
||||||
if (newDomain.endsWith("/")) newDomain = newDomain.slice(0, -1);
|
if (newDomain.endsWith("/")) newDomain = newDomain.slice(0, -1);
|
||||||
|
|
||||||
if (!file) {
|
console.log("downloading");
|
||||||
console.log("downloading");
|
update_status("下载中...");
|
||||||
update_status("Downloading...");
|
let file = await downloadFile("https://file.zhushenwudi.top/pd/1/SIF_CLIENT/lovelive-community." + (android ? "apk" : "ipa"));
|
||||||
file = await (await fetch("https://ethanthesleepy.one/public/lovelive/sif/lovelive-community." + (android ? "apk" : "ipa"))).blob();
|
console.log("downloaded");
|
||||||
console.log("downloaded");
|
|
||||||
}
|
|
||||||
console.log("loaded");
|
console.log("loaded");
|
||||||
update_status("Opening file");
|
update_status("解压客户端...");
|
||||||
const zip = new JSZip();
|
const zip = new JSZip();
|
||||||
await zip.loadAsync(file);
|
await zip.loadAsync(file);
|
||||||
update_status("Getting current config");
|
update_status("获取当前配置...");
|
||||||
|
|
||||||
let basePath = android ? "" : "Payload/LoveLive.app/";
|
let basePath = android ? "" : "Payload/LoveLive.app/";
|
||||||
let server_file;
|
let server_file;
|
||||||
@ -51,21 +74,21 @@ async function patch(file, android, newDomain, patches) {
|
|||||||
|
|
||||||
//console.log(server_file);
|
//console.log(server_file);
|
||||||
FS.writeFile("/server_info.json", new Uint8Array(server_file));
|
FS.writeFile("/server_info.json", new Uint8Array(server_file));
|
||||||
update_status("Decrypting");
|
update_status("解密中...");
|
||||||
Module.callMain(["server_info.json"]);
|
Module.callMain(["server_info.json"]);
|
||||||
update_status("Patching domain");
|
update_status("修补地址中...");
|
||||||
const data = FS.readFile("/server_info.json", {encoding: 'utf8'});
|
const data = FS.readFile("/server_info.json", {encoding: 'utf8'});
|
||||||
const currentData = JSON.parse(data);
|
const currentData = JSON.parse(data);
|
||||||
const currentDomain = currentData.domain;
|
const currentDomain = currentData.domain;
|
||||||
const newData = data.split(currentDomain).join(newDomain);
|
const newData = data.split(currentDomain).join(newDomain);
|
||||||
FS.writeFile("/server_info.json", newData);
|
FS.writeFile("/server_info.json", newData);
|
||||||
update_status("Encrypting");
|
update_status("加密中...");
|
||||||
Module.callMain(["-e", "-j", "server_info.json"]);
|
Module.callMain(["-e", "-j", "server_info.json"]);
|
||||||
const new_server_info = FS.readFile("/server_info.json");
|
const new_server_info = FS.readFile("/server_info.json");
|
||||||
|
|
||||||
let type;
|
let type;
|
||||||
let ext;
|
let ext;
|
||||||
update_status("Applying changes");
|
update_status("打包中...");
|
||||||
if (android) {
|
if (android) {
|
||||||
let server_info = await zip.file("assets/AppAssets.zip").async("arraybuffer");
|
let server_info = await zip.file("assets/AppAssets.zip").async("arraybuffer");
|
||||||
const zip2 = new JSZip();
|
const zip2 = new JSZip();
|
||||||
@ -94,11 +117,11 @@ async function patch(file, android, newDomain, patches) {
|
|||||||
ext = "ipa";
|
ext = "ipa";
|
||||||
}
|
}
|
||||||
let finalized = await zip.generateAsync({type: "uint8array"});
|
let finalized = await zip.generateAsync({type: "uint8array"});
|
||||||
update_status("Finalizing");
|
update_status("请选择下载成果物");
|
||||||
const downloadUrl = URL.createObjectURL(new Blob([finalized], {type: type}));
|
const downloadUrl = URL.createObjectURL(new Blob([finalized], {type: type}));
|
||||||
const b = document.createElement("a");
|
const b = document.createElement("a");
|
||||||
b.href = URL.createObjectURL(new Blob([new_server_info], {type: "application/json"}))
|
b.href = URL.createObjectURL(new Blob([new_server_info], {type: "application/json"}))
|
||||||
b.innerText = "Download patched server_info.json (you probably dont need this)";
|
b.innerText = "修补文件:server_info.json(你可能不需要这个)";
|
||||||
b.download = "server_info.json";
|
b.download = "server_info.json";
|
||||||
document.body.appendChild(b);
|
document.body.appendChild(b);
|
||||||
|
|
||||||
@ -107,26 +130,26 @@ async function patch(file, android, newDomain, patches) {
|
|||||||
|
|
||||||
const a = document.createElement("a");
|
const a = document.createElement("a");
|
||||||
a.href = downloadUrl;
|
a.href = downloadUrl;
|
||||||
a.innerText = "Download";
|
a.innerText = "下载客户端";
|
||||||
a.download = "lovelive-patched."+ext;
|
a.download = "lovelive-patched."+ext;
|
||||||
document.body.appendChild(a);
|
document.body.appendChild(a);
|
||||||
update_status("Done!");
|
update_status("完成!");
|
||||||
if (android) {
|
if (android) {
|
||||||
const p = document.createElement("p");
|
const p = document.createElement("p");
|
||||||
p.innerHTML = "Package is not signed. Using <a href=\"https://github.com/patrickfav/uber-apk-signer/releases\">uber-apk-signer</a>, sign it with the command `java -jar uber-apk-signer-<version>.jar -a lovelive.apk`.";
|
p.innerHTML = "修补的安装包未签名,可以使用 <a href=\"https://github.com/patrickfav/uber-apk-signer/releases\">uber-apk-signer</a>, 使用如下命令 `java -jar uber-apk-signer-<version>.jar -a lovelive.apk` 进行签名.";
|
||||||
document.body.appendChild(p);
|
document.body.appendChild(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function init_honoka(file, android, newDomain, patches) {
|
function init_honoka(android, newDomain, patches) {
|
||||||
window.Module = {
|
window.Module = {
|
||||||
noInitialRun: true,
|
noInitialRun: true,
|
||||||
onRuntimeInitialized: async function() {
|
onRuntimeInitialized: async function() {
|
||||||
try {
|
try {
|
||||||
await patch(file, android, newDomain, patches);
|
await patch(android, newDomain, patches);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
console.warn(e);
|
console.warn(e);
|
||||||
document.getElementById("status").innerText = "It didnt work. Are your files/options invalid?";
|
document.getElementById("status").innerText = "失败。您的文件/选项无效吗?";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
arguments: [],
|
arguments: [],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user