♻️ Move parsing and extracting into modules

This commit is contained in:
C-3PO 2018-06-22 16:14:40 +02:00
parent 2dae5f6c58
commit 62a877617b
Signed by: c3po
GPG key ID: 62993C4BB4D86F24
4 changed files with 57 additions and 25 deletions

View file

@ -1,29 +1,14 @@
import { TextDecoder } from 'util';
import extractFile from './ssn/extractFile';
import getPatchmanifest from './ssn/getPatchmanifest';
import getSolidpkg from './ssn/getSolidpkg';
import readSsnFile from './ssn/readSsnFile';
const Decoder = new TextDecoder('utf-8');
(async () => {
//----- PATCHMANIFEST -----
//.patchmanifest files contain a single XML file called "manifest.xml"
const patchmanifestBuffer = await getPatchmanifest('assets_swtor_de_de');
console.log(patchmanifestBuffer.byteLength, patchmanifestBuffer);
const patchmanifestFiles = readSsnFile(patchmanifestBuffer);
console.log(patchmanifestFiles);
const patchmanifestFile = extractFile(patchmanifestFiles[0], [new DataView(patchmanifestBuffer)]);
const patchmanifestXml = Decoder.decode(patchmanifestFile);
const patchmanifestXml = await getPatchmanifest('assets_swtor_de_de');
console.log(patchmanifestXml);
//----- SOLIDPKG -----
//.solidpkg files contain a single Bencode file called "metafile.solid"
const solidpkgBuffer = await getSolidpkg('assets_swtor_de_de', -1, 0);
console.log(solidpkgBuffer.byteLength, solidpkgBuffer);
const solidPkgFiles = readSsnFile(solidpkgBuffer);
console.log(solidPkgFiles);
const solidFile = await getSolidpkg('assets_swtor_de_de', -1, 0);
console.log(solidFile);
})();

View file

@ -41,7 +41,7 @@ class ByteReader {
/** Extracts the given file from the given DataView array and returns it as an ArrayBuffer.
* Will throw an error when end of final DataView is reached.
*/
export default function extractFile(file: ISsnFileEntry, dvArray: DataView[]): ArrayBuffer {
export default async function extractFile(file: ISsnFileEntry, dvArray: DataView[]): Promise<ArrayBuffer> {
//use ByteReader for reading a uint8 and seeking forward across DataView boundaries
const byteReader = new ByteReader(dvArray, file.diskNumberStart, file.offset);
@ -61,6 +61,10 @@ export default function extractFile(file: ISsnFileEntry, dvArray: DataView[]): A
}
//uncompress file
const uncompressedBuffer = zlib.inflateRawSync(dvFinal);
const uncompressedBuffer: Buffer = await new Promise((resolve) => {
zlib.inflateRaw(dvFinal, (error, result) => {
resolve(result);
});
}) as Buffer;
return uncompressedBuffer.buffer as ArrayBuffer;
}

View file

@ -1,12 +1,36 @@
import { TextDecoder } from 'util';
import getUrlContents from '../getUrlContents';
import { Product } from '../interfaces/ISettings';
import verifyProductName from '../verifyProductName';
import extractFile from './extractFile';
import readSsnFile from './readSsnFile';
export default function getPatchmanifest(product: Product): Promise<ArrayBuffer> {
const Decoder = new TextDecoder('utf-8');
export default async function getPatchmanifest(product: Product): Promise<string> {
//Verify function arguments
if (!verifyProductName(product)) {
throw new Error(`"${product}" is not a valid product.`);
}
return getUrlContents({ host: 'manifest.swtor.com', path: `/patch/${product}.patchmanifest` });
//Download .patchmanifest file
const ssnFile = await getUrlContents({ host: 'manifest.swtor.com', path: `/patch/${product}.patchmanifest` });
//Parse .patchmanifest file
const fileEntries = readSsnFile(ssnFile);
if (fileEntries.length !== 1) {
throw new Error(`Expected .patchmanifest to contain 1 file but it had "${fileEntries.length}" files.`);
}
const firstFile = fileEntries[0];
if (firstFile.name !== 'manifest.xml') {
throw new Error(`Expected .patchmanifest to contain a file called manifest.xml but it is called "${firstFile.name}".`);
}
//Extract manifest.xml file
const patchmanifestFile = await extractFile(firstFile, [new DataView(ssnFile)]);
const patchmanifestXml = Decoder.decode(patchmanifestFile);
return patchmanifestXml;
}

View file

@ -1,13 +1,14 @@
import getUrlContents from '../getUrlContents';
import { Product } from '../interfaces/ISettings';
import verifyProductName from '../verifyProductName';
import extractFile from './extractFile';
import readSsnFile from './readSsnFile';
export default function getSolidpkg(product: Product, from: number, to: number): Promise<ArrayBuffer> {
export default async function getSolidpkg(product: Product, from: number, to: number): Promise<ArrayBuffer> {
//Verify function arguments
if (!verifyProductName(product)) {
throw new Error(`"${product}" is not a valid product.`);
}
if (typeof from !== 'number' || (from | 0) !== from || from < -1) {
throw new Error(`from must be an integer greater than or equal to -1 but it is "${from}"`);
}
@ -18,5 +19,23 @@ export default function getSolidpkg(product: Product, from: number, to: number):
throw new Error(`from must be less than to but "${from}" is not less than "${to}".`);
}
return getUrlContents({ host: 'cdn-patch.swtor.com', path: `/patch/${product}/${product}_${from}to${to}.solidpkg` });
//Download .solidpkg file
const ssnFile = await getUrlContents({ host: 'cdn-patch.swtor.com', path: `/patch/${product}/${product}_${from}to${to}.solidpkg` });
//Parse .solidpkg file
const fileEntries = readSsnFile(ssnFile);
if (fileEntries.length !== 1) {
throw new Error(`Expected .solidpkg to contain 1 file but it had "${fileEntries.length}" files.`);
}
const firstFile = fileEntries[0];
if (firstFile.name !== 'metafile.solid') {
throw new Error(`Expected .solidpkg to contain a file called metafile.solid but it is called "${firstFile.name}".`);
}
//Extract metafile.solid file
const solidFile = await extractFile(firstFile, [new DataView(ssnFile)]);
return solidFile;
}