From 7b463ab250f049d36bdd9a4fcbe66fbdace2fc2d Mon Sep 17 00:00:00 2001 From: Bill Date: Mon, 22 Feb 2021 00:39:02 -0500 Subject: [PATCH] Add external texts converter --- package.json | 4 +- src/Main.ts | 59 +++-------- src/common/converters/Converter.ts | 9 +- src/common/converters/IConverter.ts | 4 + src/configuration.json.example | 3 +- src/converters/effect/EffectConverter.ts | 2 + .../effectmap/EffectMapConverter.ts | 2 + .../externaltexts/ExternalTextsConverter.ts | 97 +++++++++++++++++++ .../externaltexts/ExternalTextsDownloader.ts | 32 ++++++ src/converters/figure/FigureConverter.ts | 2 + .../figuremap/FigureMapConverter.ts | 2 + .../furniture/FurnitureConverter.ts | 2 + .../furnituredata/FurnitureDataConverter.ts | 2 + src/converters/pet/PetConverter.ts | 2 + .../productdata/ProductDataConverter.ts | 2 + .../json/externaltexts/IExternalTexts.ts | 4 + src/mapping/json/externaltexts/index.ts | 1 + src/mapping/json/index.ts | 1 + 18 files changed, 182 insertions(+), 48 deletions(-) create mode 100644 src/common/converters/IConverter.ts create mode 100644 src/converters/externaltexts/ExternalTextsConverter.ts create mode 100644 src/converters/externaltexts/ExternalTextsDownloader.ts create mode 100644 src/mapping/json/externaltexts/IExternalTexts.ts create mode 100644 src/mapping/json/externaltexts/index.ts diff --git a/package.json b/package.json index 3211635..2f40964 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { - "name": "nitroassetconverter", + "name": "nitro-converter", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { - "start:dev": "ts-node-dev --respawn --transpile-only src/Main.ts" + "start:dev": "ts-node-dev --respawn --transpile-only src/main.ts" }, "author": "", "license": "ISC", diff --git a/src/Main.ts b/src/Main.ts index 265c991..ed731fe 100644 --- a/src/Main.ts +++ b/src/Main.ts @@ -1,8 +1,10 @@ import 'reflect-metadata'; import { container } from 'tsyringe'; import { Configuration } from './common/config/Configuration'; +import { IConverter } from './common/converters/IConverter'; import { EffectConverter } from './converters/effect/EffectConverter'; import { EffectMapConverter } from './converters/effectmap/EffectMapConverter'; +import { ExternalTextsConverter } from './converters/externaltexts/ExternalTextsConverter'; import { FigureConverter } from './converters/figure/FigureConverter'; import { FigureMapConverter } from './converters/figuremap/FigureMapConverter'; import { FurnitureConverter } from './converters/furniture/FurnitureConverter'; @@ -15,51 +17,22 @@ import { ProductDataConverter } from './converters/productdata/ProductDataConver const config = container.resolve(Configuration); await config.init(); - if(config.getBoolean('convert.figuremap')) - { - const figureMapConverter = container.resolve(FigureMapConverter); - await figureMapConverter.convertAsync(); - } + const converters = [ + FigureMapConverter, + EffectMapConverter, + FurnitureDataConverter, + ProductDataConverter, + ExternalTextsConverter, + FigureConverter, + EffectConverter, + FurnitureConverter, + PetConverter + ]; - if(config.getBoolean('convert.effectmap')) + for(const converterClass of converters) { - const effectMapConverter = container.resolve(EffectMapConverter); - await effectMapConverter.convertAsync(); - } + const converter = (container.resolve(converterClass) as IConverter); - if(config.getBoolean('convert.furnidata')) - { - const furniDataConverter = container.resolve(FurnitureDataConverter); - await furniDataConverter.convertAsync(); - } - - if(config.getBoolean('convert.productdata')) - { - const productDataConverter = container.resolve(ProductDataConverter); - await productDataConverter.convertAsync(); - } - - if(config.getBoolean('convert.figure')) - { - const figureConverter = container.resolve(FigureConverter); - await figureConverter.convertAsync(); - } - - if(config.getBoolean('convert.effect')) - { - const effectConverter = container.resolve(EffectConverter); - await effectConverter.convertAsync(); - } - - if(config.getBoolean('convert.furniture')) - { - const furnitureConverter = container.resolve(FurnitureConverter); - await furnitureConverter.convertAsync(); - } - - if(config.getBoolean('convert.pet')) - { - const petConverter = container.resolve(PetConverter); - await petConverter.convertAsync(); + await converter.convertAsync(); } })(); diff --git a/src/common/converters/Converter.ts b/src/common/converters/Converter.ts index 41245b6..766be8c 100644 --- a/src/common/converters/Converter.ts +++ b/src/common/converters/Converter.ts @@ -1,4 +1,9 @@ -export class Converter -{ +import { IConverter } from './IConverter'; +export class Converter implements IConverter +{ + public async convertAsync(): Promise + { + return; + } } diff --git a/src/common/converters/IConverter.ts b/src/common/converters/IConverter.ts new file mode 100644 index 0000000..7375373 --- /dev/null +++ b/src/common/converters/IConverter.ts @@ -0,0 +1,4 @@ +export interface IConverter +{ + convertAsync(): Promise; +} diff --git a/src/configuration.json.example b/src/configuration.json.example index 067e69a..c269bf4 100644 --- a/src/configuration.json.example +++ b/src/configuration.json.example @@ -11,7 +11,8 @@ "flash.dynamic.download.url": "", "dynamic.download.furniture.url": "${flash.dynamic.download.url}%revision%/%className%.swf", "external.variables.url": "https://www.habbo.com/gamedata/external_variables/1", - "convert.furnidata": "1", + "external.texts.url": "${external.texts.txt}", + "convert.furnituredata": "1", "convert.productdata": "1", "convert.figuremap": "1", "convert.effectmap": "1", diff --git a/src/converters/effect/EffectConverter.ts b/src/converters/effect/EffectConverter.ts index 37ea378..a916147 100644 --- a/src/converters/effect/EffectConverter.ts +++ b/src/converters/effect/EffectConverter.ts @@ -24,6 +24,8 @@ export class EffectConverter extends SWFConverter public async convertAsync(): Promise { + if(!this._configuration.getBoolean('convert.effect')) return; + const now = Date.now(); const spinner = ora('Preparing Effects').start(); diff --git a/src/converters/effectmap/EffectMapConverter.ts b/src/converters/effectmap/EffectMapConverter.ts index 1218419..629fa79 100644 --- a/src/converters/effectmap/EffectMapConverter.ts +++ b/src/converters/effectmap/EffectMapConverter.ts @@ -23,6 +23,8 @@ export class EffectMapConverter extends Converter public async convertAsync(): Promise { + if(!this._configuration.getBoolean('convert.effectmap')) return; + const now = Date.now(); const spinner = ora('Preparing EffectMap').start(); diff --git a/src/converters/externaltexts/ExternalTextsConverter.ts b/src/converters/externaltexts/ExternalTextsConverter.ts new file mode 100644 index 0000000..c5983e6 --- /dev/null +++ b/src/converters/externaltexts/ExternalTextsConverter.ts @@ -0,0 +1,97 @@ +import { writeFile } from 'fs/promises'; +import * as ora from 'ora'; +import { singleton } from 'tsyringe'; +import { Configuration } from '../../common/config/Configuration'; +import { Converter } from '../../common/converters/Converter'; +import { IExternalTexts } from '../../mapping/json'; +import File from '../../utils/File'; +import { Logger } from '../../utils/Logger'; +import { ExternalTextsDownloader } from './ExternalTextsDownloader'; + +@singleton() +export class ExternalTextsConverter extends Converter +{ + constructor( + private readonly _externalTextsDownloader: ExternalTextsDownloader, + private readonly _configuration: Configuration, + private readonly _logger: Logger) + { + super(); + } + + public async convertAsync(): Promise + { + if(!this._configuration.getBoolean('convert.externaltexts')) return; + + const now = Date.now(); + + const spinner = ora('Preparing ExternalTexts').start(); + + const directory = this.getDirectory(); + + try + { + await this._externalTextsDownloader.download(async (content: string) => + { + spinner.text = 'Parsing ExternalTexts'; + + spinner.render(); + + let externalTextsString = content; + + if(!externalTextsString.startsWith('{')) + { + const externalTexts = await this.mapText2JSON(externalTextsString); + + externalTextsString = JSON.stringify(externalTexts); + } + + const path = directory.path + '/ExternalTexts.json'; + + await writeFile(path, externalTextsString, 'utf8'); + }); + + spinner.succeed(`ExternalTexts finished in ${ Date.now() - now }ms`); + } + + catch (error) + { + spinner.fail('ExternalTexts failed: ' + error.message); + } + } + + private getDirectory(): File + { + const baseFolder = new File(this._configuration.getValue('output.folder')); + + if(!baseFolder.isDirectory()) baseFolder.mkdirs(); + + const gameDataFolder = new File(baseFolder.path + '/gamedata'); + + if(!gameDataFolder.isDirectory()) gameDataFolder.mkdirs(); + + const jsonFolder = new File(gameDataFolder.path + '/json'); + + if(!jsonFolder.isDirectory()) jsonFolder.mkdirs(); + + return jsonFolder; + } + + private async mapText2JSON(text: string): Promise + { + if(!text) return null; + + const output: IExternalTexts = {}; + + const parts = text.split(/\n\r{1,}|\n{1,}|\r{1,}/mg); + + for(const part of parts) + { + const [ key, value ] = part.split('='); + + output[key] = value; + } + + return output; + } +} diff --git a/src/converters/externaltexts/ExternalTextsDownloader.ts b/src/converters/externaltexts/ExternalTextsDownloader.ts new file mode 100644 index 0000000..709dbb2 --- /dev/null +++ b/src/converters/externaltexts/ExternalTextsDownloader.ts @@ -0,0 +1,32 @@ +import { singleton } from 'tsyringe'; +import { Configuration } from '../../common/config/Configuration'; +import { FileUtilities } from '../../utils/FileUtilities'; + +@singleton() +export class ExternalTextsDownloader +{ + constructor(private readonly _configuration: Configuration) + {} + + public async download(callback: (content: string) => Promise): Promise + { + const productData = await this.parseExternalTexts(); + + if(!productData) throw new Error('invalid_external_texts'); + + callback(productData); + } + + public async parseExternalTexts(): Promise + { + const url = this._configuration.getValue('external.texts.url'); + + if(!url || !url.length) return null; + + const content = await FileUtilities.readFileAsString(url); + + if(!content || !content.length) return null; + + return content; + } +} diff --git a/src/converters/figure/FigureConverter.ts b/src/converters/figure/FigureConverter.ts index bdd0c0e..2cda8b2 100644 --- a/src/converters/figure/FigureConverter.ts +++ b/src/converters/figure/FigureConverter.ts @@ -24,6 +24,8 @@ export class FigureConverter extends SWFConverter public async convertAsync(): Promise { + if(!this._configuration.getBoolean('convert.figure')) return; + const now = Date.now(); const spinner = ora('Preparing Figure').start(); diff --git a/src/converters/figuremap/FigureMapConverter.ts b/src/converters/figuremap/FigureMapConverter.ts index 14a5fc2..4234475 100644 --- a/src/converters/figuremap/FigureMapConverter.ts +++ b/src/converters/figuremap/FigureMapConverter.ts @@ -23,6 +23,8 @@ export class FigureMapConverter extends Converter public async convertAsync(): Promise { + if(!this._configuration.getBoolean('convert.figuremap')) return; + const now = Date.now(); const spinner = ora('Preparing FigureMap').start(); diff --git a/src/converters/furniture/FurnitureConverter.ts b/src/converters/furniture/FurnitureConverter.ts index e6808f3..1ee9647 100644 --- a/src/converters/furniture/FurnitureConverter.ts +++ b/src/converters/furniture/FurnitureConverter.ts @@ -24,6 +24,8 @@ export class FurnitureConverter extends SWFConverter public async convertAsync(): Promise { + if(!this._configuration.getBoolean('convert.furniture')) return; + const now = Date.now(); const spinner = ora('Preparing Furniture').start(); diff --git a/src/converters/furnituredata/FurnitureDataConverter.ts b/src/converters/furnituredata/FurnitureDataConverter.ts index 178f352..d142134 100644 --- a/src/converters/furnituredata/FurnitureDataConverter.ts +++ b/src/converters/furnituredata/FurnitureDataConverter.ts @@ -23,6 +23,8 @@ export class FurnitureDataConverter extends Converter public async convertAsync(): Promise { + if(!this._configuration.getBoolean('convert.furnituredata')) return; + const now = Date.now(); const spinner = ora('Preparing FurnitureData').start(); diff --git a/src/converters/pet/PetConverter.ts b/src/converters/pet/PetConverter.ts index ae41aa0..4bdbfd8 100644 --- a/src/converters/pet/PetConverter.ts +++ b/src/converters/pet/PetConverter.ts @@ -24,6 +24,8 @@ export class PetConverter extends SWFConverter public async convertAsync(): Promise { + if(!this._configuration.getBoolean('convert.pet')) return; + const now = Date.now(); const spinner = ora('Preparing Pets').start(); diff --git a/src/converters/productdata/ProductDataConverter.ts b/src/converters/productdata/ProductDataConverter.ts index 8a4a8f5..4d8938c 100644 --- a/src/converters/productdata/ProductDataConverter.ts +++ b/src/converters/productdata/ProductDataConverter.ts @@ -21,6 +21,8 @@ export class ProductDataConverter extends Converter public async convertAsync(): Promise { + if(!this._configuration.getBoolean('convert.productdata')) return; + const now = Date.now(); const spinner = ora('Preparing ProductData').start(); diff --git a/src/mapping/json/externaltexts/IExternalTexts.ts b/src/mapping/json/externaltexts/IExternalTexts.ts new file mode 100644 index 0000000..2c954f9 --- /dev/null +++ b/src/mapping/json/externaltexts/IExternalTexts.ts @@ -0,0 +1,4 @@ +export interface IExternalTexts +{ + [index: string]: string +} diff --git a/src/mapping/json/externaltexts/index.ts b/src/mapping/json/externaltexts/index.ts new file mode 100644 index 0000000..f5eca28 --- /dev/null +++ b/src/mapping/json/externaltexts/index.ts @@ -0,0 +1 @@ +export * from './IExternalTexts'; diff --git a/src/mapping/json/index.ts b/src/mapping/json/index.ts index ac7848f..f23311b 100644 --- a/src/mapping/json/index.ts +++ b/src/mapping/json/index.ts @@ -1,5 +1,6 @@ export * from './asset'; export * from './effectmap'; +export * from './externaltexts'; export * from './figuremap'; export * from './furnituredata'; export * from './productdata';