diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..ef1410a --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,63 @@ +# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs + +name: Node.js CI +permissions: write-all +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + create-release: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Get version + run: echo "version=$(jq -r .version package.json)" >> $GITHUB_ENV + + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.github_token }} + with: + tag_name: ${{ env.version }} + release_name: release ${{ env.version }} + draft: false + prerelease: ${{ contains(env.version, 'beta') || contains(env.version, 'alpha') }} + + build-launcher: + needs: create-release + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: [macos-latest, ubuntu-latest, windows-latest] + + steps: + - name: Check out Git repository + uses: actions/checkout@v1 + + - name: Set up Node + uses: actions/setup-node@v3 + with: + node-version: 18.x + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: 3.x + + - name: Install Dependencies + run: npm ci + shell: bash + + - name: Build + env: + GH_TOKEN: ${{ secrets.github_token }} + run: npm run build + shell: bash diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..2408e1e --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,57 @@ +name: Launcher Build +on: + push: + branches: [ master ] + +jobs: + create-release: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Get version + run: echo "version=$(jq -r .version package.json)" >> $GITHUB_ENV + + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ env.version }} + release_name: release ${{ env.version }} + draft: false + prerelease: ${{ contains(env.version, 'beta') || contains(env.version, 'alpha') }} + + build-launcher: + needs: create-release + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: [macos-latest, ubuntu-latest, windows-latest] + + steps: + - name: Check out Git repository + uses: actions/checkout@v1 + + - name: Set up Node + uses: actions/setup-node@v3 + with: + node-version: 18.x + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: 3.x + + - name: Install Dependencies + run: npm ci + shell: bash + + - name: Build + env: + GH_TOKEN: ${{ secrets.github_token }} + run: npm run build + shell: bash diff --git a/LICENSE.MD b/LICENSE.MD new file mode 100644 index 0000000..76c8226 --- /dev/null +++ b/LICENSE.MD @@ -0,0 +1,21 @@ +EULA del Battly Launcher + +Este Contrato de Licencia del Usuario Final (EULA) es un acuerdo legal entre tu (Usuario) y TECNO BROS (Creador). Al usar el Battly Launcher (Software), aceptas los terminos de este EULA. + +1. Licencia de Uso +1.1. Se te otorga una licencia personal, no transferible y revocable para usar el Software y acceder a Minecraft. +1.2. Debes utilizar el Software de acuerdo con las leyes y las restricciones establecidas en este EULA. + +2. Restricciones +2.1. No podras copiar, modificar, distribuir, vender, alquilar, sublicenciar, descompilar, realizar ingenieria inversa o intentar obtener el codigo fuente del Software. +2.2. No podras utilizar el Software para actividades ilegales o que infrinjan los derechos de propiedad intelectual de terceros. +2.3. No podras utilizar el Software para difamar, acosar, amenazar o danar a otros usuarios. + +3. Propiedad Intelectual +3.1. El Software y todos los derechos de propiedad intelectual asociados son propiedad exclusiva de TECNO BROS. +3.2. Reconoces que no adquieres ningun derecho de propiedad sobre el Software, excepto la licencia limitada otorgada en este EULA. + +4. Garantia y Responsabilidad +4.1. El Software se proporciona "tal cual", sin garantias expresas o implicitas sobre su funcionamiento o idoneidad para un proposito especifico. +4.2. Utilizas el Software bajo tu propio riesgo y TECNO BROS no sera responsable por ningun dano que pueda surgir del uso del Software. +4.3. Nos reservamos el derecho de suspender o interrumpir el acceso al Software en cualquier momento y sin previo aviso. \ No newline at end of file diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..76c8226 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +EULA del Battly Launcher + +Este Contrato de Licencia del Usuario Final (EULA) es un acuerdo legal entre tu (Usuario) y TECNO BROS (Creador). Al usar el Battly Launcher (Software), aceptas los terminos de este EULA. + +1. Licencia de Uso +1.1. Se te otorga una licencia personal, no transferible y revocable para usar el Software y acceder a Minecraft. +1.2. Debes utilizar el Software de acuerdo con las leyes y las restricciones establecidas en este EULA. + +2. Restricciones +2.1. No podras copiar, modificar, distribuir, vender, alquilar, sublicenciar, descompilar, realizar ingenieria inversa o intentar obtener el codigo fuente del Software. +2.2. No podras utilizar el Software para actividades ilegales o que infrinjan los derechos de propiedad intelectual de terceros. +2.3. No podras utilizar el Software para difamar, acosar, amenazar o danar a otros usuarios. + +3. Propiedad Intelectual +3.1. El Software y todos los derechos de propiedad intelectual asociados son propiedad exclusiva de TECNO BROS. +3.2. Reconoces que no adquieres ningun derecho de propiedad sobre el Software, excepto la licencia limitada otorgada en este EULA. + +4. Garantia y Responsabilidad +4.1. El Software se proporciona "tal cual", sin garantias expresas o implicitas sobre su funcionamiento o idoneidad para un proposito especifico. +4.2. Utilizas el Software bajo tu propio riesgo y TECNO BROS no sera responsable por ningun dano que pueda surgir del uso del Software. +4.3. Nos reservamos el derecho de suspender o interrumpir el acceso al Software en cualquier momento y sin previo aviso. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..f68840f --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +# Battly Launcher [![Node.js CI](https://github.com/1ly4s0/battlylauncher/actions/workflows/build.yml/badge.svg)](https://github.com/1ly4s0/battlylauncher/actions/workflows/build.yml) + +![BattlyLauncher_Banner_Low](https://github.com/1ly4s0/battlylauncher/assets/67460389/2574bdeb-c8bb-47ac-b263-e4bd687494af) + + +Battly es un launcher de Minecraft para usuarios premium y no-premium para jugar a Minecraft totalmente gratis. + +La interfaz de usuario de Battly es simple y fácil de usar, lo que permite una experiencia de juego fluida y sin complicaciones. Además, Battly tiene todas las versiones de Minecraft disponibles hasta el momento, y también incluye Forge para todas las versiones de Minecraft, lo que te permite instalar tus mods favoritos con facilidad. + +No sólo eso, Battly también tiene configuraciones que te servirán para ajustar el uso de recursos del sistema, tales como ram, etc. + +También estará disponible para Windows, MAC y todas las distribuciones de Linux, tales como Debian o Ubuntu, absolutamente todos los sistemas operativos que hay actualmente. + + + + +## Sugerencias +Recordad que si tenéis alguna sugerencia para Battly me la podéis dejar aquí debajo en los comentarios, en el servidor de Discord o mandando un correo a sugerencias@battlylauncher.com + + + +## Descargas +Se puede descargar en la página oficial de Battly [aquí](https://battlylauncher.com/download) diff --git a/build.js b/build.js new file mode 100644 index 0000000..12104b2 --- /dev/null +++ b/build.js @@ -0,0 +1,126 @@ +const builder = require('electron-builder'); +const obfuscator = require('javascript-obfuscator'); +const fs = require('fs-extra'); +const path = require('path'); +const { productname } = require('./package.json'); + +// Función para obfuscar un archivo +async function obfuscateFile(filePath) { + try { + const code = await fs.readFile(filePath, 'utf-8'); + const obfuscatedCode = obfuscator.obfuscate(code, { /* opciones de obfuscator */ }).getObfuscatedCode(); + await fs.writeFile(filePath, obfuscatedCode); + console.log(`✅ Código obfuscado correctamente: ${filePath}`); + } catch (error) { + console.error(`Error al obfuscar el archivo ${filePath}`, error); + } +} + +// Función para obfuscar todos los archivos .js en el directorio src +async function obfuscateSrc() { + try { + const srcPath = './src'; + const files = await fs.readdir(srcPath); + + // Filtrar solo archivos .js + const jsFiles = files.filter(file => path.extname(file) === '.js'); + + // Obfuscar cada archivo .js + await Promise.all(jsFiles.map(file => obfuscateFile(path.join(srcPath, file)))); + } catch (error) { + console.error('Error al obfuscar el código', error); + } +} +// Ejecutar la obfuscación antes de construir +obfuscateSrc().then(() => { + + builder.build({ + config: { + publish: [ + { + provider: "github", + owner: "1ly4s0", + repo: "battlylauncher", + releaseType: "release" + } + ], + generateUpdatesFilesForAllChannels: true, + appId: productname, + productName: productname, + artifactName: '${productName}-${os}-${arch}.${ext}', + files: ["src/**/*", "package.json", "LICENSE.md"], + directories: { "output": "dist" }, + compression: 'maximum', + asar: false, + //asar unpack de 7zip-bin + asarUnpack: [ + "node_modules/7zip-bin/**/*", + "node_modules/7zip/**/*", + ], + win: { + icon: "./src/assets/images/icon.ico", + target: [{ + target: "nsis", + arch: ["x64", "ia32"] + }] + }, + nsis: { + oneClick: false, + allowToChangeInstallationDirectory: true, + createDesktopShortcut: true, + runAfterFinish: true, + installerLanguages: ['es'], + multiLanguageInstaller: true, + license: "./LICENSE.md", + }, + + mac: { + icon: "./src/assets/images/icon.icns", + category: "public.app-category.games", + target: [{ + target: "dmg", + arch: ["x64", "arm64"] + }] + }, + linux: { + icon: "./src/assets/images/icon.png", + target: [{ + target: "AppImage", + arch: ["x64"] + }, { + target: "tar.gz", + arch: ["x64"] + }, + { + target: "deb", + arch: ["x64"] + }, + { + target: "rpm", + arch: ["x64"] + }, + { + target: "AppImage", + arch: ["armv7l"] + }, + { + target: "tar.gz", + arch: ["armv7l"] + }, + { + target: "deb", + arch: ["armv7l"] + }, + { + target: "rpm", + arch: ["armv7l"] + } + ] + } + } + }).then(() => { + console.log('✅ El build se ha realizado correctamente.') + }).catch(err => { + console.error('Error al realizar el build', err) + }) +}); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..c789b2e --- /dev/null +++ b/package-lock.json @@ -0,0 +1,4585 @@ +{ + "name": "BattlyLauncher", + "version": "1.7.2", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "BattlyLauncher", + "version": "1.7.3", + "license": "CC0", + "dependencies": { + "adm-zip": "^0.5.10", + "axios": "^1.6.4", + "electron-updater": "^6.1.7", + "javascript-obfuscator": "^4.1.0", + "minecraft-launcher-core": "^3.17.3", + "nbtify": "^1.85.0", + "node-fetch": "^2.7.0", + "protobufjs": "^7.2.5", + "socket.io-client": "^4.7.3", + "ws": "^8.16.0", + "ytdl-core": "^4.9.1" + }, + "devDependencies": { + "cross-env": "^7.0.3", + "electron": "^22.3.27", + "electron-builder": "^24.9.1", + "nodemon": "^3.0.2" + }, + "engines": { + "node": "^18.x.x" + } + }, + "node_modules/@develar/schema-utils": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", + "integrity": "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==", + "dev": true, + "dependencies": { + "ajv": "^6.12.0", + "ajv-keywords": "^3.4.1" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@electron/asar": { + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.2.8.tgz", + "integrity": "sha512-cmskk5M06ewHMZAplSiF4AlME3IrnnZhKnWbtwKVLRkdJkKyUVjMLhDIiPIx/+6zQWVlKX/LtmK9xDme7540Sg==", + "dev": true, + "dependencies": { + "commander": "^5.0.0", + "glob": "^7.1.6", + "minimatch": "^3.0.4" + }, + "bin": { + "asar": "bin/asar.js" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/@electron/get": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", + "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "env-paths": "^2.2.0", + "fs-extra": "^8.1.0", + "got": "^11.8.5", + "progress": "^2.0.3", + "semver": "^6.2.0", + "sumchecker": "^3.0.1" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "global-agent": "^3.0.0" + } + }, + "node_modules/@electron/get/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/@electron/get/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@electron/get/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/@electron/notarize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.1.0.tgz", + "integrity": "sha512-Q02xem1D0sg4v437xHgmBLxI2iz/fc0D4K7fiVWHa/AnW8o7D751xyKNXgziA6HrTOme9ul1JfWN5ark8WH1xA==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "fs-extra": "^9.0.1", + "promise-retry": "^2.0.1" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@electron/notarize/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@electron/osx-sign": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.0.5.tgz", + "integrity": "sha512-k9ZzUQtamSoweGQDV2jILiRIHUu7lYlJ3c6IEmjv1hC17rclE+eb9U+f6UFlOOETo0JzY1HNlXy4YOlCvl+Lww==", + "dev": true, + "dependencies": { + "compare-version": "^0.1.2", + "debug": "^4.3.4", + "fs-extra": "^10.0.0", + "isbinaryfile": "^4.0.8", + "minimist": "^1.2.6", + "plist": "^3.0.5" + }, + "bin": { + "electron-osx-flat": "bin/electron-osx-flat.js", + "electron-osx-sign": "bin/electron-osx-sign.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@electron/osx-sign/node_modules/isbinaryfile": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", + "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", + "dev": true, + "engines": { + "node": ">= 8.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/@electron/universal": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.4.1.tgz", + "integrity": "sha512-lE/U3UNw1YHuowNbTmKNs9UlS3En3cPgwM5MI+agIgr/B1hSze9NdOP0qn7boZaI9Lph8IDv3/24g9IxnJP7aQ==", + "dev": true, + "dependencies": { + "@electron/asar": "^3.2.1", + "@malept/cross-spawn-promise": "^1.1.0", + "debug": "^4.3.1", + "dir-compare": "^3.0.0", + "fs-extra": "^9.0.1", + "minimatch": "^3.0.4", + "plist": "^3.0.4" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/@electron/universal/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@javascript-obfuscator/escodegen": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@javascript-obfuscator/escodegen/-/escodegen-2.3.0.tgz", + "integrity": "sha512-QVXwMIKqYMl3KwtTirYIA6gOCiJ0ZDtptXqAv/8KWLG9uQU2fZqTVy7a/A5RvcoZhbDoFfveTxuGxJ5ibzQtkw==", + "dependencies": { + "@javascript-obfuscator/estraverse": "^5.3.0", + "esprima": "^4.0.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/@javascript-obfuscator/estraverse": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@javascript-obfuscator/estraverse/-/estraverse-5.4.0.tgz", + "integrity": "sha512-CZFX7UZVN9VopGbjTx4UXaXsi9ewoM1buL0kY7j1ftYdSs7p2spv9opxFjHlQ/QGTgh4UqufYqJJ0WKLml7b6w==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@malept/cross-spawn-promise": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", + "integrity": "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/malept" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" + } + ], + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@malept/flatpak-bundler": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@malept/flatpak-bundler/-/flatpak-bundler-0.4.0.tgz", + "integrity": "sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "fs-extra": "^9.0.0", + "lodash": "^4.17.15", + "tmp-promise": "^3.0.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@malept/flatpak-bundler/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dev": true, + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "dev": true, + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dev": true, + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/fs-extra": { + "version": "9.0.13", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", + "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "dev": true + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==" + }, + "node_modules/@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.11.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.20.tgz", + "integrity": "sha512-7/rR21OS+fq8IyHTgtLkDK949uzsa6n8BkziAKtPVpugIkO6D+/ooXMvzXxDnZrmtXVfjb1bKQafYpb8s89LOg==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/plist": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/plist/-/plist-3.0.5.tgz", + "integrity": "sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==", + "dev": true, + "optional": true, + "dependencies": { + "@types/node": "*", + "xmlbuilder": ">=11.0.1" + } + }, + "node_modules/@types/responselike": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", + "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/validator": { + "version": "13.11.9", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.9.tgz", + "integrity": "sha512-FCTsikRozryfayPuiI46QzH3fnrOoctTjvOYZkho9BTFLCOZ2rgZJHMOVgCOfttjPJcgOx52EpkY0CMfy87MIw==" + }, + "node_modules/@types/verror": { + "version": "1.10.9", + "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.9.tgz", + "integrity": "sha512-MLx9Z+9lGzwEuW16ubGeNkpBDE84RpB/NyGgg6z2BTpWzKkGU451cAY3UkUzZEp72RHF585oJ3V8JVNqIplcAQ==", + "dev": true, + "optional": true + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "dev": true, + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", + "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/7zip-bin": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.2.0.tgz", + "integrity": "sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A==", + "dev": true + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/adm-zip": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz", + "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/app-builder-bin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-4.0.0.tgz", + "integrity": "sha512-xwdG0FJPQMe0M0UA4Tz0zEB8rBJTRA5a476ZawAqiBkMv16GRK5xpXThOjMaEOFnZ6zabejjG4J3da0SXG63KA==", + "dev": true + }, + "node_modules/app-builder-lib": { + "version": "24.9.1", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-24.9.1.tgz", + "integrity": "sha512-Q1nYxZcio4r+W72cnIRVYofEAyjBd3mG47o+zms8HlD51zWtA/YxJb01Jei5F+jkWhge/PTQK+uldsPh6d0/4g==", + "dev": true, + "dependencies": { + "@develar/schema-utils": "~2.6.5", + "@electron/notarize": "2.1.0", + "@electron/osx-sign": "1.0.5", + "@electron/universal": "1.4.1", + "@malept/flatpak-bundler": "^0.4.0", + "@types/fs-extra": "9.0.13", + "7zip-bin": "~5.2.0", + "async-exit-hook": "^2.0.1", + "bluebird-lst": "^1.0.9", + "builder-util": "24.8.1", + "builder-util-runtime": "9.2.3", + "chromium-pickle-js": "^0.2.0", + "debug": "^4.3.4", + "ejs": "^3.1.8", + "electron-publish": "24.8.1", + "form-data": "^4.0.0", + "fs-extra": "^10.1.0", + "hosted-git-info": "^4.1.0", + "is-ci": "^3.0.0", + "isbinaryfile": "^5.0.0", + "js-yaml": "^4.1.0", + "lazy-val": "^1.0.5", + "minimatch": "^5.1.1", + "read-config-file": "6.3.2", + "sanitize-filename": "^1.6.3", + "semver": "^7.3.8", + "tar": "^6.1.12", + "temp-file": "^3.4.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/app-builder-lib/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/app-builder-lib/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/app-builder-lib/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/array-differ": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", + "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "engines": { + "node": ">=8" + } + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.0.0.tgz", + "integrity": "sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==", + "dependencies": { + "es6-object-assign": "^1.1.0", + "is-nan": "^1.2.1", + "object-is": "^1.0.1", + "util": "^0.12.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", + "dev": true + }, + "node_modules/async-exit-hook": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", + "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", + "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" + }, + "node_modules/axios": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.4.tgz", + "integrity": "sha512-heJnIs6N4aa1eSthhN9M5ioILu8Wi8vmQW9iHQ9NUvfkJb0lEEDUiIdQNAuBtfUt3FxReaKdpQA5DbmMOqzF/A==", + "dependencies": { + "follow-redirects": "^1.15.4", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "node_modules/bluebird-lst": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/bluebird-lst/-/bluebird-lst-1.0.9.tgz", + "integrity": "sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw==", + "dev": true, + "dependencies": { + "bluebird": "^3.5.5" + } + }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "dev": true, + "optional": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "optional": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.1.tgz", + "integrity": "sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==", + "dev": true, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/builder-util": { + "version": "24.8.1", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-24.8.1.tgz", + "integrity": "sha512-ibmQ4BnnqCnJTNrdmdNlnhF48kfqhNzSeqFMXHLIl+o9/yhn6QfOaVrloZ9YUu3m0k3rexvlT5wcki6LWpjTZw==", + "dev": true, + "dependencies": { + "@types/debug": "^4.1.6", + "7zip-bin": "~5.2.0", + "app-builder-bin": "4.0.0", + "bluebird-lst": "^1.0.9", + "builder-util-runtime": "9.2.3", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", + "debug": "^4.3.4", + "fs-extra": "^10.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "is-ci": "^3.0.0", + "js-yaml": "^4.1.0", + "source-map-support": "^0.5.19", + "stat-mode": "^1.0.0", + "temp-file": "^3.4.0" + } + }, + "node_modules/builder-util-runtime": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.3.tgz", + "integrity": "sha512-FGhkqXdFFZ5dNC4C+yuQB9ak311rpGAw+/ASz8ZdxwODCv1GGMWgLDeofRkdi0F3VCHQEWy/aXcJQozx2nOPiw==", + "dependencies": { + "debug": "^4.3.4", + "sax": "^1.2.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "dev": true, + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "dev": true, + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chance": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/chance/-/chance-1.1.9.tgz", + "integrity": "sha512-TfxnA/DcZXRTA4OekA2zL9GH8qscbbl6X0ZqU4tXhGveVY/mXWvEQLt5GwZcYXTEyEFflVtj+pG8nc8EwSm1RQ==" + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", + "engines": { + "node": "*" + } + }, + "node_modules/checksum": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/checksum/-/checksum-0.1.1.tgz", + "integrity": "sha512-xWkkJpoWQ6CptWw2GvtoQbScL3xtvGjoqvHpALE7B0tSHxSw0ex0tlsKOKkbETaOYGBhMliAyscestDyAZIN9g==", + "dependencies": { + "optimist": "~0.3.5" + }, + "bin": { + "checksum": "bin/checksum-cli.js" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chromium-pickle-js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", + "integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==", + "dev": true + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/class-validator": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.0.tgz", + "integrity": "sha512-ct3ltplN8I9fOwUd8GrP8UQixwff129BkEtuWDKL5W45cQuLd19xqmTLu5ge78YDm/fdje6FMt0hGOhl0lii3A==", + "dependencies": { + "@types/validator": "^13.7.10", + "libphonenumber-js": "^1.10.14", + "validator": "^13.7.0" + } + }, + "node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "optional": true, + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/compare-version": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", + "integrity": "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/config-file-ts": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.6.tgz", + "integrity": "sha512-6boGVaglwblBgJqGyxm4+xCmEGcWgnWHSWHY5jad58awQhB6gftq0G8HbzU39YqCIYHMLAiL1yjwiZ36m/CL8w==", + "dev": true, + "dependencies": { + "glob": "^10.3.10", + "typescript": "^5.3.3" + } + }, + "node_modules/config-file-ts/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/config-file-ts/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/config-file-ts/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" + }, + "node_modules/crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "dev": true, + "optional": true, + "dependencies": { + "buffer": "^5.1.0" + } + }, + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", + "engines": { + "node": "*" + } + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true, + "optional": true + }, + "node_modules/dir-compare": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-3.3.0.tgz", + "integrity": "sha512-J7/et3WlGUCxjdnD3HAAzQ6nsnc0WL6DD7WcwJb7c39iH1+AWfg+9OqzJNaI6PkBwBvm1mhZNL9iY/nRiZXlPg==", + "dev": true, + "dependencies": { + "buffer-equal": "^1.0.0", + "minimatch": "^3.0.4" + } + }, + "node_modules/dmg-builder": { + "version": "24.9.1", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-24.9.1.tgz", + "integrity": "sha512-huC+O6hvHd24Ubj3cy2GMiGLe2xGFKN3klqVMLAdcbB6SWMd1yPSdZvV8W1O01ICzCCRlZDHiv4VrNUgnPUfbQ==", + "dev": true, + "dependencies": { + "app-builder-lib": "24.9.1", + "builder-util": "24.8.1", + "builder-util-runtime": "9.2.3", + "fs-extra": "^10.1.0", + "iconv-lite": "^0.6.2", + "js-yaml": "^4.1.0" + }, + "optionalDependencies": { + "dmg-license": "^1.0.11" + } + }, + "node_modules/dmg-license": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.11.tgz", + "integrity": "sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==", + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "@types/plist": "^3.0.1", + "@types/verror": "^1.10.3", + "ajv": "^6.10.0", + "crc": "^3.8.0", + "iconv-corefoundation": "^1.1.7", + "plist": "^3.0.4", + "smart-buffer": "^4.0.2", + "verror": "^1.10.0" + }, + "bin": { + "dmg-license": "bin/dmg-license.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dotenv": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-9.0.2.tgz", + "integrity": "sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", + "dev": true + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ejs": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz", + "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==", + "dev": true, + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron": { + "version": "22.3.27", + "resolved": "https://registry.npmjs.org/electron/-/electron-22.3.27.tgz", + "integrity": "sha512-hsQr9clm8NCAMv4uhHlXThHn52UAgrHgyz3ubBAxZIPuUcpKVDtg4HPmx4hbmHIbYICI5OyLN3Ztp7rS+Dn4Lw==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@electron/get": "^2.0.0", + "@types/node": "^20.9.0", + "extract-zip": "^2.0.1" + }, + "bin": { + "electron": "cli.js" + }, + "engines": { + "node": ">= 12.20.55" + } + }, + "node_modules/electron-builder": { + "version": "24.9.1", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-24.9.1.tgz", + "integrity": "sha512-v7BuakDuY6sKMUYM8mfQGrwyjBpZ/ObaqnenU0H+igEL10nc6ht049rsCw2HghRBdEwJxGIBuzs3jbEhNaMDmg==", + "dev": true, + "dependencies": { + "app-builder-lib": "24.9.1", + "builder-util": "24.8.1", + "builder-util-runtime": "9.2.3", + "chalk": "^4.1.2", + "dmg-builder": "24.9.1", + "fs-extra": "^10.1.0", + "is-ci": "^3.0.0", + "lazy-val": "^1.0.5", + "read-config-file": "6.3.2", + "simple-update-notifier": "2.0.0", + "yargs": "^17.6.2" + }, + "bin": { + "electron-builder": "cli.js", + "install-app-deps": "install-app-deps.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/electron-publish": { + "version": "24.8.1", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-24.8.1.tgz", + "integrity": "sha512-IFNXkdxMVzUdweoLJNXSupXkqnvgbrn3J4vognuOY06LaS/m0xvfFYIf+o1CM8if6DuWYWoQFKPcWZt/FUjZPw==", + "dev": true, + "dependencies": { + "@types/fs-extra": "^9.0.11", + "builder-util": "24.8.1", + "builder-util-runtime": "9.2.3", + "chalk": "^4.1.2", + "fs-extra": "^10.1.0", + "lazy-val": "^1.0.5", + "mime": "^2.5.2" + } + }, + "node_modules/electron-updater": { + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.1.7.tgz", + "integrity": "sha512-SNOhYizjkm4ET+Y8ilJyUzcVsFJDtINzVN1TyHnZeMidZEG3YoBebMyXc/J6WSiXdUaOjC7ngekN6rNp6ardHA==", + "dependencies": { + "builder-util-runtime": "9.2.3", + "fs-extra": "^10.1.0", + "js-yaml": "^4.1.0", + "lazy-val": "^1.0.5", + "lodash.escaperegexp": "^4.1.2", + "lodash.isequal": "^4.5.0", + "semver": "^7.3.8", + "tiny-typed-emitter": "^2.1.0" + } + }, + "node_modules/electron-updater/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "peer": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/engine.io-client": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz", + "integrity": "sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.11.0", + "xmlhttprequest-ssl": "~2.0.0" + } + }, + "node_modules/engine.io-client/node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", + "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true, + "optional": true + }, + "node_modules/es6-object-assign": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", + "integrity": "sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==" + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/extsprintf": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz", + "integrity": "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "optional": true + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", + "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/global-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", + "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "dev": true, + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "es6-error": "^4.1.1", + "matcher": "^3.0.0", + "roarr": "^2.15.3", + "semver": "^7.3.2", + "serialize-error": "^7.0.1" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/global-agent/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "optional": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "optional": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "dev": true + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.2" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dev": true, + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/iconv-corefoundation": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz", + "integrity": "sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==", + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "cli-truncate": "^2.1.0", + "node-addon-api": "^1.6.3" + }, + "engines": { + "node": "^8.11.2 || >=10" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "devOptional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "optional": true + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/inversify": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/inversify/-/inversify-6.0.1.tgz", + "integrity": "sha512-B3ex30927698TJENHR++8FfEaJGqoWOgI6ZY5Ht/nLUsFCwHn6akbwtnUAPCgUepAnTpe2qHxhDNjoKLyz6rgQ==" + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "dev": true, + "dependencies": { + "ci-info": "^3.2.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, + "node_modules/isbinaryfile": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.0.tgz", + "integrity": "sha512-UDdnyGvMajJUWCkib7Cei/dvyJrrvo4FIrsvSFWdPpXSUorzXrDJ0S+X5Q4ZlasfPjca4yqCNNsjbCeiy8FFeg==", + "dev": true, + "engines": { + "node": ">= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" + }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jake": { + "version": "10.8.7", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", + "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==", + "dev": true, + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/javascript-obfuscator": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/javascript-obfuscator/-/javascript-obfuscator-4.1.0.tgz", + "integrity": "sha512-ckC0VFKQ0/sFtLH9apW/ZLfsP8LuZqZhVEM4VTJ5KLzyLaodW6C1lTU8808eboDmddKyvd2uyRx5bzc0Me0GYg==", + "hasInstallScript": true, + "dependencies": { + "@javascript-obfuscator/escodegen": "2.3.0", + "@javascript-obfuscator/estraverse": "5.4.0", + "acorn": "8.8.2", + "assert": "2.0.0", + "chalk": "4.1.2", + "chance": "1.1.9", + "class-validator": "0.14.0", + "commander": "10.0.0", + "eslint-scope": "7.1.1", + "eslint-visitor-keys": "3.3.0", + "fast-deep-equal": "3.1.3", + "inversify": "6.0.1", + "js-string-escape": "1.0.1", + "md5": "2.3.0", + "mkdirp": "2.1.3", + "multimatch": "5.0.0", + "opencollective-postinstall": "2.0.3", + "process": "0.11.10", + "reflect-metadata": "0.1.13", + "source-map-support": "0.5.21", + "string-template": "1.0.0", + "stringz": "2.1.0", + "tslib": "2.5.0" + }, + "bin": { + "javascript-obfuscator": "bin/javascript-obfuscator" + }, + "engines": { + "node": "^12.22.0 || ^14.0.0 || ^16.0.0 || ^17.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/javascript-obfuscator" + } + }, + "node_modules/javascript-obfuscator/node_modules/commander": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.0.tgz", + "integrity": "sha512-zS5PnTI22FIRM6ylNW8G4Ap0IEOyk62fhLSD0+uHRT9McRCLGpkVNvao4bjimpK/GShynyQkFFxHhwMcETmduA==", + "engines": { + "node": ">=14" + } + }, + "node_modules/javascript-obfuscator/node_modules/mkdirp": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.3.tgz", + "integrity": "sha512-sjAkg21peAG9HS+Dkx7hlG9Ztx7HLeKnvB3NQRcu/mltCVmvkF0pisbiTSfDVYTT86XEfZrTUosLdZLStquZUw==", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/js-string-escape": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", + "integrity": "sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/jsprim/node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/jsprim/node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/lazy-val": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", + "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==" + }, + "node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/libphonenumber-js": { + "version": "1.10.57", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.57.tgz", + "integrity": "sha512-OjsEd9y4LgcX+Ig09SbxWqcGESxliDDFNVepFhB9KEsQZTrnk3UdEU+cO0sW1APvLprHstQpS23OQpZ3bwxy6Q==" + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.escaperegexp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", + "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" + }, + "node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/m3u8stream": { + "version": "0.8.6", + "resolved": "https://registry.npmjs.org/m3u8stream/-/m3u8stream-0.8.6.tgz", + "integrity": "sha512-LZj8kIVf9KCphiHmH7sbFQTVe4tOemb202fWwvJwR9W5ENW/1hxJN6ksAWGhQgSBSa3jyWhnjKU1Fw1GaOdbyA==", + "dependencies": { + "miniget": "^4.2.2", + "sax": "^1.2.4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/matcher": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", + "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "dev": true, + "optional": true, + "dependencies": { + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/md5": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", + "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", + "dependencies": { + "charenc": "0.0.2", + "crypt": "0.0.2", + "is-buffer": "~1.1.6" + } + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/minecraft-launcher-core": { + "version": "3.17.3", + "resolved": "https://registry.npmjs.org/minecraft-launcher-core/-/minecraft-launcher-core-3.17.3.tgz", + "integrity": "sha512-yA/WKkw6zcIFBKS4OCXEeQfdtKhXHZVz4cS5pmouOohxk8JZQI/i+BDMl7Ny3jHUnUv7n9VPK4ZQ6jhadhhXxQ==", + "dependencies": { + "adm-zip": "^0.4.13", + "checksum": "^0.1.1", + "request": "^2.88.0", + "uuid": "^8.3.2" + } + }, + "node_modules/minecraft-launcher-core/node_modules/adm-zip": { + "version": "0.4.16", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", + "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", + "engines": { + "node": ">=0.3.0" + } + }, + "node_modules/miniget": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/miniget/-/miniget-4.2.3.tgz", + "integrity": "sha512-SjbDPDICJ1zT+ZvQwK0hUcRY4wxlhhNpHL9nJOB2MEAXRGagTljsO8MEDzQMTFf0Q8g4QNi8P9lEm/g7e+qgzA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/multimatch": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-5.0.0.tgz", + "integrity": "sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==", + "dependencies": { + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nbtify": { + "version": "1.85.0", + "resolved": "https://registry.npmjs.org/nbtify/-/nbtify-1.85.0.tgz", + "integrity": "sha512-gGi/4v0sdThz9VUs23OcxsGJOnR1ludZPFJLRHWXxtMWKgTzh1HF7jRqRwGQj2V+JxaLUhWwFoROv0qA4DFxcg==", + "bin": { + "nbtify": "dist/bin/index.js" + } + }, + "node_modules/node-addon-api": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", + "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==", + "dev": true, + "optional": true + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/nodemon": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.0.2.tgz", + "integrity": "sha512-9qIN2LNTrEzpOPBaWHTm4Asy1LxXLSickZStAQ4IZe7zsoIpD/A7LWxhZV3t4Zu352uBcqVnRsDXSMR2Sc3lTA==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/nodemon/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemon/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "engines": { + "node": "*" + } + }, + "node_modules/object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/opencollective-postinstall": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", + "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", + "bin": { + "opencollective-postinstall": "index.js" + } + }, + "node_modules/optimist": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "integrity": "sha512-TCx0dXQzVtSCg2OgY/bO9hjM9cV4XYx09TVK+s3+FhkjT6LovsLe+pPMzpWf+6yXK/hUizs2gUoTw3jHM0VaTQ==", + "dependencies": { + "wordwrap": "~0.0.2" + } + }, + "node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", + "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/plist": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", + "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", + "dev": true, + "dependencies": { + "@xmldom/xmldom": "^0.8.8", + "base64-js": "^1.5.1", + "xmlbuilder": "^15.1.1" + }, + "engines": { + "node": ">=10.4.0" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/protobufjs": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz", + "integrity": "sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-config-file": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-6.3.2.tgz", + "integrity": "sha512-M80lpCjnE6Wt6zb98DoW8WHR09nzMSpu8XHtPkiTHrJ5Az9CybfeQhTJ8D7saeBHpGhLPIVyA8lcL6ZmdKwY6Q==", + "dev": true, + "dependencies": { + "config-file-ts": "^0.2.4", + "dotenv": "^9.0.2", + "dotenv-expand": "^5.1.0", + "js-yaml": "^4.1.0", + "json5": "^2.2.0", + "lazy-val": "^1.0.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/request/node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/request/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true + }, + "node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "dev": true, + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/roarr": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", + "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", + "dev": true, + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "detect-node": "^2.0.4", + "globalthis": "^1.0.1", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sanitize-filename": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", + "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", + "dev": true, + "dependencies": { + "truncate-utf8-bytes": "^1.0.0" + } + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "dev": true, + "optional": true + }, + "node_modules/serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "dev": true, + "optional": true, + "dependencies": { + "type-fest": "^0.13.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/set-function-length": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", + "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", + "dependencies": { + "define-data-property": "^1.1.2", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "optional": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socket.io-client": { + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.3.tgz", + "integrity": "sha512-nU+ywttCyBitXIl9Xe0RSEfek4LneYkJxCeNnKCuhwoH4jGXO1ipIUw/VA/+Vvv2G1MTym11fzFC0SxkrcfXDw==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.5.2", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true, + "optional": true + }, + "node_modules/sshpk": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stat-mode": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz", + "integrity": "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/string-template": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string-template/-/string-template-1.0.0.tgz", + "integrity": "sha512-SLqR3GBUXuoPP5MmYtD7ompvXiG87QjT6lzOszyXjTM86Uu7At7vNnt2xgyTLq5o9T4IxTYFyGxcULqpsmsfdg==" + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/stringz": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/stringz/-/stringz-2.1.0.tgz", + "integrity": "sha512-KlywLT+MZ+v0IRepfMxRtnSvDCMc3nR1qqCs3m/qIbSOWkNZYT8XHQA31rS3TnKp0c5xjZu3M4GY/2aRKSi/6A==", + "dependencies": { + "char-regex": "^1.0.2" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sumchecker": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", + "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", + "dev": true, + "dependencies": { + "debug": "^4.1.0" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/temp-file": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz", + "integrity": "sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==", + "dev": true, + "dependencies": { + "async-exit-hook": "^2.0.1", + "fs-extra": "^10.0.0" + } + }, + "node_modules/tiny-typed-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz", + "integrity": "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA==" + }, + "node_modules/tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } + }, + "node_modules/tmp-promise": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", + "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", + "dev": true, + "dependencies": { + "tmp": "^0.2.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/truncate-utf8-bytes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", + "dev": true, + "dependencies": { + "utf8-byte-length": "^1.0.1" + } + }, + "node_modules/tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" + }, + "node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/utf8-byte-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", + "integrity": "sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA==", + "dev": true + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/validator": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", + "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/verror": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", + "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", + "dev": true, + "optional": true, + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", + "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", + "dependencies": { + "available-typed-arrays": "^1.0.6", + "call-bind": "^1.0.5", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/ws": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "dev": true, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/xmlhttprequest-ssl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", + "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/ytdl-core": { + "version": "4.11.5", + "resolved": "https://registry.npmjs.org/ytdl-core/-/ytdl-core-4.11.5.tgz", + "integrity": "sha512-27LwsW4n4nyNviRCO1hmr8Wr5J1wLLMawHCQvH8Fk0hiRqrxuIu028WzbJetiYH28K8XDbeinYW4/wcHQD1EXA==", + "dependencies": { + "m3u8stream": "^0.8.6", + "miniget": "^4.2.2", + "sax": "^1.1.3" + }, + "engines": { + "node": ">=12" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..a7d9ce1 --- /dev/null +++ b/package.json @@ -0,0 +1,50 @@ +{ + "name": "BattlyLauncher", + "productname": "Battly Launcher", + "version": "1.7.3", + "description": "El mejor Launcher Personalizado para Minecraft Premium y No premium", + "main": "src/app.js", + "author": "TECNO BROS ", + "url": "https://api.battlylauncher.com/battlylauncher", + "engines": { + "node": "^18.x.x" + }, + "scripts": { + "start:dev": "cross-env-shell NODE_ENV=dev electron .", + "start": "cross-env-shell NODE_ENV=dev electron .", + "build": "node build.js", + "dev": "nodemon --exec npm start", + "git": "electron-builder build --linux", + "publish": "electron-builder --win -p always", + "build-mac": "electron-builder build --mac", + "build-clean": "rm -rf dist" + }, + "license": "CC0", + "nodemonConfig": { + "ext": "js,html,css" + }, + "dependencies": { + "adm-zip": "^0.5.10", + "axios": "^1.6.4", + "electron-updater": "^6.1.7", + "javascript-obfuscator": "^4.1.0", + "minecraft-launcher-core": "^3.17.3", + "nbtify": "^1.85.0", + "node-fetch": "^2.7.0", + "protobufjs": "^7.2.5", + "socket.io-client": "^4.7.3", + "ws": "^8.16.0", + "ytdl-core": "^4.9.1" + }, + "devDependencies": { + "cross-env": "^7.0.3", + "electron": "^22.3.27", + "electron-builder": "^24.9.1", + "nodemon": "^3.0.2" + }, + "repository": { + "type": "git", + "url": "https://github.com/1ly4s0/battlylauncher.git" + }, + "private": true +} diff --git a/src/app.js b/src/app.js new file mode 100644 index 0000000..851c7a9 --- /dev/null +++ b/src/app.js @@ -0,0 +1,427 @@ +/** + * @author TECNO BROS + + */ + +const { app, ipcMain, protocol, BrowserWindow, shell, ipcRenderer } = require('electron'); +const { Microsoft } = require('./assets/js/libs/mc/Index'); +const { autoUpdater } = require('electron-updater') +const { io } = require("socket.io-client"); +const socket = io("http://api.battlylauncher.com"); +process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0'; +const fs = require('fs'); +const path = require('path'); +const dataDirectory = process.env.APPDATA || (process.platform == 'darwin' ? `${process.env.HOME}/Library/Application Support` : process.env.HOME) +const { Notification } = require("electron"); +app.setAppUserModelId("Battly Launcher"); +let dev = process.env.NODE_ENV === 'dev'; + +if(!fs.existsSync(path.join(dataDirectory, '.battly'))) fs.mkdirSync(path.join(dataDirectory, '.battly')); + +socket.on("connect", () => { +}); + + +socket.on('notificacion', async (data) => { + const { titulo, descripcion, url } = data; + + let notification; + + if (process.platform === 'win32') { + notification = new Notification({ + toastXml: ` + + + + ${titulo} + ${descripcion} + + + + + + ` + }); + } else { + notification = new Notification({ + title: titulo, + body: descripcion, + icon: path.join(__dirname, '/assets/images/icon.png') + }); + } + + notification.show(); + + notification.on('click', (event, arg) => { + shell.openExternal(`${url}`); + }); +}) + +socket.on('solicitudAmistad', async (data) => { + const { username } = data; + + + let notification; + + if (process.platform === 'win32') { + notification = new Notification({ + toastXml: ` + + + + Solicitud de amistad + ${username} te ha enviado una solicitud de amistad. + + + + + + + ` + }); + } else { + notification = new Notification({ + title: "Solicitud de amistad", + body: `${username} te ha enviado una solicitud de amistad.`, + icon: path.join(__dirname, '/assets/images/icon.png'), + actions: [ + { type: 'button', text: 'Aceptar', }, + { type: 'button', text: 'Rechazar', } + ] + }); + } + + notification.show(); + + notification.on('action', (event, arg) => { + const window = MainWindow.getWindow(); + window.webContents.send('cargarSolicitudAmistad', { username }); + }); +}); + +ipcMain.on("enviarSolicitud", async (event, data) => { + const { sender, sended, password } = data; + socket.emit('enviarSolicitud', { + username: sender, + amigo: sended, + password: password + }) +}); + + +ipcMain.on("socket", async (i, event, data) => { + socket.emit(event, data); +}); + +socket.on("onlineUsers", (data) => { + const window = MainWindow.getWindow(); + window.webContents.send('onlineUsers', data); +}); + +let shown = false; + +socket.on('getLogs', async (data) => { + if (shown) { + const RegistroLog = fs.readFileSync(`${dataDirectory}/.battly/Registro.log`, 'utf8'); + const window = MainWindow.getWindow(); + window.webContents.send('getLogsAnterior', { RegistroLog }); + setTimeout(() => { + socket.emit('sendLogs', RegistroLog); + }, 3000); + } else { + const { user, razon } = data; + const window = MainWindow.getWindow(); + window.webContents.send('avisoObtenerLogs', { user, razon }); + } +}); + +ipcMain.on('obtenerLogs', async (event, data) => { + const RegistroLog = fs.readFileSync(`${dataDirectory}/.battly/Registro.log`, 'utf8'); + socket.emit('sendLogs', RegistroLog); + shown = true; +}); + +ipcMain.on('obtenerSocketID', async (event, data) => { + const sessionID = socket.id; + const window = MainWindow.getWindow(); + window.webContents.send('enviarSocketID', { sessionID }); +}); + +ipcMain.on('updateStatus', async (event, data) => { + socket.emit('updateStatus', data); +}); + +ipcMain.on('obtener-solicitudes', async (event, data) => { + socket.emit('mostrarSolicitudes', data); +}); + +socket.on("mostrarSolicitudes", (data) => { + const window = MainWindow.getWindow(); + window.webContents.send('solicitudes', data); +}); + +ipcMain.on('aceptar-solicitud', async (event, data) => { + socket.emit('aceptarSolicitud', data); +}); + +ipcMain.on('rechazar-solicitud', async (event, data) => { + socket.emit('rechazarSolicitud', data); +}); + +ipcMain.on("obtener-amigos", async (event, data) => { + socket.emit('obtenerAmigos', data); +}); + +socket.on("obtenerAmigos", (data) => { + const window = MainWindow.getWindow(); + window.webContents.send('amigos', data); +}); + +if (!dev) { + if (process.defaultApp) { + if (process.argv.length >= 2) { + app.setAsDefaultProtocolClient('battly', process.execPath, [path.resolve(process.argv[1])]) + app.setAsDefaultProtocolClient('battlylauncher', process.execPath, [path.resolve(process.argv[1])]) + } + } else { + app.setAsDefaultProtocolClient('battly') + app.setAsDefaultProtocolClient('battlylauncher') + } +} + +const UpdateWindow = require("./assets/js/windows/updateWindow.js"); +const MainWindow = require("./assets/js/windows/mainWindow.js"); + +if (dev) { + let appPath = path.resolve('./AppData/Launcher').replace(/\\/g, '/'); + if (!fs.existsSync(appPath)) fs.mkdirSync(appPath, { recursive: true }); + app.setPath('userData', appPath); +} + +const gotTheLock = app.requestSingleInstanceLock(); + +if (!gotTheLock) { + app.quit(); +} else { + app.whenReady().then(() => { + UpdateWindow.createWindow(); + }); +} + +process.on('uncaughtException', (error) => { + console.log(error); +}); + +process.on('unhandledRejection', (error) => { + console.log(error); +}); + +ipcMain.on('update-window-close', () => UpdateWindow.destroyWindow()) +ipcMain.on('update-window-dev-tools', () => UpdateWindow.getWindow().webContents.openDevTools()) +ipcMain.on('main-window-open', () => MainWindow.createWindow()) +ipcMain.on('main-window-dev-tools', () => MainWindow.getWindow().webContents.openDevTools()) +ipcMain.on('main-window-close', () => MainWindow.destroyWindow()) +ipcMain.on('main-window-progress_', (progress_actual, size_actual) => { + MainWindow.getWindow().setProgressBar(parseInt(size_actual.progress) / parseInt(100)); +}) +ipcMain.on('main-window-progress', (progress_actual, size_actual) => { + MainWindow.getWindow().setProgressBar(parseInt(size_actual.progress_actual) / parseInt(size_actual.size_actual)); +}) + +ipcMain.on('main-window-progress-loading', () => { + MainWindow.getWindow().setProgressBar(2); +}) + +ipcMain.on('main-window-progress-reset', () => { + MainWindow.getWindow().setProgressBar(-1); +}) +ipcMain.on('main-window-minimize', () => MainWindow.getWindow().minimize()) + +ipcMain.on('main-window-maximize', () => { + if (MainWindow.getWindow().isMaximized()) { + MainWindow.getWindow().unmaximize(); + } else { + MainWindow.getWindow().maximize(); + } +}) + +ipcMain.on('main-window-hide', () => MainWindow.getWindow().hide()) +ipcMain.on('main-window-show', () => MainWindow.getWindow().show()) + +ipcMain.handle('Microsoft-window', async (event, client_id) => { + return await new Microsoft(client_id).getAuth(); +}) + +app.on('window-all-closed', () => { + if (process.platform !== 'darwin') app.quit(); +}); + +ipcMain.on('restartLauncher', () => { + app.relaunch(); + app.exit(); +}); + +let songPlaying; +ipcMain.on('set-song', async (info, song) => { + if (song) { + ipcMain.emit('get-song', song); + } +}); + + +let startedAppTime = Date.now(); + +const rpc = require('./assets/js/libs/discord/index'); +const { platform } = require('os'); +let client = new rpc.Client({ transport: 'ipc' }); + +ipcMain.on('new-status-discord', async () => { + client.login({ clientId: '917866962523152404' }); + client.on('ready', () => { + client.request('SET_ACTIVITY', { + pid: process.pid, + activity: { + details: 'En el menú de inicio', + assets: { + large_image: 'battly_512', + large_text: 'Battly Launcher', + }, + buttons: [ + { label: '👥 Discord', url: "https://discord.gg/tecno-bros-885235460178342009" }, + { label: '⏬ Descargar', url: "https://battlylauncher.com" } + ], + instance: false, + timestamps: { + start: startedAppTime + } + }, + }).catch(error => { }); + }); +}); + + +ipcMain.on('new-status-discord-jugando', async (event, status) => { + if (status.endsWith('-forge')) { + status = status.replace('-forge', ''); + status = `${status} - Forge`; + } else if (status.endsWith('-fabric')) { + status = status.replace('-fabric', ''); + status = `${status} - Fabric`; + } else { + status = `${status}`; + } + + if (client) await client.destroy(); + client = new rpc.Client({ transport: 'ipc' }); + client.login({ clientId: '917866962523152404' }); + client.on('ready', () => { + client.request('SET_ACTIVITY', { + pid: process.pid, + activity: { + details: status, + assets: { + large_image: 'battly_512', + small_image: 'mc_512', + small_text: 'Minecraft', + large_text: 'Battly Launcher', + }, + buttons: [ + { label: '👥 Discord', url: "https://discord.gg/tecno-bros-885235460178342009" }, + { label: '⏬ Descargar', url: "https://battlylauncher.com" } + ], + instance: false, + timestamps: { + start: startedAppTime + } + }, + }).catch(error => { }); + }); +}); + + + +ipcMain.on('new-notification', async (event, info) => { + new Notification({ + title: info.title, + body: info.body, + icon: path.join(__dirname, '/assets/images/icon.png') + }).show(); +}); + +ipcMain.on('delete-and-new-status-discord', async () => { + if (client) client.destroy(); + client = new rpc.Client({ transport: 'ipc' }); + client.login({ clientId: '917866962523152404' }); + client.on('ready', () => { + client.request('SET_ACTIVITY', { + pid: process.pid, + activity: { + details: 'En el menú de inicio', + assets: { + large_image: 'battly_512', + large_text: 'Battly Launcher', + }, + buttons: [ + { label: '👥 Discord', url: "https://discord.gg/tecno-bros-885235460178342009" }, + { label: '⏬ Descargar', url: "https://battlylauncher.com" } + ], + instance: false, + timestamps: { + start: startedAppTime + } + }, + }).catch(error => { }); + }); +}); + +ipcMain.on('delete-status-discord', async () => { + if (client) client.destroy(); +}); + +autoUpdater.autoDownload = false; + +ipcMain.handle('update-app', () => { + return new Promise(async (resolve, reject) => { + autoUpdater.checkForUpdates().then(() => { + resolve(); + }).catch(error => { + console.log(error); + resolve({ + error: true, + message: error + }) + }) + }) +}) + +autoUpdater.on('update-available', () => { + const updateWindow = UpdateWindow.getWindow(); + if (updateWindow) updateWindow.webContents.send('updateAvailable'); +}); + +ipcMain.on('start-update', () => { + autoUpdater.downloadUpdate(); +}) + +autoUpdater.on('update-not-available', () => { + const updateWindow = UpdateWindow.getWindow(); + if (updateWindow) updateWindow.webContents.send('update-not-available'); +}); + +autoUpdater.on('update-downloaded', () => { + autoUpdater.quitAndInstall(); +}); + +autoUpdater.on('download-progress', (progress) => { + const updateWindow = UpdateWindow.getWindow(); + if (updateWindow) updateWindow.webContents.send('download-progress', progress); +}) \ No newline at end of file diff --git a/src/assets/audios/error.mp3 b/src/assets/audios/error.mp3 new file mode 100644 index 0000000..a629c44 Binary files /dev/null and b/src/assets/audios/error.mp3 differ diff --git a/src/assets/audios/notificacion.mp3 b/src/assets/audios/notificacion.mp3 new file mode 100644 index 0000000..853a651 Binary files /dev/null and b/src/assets/audios/notificacion.mp3 differ diff --git a/src/assets/audios/start.mp3 b/src/assets/audios/start.mp3 new file mode 100644 index 0000000..407cc80 Binary files /dev/null and b/src/assets/audios/start.mp3 differ diff --git a/src/assets/audios/start1.mp3 b/src/assets/audios/start1.mp3 new file mode 100644 index 0000000..e987f7f Binary files /dev/null and b/src/assets/audios/start1.mp3 differ diff --git a/src/assets/audios/start2.mp3 b/src/assets/audios/start2.mp3 new file mode 100644 index 0000000..9fd8fb8 Binary files /dev/null and b/src/assets/audios/start2.mp3 differ diff --git a/src/assets/audios/start3.mp3 b/src/assets/audios/start3.mp3 new file mode 100644 index 0000000..bfbcc5c Binary files /dev/null and b/src/assets/audios/start3.mp3 differ diff --git a/src/assets/css/font.css b/src/assets/css/font.css new file mode 100644 index 0000000..092feab --- /dev/null +++ b/src/assets/css/font.css @@ -0,0 +1,48 @@ +/* Poppins */ + +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: local('Poppins Regular'), local('Poppins-Regular'), url('../fonts/Poppins-Regular.woff2') format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} + +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: local('Poppins Bold'), local('Poppins-Bold'), url('../fonts/Poppins-Bold.woff2') format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} + +@font-face { + font-family: 'Icons'; + src: url('../fonts/Icons.woff2') format('woff2'); + font-weight: normal; + font-style: normal; +} + +[class^="icon-"]:before, [class*=" icon-"]:before, [class^="icon-"]:after, [class*=" icon-"]:after, .select-wrap:after { + font-style: normal; + font-weight: normal; + display: inline-block; + text-decoration: inherit; + width: 1em; + text-align: center; + font-variant: normal; + text-transform: none; + line-height: 1em; + -webkit-font-smoothing: antialiased; +} + +.icon-close:before { font-family: "Icons"; content: "\e90e"; } +.icon-minimize:before { font-family: "Icons"; content: "\e90b"; } +.icon-maximize:before { font-family: "Icons"; content: "\e90c"; } +.icon-restore-down:before { font-family: "Icons"; content: "\e90d"; } +.icon-account-add:before { font-family: "Icons"; content: "\e901"; } +.icon-account-delete:before { font-family: "Icons"; content: "\e902"; } +.icon-settings:before { font-family: "Icons"; content: "\e909"; } +.icon-monitor:before { font-family: "Icons"; content: "\e90a"; } \ No newline at end of file diff --git a/src/assets/css/index.css b/src/assets/css/index.css new file mode 100644 index 0000000..07c53bc --- /dev/null +++ b/src/assets/css/index.css @@ -0,0 +1,160 @@ +@import "font.css"; +body { + font-family: "Poppins"; + letter-spacing: 0px; + -webkit-app-region: drag; + user-select: none; + background-image: url('../../assets/images/background/background_updater.png'); + background-size: cover; + background-repeat: no-repeat; +} + +img { + -webkit-user-drag: none; + user-select: none; +} + + + +.splash { + position: absolute; + top: 180px; + left: 50%; + transform: translate(-50%); + width: 140px; + height: 140px; + transition: opacity .3s, top 1.5s; + opacity: 0; +} + +.expand { + transform: scale(2); /* Ajusta el valor para controlar el tamaño al que se agranda la imagen */ + transition: transform 2s ease-in-out; + top: 0px; + } + +.splash.opacity { + opacity: 1; +} + +.splash.translate { + top: 129px; +} + +.splash-message { + position: absolute; + top: 279px; + left: 0px; + width: 400px; + font: normal normal bold 25px/30px Poppins; + text-align: center; + letter-spacing: 0px; + transition: opacity 1.5s; + color: #000; + opacity: 0; +} + +.splash-message.opacity { + opacity: 1; +} + +.splash-author { + position: absolute; + top: 326px; + left: 0px; + width: 400px; + text-align: center; + transition: opacity 1.5s; + font: normal normal normal 9px/13px Poppins; + color: rgb(0, 0, 0); + opacity: 0; +} + +.splash-author .author { + font: normal normal bold 14px/17px Poppins; +} + +.splash-author.opacity { + opacity: 1; +} + +.message { + position: absolute; + top: 347px; + left: 0px; + width: 400px; + text-align: center; + transition: opacity 1.5s; + font: normal normal bold 18px/27px Poppins; + color: rgb(0, 0, 0); + opacity: 0; +} + +.message.opacity { + opacity: 1; +} + +progress { + position: absolute; + top: 435px; + left: 106px; + width: 189px; + height: 10px; + appearance: none; + transition: opacity .2s; + opacity: 0; +} + +progress.show { + opacity: 1; +} + +progress::-webkit-progress-bar { + background-color: rgb(0, 0, 0); + border-radius: 10px; +} + +progress::-webkit-progress-value { + background-color: #3e8ed0; + border-radius: 5px; +} + +#btn_actualizar { + position: fixed; + top: 430px; + width: 30%; + text-align: center; + font: normal normal bold 18px/27px Poppins; + transform: translate(50%, 50%); + background-color: #3e8ed0; + border-radius: 0%; + -webkit-app-region: no-drag; + cursor: pointer; + border: none; + border-radius: 5px; + display: none; +} + +#btn_actualizar:hover { + background-color: #2196F3; +} + +#btn_jugar { + position: fixed; + top: 430px; + width: 30%; + text-align: center; + font: normal normal bold 18px/27px Poppins; + transform: translate(170%, 50%); + background-color: #3e8ed0; + border-radius: 0%; + -webkit-app-region: no-drag; + cursor: pointer; + border: none; + border-radius: 5px; + display: none; +} + +#btn_jugar:hover { + background-color: #2196F3; +} \ No newline at end of file diff --git a/src/assets/css/launcher.css b/src/assets/css/launcher.css new file mode 100644 index 0000000..e5d55e6 --- /dev/null +++ b/src/assets/css/launcher.css @@ -0,0 +1,516 @@ +@import "font.css"; +@import "panels/login.css"; +@import "panels/home.css"; +@import "panels/settings.css"; +@import "panels/mods.css"; +@import "panels/mods/style.css"; +@import "panels/music.css"; +@import "panels/music-small.css"; +@import "panels/friends.css"; +@import "skin.css"; + +* { + outline: none; +} + +body, html { + height: 100%; + + } + + html, body { + height: 100%; + overflow: hidden; + } + +body { + user-select: none; + background: linear-gradient(#00000066, #00000066), url("../images/background/light.jpg") black no-repeat center center fixed; + background-size: cover; /* Añadir para ajustar el tamaño de la imagen de fondo */ + background-attachment: fixed; /* Añadir para fijar la imagen de fondo */ + background-color: black; /* Color de fondo en caso de que la imagen no llene completamente */ +} + +body { + overflow-y: hidden; /* Hide vertical scrollbar */ + overflow-x: hidden; /* Hide horizontal scrollbar */ + } + + +body::-webkit-scrollbar { + width: 0; +} + +.swal2-container { + z-index: 999999999; +} + +img { + -webkit-user-drag: none; + user-select: none; +} + +a:link { + text-decoration: none; +} + +a:visited { + text-decoration: none; +} + +.frame { + background: #000000; + opacity: .7; + position: fixed; + display: flex; /* Usar flexbox */ + justify-content: space-between; /* Colocar elementos al principio y al final */ + top: 0px; + right: 0px; + left: 0px; /* Para que el frame ocupe todo el ancho */ + z-index: 11; + -webkit-app-region: drag; /* Hacer que el frame sea arrastrable */ + height: 26px; /* Ajustar la altura del frame */ +} + +.frame * { + pointer-events: auto; +} + +.no-drag { + -webkit-app-region: no-drag; +} + + + +.button-frame { + /* Estilos de los botones */ + width: 30px; + height: 26px; + transition: color .2s, background-color .2s; + color: #ffffff; + cursor: pointer; +} + +.buttons { + display: flex; /* Para que los botones sean flexibles */ + align-items: center; /* Centrar verticalmente los botones */ +} + + + +.titulo { + flex: 1; /* Hacer que el título ocupe el espacio disponible */ + display: flex; /* Alinear el texto verticalmente */ + align-items: center; /* Centrar verticalmente el texto */ + padding-left: 10px; /* Añadir espacio a la izquierda */ + color: #ffffff; +} + + + +.battly-title { + position: absolute; + top: 6px; + left: -90%; + font-size: 14px; + color: #f8f9f9; + +} + +.preload-content { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + z-index: 99999; +} + +.preload-content h1 { + font-family: 'Poppins'; + font-size: 18px; + color: #E1E1E1; + text-align: center; + font-weight: 700; + position: absolute; + top: 100%; + left: 50%; + transform: translate(-50%, 0%); + white-space: nowrap; + +} + +.preload-progress { + position: absolute; + left: 50%; + transform: translate(-50%, -50%); + width: 127px; +} + +.dot { + position: absolute; + width: 16px; + height: 16px; + margin-left: 14px; + margin-top: 12px; + background: #ffffff; + border-radius: 50%; + transform: translateX(0); + animation: dot 2.8s infinite; +} + +.dots { + transform: translateX(0); + margin-top: 12px; + margin-left: 31px; + animation: dots 2.8s infinite; +} + +.dots span { + display: block; + float: left; + width: 16px; + height: 16px; + margin-left: 16px; + background: #ffffff; + border-radius: 50%; +} + +@keyframes dot { + 50% { + transform: translateX(96px); + } +} + +@keyframes dots { + 50% { + transform: translateX(-31px); + } +} + +.preload-title { + font: normal normal bold 30px/40px Poppins; + color: #E1E1E1; + text-align: center; + margin: 2em 0; +} + +.panel { + position: absolute; + width: 100%; + height: 100%; + opacity: 0; + z-index: 0; + pointer-events: none; + transition: opacity 0.7s ease; +} + +.active { + opacity: 1; + z-index: 1; + pointer-events: all; +} + +.rotation { + animation: rotation 5s infinite linear; +} + +@keyframes rotation { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(359deg); + } +} + + .spinner { + -webkit-animation: rotate 2s linear infinite; + animation: rotate 2s linear infinite; + z-index: 2; + position: absolute; + top: 50%; + left: 50%; + margin: -25px 0 0 -25px; + width: 50px; + height: 50px; + } + .spinner .path { + stroke: #93bfec; + stroke-linecap: round; + -webkit-animation: dash 1.5s ease-in-out infinite; + animation: dash 1.5s ease-in-out infinite; + } + + @-webkit-keyframes rotate { + 100% { + transform: rotate(360deg); + } + } + + @keyframes rotate { + 100% { + transform: rotate(360deg); + } + } + @-webkit-keyframes dash { + 0% { + stroke-dasharray: 1, 150; + stroke-dashoffset: 0; + } + 50% { + stroke-dasharray: 90, 150; + stroke-dashoffset: -35; + } + 100% { + stroke-dasharray: 90, 150; + stroke-dashoffset: -124; + } + } + @keyframes dash { + 0% { + stroke-dasharray: 1, 150; + stroke-dashoffset: 0; + } + 50% { + stroke-dasharray: 90, 150; + stroke-dashoffset: -35; + } + 100% { + stroke-dasharray: 90, 150; + stroke-dashoffset: -124; + } + } + + + .assembly { + top: 50%; + left: 50%; + transform: rotateX(-45deg) rotateY(-45deg); + } + + .comp-3d { + animation: r 2s ease-in-out infinite; + } + + .comp-3d--i { + animation-name: ri; + } + + .comp-3d--o { + animation-name: ro; + } + + @keyframes ri { + + 0%, + 20% { + transform: rotateY(-0.5turn); + } + + 50% { + transform: none; + } + + 100%, + 80% { + transform: rotateX(-0.5turn); + } + } + + @keyframes ro { + + 0%, + 35% { + transform: rotate(-0.5turn); + } + + 65%, + 100% { + transform: none; + } + } + + .pos:nth-child(1) { + transform: scale3d(1, 1, 1) translate3d(4em, 4em, 4em); + } + + :not(.pos)>.cube:nth-child(1) { + transform: translate3d(-4em, -4em, 0em); + } + + .pos:nth-child(2) { + transform: scale3d(1, 1, -1) translate3d(4em, 4em, 4em); + } + + :not(.pos)>.cube:nth-child(2) { + transform: translate3d(-4em, 0em, -4em); + } + + :not(.pos)>.cube:nth-child(3) { + transform: translate3d(-4em, 0em, 0em); + } + + :not(.pos)>.cube:nth-child(4) { + transform: translate3d(-4em, 0em, 4em); + } + + .pos:nth-child(3) { + transform: scale3d(1, -1, 1) translate3d(4em, 4em, 4em); + } + + :not(.pos)>.cube:nth-child(5) { + transform: translate3d(-4em, 4em, 0em); + } + + .pos:nth-child(4) { + transform: scale3d(1, -1, -1) translate3d(4em, 4em, 4em); + } + + :not(.pos)>.cube:nth-child(6) { + transform: translate3d(0em, -4em, -4em); + } + + :not(.pos)>.cube:nth-child(7) { + transform: translate3d(0em, -4em, 0em); + } + + :not(.pos)>.cube:nth-child(8) { + transform: translate3d(0em, -4em, 4em); + } + + :not(.pos)>.cube:nth-child(9) { + transform: translate3d(0em, 0em, -4em); + } + + :not(.pos)>.cube:nth-child(10) { + transform: translate3d(0em, 0em, 0em); + } + + :not(.pos)>.cube:nth-child(11) { + transform: translate3d(0em, 0em, 4em); + } + + :not(.pos)>.cube:nth-child(12) { + transform: translate3d(0em, 4em, -4em); + } + + :not(.pos)>.cube:nth-child(13) { + transform: translate3d(0em, 4em, 0em); + } + + :not(.pos)>.cube:nth-child(14) { + transform: translate3d(0em, 4em, 4em); + } + + .pos:nth-child(5) { + transform: scale3d(-1, 1, 1) translate3d(4em, 4em, 4em); + } + + :not(.pos)>.cube:nth-child(15) { + transform: translate3d(4em, -4em, 0em); + } + + .pos:nth-child(6) { + transform: scale3d(-1, 1, -1) translate3d(4em, 4em, 4em); + } + + :not(.pos)>.cube:nth-child(16) { + transform: translate3d(4em, 0em, -4em); + } + + :not(.pos)>.cube:nth-child(17) { + transform: translate3d(4em, 0em, 0em); + } + + :not(.pos)>.cube:nth-child(18) { + transform: translate3d(4em, 0em, 4em); + } + + .pos:nth-child(7) { + transform: scale3d(-1, -1, 1) translate3d(4em, 4em, 4em); + } + + :not(.pos)>.cube:nth-child(19) { + transform: translate3d(4em, 4em, 0em); + } + + .pos:nth-child(8) { + transform: scale3d(-1, -1, -1) translate3d(4em, 4em, 4em); + } + + .pos .cube { + animation: m 2s ease-out infinite; + } + + .cube__face { + margin: -2em; + width: 4em; + height: 4em; + box-shadow: 0 0 2em rgba(220, 220, 220, 0.5) inset; + backface-visibility: hidden; + background: whitesmoke; + } + + .cube__face:nth-child(2n) { + filter: brightness(0.97); + } + + .cube__face:nth-child(n + 5) { + filter: brightness(1.03); + } + + .cube__face:nth-child(1) { + transform: rotateY(0deg) translateZ(2em); + } + + .cube__face:nth-child(2) { + transform: rotateY(90deg) translateZ(2em); + } + + .cube__face:nth-child(3) { + transform: rotateY(180deg) translateZ(2em); + } + + .cube__face:nth-child(4) { + transform: rotateY(270deg) translateZ(2em); + } + + .cube__face:nth-child(5) { + transform: rotateX(90deg) translateZ(2em); + } + + .cube__face:nth-child(6) { + transform: rotateX(-90deg) translateZ(2em); + } + + @keyframes m { + + 0%, + 5%, + 95%, + 100% { + transform: none; + } + + 15% { + transform: translate3d(0, 4em, 0); + } + + 25% { + transform: translate3d(0, 4em, 4em); + } + + 35%, + 65% { + transform: translate3d(4em, 4em, 4em); + } + + 75% { + transform: translate3d(4em, 0, 4em); + } + + 85% { + transform: translate3d(4em, 0, 0); + } + } \ No newline at end of file diff --git a/src/assets/css/panels/friends.css b/src/assets/css/panels/friends.css new file mode 100644 index 0000000..61baa41 --- /dev/null +++ b/src/assets/css/panels/friends.css @@ -0,0 +1,57 @@ +.has-separation { + margin: 30px; +} + +.center { + text-align: center; +} + +.lista-de-amigos { + display: flex; + flex-wrap: wrap; + justify-content: space-between; +} + +.friend-card { + width: calc(50% - 20px); + margin: 10px; + min-height: 120px; + max-height: 120px; +} + +.friend-username { + font-size: 23px; + display: inline; +} + +.status-overlay { + position: absolute; + bottom: -10px; + right: -5px; +} + +.resultado-amigos::-webkit-scrollbar { + width: var(--scroll-size, 15px); +} + +.resultado-amigos::-webkit-scrollbar-thumb { + background: var(--scroll-thumb, linear-gradient(45deg, #00aeff, #a68eff)); +} + +.resultado-amigos::-webkit-scrollbar-track { + background: var(--scroll-track, rgb(255 255 255 / 10%)); +} + +.panel-amigos { + position: fixed; + overflow-y: auto; + top: 45%; + left: 50%; + transform: translate(-50%, -45%); + width: 90%; + height: 70%; +} + +.panel-amigos::-webkit-scrollbar { + width: 0px; +} diff --git a/src/assets/css/panels/home.css b/src/assets/css/panels/home.css new file mode 100644 index 0000000..a4352c1 --- /dev/null +++ b/src/assets/css/panels/home.css @@ -0,0 +1,406 @@ +@import "https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css"; + +.swal-overlay { font-family: "Poppins"} + +span, div { + font-family: 'Poppins'; +} + +.player-head { + margin: auto 30px; + background-image: url("../../images/default/setve.png"); + background-size: cover; + background-position: center; + background-repeat: no-repeat; + background-color: transparent; + width: 3.8%; + height: 60%; + border: none; + border-radius: 15px; + position: absolute; + left: 5%; + top: -10%; + margin: 2%; + transition: all 0.5s cubic-bezier(1, 0.46, 0, 1.29); +} + +.player-head:hover { + border-radius: 5px; + transition: all 0.5s cubic-bezier(1, 0.46, 0, 1.29); +} + +.button { + font-weight: 700; +} + + +.body-home { + display: flex; + height: 78vh; + margin: 3rem 2rem; + scrollbar-width: none; +} + + +.news-list { + position: relative; + overflow: auto; + width: 100%; +} + +.news-list::-webkit-scrollbar { + width: 0; +} + +.news-block { + margin-bottom: 1rem; + transition: opacity 1s; + opacity: .4; +} + +.news-block:hover { + transition: opacity 1s; + opacity: 1; +} + +.opacity-1 { + opacity: 1; +} + +.news-header { + position: relative; + top: 0px; + left: 0px; + width: 100%; + height: 87px; + background-color: #292929; + border-radius: 5px 5px 0px 0px; + transition: color .2s, filter .2s; +} + +.title_ { + position: absolute; + font: normal normal bold 27px/40px Poppins; + letter-spacing: 0px; + color: #E1E1E1; + display: flex; + position: absolute; + text-decoration: none; + max-width: calc(100% - 158px); + font-weight: 600; + font-size: 18px; + top: 50%; + left: 30px; + transform: translate(0, -50%); + overflow: hidden; + line-height: 25px; + align-items: center; + height: 3em; + transition: color .2s; +} + +.date { + position: absolute; + top: 15px; + right: 20px; + color: #E1E1E1; + width: 75px; + text-align: center; + font-weight: 900; + font-family: Poppins; + transition: color .2s; +} + +.day { + font-size: 28px; + margin-bottom: -10px; + display: block; +} + +.month { + text-transform: uppercase; + font-size: 13px; +} + +.news-content { + position: relative; + width: 100%; +} + +.bbWrapper { + position: relative; + padding: 20px; + background-color: #1f1f1f; + font-family: Poppins; + font-size: 13px !important; + color: #E1E1E1; + text-decoration: none; + border-radius: 0px 0px 5px 5px; + transition: color .2s; +} + +.news-author { + text-align: end; + margin: 0; + color: #F1F1F1; +} + +.news-author span { + font-style: italic; +} + +.info-list { + position: relative; + width: 65vh; + padding-left: 1rem; + background: none; + text-align: center; + opacity: 1; +} + +@keyframes fadeIn { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } +} + +.server { + position: relative; + width: 100%; + height: 60px; + background-color: #292929; + border-radius: 5px; + opacity: .4; + margin-bottom: -15px; +} + +.server1 { + position: relative; + width: 100%; + height: 60px; + background-color: #292929; + border-radius: 5px; + opacity: .4; + margin-bottom: -15px; + } + +.server:hover { + transition: opacity 1s; + opacity: 1; +} + +.server1:hover { + transition: opacity 1s; + opacity: 1; +} + +.server-img { + position: absolute; + width: 45px; + height: 45px; + top: 6px; + left: 15px; +} + +.music-img { + position: absolute; + width: 40px; + height: 40px; + top: 10px; + left: 15px; + object-fit: cover; + /* Añadido para ajustar la imagen al cuadro sin distorsionarla */ + background-size: cover; + /* Asegura que la imagen de fondo se ajuste al cuadro */ +} +.name { + position: absolute; + font: normal normal bold 17px/25px Poppins; + color: #E1E1E1; + top: 10px; + left: 70px; + transition: color .2s; +} + +.name1 { + position: absolute; + font: normal normal bold 17px/25px Poppins; + color: #E1E1E1; + top: 15px; + left: 70px; + transition: color .2s; +} + +.btn-mods { + position: absolute; + font: normal normal bold 17px/25px Poppins; + color: #000; + top: 40px; + left: 50%; + transform: translate(-50%, 0); + transition: color .2s; + align-items: center; + justify-content: center; + +} + +.nombre { + position: relative; + font: normal normal bold 17px/25px Poppins; + color: #E1E1E1; + top: 10px; + left: 50%; + transform: translate(-50%, 0); + transition: color .2s; +} + +.desc { + position: absolute; + font: normal normal normal 11px/17px Poppins; + color: #E1E1E1; + transition: all .2s; + top: 30px; + left: 70px; + transition: color .2s; +} + +.green { + color: #1AC707; +} + +.red { + color: #FF0409; +} + +.etat-text { + position: absolute; + top: 20px; + right: 14px; + width: 49px; + height: 33px; + background-color: #292929; + border-radius: 4px; + transition: background-color .2s; +} + +.text { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + font: normal normal bold 13px/15px Poppins; + letter-spacing: 0px; + color: #E1E1E1; + transition: color .2s; +} + +.online { + position: absolute; + top: -6px; + left: 41px; + width: 10px; + height: 10px; + border-radius: 5px; + border: 2px solid #1A1A1A; + transition: all .2s; + background-color: #1AC707; +} + +.online.off { + background-color: #FF0409; +} + +body, html { + height: 100%; + margin: 0; + font-family: 'Poppins'; + font-weight: 700; + overflow: hidden; + background-repeat: no-repeat; + background-size: 100%; +} + +* { + font-family: 'Poppins'; + font-weight: 700; +} + +.bottom_bar { + opacity: 1; + display: flex; + justify-content: space-between; + align-items: center; + height: 75px; + padding: 0 20px; + background-color: #1f1f1f; + position: fixed; + bottom: 0; + left: 0; + width: 100%; + z-index: 9999; +} + +.button { + height: 45px; + margin-left: 5px; + border-radius: 5px; +} + +#settings-btn { + margin-left: 0px; + margin-right: 0px; + width: 45px; +} + +#btnShowNews { + width: 45px; +} + +#play-btn { + margin-right: 0px; +} + +*, div { + font-family: 'Poppins'; + font-weight: 700; +} + + .errores::-webkit-scrollbar { + width: var(--scroll-size, 15px); + } + + .errores::-webkit-scrollbar-thumb { + background: var(--scroll-thumb, linear-gradient(45deg, #00aeff, #a68eff)); + border-radius: var(--scroll-radius, 3px); + } + + .errores::-webkit-scrollbar-track { + background: var(--scroll-track, rgb(255 255 255 / 10%)); + } + + .modal-card-body::-webkit-scrollbar { + width: var(--scroll-size, 15px); + } + + .modal-card-body::-webkit-scrollbar-thumb { + background: var(--scroll-thumb, linear-gradient(45deg, #00aeff, #a68eff)); + } + + .modal-card-body::-webkit-scrollbar-track { + background: var(--scroll-track, rgb(255 255 255 / 10%)); + } + + .ad { + position: relative; + width: 100%; + height: 180px; + border-radius: 5px; + opacity: 1; + margin-bottom: -20px; + background-image: url('https://api.battlylauncher.com/ads/get'); + background-size: cover; + background-repeat: no-repeat; + } \ No newline at end of file diff --git a/src/assets/css/panels/login.css b/src/assets/css/panels/login.css new file mode 100644 index 0000000..84993c2 --- /dev/null +++ b/src/assets/css/panels/login.css @@ -0,0 +1,154 @@ + +.login-card { + position: absolute; + top: 52%; + left: 50%; + transform: translate(-50%, -50%); + width: 35%; + background: #121212; + padding: 20px; + font: normal normal bold 19px/29px Poppins; + color: #E1E1E1; + border-radius: 5px; + text-align: center; +} + +.swal-overlay { font-family: "Poppins"} + +.login-type { + display: grid; + padding: 0 7%; +} + +.login-type-btn { + border-radius: 5px; + border: none; + margin: 2% 0; + height: 2em; + background-color: #3e8ed0; + color: #121212; + font: normal normal bold 19px/29px Poppins; + cursor: pointer; +} + +.login-type-btn:hover { + background-color: #2c9bf6; + box-shadow: 0 0 5px #54b2ff; +} + +.login-type-btn:disabled { + background-color: #41c3ff; + box-shadow: 0 0 5px #3ea8ff; + cursor: default; +} + +.login-type-btn:disabled:hover { + background-color: #41c3ff; + box-shadow: 0 0 5px #3ea8ff; +} + +.login-card-mojang { + position: absolute; + top: 52%; + left: 50%; + transform: translate(-50%, -50%); + width: 35%; + background: #121212; + padding: 0 20px; + font: normal normal bold 19px/29px Poppins; + color: #E1E1E1; + border-radius: 5px; + display: none; +} + +.login-card-offline { + position: absolute; + top: 52%; + left: 50%; + transform: translate(-50%, -50%); + width: 35%; + background: #121212; + padding: 0 20px; + font: normal normal bold 19px/29px Poppins; + color: #E1E1E1; + border-radius: 5px; + display: none; +} + +.info-login { + align-items: center; + display: flex; + justify-content: center; + margin: 10% 0; + font-size: 0.8em; + text-align: center; +} + +.card-body { + margin: 10%; +} + +.login-card-mojang-input { + text-align: center; + display: grid; +} + +.login-card-offline-input { + text-align: center; + display: grid; +} + +.login-mojang-input { + font-family: 'Poppins'; + letter-spacing: 2px; + color: #fff; + border: solid 0px rgba(0, 0, 0, 0); + border-radius: 5px; + background-color: #373737; + padding: 0.375rem 0.75rem; + text-align: center; + width: 100%; +} + +.loginDisclaimerText { + text-align: center; + font-size: 0.5em; +} + +.btn-option-login { + width: 100%; + display: grid; + text-align: center; +} + +.login-btn { + border-radius: 5px; + border: none; + margin: 2% 0; + height: 2em; + background-color: #3e8ed0; + color: #121212; + font: normal normal bold 19px/29px Poppins; + cursor: pointer; +} + +.login-btn:hover { + background-color: #3e8ed0; +} + +.cancel { + border: none; + background-color: #ffffff00; + color: #F1F1F1; + font: normal normal bold 19px/29px Poppins; + cursor: pointer; +} + +.cancel:hover { + color: #373737; +} + +.cancel:hover:disabled { + color: #F1F1F1; + cursor: default; +} \ No newline at end of file diff --git a/src/assets/css/panels/mods.css b/src/assets/css/panels/mods.css new file mode 100644 index 0000000..7ee1a26 --- /dev/null +++ b/src/assets/css/panels/mods.css @@ -0,0 +1,328 @@ +@import "https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css"; + +.feature-card2-feature-card { + border: 3px solid dimgrey; + width: 100%; + display: flex; + padding: var(--dl-space-space-unit); + position: relative; + align-items: flex-start; + flex-direction: row; + justify-content: flex-start; + background-color: #151515; + opacity: 0.9; + border-radius: 6px; + margin: -5px; + } + .feature-card2-icon { + fill: var(--dl-color-gray-500); + width: 5rem; + height: 5rem; + flex-shrink: 0; + margin-right: var(--dl-space-space-oneandhalfunits); + border-radius: 4px; + } + .feature-card2-container { + display: flex; + align-items: flex-start; + flex-direction: column; + justify-content: flex-start; + } + + .feature-card2-container::-webkit-scrollbar { + width: 0; +} + + + .feature-card2-text { + color: #fff; + font-weight: 700; + font-size: 20px; + margin-bottom: 0px; + } + + .feature-card2-downloads { + position: absolute; + display: flex; + bottom: 7%; + left: 6%; + } + + .feature-card2-download { + position: absolute; + top: 5%; + right: 1%; + } + + .feature-card2-download-icon { + width: 2.5rem; + height: 2.5rem; + }.feature-card2-feature-card { + width: 100%; + display: flex; + padding: var(--dl-space-space-unit); + position: relative; + align-items: flex-start; + flex-direction: row; + justify-content: flex-start; +} + +@media(max-width: 767px) { + .feature-card2-feature-card { + flex-direction: row; + } + .feature-card2-container { + flex-direction: column; + } +} +@media(max-width: 479px) { + .feature-card2-container { + flex-direction: column; + } +} + +*, html, select, button { + font-weight: 600; + font-family: 'Poppins', sans-serif; +} + + .home-container { + width: 100%; + display: flex; + overflow: auto; + min-height: 100vh; + align-items: center; + flex-direction: column; + justify-content: center; + z-index: 1; + position: absolute; + + } + +.home-container::-webkit-scrollbar { + width: 0; +} + +.modal { + z-index: 10000; +} + +.bottom_bar_mods { + opacity: 1; + display: flex; + justify-content: space-between; + align-items: center; + height: 75px; + padding: 0 20px; + background-color: #1f1f1f; + position: fixed; + bottom: 0; + left: 0; + width: 100%; + z-index: 99; +} +.boton-volver { + position: absolute; + left: 20px; + bottom: 15px; + margin-right: 20px; + font-size: 15px; + font-family: Poppins; + font-weight: 700; +} + +.buscar-mods { + border-radius: 5px; + margin-right: 20px; + width: 50%; + font-size: 15px; + font-family: Poppins; + font-weight: 700; + border: none; + color: #fff; + margin-left: 5px; + height: 40px; +} + + +.buscar-mods::placeholder { +color: #c9c6c6; +} + .home-text { + top: 35px; + left: 48px; + width: auto; + height: auto; + position: absolute; + font-size: 50px; + align-self: flex-start; + max-height: auto; + min-height: auto; + font-family: Poppins; + font-weight: 900; + position: fixed; + z-index: 9999; /* Valor alto para asegurar que esté por encima de todo */ + color: #3e8ed0; + + } + .home-features { + top: 80px; + left: 0px; + width: 100%; + display: flex; + padding: var(--dl-space-space-threeunits); + position: absolute; + max-width: 100%; + align-self: stretch; + flex-direction: column; + scrollbar-width: none; + } + + .home-features::-webkit-scrollbar { + width: 0; +} + .home-container1 { + width: 100%; + display: grid; + grid-gap: var(--dl-space-space-twounits); + grid-template-columns: 1fr 1fr; + } + + .home-container1::-webkit-scrollbar { + width: 0; +} + + .home-container2 { + width: 100%; + border: 2px dashed rgba(120, 120, 120, 0.4); + display: grid; + grid-gap: var(--dl-space-space-twounits); + grid-template-columns: 1fr 1fr; + } + + .home-container2::-webkit-scrollbar { + width: 0; +} + @media(max-width: 767px) { + .home-features { + padding-left: var(--dl-space-space-twounits); + padding-right: var(--dl-space-space-twounits); + } + .home-container1 { + grid-template-columns: 1fr; + } + .home-container2 { + grid-template-columns: 1fr; + } + } + @media(max-width: 479px) { + .home-features { + padding-top: var(--dl-space-space-twounits); + padding-left: var(--dl-space-space-unit); + padding-right: var(--dl-space-space-unit); + padding-bottom: var(--dl-space-space-twounits); + } + } + + html { + font-family: Poppins; + font-size: 16px; + } + + .body-mods { + background-repeat: no-repeat; + background-size: cover; + background-image: url("../../images/background/minecraft_fondo.jpg") !important; + + + } + + +.home-container_ { + width: 85%; + background-color: #6f6f6f; + max-width: var(--dl-size-size-maxwidth); + display: flex; + position: absolute; + top: 15%; /* Ajustamos la posición vertical al 50% */ + left: 50%; /* Ajustamos la posición horizontal al 50% */ + transform: translate(-50%, -50%); /* Centramos tanto en el eje x como en el eje y */ + margin-top: 300px; + z-index: 999; + border: 2px solid #1f1f1f; + border-radius: 10px; + } + .home-hero_ { + width: 100%; + height: 100%; + display: flex; + } + .home-image_ { + width: 30%; + height: 30%; + object-fit: cover; + } + .home-container1_ { + display: flex; + margin-left: var(--dl-space-space-twounits); + flex-direction: column; + } + .home-text_ { + font-size: 3rem; + font-weight: 700; + color:#3e8ed0; + } + .home-text01_ { + margin-top: var(--dl-space-space-unit); + font-weight: 600; + margin-bottom: var(--dl-space-space-unit); + color: #3e8ed0; + font-size: 20px; + font-family: Poppins; + font-weight: 700; + } + .home-btn-group_ { + display: flex; + margin-top: var(--dl-space-space-unit); + align-items: center; + margin-bottom: var(--dl-space-space-unit); + flex-direction: row; + } + .home-button_ { + color: var(--dl-color-primary-300); + transition: 0.3s; + padding-top: var(--dl-space-space-unit); + padding-left: var(--dl-space-space-twounits); + padding-right: var(--dl-space-space-twounits); + padding-bottom: var(--dl-space-space-unit); + background-color: var(--dl-color-gray-black); + font-size: 20px; + font-family: Poppins; + font-weight: 700; + } + .home-button_:hover { + transform: scale(1.02); + } + .home-button1_ { + transition: 0.3s; + margin-left: var(--dl-space-space-unit); + padding-top: var(--dl-space-space-unit); + padding-left: var(--dl-space-space-twounits); + padding-right: var(--dl-space-space-twounits); + padding-bottom: var(--dl-space-space-unit); + font-size: 20px; + font-family: Poppins; + font-weight: 700; + } + .home-button1_:hover { + transform: scale(1.02); + } + .home-text02_ { + margin-top: var(--dl-space-space-twounits); + margin-bottom: var(--dl-space-space-twounits); + padding-right: var(--dl-space-space-threeunits); + font-weight: 700; + } + h1, h2, span, a, button { + font-family: 'Poppins'; + } \ No newline at end of file diff --git a/src/assets/css/panels/mods/style.css b/src/assets/css/panels/mods/style.css new file mode 100644 index 0000000..fd1f970 --- /dev/null +++ b/src/assets/css/panels/mods/style.css @@ -0,0 +1,91 @@ +:root { + --dl-color-gray-500: #595959; + --dl-color-gray-700: #999999; + --dl-color-gray-900: #D9D9D9; + --dl-size-size-large: 144px; + --dl-size-size-small: 48px; + --dl-color-danger-300: #A22020; + --dl-color-danger-500: #BF2626; + --dl-color-danger-700: #E14747; + --dl-color-gray-black: #000000; + --dl-color-gray-white: #FFFFFF; + --dl-size-size-medium: 96px; + --dl-size-size-xlarge: 192px; + --dl-size-size-xsmall: 16px; + --dl-space-space-unit: 10px; + --dl-color-primary-100: #003EB3; + --dl-color-primary-300: #3e8ed0; + --dl-color-primary-500: #14A9FF; + --dl-color-primary-700: #85DCFF; + --dl-color-success-300: #199033; + --dl-color-success-500: #32A94C; + --dl-color-success-700: #4CC366; + --dl-size-size-xxlarge: 288px; + --dl-size-size-maxwidth: 1400px; + --dl-radius-radius-round: 50%; + --dl-space-space-halfunit: 8px; + --dl-space-space-sixunits: 96px; + --dl-space-space-twounits: 32px; + --dl-radius-radius-radius2: 2px; + --dl-radius-radius-radius4: 4px; + --dl-radius-radius-radius8: 8px; + --dl-space-space-fiveunits: 80px; + --dl-space-space-fourunits: 64px; + --dl-space-space-threeunits: 48px; + --dl-space-space-oneandhalfunits: 24px; +} +.input { + color: var(--dl-color-gray-black); + cursor: auto; + padding: 0.5rem 1rem; + border-color: var(--dl-color-gray-black); + border-width: 1px; + border-radius: 4px; + background-color: var(--dl-color-gray-white); +} +.textarea { + color: var(--dl-color-gray-black); + cursor: auto; + padding: 0.5rem; + border-color: var(--dl-color-gray-black); + border-width: 1px; + border-radius: 4px; + background-color: var(--dl-color-gray-white); +} +.list { + width: 100%; + margin: 1em 0px 1em 0px; + display: block; + padding: 0px 0px 0px 1.5rem; + list-style-type: none; + list-style-position: outside; +} +.list-item { + display: list-item; +} +.teleport-show { + display: flex !important; + transform: none !important; +} +.Content { + font-size: 16px; + font-family: Inter; + font-weight: 400; + line-height: 1.15; + text-transform: none; + text-decoration: none; +} +.Heading { + font-size: 32px; + font-family: Inter; + font-weight: 700; + line-height: 1.15; + text-transform: none; + text-decoration: none; +} + +html { line-height: 1.15;}body { margin: 0;}* { box-sizing: border-box; border-width: 0; border-style: solid;}p,li,ul,pre,div,h1,h2,h3,h4,h5,h6,figure,blockquote,figcaption { margin: 0; padding: 0;}button { background-color: transparent;}button,input,optgroup,select,textarea { font-family: inherit; font-size: 100%; line-height: 1.15; margin: 0;}button,select { text-transform: none;}button,[type="button"],[type="reset"],[type="submit"] { -webkit-appearance: button;}button::-moz-focus-inner,[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner { border-style: none; padding: 0;}button:-moz-focus,[type="button"]:-moz-focus,[type="reset"]:-moz-focus,[type="submit"]:-moz-focus { outline: 1px dotted ButtonText;}a { color: inherit; text-decoration: inherit;}input { padding: 2px 4px;}img { display: block;}html { scroll-behavior: smooth } + +h2, span, a { + font-family: 'Poppins'; +} \ No newline at end of file diff --git a/src/assets/css/panels/music-small.css b/src/assets/css/panels/music-small.css new file mode 100644 index 0000000..e69de29 diff --git a/src/assets/css/panels/music.css b/src/assets/css/panels/music.css new file mode 100644 index 0000000..f556ddf --- /dev/null +++ b/src/assets/css/panels/music.css @@ -0,0 +1,392 @@ +@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap'); +*{ + font-family: "Poppins", sans-serif; +} + + +:root{ + --pink: #3e8ed0; + --violet: #3eaed0; + --lightblack: #515C6F; + --white: #ffffff; + --darkwhite: #cecaca; + --pinkshadow: #ffcbdd; + --lightbshadow: rgba(0,0,0,0.15); +} +.top-bar, .progress-area .song-timer, +.controls, .music-list .header, .music-list ul li{ + display: flex; + align-items: center; + justify-content: space-between; +} +.top-bar i{ + font-size: 30px; + color: var(--lightblack); +} +.top-bar i:first-child{ + margin-left: -7px; +} +.top-bar span{ + font-size: 18px; + margin-left: -3px; + color: var(--lightblack); +} +.img-area{ + width: 80%; + height: 210px; + transform: translate(25px, 0px); + overflow: hidden; + margin-top: 25px; + border-radius: 15px; + box-shadow: 0px 6px 12px var(--lightbshadow); +} +.img-area img{ + width: 100%; + height: 100%; + object-fit: cover; +} +.song-details { + text-align: center; + display: flex; + flex-direction: column; /* Cambiar el orden de los elementos a columna */ + align-items: center; /* Centrar horizontalmente */ +} + +.song-details p{ + color: var(--lightblack); +} +.song-details .name{ + font-size: 15px; +} +.song-details .artist{ + font-size: 18px; + opacity: 0.9; +} +.progress-area{ + height: 6px; + width: 100%; + border-radius: 50px; + background: #1f1f1f; + cursor: pointer; +} +.progress-area .progress-bar{ + height: inherit; + width: 0%; + position: relative; + border-radius: inherit; + background: linear-gradient(90deg, var(--pink) 0%, var(--violet) 100%); +} +.progress-bar::before{ + content: ""; + position: absolute; + height: 12px; + width: 12px; + border-radius: 50%; + top: 50%; + right: -5px; + z-index: 2; + opacity: 0; + pointer-events: none; + transform: translateY(-50%); + background: inherit; + transition: opacity 0.2s ease; +} +.progress-area:hover .progress-bar::before{ + opacity: 1; + pointer-events: auto; +} +.progress-area .song-timer{ + margin-top: 2px; +} +.song-timer span{ + font-size: 13px; + color: var(--lightblack); +} +.controls{ + margin: 40px 0 5px 0; +} +.controls i{ + font-size: 28px; + user-select: none; + background: linear-gradient(var(--pink) 0%, var(--violet) 100%); + background-clip: text; + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; +} +.controls i:nth-child(2), +.controls i:nth-child(4){ + font-size: 43px; +} +.controls #prev{ + margin-right: -13px; +} +.controls #next{ + margin-left: -13px; +} +.controls .play-pause{ + height: 54px; + width: 54px; + display: flex; + cursor: pointer; + align-items: center; + justify-content: center; + border-radius: 50%; + background: linear-gradient(#1f1f1f 0%, #585858 100%); + box-shadow: 0px 0px 5px var(--pink); +} +.play-pause::before{ + position: absolute; + content: ""; + height: 43px; + width: 43px; + border-radius: inherit; + background: linear-gradient(var(--pink) 0%, var(--violet) 100%); +} +.play-pause i{ + height: 43px; + width: 43px; + line-height: 43px; + text-align: center; + background: inherit; + background-clip: text; + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + position: absolute; +} + +.music-list{ + position: absolute; + background: var(--white); + width: 100%; + left: 0; + bottom: -55%; + opacity: 0; + pointer-events: none; + z-index: 5; + padding: 15px 30px; + border-radius: 15px; + box-shadow: 0px -5px 10px rgba(0,0,0,0.1); + transition: all 0.15s ease-out; +} +.music-list.show{ + bottom: 0; + opacity: 1; + pointer-events: auto; +} +.header .row{ + display: block; + font-size: 20px; + color: var(--lightblack); +} +.header .row i{ + cursor: default; +} +.header .row span{ + font-size: 20px; +} +.header #close{ + font-size: 22px; + color: var(--lightblack); +} +.music-list ul{ + margin: 10px 0; + max-height: 260px; + overflow: auto; +} +.music-list ul::-webkit-scrollbar{ + width: 0px; +} +.music-list ul li{ + list-style: none; + display: flex; + cursor: pointer; + padding-bottom: 10px; + margin-bottom: 5px; + color: var(--lightblack); + border-bottom: 1px solid #E5E5E5; +} +.music-list ul li:last-child{ + border-bottom: 0px; +} +.music-list ul li .row p{ + opacity: 0.9; +} +ul li .audio-duration{ + font-size: 15px; +} +ul li.playing{ + pointer-events: none; + color: var(--violet); +} +body { + display: flex; /* Agregar display: flex para ajustar automáticamente al tamaño de la ventana */ +} + +.musicplayer { + width: 25%; + height: 75vh; + overflow: hidden; + margin-right: 2%; + margin-left: 3%; + /* Reducir el margen izquierdo para mantener el ancho total menor que el ancho de la ventana */ + margin-top: 4%; + border-radius: 15px; +} + +.search { + width: 65%; + height: 75vh; + overflow: auto; + margin-right: 3%; + margin-left: 2%; + margin-top: 4%; + border-radius: 15px; +} + + +/* Estilos de la barra de desplazamiento (ten en cuenta que estos estilos pueden no funcionar en todos los navegadores) */ +.search::-webkit-scrollbar { + width: var(--scroll-size, 15px); +} + +.search::-webkit-scrollbar-thumb { + background: var(--scroll-thumb, linear-gradient(45deg, #00aeff, #a68eff)); + border-radius: var(--scroll-radius, 20px); +} + +.search::-webkit-scrollbar-track { + background: var(--scroll-track, rgb(255 255 255 / 10%)); +} + + +.search-container { + display: flex; + align-items: center; /* Centrar verticalmente */ +} + + +#volumen { + -webkit-appearance: none; + background: transparent; + width: 90%; + max-width: 500px; + outline: none; +} +#volumen:focus, +#volumen:active, +#volumen::-moz-focus-inner, +#volumen::-moz-focus-outer { + border: 0; + outline: none; +} +#volumen::-moz-range-thumb { + border: none; + height: 50px; + width: 50px; + background-color: transparent; + background-image: url("https://storage.googleapis.com/pw-stuff/thumbs-sprite.png"); + background-position: 0 0; + background-size: cover; + transform: scale(1.9) rotateZ(var(--thumb-rotate, 10deg)); + cursor: pointer; +} +#volumen::-moz-range-thumb:active { + background-position: 100% 0px; + transform: scale(2) rotateZ(var(--thumb-rotate, 10deg)); +} +#volumen::-moz-range-track { + width: 100%; + height: 20px; + background: #eee; + border-radius: 10px; + box-shadow: 2px 2px 4px rgba(0,0,0,0.4); + cursor: pointer; +} +#volumen::-moz-range-progress { + height: 20px; + background: #4685d7; + border-radius: 10px; + cursor: pointer; +} +#volumen::-webkit-slider-thumb { + border: none; + height: 25px; + width: 25px; + background-color: transparent; + background-image: url("https://storage.googleapis.com/pw-stuff/thumbs-sprite.png"); + background-position: 0 0; + background-size: cover; + transform: scale(1.9) rotateZ(var(--thumb-rotate, 10deg)); + cursor: pointer; + margin-top: -5px; + -webkit-appearance: none; +} +#volumen::-webkit-slider-thumb:active { + background-position: 100% 0px; + transform: scale(2) rotateZ(var(--thumb-rotate, 10deg)); +} +#volumen::-webkit-slider-runnable-track { + width: 100%; + height: 20px; + background: #eee; + border-radius: 10px; + box-shadow: 2px 2px 4px rgba(0,0,0,0.4); + cursor: pointer; + -webkit-appearance: none; +} + +#label-volumen { + font-size: 20px; + color:#3e8ed0; + opacity: 1; +} + + +.cards { + display: flex; + overflow: hidden; + margin-top: 10px; + margin-bottom: 10px; +} + +.grab { + cursor: grab; +} + +.thumbnail { + width: 20%; + height: 22%; + object-fit: cover; + margin-left: 10px; + margin-top: auto; + margin-bottom: auto; + border-radius: 5px; +} + +.card-content1 { + flex: 1; + display: flex; + flex-direction: column; +} + +.song-title { + font-size: 25px; + font-weight: bold; + margin-bottom: 8px; +} + +.artist { + font-size: 20px; + color: #888; +} + +.delete-button { + color: #fff; + align-self: flex-end; +} + +/* Estilos adicionales para el efecto de selección */ +.seleccionado { + background-color: #3e8ed0; + color: white; +} \ No newline at end of file diff --git a/src/assets/css/panels/settings.css b/src/assets/css/panels/settings.css new file mode 100644 index 0000000..8fae601 --- /dev/null +++ b/src/assets/css/panels/settings.css @@ -0,0 +1,510 @@ +.tabs-settings-btn { + position: fixed; + bottom: 0; + width: 100%; + height: 85px; + border-top-left-radius: 10px; + border-top-right-radius: 10px; + background: #00000080; + display: flex; + justify-content: center; +} + +.swal-overlay { font-family: "Poppins"} + +.media-content, section { + overflow: hidden; +} + +.modal-card-body { + overflow: hidden; +} + +.tab-btn-css { + border-radius: 5px; + width: auto; + height: 37px; + margin: 10px; + font-family: Poppins; + font-weight: 700; + font-size: 17px; + cursor: pointer; + outline: none; + color: #fff; +} + +.tab-btn-css:hover { + background: #3e8ed0; +} + + +.bottom_bar_settings { + display: flex; + justify-content: space-between; + align-items: center; + height: 75px; + padding: 0 20px; + background-color: #1f1f1f; + position: fixed; + bottom: 0; + left: 0; + width: 100%; + z-index: 999; + overflow: -moz-scrollbars-none; + -ms-overflow-style: none; + overflow-y: scroll; + overflow-x: hidden; + display: flex; + justify-content: center; + align-items: center; +} + +.bottom_bar_settings::-webkit-scrollbar { + width: 0; +} + +.active-tab-btn { + background: #3ea8ff; + border: none; + box-shadow: 0 0 5px #1e4e76; +} + +.active-tab-btn:hover { + background: #3e8ed0; + border: none; +} + +.tabs-settings-content { + position: absolute; + top: 47%; + left: 50%; + transform: translate(-50%, -50%); + width: 95%; + height: 80%; + padding-bottom: 1.5rem; + border-radius: 5px; + background: transparent; + opacity: 0; + pointer-events: none; +} + +.active-tab-content { + opacity: 1; + pointer-events: all; +} + +.information { + padding: 0 40px; + font: normal normal normal 16px/25px Poppins; + color: #F1F1F1; +} + +.title-settings { + text-align: center; + font: normal normal bold 20px/25px Poppins; + color: #F1F1F1; + margin: 2% 0; +} + +.center-align { + text-align: center; +} + +.settings-content-scroll { + overflow: auto; + width: 100%; + height: 100%; +} + +.settings-content-scroll::-webkit-scrollbar { + width: 0; +} + +.center-page { + top: 47%; + left: 50%; + transform: translate(-50%, -50%); + position: absolute; + width: 100%; +} + + +/******************************************************************************* + * * + * account sttings * + * * + ******************************************************************************/ + +.add-account { + width: 70%; + height: 10%; + border: none; + border-radius: 5px; + font: normal normal bold 30px/40px Poppins; + color: #D1D1D1; + background-color: #303030; + box-shadow: 1px 2px 5px #585858; + margin: 20px 0; + margin-bottom: 10px; +} + +.add-account:hover { + background-color: #005daa; + box-shadow: 1px 2px 5px #275276; +} + +.accounts { + display: contents; + justify-content: center; +} + +.account { + display: inline-block; + background: #3e8ed0; + border: 4px solid #005daa; + font: normal normal bold 30px/40px Poppins; + width: 500px; + height: 100px; + margin: 1% 2%; + border-radius:5px; + text-align: start; + color: #fff; +} + +.account:hover { + background: #005daa; + border: 4px solid #275276; +} + + +.active-account { + background: #3e8ed0; + border: 4px solid #00ff91; + color: #fff; +} + +.active-account:hover { + background: #005daa; + border: 4px solid #275276; +} + + +.account-image { + position: absolute; + height: 70px; + margin: 15px 20px; + pointer-events: none; +} + +.account-name { + margin: 0 100px; + margin-top: 25px; + font: normal normal bold 40px/45px Poppins; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + max-width: 29ch; + pointer-events: none; +} + +.account-uuid { + margin: 0 100px; + font: normal normal normal 18px/27px Poppins; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + max-width: 29ch; + pointer-events: none; +} + +.account-delete { + margin: -50px 415px; + font-size: 50px; + width: 65px; + height: 65px; + border-radius: 5px; + cursor: pointer; + text-align: center; +} + +.icon-account-delete-btn { + margin: 7px 9px; + position: absolute; + pointer-events: none; +} + + +/******************************************************************************* + * * + * java settings * + * * + ******************************************************************************/ + +.java-settings { + background: #292929; + border-radius: 5px; + width: 90%; + margin: 0 auto; + padding: 20px; +} + +.memory-slider { + position: relative; + margin: 24px; + height: 18px; + width: 550px; + user-select: none; +} + +.slider-touch-left, +.slider-touch-right { + box-sizing: border-box; + display: block; + position: absolute; + height: 18px; + width: 18px; + z-index: 2; + top: 4; +} + +.slider-touch-left span, +.slider-touch-right span { + display: block; + width: 20px; + height: 10px; + background: #F1F1F1; + border: 4px solid #3e8ed0; + transition: background-color .2s, border .2s; + border-radius: 18px; + cursor: pointer; +} + +.slider-touch-left span:after, +.slider-touch-right span:after { + content: attr(value); + color: #3e8ed0; + font: normal normal bold 12px/18px Poppins; + white-space: nowrap; + pointer-events: none; + position: absolute; + top: -20px; + left: 83%; + transform: translate(-50%); +} + +.slider-line { + box-sizing: border-box; + position: absolute; + width: calc(100% - 18px); + left: 9px; + top: 7px; + height: 4px; + border-radius: 4px; + background-color: #F0F0F0; + transition: background-color .2s; + z-index: 0; + overflow: hidden; +} + +.slider-line span { + display: block; + height: 100%; + width: 0%; + background: #3e8ed0; + transition: background-color .2s; +} + +.ram-info { + display: flex; + align-items: center; + font: normal normal bold 15px/25px Poppins; + color: #F1F1F1F1; +} + +.path { + min-width: 50%; + font: normal normal normal 13px/20px Poppins; + border-radius: 18px; + padding: 8px 16px; + margin: 0 40px; + margin-top: 2%; + color: #F1F1F1F1; + background-color: #1f1f1f; + user-select: text; + transition: color .2s, background-color .2s; + border: none; + outline: none; +} + +.path-button { + font: normal normal bold 13px/20px Poppins; + border-radius: 18px; + padding: 8px 30px; + background-color: #00bd7a; + cursor: pointer; + margin-left: 20px; + transition: color .2s, background-color .2s; + border: none; + outline: none; +} + +.path-button:hover { + background-color: #1f1f1f; +} + +.path-button-reset { + font: normal normal bold 13px/20px Poppins; + border-radius: 18px; + padding: 8px 30px; + background-color: #00bd7a; + cursor: pointer; + margin-left: 20px; + transition: color .2s, background-color .2s; + border: none; + outline: none; +} + +.path-button-reset:hover { + background-color: #1f1f1f; +} + +.path-file { + display: none; + pointer-events: none; +} + +.args-settings { + min-width: 50%; + font: normal normal normal 13px/20px Poppins; + border-radius: 18px; + padding: 8px 16px; + margin: 0 40px; + margin-top: 2%; + color: #F1F1F1F1; + background-color: #1f1f1f; + user-select: text; + transition: color .2s, background-color .2s; + border: none; + outline: none; +} + + +/******************************************************************************* + * * + * resolution settings * + * * + ******************************************************************************/ + +.input-size-content { + height: 5rem; +} + +.input-size { + position: absolute; + display: flex; + left: 50%; + top: 70%; + transform: translate(-50%, 0); +} + +.input-settings { + text-align: center; + background: #1f1f1f; + border: none; + outline: none; + border-radius: 40px; + font-size: 20px; + width: 100px; + color: #F1F1F1F1; +} + +.size-cross { + margin: 10px; +} + +.size-cross:before { + font: normal normal bold 20px Icons; + content: "\e90e"; +} + +.select-wrap { + display: inline-flex; + margin-left: 10px; +} + +.select-wrap:before { + position: absolute; + top: 53%; + transform: translate(20px, -50%); + font-size: 24px; + pointer-events: none; +} + +.select-wrap:after { + position: relative; + top: -6px; + content: "\e903"; + font-family: 'Icons'; + margin-left: -1.2em; + font-size: 24px; + pointer-events: none; + transform: rotate(180deg); + color: black; + transition: color .2s; + pointer-events: none; +} + +.select { + border-radius: 40px; + background-color: #00bd7a; + font: normal normal normal 12px/18px Poppins; + transition: color .2s, box-shadow .2s; + border: none; + outline: none; + appearance: none; +} + + +/******************************************************************************* + * * + * launcher settings * + * * + ******************************************************************************/ + .checkbox-settings { + display: none; +} + +.checkbox-settings+label { + display: inline; + position: relative; + top: 2px; + margin-right: 24px; + width: 16px; + height: 16px; + border-radius: 8px; + transition: background-color .2s; + padding: 0px; + background-color: #FFFFFF; + cursor: pointer; +} + +.checkround { + position: absolute; + z-index: 2; + border-radius: 7px; + transition: all .2s; + background-color: #FFFFFF; +} + +.checkbox-settings:checked+label { + background-color: #285880; +} + +.checkround { + border-radius: 3px; +} + +.checkbox-settings+label { + display: inline-block; + margin-right: 8px; +} \ No newline at end of file diff --git a/src/assets/css/skin.css b/src/assets/css/skin.css new file mode 100644 index 0000000..a5a1254 --- /dev/null +++ b/src/assets/css/skin.css @@ -0,0 +1,1359 @@ +/*! + * Copyright 2018 Robert Koszewski + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + @keyframes spin { + from { + transform: rotateY(360deg); + } + to { + transform: rotateY(0); + } + } + @keyframes waving { + 0% { + transform: rotateX(-2deg); + } + 50% { + transform: rotateX(2deg); + } + 100% { + transform: rotateX(-2deg); + } + } + .mc-face-viewer-4x { + image-rendering: optimizeSpeed; + /* Legal fallback */ + image-rendering: -moz-crisp-edges; + /* Firefox */ + image-rendering: -o-crisp-edges; + /* Opera */ + image-rendering: -webkit-optimize-contrast; + /* Safari */ + image-rendering: optimize-contrast; + /* CSS3 Proposed */ + image-rendering: crisp-edges; + /* CSS4 Proposed */ + image-rendering: pixelated; + /* CSS4 Proposed */ + -ms-interpolation-mode: nearest-neighbor; + /* IE8+ */ + background-size: 256px; + width: 32px; + height: 32px; + background-position: -32px -32px; + overflow: hidden; + display: inline-block; + } + .mc-face-viewer-4x::after { + content: " "; + width: 32px; + height: 32px; + background-size: 288px; + background-image: inherit; + background-position: -182px -38px; + overflow: hidden; + display: inline-block; + } + .mc-face-viewer-8x { + image-rendering: optimizeSpeed; + /* Legal fallback */ + image-rendering: -moz-crisp-edges; + /* Firefox */ + image-rendering: -o-crisp-edges; + /* Opera */ + image-rendering: -webkit-optimize-contrast; + /* Safari */ + image-rendering: optimize-contrast; + /* CSS3 Proposed */ + image-rendering: crisp-edges; + /* CSS4 Proposed */ + image-rendering: pixelated; + /* CSS4 Proposed */ + -ms-interpolation-mode: nearest-neighbor; + /* IE8+ */ + background-size: 512px; + width: 64px; + height: 64px; + background-position: -64px -64px; + overflow: hidden; + display: inline-block; + } + .mc-face-viewer-8x::after { + content: " "; + width: 64px; + height: 64px; + background-size: 576px; + background-image: inherit; + background-position: -364px -76px; + overflow: hidden; + display: inline-block; + } + .mc-skin-viewer-9x { + width: 72px; + height: 288px; + margin: 15px auto 40px auto; + perspective: 800px; + perspective-origin: 50% 100px; + transform-style: preserve-3d; + background-image: none !important; + image-rendering: optimizeSpeed; + /* Legal fallback */ + image-rendering: -moz-crisp-edges; + /* Firefox */ + image-rendering: -o-crisp-edges; + /* Opera */ + image-rendering: -webkit-optimize-contrast; + /* Safari */ + image-rendering: optimize-contrast; + /* CSS3 Proposed */ + image-rendering: crisp-edges; + /* CSS4 Proposed */ + image-rendering: pixelated; + /* CSS4 Proposed */ + -ms-interpolation-mode: nearest-neighbor; + /* IE8+ */ + } + .mc-skin-viewer-9x.hide-accessories .accessory { + display: none; + } + .mc-skin-viewer-9x.spin > .player { + animation: spin 12s infinite linear; + } + .mc-skin-viewer-9x .player { + transform-style: preserve-3d; + } + .mc-skin-viewer-9x .player .front, + .mc-skin-viewer-9x .player .back, + .mc-skin-viewer-9x .player .left, + .mc-skin-viewer-9x .player .right, + .mc-skin-viewer-9x .player .top, + .mc-skin-viewer-9x .player .bottom { + position: absolute; + background-size: 576px; + background-repeat: no-repeat; + backface-visibility: hidden; + } + .mc-skin-viewer-9x .player .accessory { + background-image: none; + } + .mc-skin-viewer-9x .player .accessory .front, + .mc-skin-viewer-9x .player .accessory .back, + .mc-skin-viewer-9x .player .accessory .left, + .mc-skin-viewer-9x .player .accessory .right, + .mc-skin-viewer-9x .player .accessory .top, + .mc-skin-viewer-9x .player .accessory .bottom { + backface-visibility: visible; + } + .mc-skin-viewer-9x .player > .head { + position: absolute; + transform-style: preserve-3d; + width: 72px; + height: 72px; + margin: 0 auto; + background-image: none !important; + } + .mc-skin-viewer-9x .player > .head .front, + .mc-skin-viewer-9x .player > .head .back, + .mc-skin-viewer-9x .player > .head .left, + .mc-skin-viewer-9x .player > .head .right, + .mc-skin-viewer-9x .player > .head .top, + .mc-skin-viewer-9x .player > .head .bottom { + width: 72px; + height: 72px; + } + .mc-skin-viewer-9x .player > .head .front { + background-position: -72px -72px; + transform: rotateX(0deg) rotateY(0deg) translateX(0px) translateY(0px) translateZ(36px); + } + .mc-skin-viewer-9x .player > .head .back { + background-position: -216px -72px; + transform: rotateX(0deg) rotateY(180deg) translateX(0px) translateY(0px) translateZ(36px); + } + .mc-skin-viewer-9x .player > .head .right { + background-position: 0px -72px; + transform: rotateX(0deg) rotateY(270deg) translateX(0px) translateY(0px) translateZ(36px); + } + .mc-skin-viewer-9x .player > .head .left { + background-position: -144px -72px; + transform: rotateX(0deg) rotateY(90deg) translateX(0px) translateY(0px) translateZ(36px); + } + .mc-skin-viewer-9x .player > .head .top { + background-position: -72px 0px; + transform: rotateX(90deg) rotateY(0deg) translateX(0px) translateY(0px) translateZ(36px); + } + .mc-skin-viewer-9x .player > .head .bottom { + background-position: -144px 0px; + transform: rotateX(270deg) rotateY(0deg) rotateZ(180deg) translateX(0px) translateY(0px) translateZ(36px); + } + .mc-skin-viewer-9x .player > .head > .accessory { + transform-style: preserve-3d; + transform: scale3d(1.125, 1.125, 1.125) translateY(-3.5px); + } + .mc-skin-viewer-9x .player > .head > .accessory > .front { + background-position: -360px -72px; + } + .mc-skin-viewer-9x .player > .head > .accessory > .back { + background-position: -504px -72px; + } + .mc-skin-viewer-9x .player > .head > .accessory > .right { + background-position: -288px -72px; + } + .mc-skin-viewer-9x .player > .head > .accessory > .left { + background-position: -432px -72px; + } + .mc-skin-viewer-9x .player > .head > .accessory > .top { + background-position: -360px 0px; + } + .mc-skin-viewer-9x .player > .head > .accessory > .bottom { + background-position: -432px 0px; + } + .mc-skin-viewer-9x .player > .body { + position: absolute; + transform-style: preserve-3d; + width: 72px; + height: 72px; + margin: 0 auto; + transform: translateY(72px); + background-image: none !important; + } + .mc-skin-viewer-9x .player > .body .front, + .mc-skin-viewer-9x .player > .body .back, + .mc-skin-viewer-9x .player > .body .left, + .mc-skin-viewer-9x .player > .body .right, + .mc-skin-viewer-9x .player > .body .top, + .mc-skin-viewer-9x .player > .body .bottom { + width: 72px; + height: 108px; + } + .mc-skin-viewer-9x .player > .body .left, + .mc-skin-viewer-9x .player > .body .right { + width: 36px; + } + .mc-skin-viewer-9x .player > .body .top, + .mc-skin-viewer-9x .player > .body .bottom { + height: 36px; + } + .mc-skin-viewer-9x .player > .body .front { + background-position: -180px -180px; + transform: rotateX(0deg) rotateY(0deg) translateX(0px) translateY(0px) translateZ(18px); + } + .mc-skin-viewer-9x .player > .body .back { + background-position: -288px -180px; + transform: rotateX(0deg) rotateY(180deg) translateX(0px) translateY(0px) translateZ(18px); + } + .mc-skin-viewer-9x .player > .body .right { + background-position: -144px -180px; + transform: rotateX(0deg) rotateY(270deg) translateX(0px) translateY(0px) translateZ(18px); + } + .mc-skin-viewer-9x .player > .body .left { + background-position: -252px -180px; + transform: rotateX(0deg) rotateY(90deg) translateX(0px) translateY(0px) translateZ(54px); + } + .mc-skin-viewer-9x .player > .body .top { + background-position: -180px -144px; + transform: rotateX(90deg) rotateY(0deg) translateX(0px) translateY(0px) translateZ(18px); + } + .mc-skin-viewer-9x .player > .body .bottom { + background-position: -252px -144px; + transform: rotateX(270deg) rotateY(0deg) translateX(0px) translateY(0px) translateZ(90px); + } + .mc-skin-viewer-9x .player > .body > .accessory { + transform-style: preserve-3d; + transform: scale3d(1.0625, 1.0625, 1.0625) translateY(-3.375px); + } + .mc-skin-viewer-9x .player > .body > .accessory > .front { + background-position: -180px -324px; + } + .mc-skin-viewer-9x .player > .body > .accessory > .back { + background-position: -288px -324px; + } + .mc-skin-viewer-9x .player > .body > .accessory > .right { + background-position: -144px -324px; + } + .mc-skin-viewer-9x .player > .body > .accessory > .left { + background-position: -252px -324px; + } + .mc-skin-viewer-9x .player > .body > .accessory > .top { + background-position: -180px -288px; + } + .mc-skin-viewer-9x .player > .body > .accessory > .bottom { + background-position: -252px -288px; + } + .mc-skin-viewer-9x .player > .left-arm, + .mc-skin-viewer-9x .player > .right-arm { + position: absolute; + transform-style: preserve-3d; + width: 36px; + height: 108px; + margin: 0 auto; + transform: translateY(72px) translateX(-36px); + background-image: none !important; + } + .mc-skin-viewer-9x .player > .left-arm .front, + .mc-skin-viewer-9x .player > .right-arm .front, + .mc-skin-viewer-9x .player > .left-arm .back, + .mc-skin-viewer-9x .player > .right-arm .back, + .mc-skin-viewer-9x .player > .left-arm .left, + .mc-skin-viewer-9x .player > .right-arm .left, + .mc-skin-viewer-9x .player > .left-arm .right, + .mc-skin-viewer-9x .player > .right-arm .right, + .mc-skin-viewer-9x .player > .left-arm .top, + .mc-skin-viewer-9x .player > .right-arm .top, + .mc-skin-viewer-9x .player > .left-arm .bottom, + .mc-skin-viewer-9x .player > .right-arm .bottom { + width: 36px; + height: 108px; + } + .mc-skin-viewer-9x .player > .left-arm .top, + .mc-skin-viewer-9x .player > .right-arm .top, + .mc-skin-viewer-9x .player > .left-arm .bottom, + .mc-skin-viewer-9x .player > .right-arm .bottom { + height: 36px; + } + .mc-skin-viewer-9x .player > .left-arm .front, + .mc-skin-viewer-9x .player > .right-arm .front { + background-position: -396px -180px; + transform: rotateX(0deg) rotateY(0deg) translateX(0px) translateY(0px) translateZ(18px); + } + .mc-skin-viewer-9x .player > .left-arm .back, + .mc-skin-viewer-9x .player > .right-arm .back { + background-position: -468px -180px; + transform: rotateX(0deg) rotateY(180deg) translateX(0px) translateY(0px) translateZ(18px); + } + .mc-skin-viewer-9x .player > .left-arm .right, + .mc-skin-viewer-9x .player > .right-arm .right { + background-position: -360px -180px; + transform: rotateX(0deg) rotateY(270deg) translateX(0px) translateY(0px) translateZ(18px); + } + .mc-skin-viewer-9x .player > .left-arm .left, + .mc-skin-viewer-9x .player > .right-arm .left { + background-position: -432px -180px; + transform: rotateX(0deg) rotateY(90deg) translateX(0px) translateY(0px) translateZ(18px); + } + .mc-skin-viewer-9x .player > .left-arm .top, + .mc-skin-viewer-9x .player > .right-arm .top { + background-position: -396px -144px; + transform: rotateX(90deg) rotateY(0deg) translateX(0px) translateY(0px) translateZ(18px); + } + .mc-skin-viewer-9x .player > .left-arm .bottom, + .mc-skin-viewer-9x .player > .right-arm .bottom { + background-position: -432px -144px; + transform: rotateX(270deg) rotateY(0deg) translateX(0px) translateY(0px) translateZ(90px); + } + .mc-skin-viewer-9x .player > .left-arm > .accessory, + .mc-skin-viewer-9x .player > .right-arm > .accessory { + transform-style: preserve-3d; + transform: scale3d(1.0625, 1.0625, 1.0625) translateY(-3.375px); + } + .mc-skin-viewer-9x .player > .left-arm > .accessory .front, + .mc-skin-viewer-9x .player > .right-arm > .accessory .front { + background-position: -396px -324px; + } + .mc-skin-viewer-9x .player > .left-arm > .accessory .back, + .mc-skin-viewer-9x .player > .right-arm > .accessory .back { + background-position: -468px -324px; + } + .mc-skin-viewer-9x .player > .left-arm > .accessory .right, + .mc-skin-viewer-9x .player > .right-arm > .accessory .right { + background-position: -360px -324px; + } + .mc-skin-viewer-9x .player > .left-arm > .accessory .left, + .mc-skin-viewer-9x .player > .right-arm > .accessory .left { + background-position: -432px -324px; + } + .mc-skin-viewer-9x .player > .left-arm > .accessory .top, + .mc-skin-viewer-9x .player > .right-arm > .accessory .top { + background-position: -396px -288px; + } + .mc-skin-viewer-9x .player > .left-arm > .accessory .bottom, + .mc-skin-viewer-9x .player > .right-arm > .accessory .bottom { + background-position: -432px -288px; + } + .mc-skin-viewer-9x .player > .right-arm { + transform: translateY(72px) translateX(72px) scaleX(-1); + } + .mc-skin-viewer-9x .player > .left-leg, + .mc-skin-viewer-9x .player > .right-leg { + position: absolute; + transform-style: preserve-3d; + width: 36px; + height: 108px; + margin: 0 auto; + transform: translateY(180px); + background-image: none !important; + } + .mc-skin-viewer-9x .player > .left-leg .front, + .mc-skin-viewer-9x .player > .right-leg .front, + .mc-skin-viewer-9x .player > .left-leg .back, + .mc-skin-viewer-9x .player > .right-leg .back, + .mc-skin-viewer-9x .player > .left-leg .left, + .mc-skin-viewer-9x .player > .right-leg .left, + .mc-skin-viewer-9x .player > .left-leg .right, + .mc-skin-viewer-9x .player > .right-leg .right, + .mc-skin-viewer-9x .player > .left-leg .top, + .mc-skin-viewer-9x .player > .right-leg .top, + .mc-skin-viewer-9x .player > .left-leg .bottom, + .mc-skin-viewer-9x .player > .right-leg .bottom { + width: 36px; + height: 108px; + } + .mc-skin-viewer-9x .player > .left-leg .top, + .mc-skin-viewer-9x .player > .right-leg .top, + .mc-skin-viewer-9x .player > .left-leg .bottom, + .mc-skin-viewer-9x .player > .right-leg .bottom { + height: 36px; + } + .mc-skin-viewer-9x .player > .left-leg .front, + .mc-skin-viewer-9x .player > .right-leg .front { + background-position: -36px -180px; + transform: rotateX(0deg) rotateY(0deg) translateX(0px) translateY(0px) translateZ(18px); + } + .mc-skin-viewer-9x .player > .left-leg .back, + .mc-skin-viewer-9x .player > .right-leg .back { + background-position: -108px -180px; + transform: rotateX(0deg) rotateY(180deg) translateX(0px) translateY(0px) translateZ(18px); + } + .mc-skin-viewer-9x .player > .left-leg .right, + .mc-skin-viewer-9x .player > .right-leg .right { + background-position: 0px -180px; + transform: rotateX(0deg) rotateY(270deg) translateX(0px) translateY(0px) translateZ(18px); + } + .mc-skin-viewer-9x .player > .left-leg .left, + .mc-skin-viewer-9x .player > .right-leg .left { + background-position: -72px -180px; + transform: rotateX(0deg) rotateY(90deg) translateX(0px) translateY(0px) translateZ(18px); + } + .mc-skin-viewer-9x .player > .left-leg .top, + .mc-skin-viewer-9x .player > .right-leg .top { + background-position: -36px -144px; + transform: rotateX(90deg) rotateY(0deg) translateX(0px) translateY(0px) translateZ(18px); + } + .mc-skin-viewer-9x .player > .left-leg .bottom, + .mc-skin-viewer-9x .player > .right-leg .bottom { + background-position: -72px -144px; + transform: rotateX(270deg) rotateY(0deg) translateX(0px) translateY(0px) translateZ(90px); + } + .mc-skin-viewer-9x .player > .left-leg > .accessory, + .mc-skin-viewer-9x .player > .right-leg > .accessory { + transform-style: preserve-3d; + transform: scale3d(1.03125, 1.03125, 1.03125) translateY(-1.6875px); + } + .mc-skin-viewer-9x .player > .left-leg > .accessory .front, + .mc-skin-viewer-9x .player > .right-leg > .accessory .front { + background-position: -36px -324px; + } + .mc-skin-viewer-9x .player > .left-leg > .accessory .back, + .mc-skin-viewer-9x .player > .right-leg > .accessory .back { + background-position: -108px -324px; + } + .mc-skin-viewer-9x .player > .left-leg > .accessory .right, + .mc-skin-viewer-9x .player > .right-leg > .accessory .right { + background-position: 0px -324px; + } + .mc-skin-viewer-9x .player > .left-leg > .accessory .left, + .mc-skin-viewer-9x .player > .right-leg > .accessory .left { + background-position: -72px -324px; + } + .mc-skin-viewer-9x .player > .left-leg > .accessory .top, + .mc-skin-viewer-9x .player > .right-leg > .accessory .top { + background-position: -36px -288px; + } + .mc-skin-viewer-9x .player > .left-leg > .accessory .bottom, + .mc-skin-viewer-9x .player > .right-leg > .accessory .bottom { + background-position: -72px -288px; + } + .mc-skin-viewer-9x .player > .right-leg { + transform: translateY(180px) translateX(36px) scaleX(-1); + } + .mc-skin-viewer-9x:not(.legacy) .player > .right-arm { + transform: translateY(72px) translateX(72px); + } + .mc-skin-viewer-9x:not(.legacy) .player > .right-arm .front { + background-position: -324px -468px; + } + .mc-skin-viewer-9x:not(.legacy) .player > .right-arm .back { + background-position: -396px -468px; + } + .mc-skin-viewer-9x:not(.legacy) .player > .right-arm .right { + background-position: -288px -468px; + } + .mc-skin-viewer-9x:not(.legacy) .player > .right-arm .left { + background-position: -360px -468px; + } + .mc-skin-viewer-9x:not(.legacy) .player > .right-arm .top { + background-position: -324px -432px; + } + .mc-skin-viewer-9x:not(.legacy) .player > .right-arm .bottom { + background-position: -360px -432px; + } + .mc-skin-viewer-9x:not(.legacy) .player > .right-arm > .accessory .front { + background-position: -468px -468px; + } + .mc-skin-viewer-9x:not(.legacy) .player > .right-arm > .accessory .back { + background-position: -540px -468px; + } + .mc-skin-viewer-9x:not(.legacy) .player > .right-arm > .accessory .right { + background-position: -432px -468px; + } + .mc-skin-viewer-9x:not(.legacy) .player > .right-arm > .accessory .left { + background-position: -504px -468px; + } + .mc-skin-viewer-9x:not(.legacy) .player > .right-arm > .accessory .top { + background-position: -468px -432px; + } + .mc-skin-viewer-9x:not(.legacy) .player > .right-arm > .accessory .bottom { + background-position: -504px -432px; + } + .mc-skin-viewer-9x:not(.legacy) .player > .right-leg { + transform: translateY(180px) translateX(36px); + } + .mc-skin-viewer-9x:not(.legacy) .player > .right-leg .front { + background-position: -180px -468px; + } + .mc-skin-viewer-9x:not(.legacy) .player > .right-leg .back { + background-position: -252px -468px; + } + .mc-skin-viewer-9x:not(.legacy) .player > .right-leg .right { + background-position: -144px -468px; + } + .mc-skin-viewer-9x:not(.legacy) .player > .right-leg .left { + background-position: -216px -468px; + } + .mc-skin-viewer-9x:not(.legacy) .player > .right-leg .top { + background-position: -180px -432px; + } + .mc-skin-viewer-9x:not(.legacy) .player > .right-leg .bottom { + background-position: -216px -432px; + } + .mc-skin-viewer-9x:not(.legacy) .player > .right-leg > .accessory .front { + background-position: -36px -468px; + } + .mc-skin-viewer-9x:not(.legacy) .player > .right-leg > .accessory .back { + background-position: -108px -468px; + } + .mc-skin-viewer-9x:not(.legacy) .player > .right-leg > .accessory .right { + background-position: 0px -468px; + } + .mc-skin-viewer-9x:not(.legacy) .player > .right-leg > .accessory .left { + background-position: -72px -468px; + } + .mc-skin-viewer-9x:not(.legacy) .player > .right-leg > .accessory .top { + background-position: -36px -432px; + } + .mc-skin-viewer-9x:not(.legacy) .player > .right-leg > .accessory .bottom { + background-position: -72px -432px; + } + .mc-skin-viewer-9x.slim .player > .left-arm .front, + .mc-skin-viewer-9x.slim .player > .right-arm .front, + .mc-skin-viewer-9x.slim .player > .left-arm .back, + .mc-skin-viewer-9x.slim .player > .right-arm .back, + .mc-skin-viewer-9x.slim .player > .left-arm .top, + .mc-skin-viewer-9x.slim .player > .right-arm .top, + .mc-skin-viewer-9x.slim .player > .left-arm .bottom, + .mc-skin-viewer-9x.slim .player > .right-arm .bottom { + width: 27px; + } + .mc-skin-viewer-9x.slim .player > .left-arm .front { + transform: rotateX(0deg) rotateY(0deg) translateX(9px) translateY(0px) translateZ(18px); + } + .mc-skin-viewer-9x.slim .player > .left-arm .back { + background-position: -459px -180px; + transform: rotateX(0deg) rotateY(180deg) translateX(-9px) translateY(0px) translateZ(18px); + } + .mc-skin-viewer-9x.slim .player > .left-arm .right { + transform: rotateX(0deg) rotateY(270deg) translateX(0px) translateY(0px) translateZ(9px); + } + .mc-skin-viewer-9x.slim .player > .left-arm .left { + background-position: -423px -180px; + } + .mc-skin-viewer-9x.slim .player > .left-arm .top { + transform: rotateX(90deg) rotateY(0deg) translateX(9px) translateY(0px) translateZ(18px); + } + .mc-skin-viewer-9x.slim .player > .left-arm .bottom { + background-position: -423px -144px; + transform: rotateX(270deg) rotateY(0deg) translateX(9px) translateY(0px) translateZ(90px); + } + .mc-skin-viewer-9x.slim .player > .left-arm > .accessory .back { + background-position: -459px -324px; + } + .mc-skin-viewer-9x.slim .player > .left-arm > .accessory .left { + background-position: -423px -324px; + } + .mc-skin-viewer-9x.slim .player > .left-arm > .accessory .bottom { + background-position: -423px -288px; + } + .mc-skin-viewer-9x.slim .player > .right-arm .back { + background-position: -387px -468px; + } + .mc-skin-viewer-9x.slim .player > .right-arm .left { + background-position: -351px -468px; + transform: rotateX(0deg) rotateY(90deg) translateX(0px) translateY(0px) translateZ(9px); + } + .mc-skin-viewer-9x.slim .player > .right-arm .bottom { + background-position: -351px -432px; + } + .mc-skin-viewer-9x.slim .player > .right-arm > .accessory .back { + background-position: -531px -468px; + } + .mc-skin-viewer-9x.slim .player > .right-arm > .accessory .left { + background-position: -495px -468px; + } + .mc-skin-viewer-9x.slim .player > .right-arm > .accessory .bottom { + background-position: -495px -432px; + } + .mc-skin-viewer-9x.slim.legacy .player > .right-arm { + transform: translateY(72px) translateX(63px) scaleX(-1); + } + .mc-skin-viewer-9x.slim.legacy .player > .right-arm .back { + background-position: -459px -180px; + } + .mc-skin-viewer-9x.slim.legacy .player > .right-arm > .accessory .back { + background-position: -459px -324px; + } + .mc-skin-viewer-9x .player .cape { + transform-style: preserve-3d; + transform: rotateY(180deg) translateX(-9px) translateZ(22.5px) translateY(67.5px) rotateX(5deg); + } + .mc-skin-viewer-9x .player .cape > .front, + .mc-skin-viewer-9x .player .cape > .back, + .mc-skin-viewer-9x .player .cape > .left, + .mc-skin-viewer-9x .player .cape > .right, + .mc-skin-viewer-9x .player .cape > .top, + .mc-skin-viewer-9x .player .cape > .bottom { + position: absolute; + background-image: inherit!important; + background-size: 576px 288px; + backface-visibility: hidden; + } + .mc-skin-viewer-9x .player .cape > .front, + .mc-skin-viewer-9x .player .cape > .back { + width: 90px; + height: 135px; + } + .mc-skin-viewer-9x .player .cape > .left, + .mc-skin-viewer-9x .player .cape > .right { + width: 9px; + height: 135px; + } + .mc-skin-viewer-9x .player .cape > .top, + .mc-skin-viewer-9x .player .cape > .bottom { + width: 90px; + height: 9px; + } + .mc-skin-viewer-9x .player .cape > .front { + background-position: -9px -9px; + transform: translateZ(4.5px); + } + .mc-skin-viewer-9x .player .cape > .back { + background-position: -108px -9px; + transform: translateZ(-4.5px) rotateY(180deg); + } + .mc-skin-viewer-9x .player .cape > .left { + background-position: 0px -9px; + transform: rotateY(270deg) translateZ(4.5px); + } + .mc-skin-viewer-9x .player .cape > .right { + background-position: -99px -9px; + transform: rotateY(-270deg) translateZ(85.5px); + } + .mc-skin-viewer-9x .player .cape > .top { + background-position: -9px 0px; + transform: rotateX(90deg) rotateY(0deg) translateX(0px) translateY(0px) translateZ(4.5px); + } + .mc-skin-viewer-9x .player .cape > .bottom { + background-position: -99px 0px; + transform: rotateX(-90deg) translateZ(130.5px); + } + .mc-skin-viewer-9x.legacy-cape > .player .cape > .front, + .mc-skin-viewer-9x.legacy-cape > .player .cape > .back, + .mc-skin-viewer-9x.legacy-cape > .player .cape > .left, + .mc-skin-viewer-9x.legacy-cape > .player .cape > .right, + .mc-skin-viewer-9x.legacy-cape > .player .cape > .top, + .mc-skin-viewer-9x.legacy-cape > .player .cape > .bottom { + background-size: 198px 153px; + } + .mc-skin-viewer-11x { + width: 88px; + height: 352px; + margin: 15px auto 40px auto; + perspective: 800px; + perspective-origin: 50% 100px; + transform-style: preserve-3d; + background-image: none !important; + image-rendering: optimizeSpeed; + /* Legal fallback */ + image-rendering: -moz-crisp-edges; + /* Firefox */ + image-rendering: -o-crisp-edges; + /* Opera */ + image-rendering: -webkit-optimize-contrast; + /* Safari */ + image-rendering: optimize-contrast; + /* CSS3 Proposed */ + image-rendering: crisp-edges; + /* CSS4 Proposed */ + image-rendering: pixelated; + /* CSS4 Proposed */ + -ms-interpolation-mode: nearest-neighbor; + /* IE8+ */ + } + .mc-skin-viewer-11x.hide-accessories .accessory { + display: none; + } + .mc-skin-viewer-11x.spin > .player { + animation: spin 12s infinite linear; + } + .mc-skin-viewer-11x .player { + transform-style: preserve-3d; + } + .mc-skin-viewer-11x .player .front, + .mc-skin-viewer-11x .player .back, + .mc-skin-viewer-11x .player .left, + .mc-skin-viewer-11x .player .right, + .mc-skin-viewer-11x .player .top, + .mc-skin-viewer-11x .player .bottom { + position: absolute; + background-size: 704px; + background-repeat: no-repeat; + backface-visibility: hidden; + } + .mc-skin-viewer-11x .player .accessory { + background-image: none; + } + .mc-skin-viewer-11x .player .accessory .front, + .mc-skin-viewer-11x .player .accessory .back, + .mc-skin-viewer-11x .player .accessory .left, + .mc-skin-viewer-11x .player .accessory .right, + .mc-skin-viewer-11x .player .accessory .top, + .mc-skin-viewer-11x .player .accessory .bottom { + backface-visibility: visible; + } + .mc-skin-viewer-11x .player > .head { + position: absolute; + transform-style: preserve-3d; + width: 88px; + height: 88px; + margin: 0 auto; + background-image: none !important; + } + .mc-skin-viewer-11x .player > .head .front, + .mc-skin-viewer-11x .player > .head .back, + .mc-skin-viewer-11x .player > .head .left, + .mc-skin-viewer-11x .player > .head .right, + .mc-skin-viewer-11x .player > .head .top, + .mc-skin-viewer-11x .player > .head .bottom { + width: 88px; + height: 88px; + } + .mc-skin-viewer-11x .player > .head .front { + background-position: -88px -88px; + transform: rotateX(0deg) rotateY(0deg) translateX(0px) translateY(0px) translateZ(44px); + } + .mc-skin-viewer-11x .player > .head .back { + background-position: -264px -88px; + transform: rotateX(0deg) rotateY(180deg) translateX(0px) translateY(0px) translateZ(44px); + } + .mc-skin-viewer-11x .player > .head .right { + background-position: 0px -88px; + transform: rotateX(0deg) rotateY(270deg) translateX(0px) translateY(0px) translateZ(44px); + } + .mc-skin-viewer-11x .player > .head .left { + background-position: -176px -88px; + transform: rotateX(0deg) rotateY(90deg) translateX(0px) translateY(0px) translateZ(44px); + } + .mc-skin-viewer-11x .player > .head .top { + background-position: -88px 0px; + transform: rotateX(90deg) rotateY(0deg) translateX(0px) translateY(0px) translateZ(44px); + } + .mc-skin-viewer-11x .player > .head .bottom { + background-position: -176px 0px; + transform: rotateX(270deg) rotateY(0deg) rotateZ(180deg) translateX(0px) translateY(0px) translateZ(44px); + } + .mc-skin-viewer-11x .player > .head > .accessory { + transform-style: preserve-3d; + transform: scale3d(1.125, 1.125, 1.125) translateY(-4.5px); + } + .mc-skin-viewer-11x .player > .head > .accessory > .front { + background-position: -440px -88px; + } + .mc-skin-viewer-11x .player > .head > .accessory > .back { + background-position: -616px -88px; + } + .mc-skin-viewer-11x .player > .head > .accessory > .right { + background-position: -352px -88px; + } + .mc-skin-viewer-11x .player > .head > .accessory > .left { + background-position: -528px -88px; + } + .mc-skin-viewer-11x .player > .head > .accessory > .top { + background-position: -440px 0px; + } + .mc-skin-viewer-11x .player > .head > .accessory > .bottom { + background-position: -528px 0px; + } + .mc-skin-viewer-11x .player > .body { + position: absolute; + transform-style: preserve-3d; + width: 88px; + height: 88px; + margin: 0 auto; + transform: translateY(88px); + background-image: none !important; + } + .mc-skin-viewer-11x .player > .body .front, + .mc-skin-viewer-11x .player > .body .back, + .mc-skin-viewer-11x .player > .body .left, + .mc-skin-viewer-11x .player > .body .right, + .mc-skin-viewer-11x .player > .body .top, + .mc-skin-viewer-11x .player > .body .bottom { + width: 88px; + height: 132px; + } + .mc-skin-viewer-11x .player > .body .left, + .mc-skin-viewer-11x .player > .body .right { + width: 44px; + } + .mc-skin-viewer-11x .player > .body .top, + .mc-skin-viewer-11x .player > .body .bottom { + height: 44px; + } + .mc-skin-viewer-11x .player > .body .front { + background-position: -220px -220px; + transform: rotateX(0deg) rotateY(0deg) translateX(0px) translateY(0px) translateZ(22px); + } + .mc-skin-viewer-11x .player > .body .back { + background-position: -352px -220px; + transform: rotateX(0deg) rotateY(180deg) translateX(0px) translateY(0px) translateZ(22px); + } + .mc-skin-viewer-11x .player > .body .right { + background-position: -176px -220px; + transform: rotateX(0deg) rotateY(270deg) translateX(0px) translateY(0px) translateZ(22px); + } + .mc-skin-viewer-11x .player > .body .left { + background-position: -308px -220px; + transform: rotateX(0deg) rotateY(90deg) translateX(0px) translateY(0px) translateZ(66px); + } + .mc-skin-viewer-11x .player > .body .top { + background-position: -220px -176px; + transform: rotateX(90deg) rotateY(0deg) translateX(0px) translateY(0px) translateZ(22px); + } + .mc-skin-viewer-11x .player > .body .bottom { + background-position: -308px -176px; + transform: rotateX(270deg) rotateY(0deg) translateX(0px) translateY(0px) translateZ(110px); + } + .mc-skin-viewer-11x .player > .body > .accessory { + transform-style: preserve-3d; + transform: scale3d(1.0625, 1.0625, 1.0625) translateY(-4.125px); + } + .mc-skin-viewer-11x .player > .body > .accessory > .front { + background-position: -220px -396px; + } + .mc-skin-viewer-11x .player > .body > .accessory > .back { + background-position: -352px -396px; + } + .mc-skin-viewer-11x .player > .body > .accessory > .right { + background-position: -176px -396px; + } + .mc-skin-viewer-11x .player > .body > .accessory > .left { + background-position: -308px -396px; + } + .mc-skin-viewer-11x .player > .body > .accessory > .top { + background-position: -220px -352px; + } + .mc-skin-viewer-11x .player > .body > .accessory > .bottom { + background-position: -308px -352px; + } + .mc-skin-viewer-11x .player > .left-arm, + .mc-skin-viewer-11x .player > .right-arm { + position: absolute; + transform-style: preserve-3d; + width: 44px; + height: 132px; + margin: 0 auto; + transform: translateY(88px) translateX(-44px); + background-image: none !important; + } + .mc-skin-viewer-11x .player > .left-arm .front, + .mc-skin-viewer-11x .player > .right-arm .front, + .mc-skin-viewer-11x .player > .left-arm .back, + .mc-skin-viewer-11x .player > .right-arm .back, + .mc-skin-viewer-11x .player > .left-arm .left, + .mc-skin-viewer-11x .player > .right-arm .left, + .mc-skin-viewer-11x .player > .left-arm .right, + .mc-skin-viewer-11x .player > .right-arm .right, + .mc-skin-viewer-11x .player > .left-arm .top, + .mc-skin-viewer-11x .player > .right-arm .top, + .mc-skin-viewer-11x .player > .left-arm .bottom, + .mc-skin-viewer-11x .player > .right-arm .bottom { + width: 44px; + height: 132px; + } + .mc-skin-viewer-11x .player > .left-arm .top, + .mc-skin-viewer-11x .player > .right-arm .top, + .mc-skin-viewer-11x .player > .left-arm .bottom, + .mc-skin-viewer-11x .player > .right-arm .bottom { + height: 44px; + } + .mc-skin-viewer-11x .player > .left-arm .front, + .mc-skin-viewer-11x .player > .right-arm .front { + background-position: -484px -220px; + transform: rotateX(0deg) rotateY(0deg) translateX(0px) translateY(0px) translateZ(22px); + } + .mc-skin-viewer-11x .player > .left-arm .back, + .mc-skin-viewer-11x .player > .right-arm .back { + background-position: -572px -220px; + transform: rotateX(0deg) rotateY(180deg) translateX(0px) translateY(0px) translateZ(22px); + } + .mc-skin-viewer-11x .player > .left-arm .right, + .mc-skin-viewer-11x .player > .right-arm .right { + background-position: -440px -220px; + transform: rotateX(0deg) rotateY(270deg) translateX(0px) translateY(0px) translateZ(22px); + } + .mc-skin-viewer-11x .player > .left-arm .left, + .mc-skin-viewer-11x .player > .right-arm .left { + background-position: -528px -220px; + transform: rotateX(0deg) rotateY(90deg) translateX(0px) translateY(0px) translateZ(22px); + } + .mc-skin-viewer-11x .player > .left-arm .top, + .mc-skin-viewer-11x .player > .right-arm .top { + background-position: -484px -176px; + transform: rotateX(90deg) rotateY(0deg) translateX(0px) translateY(0px) translateZ(22px); + } + .mc-skin-viewer-11x .player > .left-arm .bottom, + .mc-skin-viewer-11x .player > .right-arm .bottom { + background-position: -528px -176px; + transform: rotateX(270deg) rotateY(0deg) translateX(0px) translateY(0px) translateZ(110px); + } + .mc-skin-viewer-11x .player > .left-arm > .accessory, + .mc-skin-viewer-11x .player > .right-arm > .accessory { + transform-style: preserve-3d; + transform: scale3d(1.0625, 1.0625, 1.0625) translateY(-4.125px); + } + .mc-skin-viewer-11x .player > .left-arm > .accessory .front, + .mc-skin-viewer-11x .player > .right-arm > .accessory .front { + background-position: -484px -396px; + } + .mc-skin-viewer-11x .player > .left-arm > .accessory .back, + .mc-skin-viewer-11x .player > .right-arm > .accessory .back { + background-position: -572px -396px; + } + .mc-skin-viewer-11x .player > .left-arm > .accessory .right, + .mc-skin-viewer-11x .player > .right-arm > .accessory .right { + background-position: -440px -396px; + } + .mc-skin-viewer-11x .player > .left-arm > .accessory .left, + .mc-skin-viewer-11x .player > .right-arm > .accessory .left { + background-position: -528px -396px; + } + .mc-skin-viewer-11x .player > .left-arm > .accessory .top, + .mc-skin-viewer-11x .player > .right-arm > .accessory .top { + background-position: -484px -352px; + } + .mc-skin-viewer-11x .player > .left-arm > .accessory .bottom, + .mc-skin-viewer-11x .player > .right-arm > .accessory .bottom { + background-position: -528px -352px; + } + .mc-skin-viewer-11x .player > .right-arm { + transform: translateY(88px) translateX(88px) scaleX(-1); + } + .mc-skin-viewer-11x .player > .left-leg, + .mc-skin-viewer-11x .player > .right-leg { + position: absolute; + transform-style: preserve-3d; + width: 44px; + height: 132px; + margin: 0 auto; + transform: translateY(220px); + background-image: none !important; + } + .mc-skin-viewer-11x .player > .left-leg .front, + .mc-skin-viewer-11x .player > .right-leg .front, + .mc-skin-viewer-11x .player > .left-leg .back, + .mc-skin-viewer-11x .player > .right-leg .back, + .mc-skin-viewer-11x .player > .left-leg .left, + .mc-skin-viewer-11x .player > .right-leg .left, + .mc-skin-viewer-11x .player > .left-leg .right, + .mc-skin-viewer-11x .player > .right-leg .right, + .mc-skin-viewer-11x .player > .left-leg .top, + .mc-skin-viewer-11x .player > .right-leg .top, + .mc-skin-viewer-11x .player > .left-leg .bottom, + .mc-skin-viewer-11x .player > .right-leg .bottom { + width: 44px; + height: 132px; + } + .mc-skin-viewer-11x .player > .left-leg .top, + .mc-skin-viewer-11x .player > .right-leg .top, + .mc-skin-viewer-11x .player > .left-leg .bottom, + .mc-skin-viewer-11x .player > .right-leg .bottom { + height: 44px; + } + .mc-skin-viewer-11x .player > .left-leg .front, + .mc-skin-viewer-11x .player > .right-leg .front { + background-position: -44px -220px; + transform: rotateX(0deg) rotateY(0deg) translateX(0px) translateY(0px) translateZ(22px); + } + .mc-skin-viewer-11x .player > .left-leg .back, + .mc-skin-viewer-11x .player > .right-leg .back { + background-position: -132px -220px; + transform: rotateX(0deg) rotateY(180deg) translateX(0px) translateY(0px) translateZ(22px); + } + .mc-skin-viewer-11x .player > .left-leg .right, + .mc-skin-viewer-11x .player > .right-leg .right { + background-position: 0px -220px; + transform: rotateX(0deg) rotateY(270deg) translateX(0px) translateY(0px) translateZ(22px); + } + .mc-skin-viewer-11x .player > .left-leg .left, + .mc-skin-viewer-11x .player > .right-leg .left { + background-position: -88px -220px; + transform: rotateX(0deg) rotateY(90deg) translateX(0px) translateY(0px) translateZ(22px); + } + .mc-skin-viewer-11x .player > .left-leg .top, + .mc-skin-viewer-11x .player > .right-leg .top { + background-position: -44px -176px; + transform: rotateX(90deg) rotateY(0deg) translateX(0px) translateY(0px) translateZ(22px); + } + .mc-skin-viewer-11x .player > .left-leg .bottom, + .mc-skin-viewer-11x .player > .right-leg .bottom { + background-position: -88px -176px; + transform: rotateX(270deg) rotateY(0deg) translateX(0px) translateY(0px) translateZ(110px); + } + .mc-skin-viewer-11x .player > .left-leg > .accessory, + .mc-skin-viewer-11x .player > .right-leg > .accessory { + transform-style: preserve-3d; + transform: scale3d(1.03125, 1.03125, 1.03125) translateY(-2.0625px); + } + .mc-skin-viewer-11x .player > .left-leg > .accessory .front, + .mc-skin-viewer-11x .player > .right-leg > .accessory .front { + background-position: -44px -396px; + } + .mc-skin-viewer-11x .player > .left-leg > .accessory .back, + .mc-skin-viewer-11x .player > .right-leg > .accessory .back { + background-position: -132px -396px; + } + .mc-skin-viewer-11x .player > .left-leg > .accessory .right, + .mc-skin-viewer-11x .player > .right-leg > .accessory .right { + background-position: 0px -396px; + } + .mc-skin-viewer-11x .player > .left-leg > .accessory .left, + .mc-skin-viewer-11x .player > .right-leg > .accessory .left { + background-position: -88px -396px; + } + .mc-skin-viewer-11x .player > .left-leg > .accessory .top, + .mc-skin-viewer-11x .player > .right-leg > .accessory .top { + background-position: -44px -352px; + } + .mc-skin-viewer-11x .player > .left-leg > .accessory .bottom, + .mc-skin-viewer-11x .player > .right-leg > .accessory .bottom { + background-position: -88px -352px; + } + .mc-skin-viewer-11x .player > .right-leg { + transform: translateY(220px) translateX(44px) scaleX(-1); + } + .mc-skin-viewer-11x:not(.legacy) .player > .right-arm { + transform: translateY(88px) translateX(88px); + } + .mc-skin-viewer-11x:not(.legacy) .player > .right-arm .front { + background-position: -396px -572px; + } + .mc-skin-viewer-11x:not(.legacy) .player > .right-arm .back { + background-position: -484px -572px; + } + .mc-skin-viewer-11x:not(.legacy) .player > .right-arm .right { + background-position: -352px -572px; + } + .mc-skin-viewer-11x:not(.legacy) .player > .right-arm .left { + background-position: -440px -572px; + } + .mc-skin-viewer-11x:not(.legacy) .player > .right-arm .top { + background-position: -396px -528px; + } + .mc-skin-viewer-11x:not(.legacy) .player > .right-arm .bottom { + background-position: -440px -528px; + } + .mc-skin-viewer-11x:not(.legacy) .player > .right-arm > .accessory .front { + background-position: -572px -572px; + } + .mc-skin-viewer-11x:not(.legacy) .player > .right-arm > .accessory .back { + background-position: -660px -572px; + } + .mc-skin-viewer-11x:not(.legacy) .player > .right-arm > .accessory .right { + background-position: -528px -572px; + } + .mc-skin-viewer-11x:not(.legacy) .player > .right-arm > .accessory .left { + background-position: -616px -572px; + } + .mc-skin-viewer-11x:not(.legacy) .player > .right-arm > .accessory .top { + background-position: -572px -528px; + } + .mc-skin-viewer-11x:not(.legacy) .player > .right-arm > .accessory .bottom { + background-position: -616px -528px; + } + .mc-skin-viewer-11x:not(.legacy) .player > .right-leg { + transform: translateY(220px) translateX(44px); + } + .mc-skin-viewer-11x:not(.legacy) .player > .right-leg .front { + background-position: -220px -572px; + } + .mc-skin-viewer-11x:not(.legacy) .player > .right-leg .back { + background-position: -308px -572px; + } + .mc-skin-viewer-11x:not(.legacy) .player > .right-leg .right { + background-position: -176px -572px; + } + .mc-skin-viewer-11x:not(.legacy) .player > .right-leg .left { + background-position: -264px -572px; + } + .mc-skin-viewer-11x:not(.legacy) .player > .right-leg .top { + background-position: -220px -528px; + } + .mc-skin-viewer-11x:not(.legacy) .player > .right-leg .bottom { + background-position: -264px -528px; + } + .mc-skin-viewer-11x:not(.legacy) .player > .right-leg > .accessory .front { + background-position: -44px -572px; + } + .mc-skin-viewer-11x:not(.legacy) .player > .right-leg > .accessory .back { + background-position: -132px -572px; + } + .mc-skin-viewer-11x:not(.legacy) .player > .right-leg > .accessory .right { + background-position: 0px -572px; + } + .mc-skin-viewer-11x:not(.legacy) .player > .right-leg > .accessory .left { + background-position: -88px -572px; + } + .mc-skin-viewer-11x:not(.legacy) .player > .right-leg > .accessory .top { + background-position: -44px -528px; + } + .mc-skin-viewer-11x:not(.legacy) .player > .right-leg > .accessory .bottom { + background-position: -88px -528px; + } + .mc-skin-viewer-11x.slim .player > .left-arm .front, + .mc-skin-viewer-11x.slim .player > .right-arm .front, + .mc-skin-viewer-11x.slim .player > .left-arm .back, + .mc-skin-viewer-11x.slim .player > .right-arm .back, + .mc-skin-viewer-11x.slim .player > .left-arm .top, + .mc-skin-viewer-11x.slim .player > .right-arm .top, + .mc-skin-viewer-11x.slim .player > .left-arm .bottom, + .mc-skin-viewer-11x.slim .player > .right-arm .bottom { + width: 33px; + } + .mc-skin-viewer-11x.slim .player > .left-arm .front { + transform: rotateX(0deg) rotateY(0deg) translateX(11px) translateY(0px) translateZ(22px); + } + .mc-skin-viewer-11x.slim .player > .left-arm .back { + background-position: -561px -220px; + transform: rotateX(0deg) rotateY(180deg) translateX(-11px) translateY(0px) translateZ(22px); + } + .mc-skin-viewer-11x.slim .player > .left-arm .right { + transform: rotateX(0deg) rotateY(270deg) translateX(0px) translateY(0px) translateZ(11px); + } + .mc-skin-viewer-11x.slim .player > .left-arm .left { + background-position: -517px -220px; + } + .mc-skin-viewer-11x.slim .player > .left-arm .top { + transform: rotateX(90deg) rotateY(0deg) translateX(11px) translateY(0px) translateZ(22px); + } + .mc-skin-viewer-11x.slim .player > .left-arm .bottom { + background-position: -517px -176px; + transform: rotateX(270deg) rotateY(0deg) translateX(11px) translateY(0px) translateZ(110px); + } + .mc-skin-viewer-11x.slim .player > .left-arm > .accessory .back { + background-position: -561px -396px; + } + .mc-skin-viewer-11x.slim .player > .left-arm > .accessory .left { + background-position: -517px -396px; + } + .mc-skin-viewer-11x.slim .player > .left-arm > .accessory .bottom { + background-position: -517px -352px; + } + .mc-skin-viewer-11x.slim .player > .right-arm .back { + background-position: -473px -572px; + } + .mc-skin-viewer-11x.slim .player > .right-arm .left { + background-position: -429px -572px; + transform: rotateX(0deg) rotateY(90deg) translateX(0px) translateY(0px) translateZ(11px); + } + .mc-skin-viewer-11x.slim .player > .right-arm .bottom { + background-position: -429px -528px; + } + .mc-skin-viewer-11x.slim .player > .right-arm > .accessory .back { + background-position: -649px -572px; + } + .mc-skin-viewer-11x.slim .player > .right-arm > .accessory .left { + background-position: -605px -572px; + } + .mc-skin-viewer-11x.slim .player > .right-arm > .accessory .bottom { + background-position: -605px -528px; + } + .mc-skin-viewer-11x.slim.legacy .player > .right-arm { + transform: translateY(88px) translateX(77px) scaleX(-1); + } + .mc-skin-viewer-11x.slim.legacy .player > .right-arm .back { + background-position: -561px -220px; + } + .mc-skin-viewer-11x.slim.legacy .player > .right-arm > .accessory .back { + background-position: -561px -396px; + } + .mc-skin-viewer-11x .player .cape { + transform-style: preserve-3d; + transform: rotateY(180deg) translateX(-11px) translateZ(27.5px) translateY(82.5px) rotateX(5deg); + } + .mc-skin-viewer-11x .player .cape > .front, + .mc-skin-viewer-11x .player .cape > .back, + .mc-skin-viewer-11x .player .cape > .left, + .mc-skin-viewer-11x .player .cape > .right, + .mc-skin-viewer-11x .player .cape > .top, + .mc-skin-viewer-11x .player .cape > .bottom { + position: absolute; + background-image: inherit!important; + background-size: 704px 352px; + backface-visibility: hidden; + } + .mc-skin-viewer-11x .player .cape > .front, + .mc-skin-viewer-11x .player .cape > .back { + width: 110px; + height: 165px; + } + .mc-skin-viewer-11x .player .cape > .left, + .mc-skin-viewer-11x .player .cape > .right { + width: 11px; + height: 165px; + } + .mc-skin-viewer-11x .player .cape > .top, + .mc-skin-viewer-11x .player .cape > .bottom { + width: 110px; + height: 11px; + } + .mc-skin-viewer-11x .player .cape > .front { + background-position: -11px -11px; + transform: translateZ(5.5px); + } + .mc-skin-viewer-11x .player .cape > .back { + background-position: -132px -11px; + transform: translateZ(-5.5px) rotateY(180deg); + } + .mc-skin-viewer-11x .player .cape > .left { + background-position: 0px -11px; + transform: rotateY(270deg) translateZ(5.5px); + } + .mc-skin-viewer-11x .player .cape > .right { + background-position: -121px -11px; + transform: rotateY(-270deg) translateZ(104.5px); + } + .mc-skin-viewer-11x .player .cape > .top { + background-position: -11px 0px; + transform: rotateX(90deg) rotateY(0deg) translateX(0px) translateY(0px) translateZ(5.5px); + } + .mc-skin-viewer-11x .player .cape > .bottom { + background-position: -121px 0px; + transform: rotateX(-90deg) translateZ(159.5px); + } + .mc-skin-viewer-11x.legacy-cape > .player .cape > .front, + .mc-skin-viewer-11x.legacy-cape > .player .cape > .back, + .mc-skin-viewer-11x.legacy-cape > .player .cape > .left, + .mc-skin-viewer-11x.legacy-cape > .player .cape > .right, + .mc-skin-viewer-11x.legacy-cape > .player .cape > .top, + .mc-skin-viewer-11x.legacy-cape > .player .cape > .bottom { + background-size: 242px 187px; + } + .mc-cape-viewer-9x { + width: 90px; + height: 135px; + margin: 10px auto; + perspective: 800px; + perspective-origin: 50% 100px; + background-image: none; + image-rendering: optimizeSpeed; + /* Legal fallback */ + image-rendering: -moz-crisp-edges; + /* Firefox */ + image-rendering: -o-crisp-edges; + /* Opera */ + image-rendering: -webkit-optimize-contrast; + /* Safari */ + image-rendering: optimize-contrast; + /* CSS3 Proposed */ + image-rendering: crisp-edges; + /* CSS4 Proposed */ + image-rendering: pixelated; + /* CSS4 Proposed */ + -ms-interpolation-mode: nearest-neighbor; + /* IE8+ */ + } + .mc-cape-viewer-9x .wrapper { + transform-style: preserve-3d; + width: 90px; + height: 135px; + position: relative; + background-image: none !important; + } + .mc-cape-viewer-9x .wrapper .cape { + transform-style: preserve-3d; + } + .mc-cape-viewer-9x .wrapper .cape > .front, + .mc-cape-viewer-9x .wrapper .cape > .back, + .mc-cape-viewer-9x .wrapper .cape > .left, + .mc-cape-viewer-9x .wrapper .cape > .right, + .mc-cape-viewer-9x .wrapper .cape > .top, + .mc-cape-viewer-9x .wrapper .cape > .bottom { + position: absolute; + background-size: 576px 288px; + backface-visibility: hidden; + } + .mc-cape-viewer-9x .wrapper .cape > .front, + .mc-cape-viewer-9x .wrapper .cape > .back { + width: 90px; + height: 135px; + } + .mc-cape-viewer-9x .wrapper .cape > .left, + .mc-cape-viewer-9x .wrapper .cape > .right { + width: 9px; + height: 135px; + } + .mc-cape-viewer-9x .wrapper .cape > .top, + .mc-cape-viewer-9x .wrapper .cape > .bottom { + width: 90px; + height: 9px; + } + .mc-cape-viewer-9x .wrapper .cape > .front { + background-position: -9px -9px; + transform: translateZ(4.5px); + } + .mc-cape-viewer-9x .wrapper .cape > .back { + background-position: -108px -9px; + transform: translateZ(-4.5px) rotateY(180deg); + } + .mc-cape-viewer-9x .wrapper .cape > .left { + background-position: 0px -9px; + transform: rotateY(270deg) translateZ(4.5px); + } + .mc-cape-viewer-9x .wrapper .cape > .right { + background-position: -99px -9px; + transform: rotateY(-270deg) translateZ(85.5px); + } + .mc-cape-viewer-9x .wrapper .cape > .top { + background-position: -9px 0px; + transform: rotateX(90deg) rotateY(0deg) translateX(0px) translateY(0px) translateZ(4.5px); + } + .mc-cape-viewer-9x .wrapper .cape > .bottom { + background-position: -99px 0px; + transform: rotateX(-90deg) translateZ(130.5px); + } + .mc-cape-viewer-9x.legacy .wrapper .cape > .front, + .mc-cape-viewer-9x.legacy .wrapper .cape > .back, + .mc-cape-viewer-9x.legacy .wrapper .cape > .left, + .mc-cape-viewer-9x.legacy .wrapper .cape > .right { + background-size: 198px 153px; + } + .mc-cape-viewer-9x.waving > .wrapper > .cape { + animation: waving 2s infinite ease-in-out; + } + .mc-cape-viewer-9x.spin > .wrapper > .cape { + animation: spin 12s infinite linear; + } \ No newline at end of file diff --git a/src/assets/fonts/Icons.woff2 b/src/assets/fonts/Icons.woff2 new file mode 100644 index 0000000..ea72293 Binary files /dev/null and b/src/assets/fonts/Icons.woff2 differ diff --git a/src/assets/fonts/Poppins-Bold.woff2 b/src/assets/fonts/Poppins-Bold.woff2 new file mode 100644 index 0000000..8030061 Binary files /dev/null and b/src/assets/fonts/Poppins-Bold.woff2 differ diff --git a/src/assets/fonts/Poppins-Regular.woff2 b/src/assets/fonts/Poppins-Regular.woff2 new file mode 100644 index 0000000..2934dec Binary files /dev/null and b/src/assets/fonts/Poppins-Regular.woff2 differ diff --git a/src/assets/images/background/background_updater.png b/src/assets/images/background/background_updater.png new file mode 100644 index 0000000..f0f961b Binary files /dev/null and b/src/assets/images/background/background_updater.png differ diff --git a/src/assets/images/background/light.jpg b/src/assets/images/background/light.jpg new file mode 100644 index 0000000..a5a6c15 Binary files /dev/null and b/src/assets/images/background/light.jpg differ diff --git a/src/assets/images/default/setve.png b/src/assets/images/default/setve.png new file mode 100644 index 0000000..0042fb9 Binary files /dev/null and b/src/assets/images/default/setve.png differ diff --git a/src/assets/images/descargar.png b/src/assets/images/descargar.png new file mode 100644 index 0000000..465ef78 Binary files /dev/null and b/src/assets/images/descargar.png differ diff --git a/src/assets/images/flags/ar.png b/src/assets/images/flags/ar.png new file mode 100644 index 0000000..d9ab036 Binary files /dev/null and b/src/assets/images/flags/ar.png differ diff --git a/src/assets/images/flags/de.png b/src/assets/images/flags/de.png new file mode 100644 index 0000000..d54d830 Binary files /dev/null and b/src/assets/images/flags/de.png differ diff --git a/src/assets/images/flags/en.png b/src/assets/images/flags/en.png new file mode 100644 index 0000000..31cec2b Binary files /dev/null and b/src/assets/images/flags/en.png differ diff --git a/src/assets/images/flags/es.png b/src/assets/images/flags/es.png new file mode 100644 index 0000000..bcf060f Binary files /dev/null and b/src/assets/images/flags/es.png differ diff --git a/src/assets/images/flags/fr.png b/src/assets/images/flags/fr.png new file mode 100644 index 0000000..a86b49e Binary files /dev/null and b/src/assets/images/flags/fr.png differ diff --git a/src/assets/images/flags/it.png b/src/assets/images/flags/it.png new file mode 100644 index 0000000..61f026d Binary files /dev/null and b/src/assets/images/flags/it.png differ diff --git a/src/assets/images/flags/jp.png b/src/assets/images/flags/jp.png new file mode 100644 index 0000000..95c8fb9 Binary files /dev/null and b/src/assets/images/flags/jp.png differ diff --git a/src/assets/images/flags/pt.png b/src/assets/images/flags/pt.png new file mode 100644 index 0000000..f26ce3b Binary files /dev/null and b/src/assets/images/flags/pt.png differ diff --git a/src/assets/images/flags/ru.png b/src/assets/images/flags/ru.png new file mode 100644 index 0000000..0daa017 Binary files /dev/null and b/src/assets/images/flags/ru.png differ diff --git a/src/assets/images/icon.icns b/src/assets/images/icon.icns new file mode 100644 index 0000000..f914427 Binary files /dev/null and b/src/assets/images/icon.icns differ diff --git a/src/assets/images/icon.ico b/src/assets/images/icon.ico new file mode 100644 index 0000000..3d47e1d Binary files /dev/null and b/src/assets/images/icon.ico differ diff --git a/src/assets/images/icon.png b/src/assets/images/icon.png new file mode 100644 index 0000000..4cc969b Binary files /dev/null and b/src/assets/images/icon.png differ diff --git a/src/assets/images/icon_transparent.png b/src/assets/images/icon_transparent.png new file mode 100644 index 0000000..c351eb5 Binary files /dev/null and b/src/assets/images/icon_transparent.png differ diff --git a/src/assets/images/icons/ares.png b/src/assets/images/icons/ares.png new file mode 100644 index 0000000..622580e Binary files /dev/null and b/src/assets/images/icons/ares.png differ diff --git a/src/assets/images/icons/batmod.png b/src/assets/images/icons/batmod.png new file mode 100644 index 0000000..32eff02 Binary files /dev/null and b/src/assets/images/icons/batmod.png differ diff --git a/src/assets/images/icons/beast.png b/src/assets/images/icons/beast.png new file mode 100644 index 0000000..a4dfa71 Binary files /dev/null and b/src/assets/images/icons/beast.png differ diff --git a/src/assets/images/icons/clients.png b/src/assets/images/icons/clients.png new file mode 100644 index 0000000..99817bf Binary files /dev/null and b/src/assets/images/icons/clients.png differ diff --git a/src/assets/images/icons/cmpack.png b/src/assets/images/icons/cmpack.png new file mode 100644 index 0000000..23ec65f Binary files /dev/null and b/src/assets/images/icons/cmpack.png differ diff --git a/src/assets/images/icons/fabric.png b/src/assets/images/icons/fabric.png new file mode 100644 index 0000000..672dfe5 Binary files /dev/null and b/src/assets/images/icons/fabric.png differ diff --git a/src/assets/images/icons/forge.png b/src/assets/images/icons/forge.png new file mode 100644 index 0000000..6c2b053 Binary files /dev/null and b/src/assets/images/icons/forge.png differ diff --git a/src/assets/images/icons/google.png b/src/assets/images/icons/google.png new file mode 100644 index 0000000..cb96f19 Binary files /dev/null and b/src/assets/images/icons/google.png differ diff --git a/src/assets/images/icons/loading.gif b/src/assets/images/icons/loading.gif new file mode 100644 index 0000000..d1b14be Binary files /dev/null and b/src/assets/images/icons/loading.gif differ diff --git a/src/assets/images/icons/microsoft.png b/src/assets/images/icons/microsoft.png new file mode 100644 index 0000000..61bf23c Binary files /dev/null and b/src/assets/images/icons/microsoft.png differ diff --git a/src/assets/images/icons/minecraft.png b/src/assets/images/icons/minecraft.png new file mode 100644 index 0000000..a943012 Binary files /dev/null and b/src/assets/images/icons/minecraft.png differ diff --git a/src/assets/images/icons/ms.png b/src/assets/images/icons/ms.png new file mode 100644 index 0000000..f66728d Binary files /dev/null and b/src/assets/images/icons/ms.png differ diff --git a/src/assets/images/icons/music.gif b/src/assets/images/icons/music.gif new file mode 100644 index 0000000..27915c2 Binary files /dev/null and b/src/assets/images/icons/music.gif differ diff --git a/src/assets/images/icons/nether.png b/src/assets/images/icons/nether.png new file mode 100644 index 0000000..dc6fcf9 Binary files /dev/null and b/src/assets/images/icons/nether.png differ diff --git a/src/assets/images/icons/optifine.png b/src/assets/images/icons/optifine.png new file mode 100644 index 0000000..b650cf8 Binary files /dev/null and b/src/assets/images/icons/optifine.png differ diff --git a/src/assets/images/icons/pixel.png b/src/assets/images/icons/pixel.png new file mode 100644 index 0000000..9c75340 Binary files /dev/null and b/src/assets/images/icons/pixel.png differ diff --git a/src/assets/images/icons/pluto.png b/src/assets/images/icons/pluto.png new file mode 100644 index 0000000..a9059b6 Binary files /dev/null and b/src/assets/images/icons/pluto.png differ diff --git a/src/assets/images/icons/quilt.png b/src/assets/images/icons/quilt.png new file mode 100644 index 0000000..b09222b Binary files /dev/null and b/src/assets/images/icons/quilt.png differ diff --git a/src/assets/images/logo/microsoft.svg b/src/assets/images/logo/microsoft.svg new file mode 100644 index 0000000..78a4ed9 --- /dev/null +++ b/src/assets/images/logo/microsoft.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/assets/images/logo/mojang.svg b/src/assets/images/logo/mojang.svg new file mode 100644 index 0000000..fa4f2d9 --- /dev/null +++ b/src/assets/images/logo/mojang.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/images/pregunta.png b/src/assets/images/pregunta.png new file mode 100644 index 0000000..5a0501e Binary files /dev/null and b/src/assets/images/pregunta.png differ diff --git a/src/assets/images/status/idle.png b/src/assets/images/status/idle.png new file mode 100644 index 0000000..1504332 Binary files /dev/null and b/src/assets/images/status/idle.png differ diff --git a/src/assets/images/status/offline.png b/src/assets/images/status/offline.png new file mode 100644 index 0000000..38a2843 Binary files /dev/null and b/src/assets/images/status/offline.png differ diff --git a/src/assets/images/status/online.png b/src/assets/images/status/online.png new file mode 100644 index 0000000..6264e8e Binary files /dev/null and b/src/assets/images/status/online.png differ diff --git a/src/assets/js/index.js b/src/assets/js/index.js new file mode 100644 index 0000000..d1d24f6 --- /dev/null +++ b/src/assets/js/index.js @@ -0,0 +1,241 @@ +/** + * @author TECNO BROS + + */ + +'use strict'; +const { + ipcRenderer +} = require('electron'); +import { + config +} from './utils.js'; + +let dev = process.env.NODE_ENV === 'dev'; +const fs = require('fs'); +const fetch = require('node-fetch'); +const axios = require("axios"); +import { Lang } from './utils/lang.js'; + +// Crea una instancia de la clase Lang +const langInstance = new Lang(); + +// Llama a GetLang en la instancia + + +/** + * Represents the Splash class. + * @class + */ +class Splash { + /** + * Creates an instance of Splash. + * @constructor + */ + constructor() { + this.splash = document.querySelector(".splash"); + this.splashMessage = document.querySelector(".splash-message"); + this.splashAuthor = document.querySelector(".splash-author"); + this.message = document.querySelector(".message"); + this.progress = document.querySelector("progress"); + document.addEventListener('DOMContentLoaded', () => this.startAnimation()); + langInstance.GetLang().then(lang => { + this.lang = lang; + this.message.innerHTML = this.lang.salutate; + }).catch(error => { + console.error(error); + }); + } + + + /** + * Starts the splash animation. + * @async + */ + async startAnimation() { + let splashes = [{ + "message": "Battly Launcher", + "author": "TECNO BROS" + },] + + let sonidoDB = localStorage.getItem("sonido-inicio") ? localStorage.getItem("sonido-inicio") : "start"; + let sonido_inicio = new Audio('./assets/audios/' + sonidoDB + '.mp3'); + sonido_inicio.volume = 0.8; + let splash = splashes[Math.floor(Math.random() * splashes.length)]; + this.splashMessage.textContent = splash.message; + this.splashAuthor.children[0].textContent = "" + splash.author; + await sleep(100); + document.querySelector("#splash").style.display = "block"; + await sleep(500); + sonido_inicio.play(); + this.splash.classList.add("opacity"); + await sleep(500); + this.splash.classList.add("translate"); + this.splashMessage.classList.add("opacity"); + this.splashAuthor.classList.add("opacity"); + this.message.classList.add("opacity"); + await sleep(1000); + + fetch("https://google.com").then(async () => { + this.checkUpdate(); + }).catch(async () => { + this.setStatus(this.lang.checking_connection); + await sleep(2000); + this.setStatus(this.lang.no_connection); + await sleep(3000); + this.setStatus(this.lang.starting_battly); + await sleep(500); + this.startLauncher(); + }) + + } + + /** + * Checks for updates. + * @async + */ + async checkUpdate() { + if(dev) return sleep(500).then(async () => { + + //aplicar las animaciones pero al reves + this.splash.classList.remove("translate"); + this.splashMessage.classList.remove("opacity"); + this.splashAuthor.classList.remove("opacity"); + await sleep(500); + this.startLauncher(); + }); + this.setStatus(this.lang.checking_updates); + + ipcRenderer.invoke('update-app').then(err => { + if(err) { + if (err.error) { + let error = err.message; + error = error.toString().slice(0, 50); + this.shutdown(`${this.lang.update_error}${error}`); + } + } + }) + + ipcRenderer.on('updateAvailable', () => { + this.setStatus(this.lang.update_available); + this.toggleProgress(); + + let boton_actualizar = document.getElementById("btn_actualizar"); + boton_actualizar.style.display = "block"; + boton_actualizar.addEventListener("click", () => { + this.setStatus(this.lang.downloading_update); + ipcRenderer.send('start-update'); + }) + + let boton_cancelar = document.getElementById("btn_jugar"); + boton_cancelar.style.display = "block"; + boton_cancelar.addEventListener("click", () => { + this.setStatus(this.lang.update_cancelled); + this.maintenanceCheck(); + }) + }) + + ipcRenderer.on('download-progress', (event, progress) => { + this.setProgress(progress.transferred, progress.total); + }) + + ipcRenderer.on('update-not-available', () => { + this.maintenanceCheck(); + }) + + ipcRenderer.on('update-downloaded', async () => { + this.setStatus(this.lang.update_downloaded); + await sleep(5000); + this.toggleProgress(); + ipcRenderer.send('update-window-close'); + ipcRenderer.send('start-update'); + } + ) + } + + /** + * Checks for maintenance mode. + * @async + */ + async maintenanceCheck() { + config.GetConfig().then(async res => { + if (res.maintenance) return this.shutdown(res.maintenance_message); + this.setStatus(this.lang.starting_launcher); + + //aplicar las animaciones pero al reves + this.splash.classList.remove("translate"); + this.splashMessage.classList.remove("opacity"); + this.splashAuthor.classList.remove("opacity"); + await sleep(500); + setTimeout(() => { + this.startLauncher(); + }, 1000); + return true; + }).catch(e => { + console.error(e); + return this.shutdown(this.lang.error_connecting_server); + }) + } + + /** + * Starts the launcher. + * @async + */ + async startLauncher() { + this.setStatus(this.lang.ending); + await sleep(500); + ipcRenderer.send('main-window-open'); + ipcRenderer.send('update-window-close'); + } + + /** + * Shuts down the launcher. + * @param {string} text - The shutdown message. + */ + shutdown(text) { + this.setStatus(`${text}
Cerrando 10s`); + let i = 10; + setInterval(() => { + this.setStatus(`${text}
${this.lang.closing_countdown} ${i}s`); + if (i < 0) ipcRenderer.send('update-window-close'); + }, 1000); + } + + /** + * Sets the status message. + * @param {string} text - The status message. + */ + setStatus(text) { + this.message.innerHTML = text; + } + + /** + * Toggles the progress bar. + */ + toggleProgress() { + if (this.progress.classList.toggle("show")) this.setProgress(0, 1); + } + + /** + * Sets the progress bar value. + * @param {number} value - The progress value. + * @param {number} max - The maximum progress value. + */ + setProgress(value, max) { + this.progress.value = value; + this.progress.max = max; + } + + +} + +function sleep(ms) { + return new Promise(r => setTimeout(r, ms)); +} + +document.addEventListener("keydown", (e) => { + if (e.ctrlKey && e.shiftKey && e.keyCode == 73 || e.keyCode == 123) { + ipcRenderer.send("update-window-dev-tools"); + } +}) +new Splash(); diff --git a/src/assets/js/launcher.js b/src/assets/js/launcher.js new file mode 100644 index 0000000..3a8d04f --- /dev/null +++ b/src/assets/js/launcher.js @@ -0,0 +1,227 @@ +/** + * @author TECNO BROS + + */ + +'use strict'; + +// libs +const fs = require('fs'); +const { Microsoft, Mojang } = require('./assets/js/libs/mc/Index'); +const { ipcRenderer } = require('electron'); + +import { config, logger, changePanel, database, addAccount, accountSelect } from './utils.js'; +import Login from './panels/login.js'; +import Home from './panels/home.js'; +import Settings from './panels/settings.js'; +import Welcome from './panels/welcome.js'; +import Mods from './panels/mods.js'; +import Music from './panels/music.js'; +import NewsPanel from './panels/news.js'; +import Friends from './panels/friends.js'; +import Chat from './panels/chat.js'; + +class Launcher { + async init() { + const loadingText = document.getElementById("loading-text"); + loadingText.innerHTML = "Cargando Panel de Inicio"; + this.initLog(); + console.log("🔄 Iniciando Launcher..."); + if (process.platform == "win32") this.initFrame(); + this.config = await config.GetConfig().then(res => res); + this.news = await config.GetNews().then(res => res); + this.database = await new database().init(); + this.createPanels(Login, Home, Settings, Welcome, Mods, Music, NewsPanel, Friends, Chat); + this.getaccounts(); + } + + initLog() { + document.querySelector(".preload-content").style.display = "block"; + document.addEventListener("keydown", (e) => { + if (e.ctrlKey && e.shiftKey && e.keyCode == 73 || e.keyCode == 123) { + ipcRenderer.send("main-window-dev-tools"); + } + }) + new logger('Launcher', '#3e8ed0') + } + + initFrame() { + const loadingText = document.getElementById("loading-text"); + loadingText.innerHTML = "Cargando Panel"; + document.querySelector(".preload-content").style.display = "block"; + console.log("🔄 Iniciando Frame...") + document.querySelector(".frame").classList.toggle("hide") + document.querySelector(".dragbar").classList.toggle("hide") + + document.querySelector("#minimize").addEventListener("click", () => { + ipcRenderer.send("main-window-minimize"); + }); + + let maximized = false; + let maximize = document.querySelector("#maximize") + maximize.addEventListener("click", () => { + if (maximized) ipcRenderer.send("main-window-maximize") + else ipcRenderer.send("main-window-maximize"); + maximized = !maximized + maximize.classList.toggle("icon-maximize") + maximize.classList.toggle("icon-restore-down") + }); + + document.querySelector("#close").addEventListener("click", () => { + ipcRenderer.send("main-window-close"); + }) + } + + createPanels(...panels) { + document.querySelector(".preload-content").style.display = ""; + let panelsElem = document.querySelector(".panels") + for (let panel of panels) { + console.log(`🔄 Iniciando panel de ${panel.name}...`); + let div = document.createElement("div"); + div.classList.add("panel", panel.id) + div.innerHTML = fs.readFileSync(`${__dirname}/panels/${panel.id}.html`, "utf8"); + panelsElem.appendChild(div); + new panel().init(this.config, this.news); + } + } + + async getaccounts() { + const loadingText = document.getElementById("loading-text"); + loadingText.innerHTML = "Cargando Cuentas"; + document.querySelector(".preload-content").style.display = "block"; + let accounts = await this.database.getAll('accounts'); + let selectaccount = (await this.database.get('1234', 'accounts-selected'))?.value?.selected; + console.log(`🔄 Iniciando ${accounts.length} cuenta(s)...`); + + + if (!accounts.length) { + changePanel("login"); + document.querySelector(".preload-content").style.display = "none"; + } else { + for (let account of accounts) { + account = account.value; + if (account.meta.type === 'Xbox') { + console.log(`🔄 Iniciando cuenta de xbox con el nombre de usuario ${account.name}...`); + let refresh = await new Microsoft(this.config.client_id).refresh(account); + let refresh_accounts; + let refresh_profile; + + if (refresh.error) { + this.database.delete(account.uuid, 'accounts'); + this.database.delete(account.uuid, 'profile'); + if (account.uuid === selectaccount) this.database.update({ uuid: "1234" }, 'accounts-selected') + console.error(`[Cuenta] ${account.uuid}: ${refresh.errorMessage}`); + continue; + } + + refresh_accounts = { + access_token: refresh.access_token, + client_token: refresh.client_token, + uuid: refresh.uuid, + name: refresh.name, + refresh_token: refresh.refresh_token, + user_properties: refresh.user_properties, + meta: { + type: refresh.meta.type, + xuid: refresh.meta.xuid, + demo: refresh.meta.demo + } + } + + refresh_profile = { + uuid: refresh.uuid, + skins: refresh.profile.skins || [], + capes: refresh.profile.capes || [], + } + + this.database.update(refresh_accounts, 'accounts'); + this.database.update(refresh_profile, 'profile'); + addAccount(refresh_accounts); + if (account.uuid === selectaccount) accountSelect(refresh.uuid) + } else if (account.meta.type === 'Mojang') { + if (account.meta.offline) { + document.querySelector(".preload-content").style.display = "block"; + console.log(`🔄 Iniciando cuenta de Mojang con el nombre de ususario ${account.name}...`); + addAccount(account); + if (account.uuid === selectaccount) accountSelect(account.uuid) + continue; + } + + let validate = await Mojang.validate(account); + if (!validate) { + this.database.delete(account.uuid, 'accounts'); + if (account.uuid === selectaccount) this.database.update({ uuid: "1234" }, 'accounts-selected') + console.error(`[Cuenta] ${account.uuid}: El token es inválido.`); + continue; + } + + let refresh = await Mojang.refresh(account); + console.log(`🔄 Iniciando cuenta de Mojang con el nombre de usuario ${account.name}...`); + let refresh_accounts; + + if (refresh.error) { + this.database.delete(account.uuid, 'accounts'); + if (account.uuid === selectaccount) this.database.update({ uuid: "1234" }, 'accounts-selected') + console.error(`[Cuenta] ${account.uuid}: ${refresh.errorMessage}`); + continue; + } + + refresh_accounts = { + access_token: refresh.access_token, + client_token: refresh.client_token, + uuid: refresh.uuid, + name: refresh.name, + user_properties: refresh.user_properties, + meta: { + type: refresh.meta.type, + offline: refresh.meta.offline + } + } + + this.database.update(refresh_accounts, 'accounts'); + addAccount(refresh_accounts); + if (account.uuid === selectaccount) accountSelect(refresh.uuid) + } else if (account.meta.type === 'cracked') { + console.log(`🔄 Iniciando cuenta de Battly con el nombre de usuario ${account.name}...`); + addAccount(account); + if (account.uuid === selectaccount) accountSelect(account.uuid) + } + } + + + + + + if (!(await this.database.get('1234', 'accounts-selected')).value.selected) { + let uuid = (await this.database.getAll('accounts'))[0]?.value?.uuid + if (uuid) { + this.database.update({ uuid: "1234", selected: uuid }, 'accounts-selected') + accountSelect(uuid) + } + } + + if ((await this.database.getAll('accounts')).length == 0) { + changePanel("login"); + document.querySelector(".preload-content").style.display = "none"; + return + } + + //comprobar si es la primera vez que se inicia el launcher + try { + if (!(await this.database.get('1234', 'first-launch')).value.firstlaunch) { + changePanel("login"); + this.database.update({ uuid: "1234", firstlaunch: true }, 'first-launch') + } + } catch (e) { + changePanel("login"); + this.database.update({ uuid: "1234", firstlaunch: true }, 'first-launch') + } + + document.querySelector(".preload-content").style.display = "none"; + changePanel("home"); + + } + } +} + +new Launcher().init(); \ No newline at end of file diff --git a/src/assets/js/libs/discord/client.js b/src/assets/js/libs/discord/client.js new file mode 100644 index 0000000..0ff29da --- /dev/null +++ b/src/assets/js/libs/discord/client.js @@ -0,0 +1,660 @@ +'use strict'; + +const EventEmitter = require('events'); +const { setTimeout, clearTimeout } = require('timers'); +const fetch = require('node-fetch'); +const transports = require('./transports'); +const { RPCCommands, RPCEvents, RelationshipTypes } = require('./constants'); +const { pid: getPid, uuid } = require('./util'); + +function subKey(event, args) { + return `${event}${JSON.stringify(args)}`; +} + +/** + * @typedef {RPCClientOptions} + * @extends {ClientOptions} + * @prop {string} transport RPC transport. one of `ipc` or `websocket` + */ + +/** + * The main hub for interacting with Discord RPC + * @extends {BaseClient} + */ +class RPCClient extends EventEmitter { + /** + * @param {RPCClientOptions} [options] Options for the client. + * You must provide a transport + */ + constructor(options = {}) { + super(); + + this.options = options; + + this.accessToken = null; + this.clientId = null; + + /** + * Application used in this client + * @type {?ClientApplication} + */ + this.application = null; + + /** + * User used in this application + * @type {?User} + */ + this.user = null; + + const Transport = transports[options.transport]; + if (!Transport) { + throw new TypeError('RPC_INVALID_TRANSPORT', options.transport); + } + + this.fetch = (method, path, { data, query } = {}) => + fetch(`${this.fetch.endpoint}${path}${query ? new URLSearchParams(query) : ''}`, { + method, + body: data, + headers: { + Authorization: `Bearer ${this.accessToken}`, + }, + }).then(async (r) => { + const body = await r.json(); + if (!r.ok) { + const e = new Error(r.status); + e.body = body; + throw e; + } + return body; + }); + + this.fetch.endpoint = 'https://discord.com/api'; + + /** + * Raw transport userd + * @type {RPCTransport} + * @private + */ + this.transport = new Transport(this); + this.transport.on('message', this._onRpcMessage.bind(this)); + + /** + * Map of nonces being expected from the transport + * @type {Map} + * @private + */ + this._expecting = new Map(); + + this._connectPromise = undefined; + } + + /** + * Search and connect to RPC + */ + connect(clientId) { + if (this._connectPromise) { + return this._connectPromise; + } + this._connectPromise = new Promise((resolve, reject) => { + this.clientId = clientId; + const timeout = setTimeout(() => reject(new Error('RPC_CONNECTION_TIMEOUT')), 10e3); + timeout.unref(); + this.once('connected', () => { + clearTimeout(timeout); + resolve(this); + }); + this.transport.once('close', () => { + this._expecting.forEach((e) => { + e.reject(new Error('connection closed')); + }); + this.emit('disconnected'); + reject(new Error('connection closed')); + }); + this.transport.connect().catch(reject); + }); + return this._connectPromise; + } + + /** + * @typedef {RPCLoginOptions} + * @param {string} clientId Client ID + * @param {string} [clientSecret] Client secret + * @param {string} [accessToken] Access token + * @param {string} [rpcToken] RPC token + * @param {string} [tokenEndpoint] Token endpoint + * @param {string[]} [scopes] Scopes to authorize with + */ + + /** + * Performs authentication flow. Automatically calls Client#connect if needed. + * @param {RPCLoginOptions} options Options for authentication. + * At least one property must be provided to perform login. + * @example client.login({ clientId: '1234567', clientSecret: 'abcdef123' }); + * @returns {Promise} + */ + async login(options = {}) { + let { clientId, accessToken } = options; + await this.connect(clientId); + if (!options.scopes) { + this.emit('ready'); + return this; + } + if (!accessToken) { + accessToken = await this.authorize(options); + } + return this.authenticate(accessToken); + } + + /** + * Request + * @param {string} cmd Command + * @param {Object} [args={}] Arguments + * @param {string} [evt] Event + * @returns {Promise} + * @private + */ + request(cmd, args, evt) { + return new Promise((resolve, reject) => { + const nonce = uuid(); + this.transport.send({ cmd, args, evt, nonce }); + this._expecting.set(nonce, { resolve, reject }); + }); + } + + /** + * Message handler + * @param {Object} message message + * @private + */ + _onRpcMessage(message) { + if (message.cmd === RPCCommands.DISPATCH && message.evt === RPCEvents.READY) { + if (message.data.user) { + this.user = message.data.user; + } + this.emit('connected'); + } else if (this._expecting.has(message.nonce)) { + const { resolve, reject } = this._expecting.get(message.nonce); + if (message.evt === 'ERROR') { + const e = new Error(message.data.message); + e.code = message.data.code; + e.data = message.data; + reject(e); + } else { + resolve(message.data); + } + this._expecting.delete(message.nonce); + } else { + this.emit(message.evt, message.data); + } + } + + /** + * Authorize + * @param {Object} options options + * @returns {Promise} + * @private + */ + async authorize({ scopes, clientSecret, rpcToken, redirectUri, prompt } = {}) { + if (clientSecret && rpcToken === true) { + const body = await this.fetch('POST', '/oauth2/token/rpc', { + data: new URLSearchParams({ + client_id: this.clientId, + client_secret: clientSecret, + }), + }); + rpcToken = body.rpc_token; + } + + const { code } = await this.request('AUTHORIZE', { + scopes, + client_id: this.clientId, + prompt, + rpc_token: rpcToken, + }); + + const response = await this.fetch('POST', '/oauth2/token', { + data: new URLSearchParams({ + client_id: this.clientId, + client_secret: clientSecret, + code, + grant_type: 'authorization_code', + redirect_uri: redirectUri, + }), + }); + + return response.access_token; + } + + /** + * Authenticate + * @param {string} accessToken access token + * @returns {Promise} + * @private + */ + authenticate(accessToken) { + return this.request('AUTHENTICATE', { access_token: accessToken }) + .then(({ application, user }) => { + this.accessToken = accessToken; + this.application = application; + this.user = user; + this.emit('ready'); + return this; + }); + } + + + /** + * Fetch a guild + * @param {Snowflake} id Guild ID + * @param {number} [timeout] Timeout request + * @returns {Promise} + */ + getGuild(id, timeout) { + return this.request(RPCCommands.GET_GUILD, { guild_id: id, timeout }); + } + + /** + * Fetch all guilds + * @param {number} [timeout] Timeout request + * @returns {Promise>} + */ + getGuilds(timeout) { + return this.request(RPCCommands.GET_GUILDS, { timeout }); + } + + /** + * Get a channel + * @param {Snowflake} id Channel ID + * @param {number} [timeout] Timeout request + * @returns {Promise} + */ + getChannel(id, timeout) { + return this.request(RPCCommands.GET_CHANNEL, { channel_id: id, timeout }); + } + + /** + * Get all channels + * @param {Snowflake} [id] Guild ID + * @param {number} [timeout] Timeout request + * @returns {Promise>} + */ + async getChannels(id, timeout) { + const { channels } = await this.request(RPCCommands.GET_CHANNELS, { + timeout, + guild_id: id, + }); + return channels; + } + + /** + * @typedef {CertifiedDevice} + * @prop {string} type One of `AUDIO_INPUT`, `AUDIO_OUTPUT`, `VIDEO_INPUT` + * @prop {string} uuid This device's Windows UUID + * @prop {object} vendor Vendor information + * @prop {string} vendor.name Vendor's name + * @prop {string} vendor.url Vendor's url + * @prop {object} model Model information + * @prop {string} model.name Model's name + * @prop {string} model.url Model's url + * @prop {string[]} related Array of related product's Windows UUIDs + * @prop {boolean} echoCancellation If the device has echo cancellation + * @prop {boolean} noiseSuppression If the device has noise suppression + * @prop {boolean} automaticGainControl If the device has automatic gain control + * @prop {boolean} hardwareMute If the device has a hardware mute + */ + + /** + * Tell discord which devices are certified + * @param {CertifiedDevice[]} devices Certified devices to send to discord + * @returns {Promise} + */ + setCertifiedDevices(devices) { + return this.request(RPCCommands.SET_CERTIFIED_DEVICES, { + devices: devices.map((d) => ({ + type: d.type, + id: d.uuid, + vendor: d.vendor, + model: d.model, + related: d.related, + echo_cancellation: d.echoCancellation, + noise_suppression: d.noiseSuppression, + automatic_gain_control: d.automaticGainControl, + hardware_mute: d.hardwareMute, + })), + }); + } + + /** + * @typedef {UserVoiceSettings} + * @prop {Snowflake} id ID of the user these settings apply to + * @prop {?Object} [pan] Pan settings, an object with `left` and `right` set between + * 0.0 and 1.0, inclusive + * @prop {?number} [volume=100] The volume + * @prop {bool} [mute] If the user is muted + */ + + /** + * Set the voice settings for a user, by id + * @param {Snowflake} id ID of the user to set + * @param {UserVoiceSettings} settings Settings + * @returns {Promise} + */ + setUserVoiceSettings(id, settings) { + return this.request(RPCCommands.SET_USER_VOICE_SETTINGS, { + user_id: id, + pan: settings.pan, + mute: settings.mute, + volume: settings.volume, + }); + } + + /** + * Move the user to a voice channel + * @param {Snowflake} id ID of the voice channel + * @param {Object} [options] Options + * @param {number} [options.timeout] Timeout for the command + * @param {boolean} [options.force] Force this move. This should only be done if you + * have explicit permission from the user. + * @returns {Promise} + */ + selectVoiceChannel(id, { timeout, force = false } = {}) { + return this.request(RPCCommands.SELECT_VOICE_CHANNEL, { channel_id: id, timeout, force }); + } + + /** + * Move the user to a text channel + * @param {Snowflake} id ID of the voice channel + * @param {Object} [options] Options + * @param {number} [options.timeout] Timeout for the command + * have explicit permission from the user. + * @returns {Promise} + */ + selectTextChannel(id, { timeout } = {}) { + return this.request(RPCCommands.SELECT_TEXT_CHANNEL, { channel_id: id, timeout }); + } + + /** + * Get current voice settings + * @returns {Promise} + */ + getVoiceSettings() { + return this.request(RPCCommands.GET_VOICE_SETTINGS) + .then((s) => ({ + automaticGainControl: s.automatic_gain_control, + echoCancellation: s.echo_cancellation, + noiseSuppression: s.noise_suppression, + qos: s.qos, + silenceWarning: s.silence_warning, + deaf: s.deaf, + mute: s.mute, + input: { + availableDevices: s.input.available_devices, + device: s.input.device_id, + volume: s.input.volume, + }, + output: { + availableDevices: s.output.available_devices, + device: s.output.device_id, + volume: s.output.volume, + }, + mode: { + type: s.mode.type, + autoThreshold: s.mode.auto_threshold, + threshold: s.mode.threshold, + shortcut: s.mode.shortcut, + delay: s.mode.delay, + }, + })); + } + + /** + * Set current voice settings, overriding the current settings until this session disconnects. + * This also locks the settings for any other rpc sessions which may be connected. + * @param {Object} args Settings + * @returns {Promise} + */ + setVoiceSettings(args) { + return this.request(RPCCommands.SET_VOICE_SETTINGS, { + automatic_gain_control: args.automaticGainControl, + echo_cancellation: args.echoCancellation, + noise_suppression: args.noiseSuppression, + qos: args.qos, + silence_warning: args.silenceWarning, + deaf: args.deaf, + mute: args.mute, + input: args.input ? { + device_id: args.input.device, + volume: args.input.volume, + } : undefined, + output: args.output ? { + device_id: args.output.device, + volume: args.output.volume, + } : undefined, + mode: args.mode ? { + type: args.mode.type, + auto_threshold: args.mode.autoThreshold, + threshold: args.mode.threshold, + shortcut: args.mode.shortcut, + delay: args.mode.delay, + } : undefined, + }); + } + + /** + * Capture a shortcut using the client + * The callback takes (key, stop) where `stop` is a function that will stop capturing. + * This `stop` function must be called before disconnecting or else the user will have + * to restart their client. + * @param {Function} callback Callback handling keys + * @returns {Promise} + */ + captureShortcut(callback) { + const subid = subKey(RPCEvents.CAPTURE_SHORTCUT_CHANGE); + const stop = () => { + this._subscriptions.delete(subid); + return this.request(RPCCommands.CAPTURE_SHORTCUT, { action: 'STOP' }); + }; + this._subscriptions.set(subid, ({ shortcut }) => { + callback(shortcut, stop); + }); + return this.request(RPCCommands.CAPTURE_SHORTCUT, { action: 'START' }) + .then(() => stop); + } + + /** + * Sets the presence for the logged in user. + * @param {object} args The rich presence to pass. + * @param {number} [pid] The application's process ID. Defaults to the executing process' PID. + * @returns {Promise} + */ + setActivity(args = {}, pid = getPid()) { + let timestamps; + let assets; + let party; + let secrets; + if (args.startTimestamp || args.endTimestamp) { + timestamps = { + start: args.startTimestamp, + end: args.endTimestamp, + }; + if (timestamps.start instanceof Date) { + timestamps.start = Math.round(timestamps.start.getTime()); + } + if (timestamps.end instanceof Date) { + timestamps.end = Math.round(timestamps.end.getTime()); + } + if (timestamps.start > 2147483647000) { + throw new RangeError('timestamps.start must fit into a unix timestamp'); + } + if (timestamps.end > 2147483647000) { + throw new RangeError('timestamps.end must fit into a unix timestamp'); + } + } + if ( + args.largeImageKey || args.largeImageText + || args.smallImageKey || args.smallImageText + ) { + assets = { + large_image: args.largeImageKey, + large_text: args.largeImageText, + small_image: args.smallImageKey, + small_text: args.smallImageText, + }; + } + if (args.partySize || args.partyId || args.partyMax) { + party = { id: args.partyId }; + if (args.partySize || args.partyMax) { + party.size = [args.partySize, args.partyMax]; + } + } + if (args.matchSecret || args.joinSecret || args.spectateSecret) { + secrets = { + match: args.matchSecret, + join: args.joinSecret, + spectate: args.spectateSecret, + }; + } + + return this.request(RPCCommands.SET_ACTIVITY, { + pid, + activity: { + state: args.state, + details: args.details, + timestamps, + assets, + party, + secrets, + buttons: args.buttons, + instance: !!args.instance, + }, + }); + } + + /** + * Clears the currently set presence, if any. This will hide the "Playing X" message + * displayed below the user's name. + * @param {number} [pid] The application's process ID. Defaults to the executing process' PID. + * @returns {Promise} + */ + clearActivity(pid = getPid()) { + return this.request(RPCCommands.SET_ACTIVITY, { + pid, + }); + } + + /** + * Invite a user to join the game the RPC user is currently playing + * @param {User} user The user to invite + * @returns {Promise} + */ + sendJoinInvite(user) { + return this.request(RPCCommands.SEND_ACTIVITY_JOIN_INVITE, { + user_id: user.id || user, + }); + } + + /** + * Request to join the game the user is playing + * @param {User} user The user whose game you want to request to join + * @returns {Promise} + */ + sendJoinRequest(user) { + return this.request(RPCCommands.SEND_ACTIVITY_JOIN_REQUEST, { + user_id: user.id || user, + }); + } + + /** + * Reject a join request from a user + * @param {User} user The user whose request you wish to reject + * @returns {Promise} + */ + closeJoinRequest(user) { + return this.request(RPCCommands.CLOSE_ACTIVITY_JOIN_REQUEST, { + user_id: user.id || user, + }); + } + + createLobby(type, capacity, metadata) { + return this.request(RPCCommands.CREATE_LOBBY, { + type, + capacity, + metadata, + }); + } + + updateLobby(lobby, { type, owner, capacity, metadata } = {}) { + return this.request(RPCCommands.UPDATE_LOBBY, { + id: lobby.id || lobby, + type, + owner_id: (owner && owner.id) || owner, + capacity, + metadata, + }); + } + + deleteLobby(lobby) { + return this.request(RPCCommands.DELETE_LOBBY, { + id: lobby.id || lobby, + }); + } + + connectToLobby(id, secret) { + return this.request(RPCCommands.CONNECT_TO_LOBBY, { + id, + secret, + }); + } + + sendToLobby(lobby, data) { + return this.request(RPCCommands.SEND_TO_LOBBY, { + id: lobby.id || lobby, + data, + }); + } + + disconnectFromLobby(lobby) { + return this.request(RPCCommands.DISCONNECT_FROM_LOBBY, { + id: lobby.id || lobby, + }); + } + + updateLobbyMember(lobby, user, metadata) { + return this.request(RPCCommands.UPDATE_LOBBY_MEMBER, { + lobby_id: lobby.id || lobby, + user_id: user.id || user, + metadata, + }); + } + + getRelationships() { + const types = Object.keys(RelationshipTypes); + return this.request(RPCCommands.GET_RELATIONSHIPS) + .then((o) => o.relationships.map((r) => ({ + ...r, + type: types[r.type], + }))); + } + + /** + * Subscribe to an event + * @param {string} event Name of event e.g. `MESSAGE_CREATE` + * @param {Object} [args] Args for event e.g. `{ channel_id: '1234' }` + * @returns {Promise} + */ + async subscribe(event, args) { + await this.request(RPCCommands.SUBSCRIBE, args, event); + return { + unsubscribe: () => this.request(RPCCommands.UNSUBSCRIBE, args, event), + }; + } + + /** + * Destroy the client + */ + async destroy() { + await this.transport.close(); + } +} + +module.exports = RPCClient; diff --git a/src/assets/js/libs/discord/constants.js b/src/assets/js/libs/discord/constants.js new file mode 100644 index 0000000..441f832 --- /dev/null +++ b/src/assets/js/libs/discord/constants.js @@ -0,0 +1,178 @@ +'use strict'; + +function keyMirror(arr) { + const tmp = {}; + for (const value of arr) { + tmp[value] = value; + } + return tmp; +} + + +exports.browser = typeof window !== 'undefined'; + +exports.RPCCommands = keyMirror([ + 'DISPATCH', + 'AUTHORIZE', + 'AUTHENTICATE', + 'GET_GUILD', + 'GET_GUILDS', + 'GET_CHANNEL', + 'GET_CHANNELS', + 'CREATE_CHANNEL_INVITE', + 'GET_RELATIONSHIPS', + 'GET_USER', + 'SUBSCRIBE', + 'UNSUBSCRIBE', + 'SET_USER_VOICE_SETTINGS', + 'SET_USER_VOICE_SETTINGS_2', + 'SELECT_VOICE_CHANNEL', + 'GET_SELECTED_VOICE_CHANNEL', + 'SELECT_TEXT_CHANNEL', + 'GET_VOICE_SETTINGS', + 'SET_VOICE_SETTINGS_2', + 'SET_VOICE_SETTINGS', + 'CAPTURE_SHORTCUT', + 'SET_ACTIVITY', + 'SEND_ACTIVITY_JOIN_INVITE', + 'CLOSE_ACTIVITY_JOIN_REQUEST', + 'ACTIVITY_INVITE_USER', + 'ACCEPT_ACTIVITY_INVITE', + 'INVITE_BROWSER', + 'DEEP_LINK', + 'CONNECTIONS_CALLBACK', + 'BRAINTREE_POPUP_BRIDGE_CALLBACK', + 'GIFT_CODE_BROWSER', + 'GUILD_TEMPLATE_BROWSER', + 'OVERLAY', + 'BROWSER_HANDOFF', + 'SET_CERTIFIED_DEVICES', + 'GET_IMAGE', + 'CREATE_LOBBY', + 'UPDATE_LOBBY', + 'DELETE_LOBBY', + 'UPDATE_LOBBY_MEMBER', + 'CONNECT_TO_LOBBY', + 'DISCONNECT_FROM_LOBBY', + 'SEND_TO_LOBBY', + 'SEARCH_LOBBIES', + 'CONNECT_TO_LOBBY_VOICE', + 'DISCONNECT_FROM_LOBBY_VOICE', + 'SET_OVERLAY_LOCKED', + 'OPEN_OVERLAY_ACTIVITY_INVITE', + 'OPEN_OVERLAY_GUILD_INVITE', + 'OPEN_OVERLAY_VOICE_SETTINGS', + 'VALIDATE_APPLICATION', + 'GET_ENTITLEMENT_TICKET', + 'GET_APPLICATION_TICKET', + 'START_PURCHASE', + 'GET_SKUS', + 'GET_ENTITLEMENTS', + 'GET_NETWORKING_CONFIG', + 'NETWORKING_SYSTEM_METRICS', + 'NETWORKING_PEER_METRICS', + 'NETWORKING_CREATE_TOKEN', + 'SET_USER_ACHIEVEMENT', + 'GET_USER_ACHIEVEMENTS', +]); + +exports.RPCEvents = keyMirror([ + 'CURRENT_USER_UPDATE', + 'GUILD_STATUS', + 'GUILD_CREATE', + 'CHANNEL_CREATE', + 'RELATIONSHIP_UPDATE', + 'VOICE_CHANNEL_SELECT', + 'VOICE_STATE_CREATE', + 'VOICE_STATE_DELETE', + 'VOICE_STATE_UPDATE', + 'VOICE_SETTINGS_UPDATE', + 'VOICE_SETTINGS_UPDATE_2', + 'VOICE_CONNECTION_STATUS', + 'SPEAKING_START', + 'SPEAKING_STOP', + 'GAME_JOIN', + 'GAME_SPECTATE', + 'ACTIVITY_JOIN', + 'ACTIVITY_JOIN_REQUEST', + 'ACTIVITY_SPECTATE', + 'ACTIVITY_INVITE', + 'NOTIFICATION_CREATE', + 'MESSAGE_CREATE', + 'MESSAGE_UPDATE', + 'MESSAGE_DELETE', + 'LOBBY_DELETE', + 'LOBBY_UPDATE', + 'LOBBY_MEMBER_CONNECT', + 'LOBBY_MEMBER_DISCONNECT', + 'LOBBY_MEMBER_UPDATE', + 'LOBBY_MESSAGE', + 'CAPTURE_SHORTCUT_CHANGE', + 'OVERLAY', + 'OVERLAY_UPDATE', + 'ENTITLEMENT_CREATE', + 'ENTITLEMENT_DELETE', + 'USER_ACHIEVEMENT_UPDATE', + 'READY', + 'ERROR', +]); + +exports.RPCErrors = { + CAPTURE_SHORTCUT_ALREADY_LISTENING: 5004, + GET_GUILD_TIMED_OUT: 5002, + INVALID_ACTIVITY_JOIN_REQUEST: 4012, + INVALID_ACTIVITY_SECRET: 5005, + INVALID_CHANNEL: 4005, + INVALID_CLIENTID: 4007, + INVALID_COMMAND: 4002, + INVALID_ENTITLEMENT: 4015, + INVALID_EVENT: 4004, + INVALID_GIFT_CODE: 4016, + INVALID_GUILD: 4003, + INVALID_INVITE: 4011, + INVALID_LOBBY: 4013, + INVALID_LOBBY_SECRET: 4014, + INVALID_ORIGIN: 4008, + INVALID_PAYLOAD: 4000, + INVALID_PERMISSIONS: 4006, + INVALID_TOKEN: 4009, + INVALID_USER: 4010, + LOBBY_FULL: 5007, + NO_ELIGIBLE_ACTIVITY: 5006, + OAUTH2_ERROR: 5000, + PURCHASE_CANCELED: 5008, + PURCHASE_ERROR: 5009, + RATE_LIMITED: 5011, + SELECT_CHANNEL_TIMED_OUT: 5001, + SELECT_VOICE_FORCE_REQUIRED: 5003, + SERVICE_UNAVAILABLE: 1001, + TRANSACTION_ABORTED: 1002, + UNAUTHORIZED_FOR_ACHIEVEMENT: 5010, + UNKNOWN_ERROR: 1000, +}; + +exports.RPCCloseCodes = { + CLOSE_NORMAL: 1000, + CLOSE_UNSUPPORTED: 1003, + CLOSE_ABNORMAL: 1006, + INVALID_CLIENTID: 4000, + INVALID_ORIGIN: 4001, + RATELIMITED: 4002, + TOKEN_REVOKED: 4003, + INVALID_VERSION: 4004, + INVALID_ENCODING: 4005, +}; + +exports.LobbyTypes = { + PRIVATE: 1, + PUBLIC: 2, +}; + +exports.RelationshipTypes = { + NONE: 0, + FRIEND: 1, + BLOCKED: 2, + PENDING_INCOMING: 3, + PENDING_OUTGOING: 4, + IMPLICIT: 5, +}; diff --git a/src/assets/js/libs/discord/index.js b/src/assets/js/libs/discord/index.js new file mode 100644 index 0000000..a3444b3 --- /dev/null +++ b/src/assets/js/libs/discord/index.js @@ -0,0 +1,10 @@ +'use strict'; + +const util = require('./util'); + +module.exports = { + Client: require('./client'), + register(id) { + return util.register(`discord-${id}`); + }, +}; diff --git a/src/assets/js/libs/discord/transports/index.js b/src/assets/js/libs/discord/transports/index.js new file mode 100644 index 0000000..42db529 --- /dev/null +++ b/src/assets/js/libs/discord/transports/index.js @@ -0,0 +1,6 @@ +'use strict'; + +module.exports = { + ipc: require('./ipc'), + websocket: require('./websocket'), +}; diff --git a/src/assets/js/libs/discord/transports/ipc.js b/src/assets/js/libs/discord/transports/ipc.js new file mode 100644 index 0000000..f050a01 --- /dev/null +++ b/src/assets/js/libs/discord/transports/ipc.js @@ -0,0 +1,173 @@ +'use strict'; + +const net = require('net'); +const EventEmitter = require('events'); +const fetch = require('node-fetch'); +const { uuid } = require('../util'); + +const OPCodes = { + HANDSHAKE: 0, + FRAME: 1, + CLOSE: 2, + PING: 3, + PONG: 4, +}; + +function getIPCPath(id) { + if (process.platform === 'win32') { + return `\\\\?\\pipe\\discord-ipc-${id}`; + } + const { env: { XDG_RUNTIME_DIR, TMPDIR, TMP, TEMP } } = process; + const prefix = XDG_RUNTIME_DIR || TMPDIR || TMP || TEMP || '/tmp'; + return `${prefix.replace(/\/$/, '')}/discord-ipc-${id}`; +} + +function getIPC(id = 0) { + return new Promise((resolve, reject) => { + const path = getIPCPath(id); + const onerror = () => { + if (id < 10) { + resolve(getIPC(id + 1)); + } else { + reject(new Error('Could not connect')); + } + }; + const sock = net.createConnection(path, () => { + sock.removeListener('error', onerror); + resolve(sock); + }); + sock.once('error', onerror); + }); +} + +async function findEndpoint(tries = 0) { + if (tries > 30) { + throw new Error('Could not find endpoint'); + } + const endpoint = `http://127.0.0.1:${6463 + (tries % 10)}`; + try { + const r = await fetch(endpoint); + if (r.status === 404) { + return endpoint; + } + return findEndpoint(tries + 1); + } catch (e) { + return findEndpoint(tries + 1); + } +} + +function encode(op, data) { + data = JSON.stringify(data); + const len = Buffer.byteLength(data); + const packet = Buffer.alloc(8 + len); + packet.writeInt32LE(op, 0); + packet.writeInt32LE(len, 4); + packet.write(data, 8, len); + return packet; +} + +const working = { + full: '', + op: undefined, +}; + +function decode(socket, callback) { + const packet = socket.read(); + if (!packet) { + return; + } + + let { op } = working; + let raw; + if (working.full === '') { + op = working.op = packet.readInt32LE(0); + const len = packet.readInt32LE(4); + raw = packet.slice(8, len + 8); + } else { + raw = packet.toString(); + } + + try { + const data = JSON.parse(working.full + raw); + callback({ op, data }); // eslint-disable-line callback-return + working.full = ''; + working.op = undefined; + } catch (err) { + working.full += raw; + } + + decode(socket, callback); +} + +class IPCTransport extends EventEmitter { + constructor(client) { + super(); + this.client = client; + this.socket = null; + } + + async connect() { + const socket = this.socket = await getIPC(); + socket.on('close', this.onClose.bind(this)); + socket.on('error', this.onClose.bind(this)); + this.emit('open'); + socket.write(encode(OPCodes.HANDSHAKE, { + v: 1, + client_id: this.client.clientId, + })); + socket.pause(); + socket.on('readable', () => { + decode(socket, ({ op, data }) => { + switch (op) { + case OPCodes.PING: + this.send(data, OPCodes.PONG); + break; + case OPCodes.FRAME: + if (!data) { + return; + } + if (data.cmd === 'AUTHORIZE' && data.evt !== 'ERROR') { + findEndpoint() + .then((endpoint) => { + this.client.request.endpoint = endpoint; + }) + .catch((e) => { + this.client.emit('error', e); + }); + } + this.emit('message', data); + break; + case OPCodes.CLOSE: + this.emit('close', data); + break; + default: + break; + } + }); + }); + } + + onClose(e) { + this.emit('close', e); + } + + send(data, op = OPCodes.FRAME) { + this.socket.write(encode(op, data)); + } + + async close() { + return new Promise((r) => { + this.once('close', r); + this.send({}, OPCodes.CLOSE); + this.socket.end(); + }); + } + + ping() { + this.send(uuid(), OPCodes.PING); + } +} + +module.exports = IPCTransport; +module.exports.encode = encode; +module.exports.decode = decode; diff --git a/src/assets/js/libs/discord/transports/websocket.js b/src/assets/js/libs/discord/transports/websocket.js new file mode 100644 index 0000000..bd5a671 --- /dev/null +++ b/src/assets/js/libs/discord/transports/websocket.js @@ -0,0 +1,77 @@ +'use strict'; + +const EventEmitter = require('events'); +const { browser } = require('../constants'); + +// eslint-disable-next-line +const WebSocket = browser ? window.WebSocket : require('ws'); + +const pack = (d) => JSON.stringify(d); +const unpack = (s) => JSON.parse(s); + +class WebSocketTransport extends EventEmitter { + constructor(client) { + super(); + this.client = client; + this.ws = null; + this.tries = 0; + } + + async connect() { + const port = 6463 + (this.tries % 10); + this.tries += 1; + + this.ws = new WebSocket( + `ws://127.0.0.1:${port}/?v=1&client_id=${this.client.clientId}`, + browser ? undefined : { origin: this.client.options.origin }, + ); + this.ws.onopen = this.onOpen.bind(this); + this.ws.onclose = this.onClose.bind(this); + this.ws.onerror = this.onError.bind(this); + this.ws.onmessage = this.onMessage.bind(this); + } + + onOpen() { + this.emit('open'); + } + + onClose(event) { + if (!event.wasClean) { + return; + } + this.emit('close', event); + } + + onError(event) { + try { + this.ws.close(); + } catch {} // eslint-disable-line no-empty + + if (this.tries > 20) { + this.emit('error', event.error); + } else { + setTimeout(() => { + this.connect(); + }, 250); + } + } + + onMessage(event) { + this.emit('message', unpack(event.data)); + } + + send(data) { + this.ws.send(pack(data)); + } + + ping() {} // eslint-disable-line no-empty-function + + close() { + return new Promise((r) => { + this.once('close', r); + this.ws.close(); + }); + } +} + +module.exports = WebSocketTransport; diff --git a/src/assets/js/libs/discord/util.js b/src/assets/js/libs/discord/util.js new file mode 100644 index 0000000..2fdc937 --- /dev/null +++ b/src/assets/js/libs/discord/util.js @@ -0,0 +1,50 @@ +'use strict'; + +let register; +try { + const { app } = require('electron'); + register = app.setAsDefaultProtocolClient.bind(app); +} catch (err) { + try { + register = require('register-scheme'); + } catch (e) {} // eslint-disable-line no-empty +} + +if (typeof register !== 'function') { + register = () => false; +} + +function pid() { + if (typeof process !== 'undefined') { + return process.pid; + } + return null; +} + +const uuid4122 = () => { + let uuid = ''; + for (let i = 0; i < 32; i += 1) { + if (i === 8 || i === 12 || i === 16 || i === 20) { + uuid += '-'; + } + let n; + if (i === 12) { + n = 4; + } else { + const random = Math.random() * 16 | 0; + if (i === 16) { + n = (random & 3) | 0; + } else { + n = random; + } + } + uuid += n.toString(16); + } + return uuid; +}; + +module.exports = { + pid, + register, + uuid: uuid4122, +}; diff --git a/src/assets/js/libs/mc/Authenticator/AZauth.d.ts b/src/assets/js/libs/mc/Authenticator/AZauth.d.ts new file mode 100644 index 0000000..03de834 --- /dev/null +++ b/src/assets/js/libs/mc/Authenticator/AZauth.d.ts @@ -0,0 +1,83 @@ +/** + * @author TECNO BROS + + */ +export default class AZauth { + url: string; + constructor(url: string); + login(username: string, password: string, A2F?: any): Promise<{ + A2F: boolean; + error?: undefined; + reason?: undefined; + message?: undefined; + access_token?: undefined; + client_token?: undefined; + uuid?: undefined; + name?: undefined; + user_properties?: undefined; + user_info?: undefined; + meta?: undefined; + } | { + error: boolean; + reason: any; + message: any; + A2F?: undefined; + access_token?: undefined; + client_token?: undefined; + uuid?: undefined; + name?: undefined; + user_properties?: undefined; + user_info?: undefined; + meta?: undefined; + } | { + access_token: any; + client_token: any; + uuid: any; + name: any; + user_properties: string; + user_info: { + banned: any; + money: any; + role: any; + }; + meta: { + online: boolean; + type: string; + }; + A2F?: undefined; + error?: undefined; + reason?: undefined; + message?: undefined; + }>; + verify(user: any): Promise<{ + error: boolean; + reason: any; + message: any; + access_token?: undefined; + client_token?: undefined; + uuid?: undefined; + name?: undefined; + user_properties?: undefined; + user_info?: undefined; + meta?: undefined; + } | { + access_token: any; + client_token: any; + uuid: any; + name: any; + user_properties: string; + user_info: { + banned: any; + money: any; + role: any; + }; + meta: { + online: boolean; + type: string; + }; + error?: undefined; + reason?: undefined; + message?: undefined; + }>; + signout(user: any): Promise; +} diff --git a/src/assets/js/libs/mc/Authenticator/AZauth.js b/src/assets/js/libs/mc/Authenticator/AZauth.js new file mode 100644 index 0000000..6cadf7a --- /dev/null +++ b/src/assets/js/libs/mc/Authenticator/AZauth.js @@ -0,0 +1,101 @@ +"use strict"; +/** + * @author TECNO BROS + + */ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const node_fetch_1 = __importDefault(require("node-fetch")); +class AZauth { + constructor(url) { + this.url = `${url}/api/auth`; + } + async login(username, password, A2F = null) { + let response = await (0, node_fetch_1.default)(`${this.url}/authenticate`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + email: username, + password: password, + code: A2F + }), + }).then((res) => res.json()); + if (response.status == 'pending' && response.reason == '2fa') { + return { A2F: true }; + } + if (response.status == 'error') { + return { + error: true, + reason: response.reason, + message: response.message + }; + } + return { + access_token: response.access_token, + client_token: response.uuid, + uuid: response.uuid, + name: response.username, + user_properties: '{}', + user_info: { + banned: response.banned, + money: response.money, + role: response.role + }, + meta: { + online: false, + type: 'AZauth', + } + }; + } + async verify(user) { + let response = await (0, node_fetch_1.default)(`${this.url}/verify`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + access_token: user.access_token + }), + }).then((res) => res.json()); + if (response.status == 'error') { + return { + error: true, + reason: response.reason, + message: response.message + }; + } + return { + access_token: response.access_token, + client_token: response.uuid, + uuid: response.uuid, + name: response.username, + user_properties: '{}', + user_info: { + banned: response.banned, + money: response.money, + role: response.role + }, + meta: { + online: false, + type: 'AZauth', + } + }; + } + async signout(user) { + let auth = await (0, node_fetch_1.default)(`${this.url}/logout`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + access_token: user.access_token + }), + }).then((res) => res.json()); + if (auth.error) + return false; + return true; + } +} +exports.default = AZauth; diff --git a/src/assets/js/libs/mc/Authenticator/GUI/Electron.d.ts b/src/assets/js/libs/mc/Authenticator/GUI/Electron.d.ts new file mode 100644 index 0000000..681285f --- /dev/null +++ b/src/assets/js/libs/mc/Authenticator/GUI/Electron.d.ts @@ -0,0 +1,13 @@ +/** + * @author TECNO BROS + + */ +declare const path: any; +declare const app: any, BrowserWindow: any, session: any; +declare const defaultProperties: { + width: number; + height: number; + resizable: boolean; + center: boolean; + icon: any; +}; diff --git a/src/assets/js/libs/mc/Authenticator/GUI/Electron.js b/src/assets/js/libs/mc/Authenticator/GUI/Electron.js new file mode 100644 index 0000000..4aa0a76 --- /dev/null +++ b/src/assets/js/libs/mc/Authenticator/GUI/Electron.js @@ -0,0 +1,57 @@ +/** + * @author TECNO BROS + + */ +const path = require('path'); +const { app, BrowserWindow, session } = require('electron'); +const defaultProperties = { + width: 1000, + height: 650, + resizable: false, + center: true, + icon: path.join(__dirname, '../../../assets/icons', `Microsoft.${(process.platform === 'win32') ? 'ico' : 'png'}`), +}; +module.exports = async function (url) { + await new Promise((resolve) => { + app.whenReady().then(() => { + session.defaultSession.cookies.get({ domain: 'live.com' }).then((cookies) => { + for (let cookie of cookies) { + let urlcookie = `http${cookie.secure ? "s" : ""}://${cookie.domain.replace(/$\./, "") + cookie.path}`; + session.defaultSession.cookies.remove(urlcookie, cookie.name); + } + }); + return resolve(); + }); + }); + return new Promise(resolve => { + app.whenReady().then(() => { + const mainWindow = new BrowserWindow(defaultProperties); + mainWindow.setMenu(null); + mainWindow.loadURL(url); + var loading = false; + mainWindow.on("close", () => { + if (!loading) + resolve("cancel"); + }); + mainWindow.webContents.on("did-finish-load", () => { + const loc = mainWindow.webContents.getURL(); + if (loc.startsWith("https://login.live.com/oauth20_desktop.srf")) { + const urlParams = new URLSearchParams(loc.substr(loc.indexOf("?") + 1)).get("code"); + if (urlParams) { + resolve(urlParams); + loading = true; + } + else { + resolve("cancel"); + } + try { + mainWindow.close(); + } + catch { + console.error("Failed to close window!"); + } + } + }); + }); + }); +}; diff --git a/src/assets/js/libs/mc/Authenticator/GUI/NW.d.ts b/src/assets/js/libs/mc/Authenticator/GUI/NW.d.ts new file mode 100644 index 0000000..25067e7 --- /dev/null +++ b/src/assets/js/libs/mc/Authenticator/GUI/NW.d.ts @@ -0,0 +1,5 @@ +/** + * @author TECNO BROS + + */ +export {}; diff --git a/src/assets/js/libs/mc/Authenticator/GUI/NW.js b/src/assets/js/libs/mc/Authenticator/GUI/NW.js new file mode 100644 index 0000000..7882941 --- /dev/null +++ b/src/assets/js/libs/mc/Authenticator/GUI/NW.js @@ -0,0 +1,58 @@ +/** + * @author TECNO BROS + + */ +'use strict'; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const path_1 = __importDefault(require("path")); +const defaultProperties = { + width: 1000, + height: 650, + resizable: false, + position: "center", + frame: true, + icon: path_1.default.join(__dirname, '../../../assets/icons/Microsoft.png') +}; +module.exports = async function (url) { + await new Promise((resolve) => { + //@ts-ignore + nw.Window.get().cookies.getAll({ domain: "live.com" }, async (cookies) => { + for await (let cookie of cookies) { + let url = `http${cookie.secure ? "s" : ""}://${cookie.domain.replace(/$\./, "") + cookie.path}`; + //@ts-ignore + nw.Window.get().cookies.remove({ url: url, name: cookie.name }); + } + return resolve(); + }); + }); + let code = await new Promise((resolve) => { + //@ts-ignore + nw.Window.open(url, defaultProperties, (Window) => { + let interval = null; + let code; + interval = setInterval(() => { + if (Window.window.document.location.href.startsWith("https://login.live.com/oauth20_desktop.srf")) { + clearInterval(interval); + try { + code = Window.window.document.location.href.split("code=")[1].split("&")[0]; + } + catch (e) { + code = "cancel"; + } + Window.close(); + } + }, 100); + Window.on('closed', () => { + if (!code) + code = "cancel"; + if (interval) + clearInterval(interval); + resolve(code); + }); + }); + }); + return code; +}; diff --git a/src/assets/js/libs/mc/Authenticator/GUI/Terminal.d.ts b/src/assets/js/libs/mc/Authenticator/GUI/Terminal.d.ts new file mode 100644 index 0000000..25067e7 --- /dev/null +++ b/src/assets/js/libs/mc/Authenticator/GUI/Terminal.d.ts @@ -0,0 +1,5 @@ +/** + * @author TECNO BROS + + */ +export {}; diff --git a/src/assets/js/libs/mc/Authenticator/GUI/Terminal.js b/src/assets/js/libs/mc/Authenticator/GUI/Terminal.js new file mode 100644 index 0000000..0634c80 --- /dev/null +++ b/src/assets/js/libs/mc/Authenticator/GUI/Terminal.js @@ -0,0 +1,15 @@ +"use strict"; +/** + * @author TECNO BROS + + */ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const prompt_1 = __importDefault(require("prompt")); +module.exports = async function (url) { + prompt_1.default.start(); + let result = await prompt_1.default.get(['copy-URL']); + return result['copy-URL'].split("code=")[1].split("&")[0]; +}; diff --git a/src/assets/js/libs/mc/Authenticator/Microsoft.d.ts b/src/assets/js/libs/mc/Authenticator/Microsoft.d.ts new file mode 100644 index 0000000..53d18c6 --- /dev/null +++ b/src/assets/js/libs/mc/Authenticator/Microsoft.d.ts @@ -0,0 +1,14 @@ +/** + * @author TECNO BROS + + */ +export default class Microsoft { + client_id: string; + type: 'electron' | 'nwjs' | 'terminal'; + constructor(client_id: string); + getAuth(type: string, url: string): Promise; + url(code: string): Promise; + refresh(acc: any): Promise; + getAccount(oauth2: any): Promise; + getProfile(mcLogin: any): Promise; +} diff --git a/src/assets/js/libs/mc/Authenticator/Microsoft.js b/src/assets/js/libs/mc/Authenticator/Microsoft.js new file mode 100644 index 0000000..72bb250 --- /dev/null +++ b/src/assets/js/libs/mc/Authenticator/Microsoft.js @@ -0,0 +1,217 @@ +"use strict"; +/** + * @author TECNO BROS + + */ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const node_fetch_1 = __importDefault(require("node-fetch")); +const crypto_1 = __importDefault(require("crypto")); +class Microsoft { + constructor(client_id) { + if (client_id === '' || !client_id) + client_id = '00000000402b5328'; + this.client_id = client_id; + if (!!process && !!process.versions && !!process.versions.electron) { + this.type = 'electron'; + } + else if (!!process && !!process.versions && !!process.versions.nw) { + this.type = 'nwjs'; + } + else { + this.type = 'terminal'; + } + } + async getAuth(type, url) { + if (!url) + url = `https://login.live.com/oauth20_authorize.srf?client_id=${this.client_id}&response_type=code&redirect_uri=https://login.live.com/oauth20_desktop.srf&scope=XboxLive.signin%20offline_access&cobrandid=8058f65d-ce06-4c30-9559-473c9275a65d&prompt=select_account`; + if (!type) + type = this.type; + if (type == "electron") { + let usercode = await (require('./GUI/Electron.js'))(url); + if (usercode === "cancel") + return false; + else + return await this.url(usercode); + } + else if (type == "nwjs") { + let usercode = await (require('./GUI/NW.js'))(url); + if (usercode === "cancel") + return false; + else + return await this.url(usercode); + } + else if (type == "terminal") { + let usercode = await (require('./GUI/Terminal.js'))(url); + if (usercode === "cancel") + return false; + else + return await this.url(usercode); + } + } + async url(code) { + let oauth2 = await (0, node_fetch_1.default)("https://login.live.com/oauth20_token.srf", { + method: "POST", + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, + body: `client_id=${this.client_id}&code=${code}&grant_type=authorization_code&redirect_uri=https://login.live.com/oauth20_desktop.srf` + }).then(res => res.json()).catch(err => { return { error: err }; }); + ; + if (oauth2.error) + return oauth2; + return await this.getAccount(oauth2); + } + async refresh(acc) { + let timeStamp = Math.floor(Date.now() / 1000); + let oauth2 = await (0, node_fetch_1.default)("https://login.live.com/oauth20_token.srf", { + method: "POST", + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, + body: `grant_type=refresh_token&client_id=${this.client_id}&refresh_token=${acc.refresh_token}` + }).then(res => res.json()).catch(err => { return { error: err }; }); + + ; + if (oauth2.error) { + oauth2.errorType = "oauth2"; + return oauth2; + } + ; + if (timeStamp < (acc?.meta?.access_token_expires_in - 7200)) { + let profile = await this.getProfile(acc); + acc.refresh_token = oauth2.refresh_token; + acc.profile = { + skins: profile.skins, + capes: profile.capes + }; + return acc; + } + else { + return await this.getAccount(oauth2); + } + } + async getAccount(oauth2) { + let xbl = await (0, node_fetch_1.default)("https://user.auth.xboxlive.com/user/authenticate", { + method: "post", + body: JSON.stringify({ + Properties: { + AuthMethod: "RPS", + SiteName: "user.auth.xboxlive.com", + RpsTicket: "d=" + oauth2.access_token + }, + RelyingParty: "http://auth.xboxlive.com", + TokenType: "JWT" + }), + headers: { "Content-Type": "application/json", Accept: "application/json" }, + }).then(res => res.json()).catch(err => { return { error: err }; }); + ; + if (xbl.error) { + xbl.errorType = "xbl"; + return xbl; + } + let xsts = await (0, node_fetch_1.default)("https://xsts.auth.xboxlive.com/xsts/authorize", { + method: "POST", + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + Properties: { + SandboxId: "RETAIL", + UserTokens: [xbl.Token] + }, + RelyingParty: "rp://api.minecraftservices.com/", + TokenType: "JWT" + }) + }).then(res => res.json()); + if (xsts.error) { + xsts.errorType = "xsts"; + return xsts; + } + let xboxAccount = await (0, node_fetch_1.default)("https://xsts.auth.xboxlive.com/xsts/authorize", { + method: "POST", + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + Properties: { + SandboxId: "RETAIL", + UserTokens: [xbl.Token] + }, + RelyingParty: "http://xboxlive.com", + TokenType: "JWT" + }) + }).then(res => res.json()).catch(err => { return { error: err }; }); + if (xsts.error) { + xsts.errorType = "xboxAccount"; + return xsts; + } + let mcLogin = await (0, node_fetch_1.default)("https://api.minecraftservices.com/authentication/login_with_xbox", { + method: "POST", + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ "identityToken": `XBL3.0 x=${xbl.DisplayClaims.xui[0].uhs};${xsts.Token}` }) + }).then(res => res.json()).catch(err => { return { error: err }; }); + if (mcLogin.error) { + mcLogin.errorType = "mcLogin"; + return mcLogin; + } + let profile = await this.getProfile(mcLogin); + if (profile.error) { + profile.errorType = "profile"; + return profile; + } + return { + access_token: mcLogin.access_token, + client_token: crypto_1.default.randomBytes(16).toString('hex'), + uuid: profile.id, + name: profile.name, + refresh_token: oauth2.refresh_token, + user_properties: '{}', + meta: { + xuid: xboxAccount.DisplayClaims.xui[0].xid, + type: "Xbox", + access_token_expires_in: mcLogin.expires_in + Math.floor(Date.now() / 1000), + demo: profile.error ? true : false + }, + profile: { + skins: profile.skins, + capes: profile.capes + } + }; + } + async getProfile(mcLogin) { + let profile = await (0, node_fetch_1.default)("https://api.minecraftservices.com/minecraft/profile", { + method: "GET", + headers: { + 'Authorization': `Bearer ${mcLogin.access_token}` + } + }).then(res => res.json()).catch(err => { return { error: err }; }); + ; + if (profile.error) + return profile; + let skins = profile.skins; + let capes = profile.capes; + for (let skin of skins) { + skin.base64 = `data:image/png;base64,${await getBass64(skin.url)}`; + } + for (let cape of capes) { + cape.base64 = `data:image/png;base64,${await getBass64(cape.url)}`; + } + return { + id: profile.id, + name: profile.name, + skins: profile.skins || [], + capes: profile.capes || [] + }; + } +} +exports.default = Microsoft; +async function getBass64(url) { + let response = await (0, node_fetch_1.default)(url); + let buffer = await response.buffer(); + return buffer.toString('base64'); +} diff --git a/src/assets/js/libs/mc/Authenticator/Mojang.d.ts b/src/assets/js/libs/mc/Authenticator/Mojang.d.ts new file mode 100644 index 0000000..8950a22 --- /dev/null +++ b/src/assets/js/libs/mc/Authenticator/Mojang.d.ts @@ -0,0 +1,10 @@ +/** + * @author TECNO BROS + + */ +declare function login(username: string, password?: string): Promise; +declare function refresh(acc: any): Promise; +declare function validate(acc: any): Promise; +declare function signout(acc: any): Promise; +declare function ChangeAuthApi(url: string): void; +export { login as login, refresh as refresh, validate as validate, signout as signout, ChangeAuthApi as ChangeAuthApi }; diff --git a/src/assets/js/libs/mc/Authenticator/Mojang.js b/src/assets/js/libs/mc/Authenticator/Mojang.js new file mode 100644 index 0000000..d410b30 --- /dev/null +++ b/src/assets/js/libs/mc/Authenticator/Mojang.js @@ -0,0 +1,134 @@ +"use strict"; +/** + * @author TECNO BROS + + */ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ChangeAuthApi = exports.signout = exports.validate = exports.refresh = exports.login = void 0; +const crypto_1 = __importDefault(require("crypto")); +const node_fetch_1 = __importDefault(require("node-fetch")); +let api_url = 'https://authserver.mojang.com'; +async function login(username, password) { + let UUID = crypto_1.default.randomBytes(16).toString('hex'); + if (!password) { + return { + access_token: UUID, + client_token: UUID, + uuid: UUID, + name: username, + user_properties: '{}', + meta: { + online: false, + type: 'Mojang' + } + }; + } + let message = await (0, node_fetch_1.default)(`${api_url}/authenticate`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + agent: { + name: "Minecraft", + version: 1 + }, + username, + password, + clientToken: UUID, + requestUser: true + }) + }).then(res => res.json()); + if (message.error) { + return message; + } + ; + let user = { + access_token: message.accessToken, + client_token: message.clientToken, + uuid: message.selectedProfile.id, + name: message.selectedProfile.name, + user_properties: '{}', + meta: { + online: true, + type: 'Mojang' + } + }; + return user; +} +exports.login = login; +async function refresh(acc) { + let message = await (0, node_fetch_1.default)(`${api_url}/refresh`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + accessToken: acc.access_token, + clientToken: acc.client_token, + requestUser: true + }) + }).then(res => res.json()); + if (message.error) { + return message; + } + ; + let user = { + access_token: message.accessToken, + client_token: message.clientToken, + uuid: message.selectedProfile.id, + name: message.selectedProfile.name, + user_properties: '{}', + meta: { + online: true, + type: 'Mojang' + } + }; + return user; +} +exports.refresh = refresh; +async function validate(acc) { + let message = await (0, node_fetch_1.default)(`${api_url}/validate`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + accessToken: acc.access_token, + clientToken: acc.client_token, + }) + }); + if (message.status == 204) { + return true; + } + else { + return false; + } +} +exports.validate = validate; +async function signout(acc) { + let message = await (0, node_fetch_1.default)(`${api_url}/invalidate`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + accessToken: acc.access_token, + clientToken: acc.client_token, + }) + }).then(res => res.text()); + if (message == "") { + return true; + } + else { + return false; + } +} +exports.signout = signout; +function ChangeAuthApi(url) { + api_url = url; +} +exports.ChangeAuthApi = ChangeAuthApi; diff --git a/src/assets/js/libs/mc/Index.d.ts b/src/assets/js/libs/mc/Index.d.ts new file mode 100644 index 0000000..f49ad8c --- /dev/null +++ b/src/assets/js/libs/mc/Index.d.ts @@ -0,0 +1,10 @@ +/** + * @author TECNO BROS + + */ +import AZauth from './Authenticator/AZauth.js'; +import Launch from './Launch.js'; +import Microsoft from './Authenticator/Microsoft.js'; +import * as Mojang from './Authenticator/Mojang.js'; +import Status from './StatusServer/status.js'; +export { AZauth as AZauth, Launch as Launch, Microsoft as Microsoft, Mojang as Mojang, Status as Status }; diff --git a/src/assets/js/libs/mc/Index.js b/src/assets/js/libs/mc/Index.js new file mode 100644 index 0000000..d6eedbd --- /dev/null +++ b/src/assets/js/libs/mc/Index.js @@ -0,0 +1,43 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Status = exports.Mojang = exports.Microsoft = exports.Launch = exports.AZauth = void 0; +/** + * @author TECNO BROS + + */ +const AZauth_js_1 = __importDefault(require("./Authenticator/AZauth.js")); +exports.AZauth = AZauth_js_1.default; +const Launch_js_1 = __importDefault(require("./Launch.js")); +exports.Launch = Launch_js_1.default; +const Microsoft_js_1 = __importDefault(require("./Authenticator/Microsoft.js")); +exports.Microsoft = Microsoft_js_1.default; +const Mojang = __importStar(require("./Authenticator/Mojang.js")); +exports.Mojang = Mojang; +const status_js_1 = __importDefault(require("./StatusServer/status.js")); +exports.Status = status_js_1.default; diff --git a/src/assets/js/libs/mc/Launch.d.ts b/src/assets/js/libs/mc/Launch.d.ts new file mode 100644 index 0000000..d67bef8 --- /dev/null +++ b/src/assets/js/libs/mc/Launch.d.ts @@ -0,0 +1,49 @@ +/** + * @author TECNO BROS + + */ +type loader = { + rootPath?: boolean; + type?: string; + build?: string; + enable?: boolean; +}; +type screen = { + width?: number; + height?: number; + fullscreen?: boolean; +}; +type memory = { + min?: string; + max?: string; +}; +type LaunchOPTS = { + url: string | null; + authenticator: any; + timeout?: number; + path: string; + version: string; + instance?: string; + detached?: boolean; + downloadFileMultiple?: number; + intelEnabledMac?: boolean; + loader: loader; + mcp: any; + verify: boolean; + ignored: string[]; + JVM_ARGS: string[]; + GAME_ARGS: string[]; + javaPath: string; + screen: screen; + memory: memory; +}; +export default class Launch { + options: LaunchOPTS; + on: any; + emit: any; + constructor(); + Launch(opt: LaunchOPTS): Promise; + start(): Promise; + DownloadGame(): Promise; +} +export {}; diff --git a/src/assets/js/libs/mc/Launch.js b/src/assets/js/libs/mc/Launch.js new file mode 100644 index 0000000..c88a892 --- /dev/null +++ b/src/assets/js/libs/mc/Launch.js @@ -0,0 +1,187 @@ +"use strict"; +/** + * @author TECNO BROS + + */ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const events_1 = require("events"); +const path_1 = __importDefault(require("path")); +const fs_1 = __importDefault(require("fs")); +const child_process_1 = require("child_process"); +const Minecraft_Json_js_1 = __importDefault(require("./Minecraft/Minecraft-Json.js")); +const Minecraft_Libraries_js_1 = __importDefault(require("./Minecraft/Minecraft-Libraries.js")); +const Minecraft_Assets_js_1 = __importDefault(require("./Minecraft/Minecraft-Assets.js")); +const Minecraft_Loader_js_1 = __importDefault(require("./Minecraft/Minecraft-Loader.js")); +const Minecraft_Java_js_1 = __importDefault(require("./Minecraft/Minecraft-Java.js")); +const Minecraft_Bundle_js_1 = __importDefault(require("./Minecraft/Minecraft-Bundle.js")); +const Minecraft_Arguments_js_1 = __importDefault(require("./Minecraft/Minecraft-Arguments.js")); +const Index_js_1 = require("./utils/Index.js"); +const Downloader_js_1 = __importDefault(require("./utils/Downloader.js")); +class Launch { + constructor() { + this.on = events_1.EventEmitter.prototype.on; + this.emit = events_1.EventEmitter.prototype.emit; + } + async Launch(opt) { + const defaultOptions = { + url: null, + authenticator: null, + timeout: 10000, + path: '.Minecraft', + version: 'latest_release', + instance: null, + detached: false, + intelEnabledMac: false, + downloadFileMultiple: 5, + loader: { + rootPath: false, + type: null, + build: 'latest', + enable: false, + }, + mcp: null, + verify: false, + ignored: [], + JVM_ARGS: [], + GAME_ARGS: [], + javaPath: null, + screen: { + width: null, + height: null, + fullscreen: false, + }, + memory: { + min: '1G', + max: '2G' + }, + ...opt, + }; + this.options = defaultOptions; + this.options.path = path_1.default.resolve(this.options.path).replace(/\\/g, '/'); + if (this.options.mcp) { + if (this.options.instance) + this.options.mcp = `${this.options.path}/instances/${this.options.instance}/${this.options.mcp}`; + else + this.options.mcp = path_1.default.resolve(`${this.options.path}/${this.options.mcp}`).replace(/\\/g, '/'); + } + if (this.options.loader.type) { + this.options.loader.type = this.options.loader.type.toLowerCase(); + this.options.loader.build = this.options.loader.build.toLowerCase(); + } + if (!this.options.authenticator) + return this.emit("error", { error: "Authenticator not found" }); + if (this.options.downloadFileMultiple < 1) + this.options.downloadFileMultiple = 1; + if (this.options.downloadFileMultiple > 30) + this.options.downloadFileMultiple = 30; + this.start(); + } + async start() { + let data = await this.DownloadGame(); + if (data.error) + return this.emit('error', data); + let { minecraftJson, minecraftLoader, minecraftVersion, minecraftJava } = data; + let minecraftArguments = await new Minecraft_Arguments_js_1.default(this.options).GetArguments(minecraftJson, minecraftLoader); + if (minecraftArguments.error) + return this.emit('error', minecraftArguments); + let loaderArguments = await new Minecraft_Loader_js_1.default(this.options).GetArguments(minecraftLoader, minecraftVersion); + if (loaderArguments.error) + return this.emit('error', loaderArguments); + let Arguments = [ + ...minecraftArguments.jvm, + ...minecraftArguments.classpath, + ...loaderArguments.jvm, + minecraftArguments.mainClass, + ...minecraftArguments.game, + ...loaderArguments.game + ]; + let java = this.options.javaPath ? this.options.javaPath : minecraftJava.path; + let logs = this.options.instance ? `${this.options.path}/instances/${this.options.instance}` : this.options.path; + if (!fs_1.default.existsSync(logs)) + fs_1.default.mkdirSync(logs, { recursive: true }); + let argumentsLogs = Arguments.join(' '); + argumentsLogs = argumentsLogs.replaceAll(this.options.authenticator.access_token, '????????'); + argumentsLogs = argumentsLogs.replaceAll(this.options.authenticator.client_token, '????????'); + argumentsLogs = argumentsLogs.replaceAll(this.options.authenticator.uuid, '????????'); + argumentsLogs = argumentsLogs.replaceAll(this.options.authenticator.xuid, '????????'); + argumentsLogs = argumentsLogs.replaceAll(`${this.options.path}/`, ''); + this.emit('data', `Launching with arguments ${argumentsLogs}`); + let minecraftDebug = (0, child_process_1.spawn)(java, Arguments, { cwd: logs, detached: this.options.detached }); + minecraftDebug.stdout.on('data', (data) => this.emit('data', data.toString('utf-8'))); + minecraftDebug.stderr.on('data', (data) => this.emit('data', data.toString('utf-8'))); + minecraftDebug.on('close', (code) => this.emit('close', 'Minecraft closed')); + } + async DownloadGame() { + let InfoVersion = await new Minecraft_Json_js_1.default(this.options).GetInfoVersion(); + let loaderJson = null; + if (InfoVersion.error) + return InfoVersion; + let { json, version } = InfoVersion; + let libraries = new Minecraft_Libraries_js_1.default(this.options); + let bundle = new Minecraft_Bundle_js_1.default(this.options); + let gameLibraries = await libraries.Getlibraries(json); + let gameAssetsOther = await libraries.GetAssetsOthers(this.options.url); + let gameAssets = await new Minecraft_Assets_js_1.default(this.options).GetAssets(json); + let gameJava = this.options.javaPath ? { files: [] } : await new Minecraft_Java_js_1.default(this.options).GetJsonJava(json); + if (gameJava.error) + return gameJava; + let filesList = await bundle.checkBundle([...gameLibraries, ...gameAssetsOther, ...gameAssets, ...gameJava.files]); + if (filesList.length > 0) { + let downloader = new Downloader_js_1.default(); + let totsize = await bundle.getTotalSize(filesList); + downloader.on("progress", (DL, totDL, element) => { + this.emit("progress", DL, totDL, element); + }); + downloader.on("speed", (speed) => { + this.emit("speed", speed); + }); + downloader.on("estimated", (time) => { + this.emit("estimated", time); + }); + downloader.on("error", (e) => { + this.emit("error", e); + }); + await downloader.downloadFileMultiple(filesList, totsize, this.options.downloadFileMultiple, this.options.timeout); + } + if (this.options.loader.enable === true) { + let loaderInstall = new Minecraft_Loader_js_1.default(this.options); + loaderInstall.on('extract', (extract) => { + this.emit('extract', extract); + }); + loaderInstall.on('progress', (progress, size, element) => { + this.emit('progress', progress, size, element); + }); + loaderInstall.on('check', (progress, size, element) => { + this.emit('check', progress, size, element); + }); + loaderInstall.on('patch', (patch) => { + this.emit('patch', patch); + }); + let jsonLoader = await loaderInstall.GetLoader(version, this.options.javaPath ? this.options.javaPath : gameJava.path) + .then((data) => data) + .catch((err) => err); + if (jsonLoader.error) + return jsonLoader; + loaderJson = jsonLoader; + } + if (this.options.verify) + await bundle.checkFiles([...gameLibraries, ...gameAssetsOther, ...gameAssets, ...gameJava.files]); + let natives = await libraries.natives(gameLibraries); + if (natives.length === 0) + json.nativesList = false; + else + json.nativesList = true; + if ((0, Index_js_1.isold)(json)) + new Minecraft_Assets_js_1.default(this.options).copyAssets(json); + return { + minecraftJson: json, + minecraftLoader: loaderJson, + minecraftVersion: version, + minecraftJava: gameJava + }; + } +} +exports.default = Launch; diff --git a/src/assets/js/libs/mc/Minecraft-Loader/index.d.ts b/src/assets/js/libs/mc/Minecraft-Loader/index.d.ts new file mode 100644 index 0000000..68b459c --- /dev/null +++ b/src/assets/js/libs/mc/Minecraft-Loader/index.d.ts @@ -0,0 +1,16 @@ +/** + * @author TECNO BROS + + */ +export default class Loader { + options: any; + on: any; + emit: any; + constructor(options: any); + install(): Promise; + forge(Loader: any): Promise; + neoForge(Loader: any): Promise; + fabric(Loader: any): Promise; + legacyFabric(Loader: any): Promise; + quilt(Loader: any): Promise; +} diff --git a/src/assets/js/libs/mc/Minecraft-Loader/index.js b/src/assets/js/libs/mc/Minecraft-Loader/index.js new file mode 100644 index 0000000..cf98593 --- /dev/null +++ b/src/assets/js/libs/mc/Minecraft-Loader/index.js @@ -0,0 +1,221 @@ +"use strict"; +/** + * @author TECNO BROS + + */ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const Index_js_1 = require("../utils/Index.js"); +const forge_js_1 = __importDefault(require("./loader/forge/forge.js")); +const neoForge_js_1 = __importDefault(require("./loader/neoForge/neoForge.js")); +const fabric_js_1 = __importDefault(require("./loader/fabric/fabric.js")); +const legacyFabric_js_1 = __importDefault(require("./loader/legacyfabric/legacyFabric.js")); +const quilt_js_1 = __importDefault(require("./loader/quilt/quilt.js")); +const events_1 = require("events"); +const fs_1 = __importDefault(require("fs")); +const path_1 = __importDefault(require("path")); +class Loader { + constructor(options) { + this.options = options; + this.on = events_1.EventEmitter.prototype.on; + this.emit = events_1.EventEmitter.prototype.emit; + } + async install() { + let Loader = (0, Index_js_1.loader)(this.options.loader.type); + if (!Loader) + return this.emit('error', { error: `Loader ${this.options.loader.type} not found` }); + if (this.options.loader.type === 'forge') { + let forge = await this.forge(Loader); + if (forge.error) + return this.emit('error', forge); + this.emit('json', forge); + } + else if (this.options.loader.type === 'neoforge') { + let neoForge = await this.neoForge(Loader); + if (neoForge.error) + return this.emit('error', neoForge); + this.emit('json', neoForge); + } + else if (this.options.loader.type === 'fabric') { + let fabric = await this.fabric(Loader); + if (fabric.error) + return this.emit('error', fabric); + this.emit('json', fabric); + } + else if (this.options.loader.type === 'legacyfabric') { + let legacyFabric = await this.legacyFabric(Loader); + if (legacyFabric.error) + return this.emit('error', legacyFabric); + this.emit('json', legacyFabric); + } + else if (this.options.loader.type === 'quilt') { + let quilt = await this.quilt(Loader); + if (quilt.error) + return this.emit('error', quilt); + this.emit('json', quilt); + } + else { + return this.emit('error', { error: `Loader ${this.options.loader.type} not found` }); + } + } + async forge(Loader) { + let forge = new forge_js_1.default(this.options); + // set event + forge.on('check', (progress, size, element) => { + this.emit('check', progress, size, element); + }); + forge.on('progress', (progress, size, element) => { + this.emit('progress', progress, size, element); + }); + forge.on('extract', (element) => { + this.emit('extract', element); + }); + forge.on('patch', patch => { + this.emit('patch', patch); + }); + // download installer + let installer = await forge.downloadInstaller(Loader); + if (installer.error) + return installer; + if (installer.ext == 'jar') { + // extract install profile + let profile = await forge.extractProfile(installer.filePath); + if (profile.error) + return profile; + let destination = path_1.default.resolve(this.options.path, 'versions', profile.version.id); + if (!fs_1.default.existsSync(destination)) + fs_1.default.mkdirSync(destination, { recursive: true }); + fs_1.default.writeFileSync(path_1.default.resolve(destination, `${profile.version.id}.json`), JSON.stringify(profile.version, null, 4)); + // extract universal jar + let universal = await forge.extractUniversalJar(profile.install, installer.filePath); + if (universal.error) + return universal; + // download libraries + let libraries = await forge.downloadLibraries(profile, universal); + if (libraries.error) + return libraries; + // patch forge if nessary + let patch = await forge.patchForge(profile.install); + if (patch.error) + return patch; + return profile.version; + } + else { + let profile = await forge.createProfile(installer.id, installer.filePath); + if (profile.error) + return profile; + let destination = path_1.default.resolve(this.options.path, 'versions', profile.id); + if (!fs_1.default.existsSync(destination)) + fs_1.default.mkdirSync(destination, { recursive: true }); + fs_1.default.writeFileSync(path_1.default.resolve(destination, `${profile.id}.json`), JSON.stringify(profile, null, 4)); + return profile; + } + } + async neoForge(Loader) { + let neoForge = new neoForge_js_1.default(this.options); + // set event + neoForge.on('check', (progress, size, element) => { + this.emit('check', progress, size, element); + }); + neoForge.on('progress', (progress, size, element) => { + this.emit('progress', progress, size, element); + }); + neoForge.on('extract', (element) => { + this.emit('extract', element); + }); + neoForge.on('patch', patch => { + this.emit('patch', patch); + }); + // download installer + let installer = await neoForge.downloadInstaller(Loader); + if (installer.error) + return installer; + // extract install profile + let profile = await neoForge.extractProfile(installer.filePath); + if (profile.error) + return profile; + let destination = path_1.default.resolve(this.options.path, 'versions', profile.version.id); + if (!fs_1.default.existsSync(destination)) + fs_1.default.mkdirSync(destination, { recursive: true }); + fs_1.default.writeFileSync(path_1.default.resolve(destination, `${profile.version.id}.json`), JSON.stringify(profile.version, null, 4)); + //extract universal jar + let universal = await neoForge.extractUniversalJar(profile.install, installer.filePath, installer.oldAPI); + if (universal.error) + return universal; + // download libraries + let libraries = await neoForge.downloadLibraries(profile, universal); + if (libraries.error) + return libraries; + // patch forge if nessary + let patch = await neoForge.patchneoForge(profile.install, installer.oldAPI); + if (patch.error) + return patch; + return profile.version; + } + async fabric(Loader) { + let fabric = new fabric_js_1.default(this.options); + // set event + fabric.on('check', (progress, size, element) => { + this.emit('check', progress, size, element); + }); + fabric.on('progress', (progress, size, element) => { + this.emit('progress', progress, size, element); + }); + // download Json + let json = await fabric.downloadJson(Loader); + if (json.error) + return json; + let destination = path_1.default.resolve(this.options.path, 'versions', json.id); + if (!fs_1.default.existsSync(destination)) + fs_1.default.mkdirSync(destination, { recursive: true }); + fs_1.default.writeFileSync(path_1.default.resolve(destination, `${json.id}.json`), JSON.stringify(json, null, 4)); + // download libraries + await fabric.downloadLibraries(json); + return json; + } + async legacyFabric(Loader) { + let legacyFabric = new legacyFabric_js_1.default(this.options); + // set event + legacyFabric.on('check', (progress, size, element) => { + this.emit('check', progress, size, element); + }); + legacyFabric.on('progress', (progress, size, element) => { + this.emit('progress', progress, size, element); + }); + // download Json + let json = await legacyFabric.downloadJson(Loader); + if (json.error) + return json; + let destination = path_1.default.resolve(this.options.path, 'versions', json.id); + if (!fs_1.default.existsSync(destination)) + fs_1.default.mkdirSync(destination, { recursive: true }); + fs_1.default.writeFileSync(path_1.default.resolve(destination, `${json.id}.json`), JSON.stringify(json, null, 4)); + // download libraries + await legacyFabric.downloadLibraries(json); + return json; + } + async quilt(Loader) { + let quilt = new quilt_js_1.default(this.options); + // set event + quilt.on('check', (progress, size, element) => { + this.emit('check', progress, size, element); + }); + quilt.on('progress', (progress, size, element) => { + this.emit('progress', progress, size, element); + }); + // download Json + let json = await quilt.downloadJson(Loader); + if (json.error) + return json; + let destination = path_1.default.resolve(this.options.path, 'versions', json.id); + if (!fs_1.default.existsSync(destination)) + fs_1.default.mkdirSync(destination, { recursive: true }); + fs_1.default.writeFileSync(path_1.default.resolve(destination, `${json.id}.json`), JSON.stringify(json, null, 4)); + // // download libraries + await quilt.downloadLibraries(json); + return json; + } +} +exports.default = Loader; diff --git a/src/assets/js/libs/mc/Minecraft-Loader/loader/fabric/fabric.d.ts b/src/assets/js/libs/mc/Minecraft-Loader/loader/fabric/fabric.d.ts new file mode 100644 index 0000000..c6175cf --- /dev/null +++ b/src/assets/js/libs/mc/Minecraft-Loader/loader/fabric/fabric.d.ts @@ -0,0 +1,12 @@ +/** + * @author TECNO BROS + + */ +export default class FabricMC { + options: any; + on: any; + emit: any; + constructor(options?: {}); + downloadJson(Loader: any): Promise; + downloadLibraries(json: any): Promise; +} diff --git a/src/assets/js/libs/mc/Minecraft-Loader/loader/fabric/fabric.js b/src/assets/js/libs/mc/Minecraft-Loader/loader/fabric/fabric.js new file mode 100644 index 0000000..8d25963 --- /dev/null +++ b/src/assets/js/libs/mc/Minecraft-Loader/loader/fabric/fabric.js @@ -0,0 +1,84 @@ +"use strict"; +/** + * @author TECNO BROS + + */ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const Index_js_1 = require("../../../utils/Index.js"); +const Downloader_js_1 = __importDefault(require("../../../utils/Downloader.js")); +const node_fetch_1 = __importDefault(require("node-fetch")); +const fs_1 = __importDefault(require("fs")); +const path_1 = __importDefault(require("path")); +const events_1 = require("events"); +class FabricMC { + constructor(options = {}) { + this.options = options; + this.on = events_1.EventEmitter.prototype.on; + this.emit = events_1.EventEmitter.prototype.emit; + } + async downloadJson(Loader) { + let build; + let metaData = await (0, node_fetch_1.default)(Loader.metaData).then(res => res.json()); + let version = metaData.game.find(version => version.version === this.options.loader.version); + let AvailableBuilds = metaData.loader.map(build => build.version); + if (!version) + return { error: `FabricMC doesn't support Minecraft ${this.options.loader.version}` }; + if (this.options.loader.build === 'latest' || this.options.loader.build === 'recommended') { + build = metaData.loader[0]; + } + else { + build = metaData.loader.find(loader => loader.version === this.options.loader.build); + } + if (!build) + return { error: `Fabric Loader ${this.options.loader.build} not found, Available builds: ${AvailableBuilds.join(', ')}` }; + let url = Loader.json.replace('${build}', build.version).replace('${version}', this.options.loader.version); + let json = await (0, node_fetch_1.default)(url).then(res => res.json()).catch(err => err); + return json; + } + async downloadLibraries(json) { + let { libraries } = json; + let downloader = new Downloader_js_1.default(); + let files = []; + let check = 0; + let size = 0; + for (let lib of libraries) { + if (lib.rules) { + this.emit('check', check++, libraries.length, 'libraries'); + continue; + } + let file = {}; + let libInfo = (0, Index_js_1.getPathLibraries)(lib.name); + let pathLib = path_1.default.resolve(this.options.path, 'libraries', libInfo.path); + let pathLibFile = path_1.default.resolve(pathLib, libInfo.name); + if (!fs_1.default.existsSync(pathLibFile)) { + let url = `${lib.url}${libInfo.path}/${libInfo.name}`; + let sizeFile = 0; + let res = await downloader.checkURL(url); + if (res.status === 200) { + sizeFile = res.size; + size += res.size; + } + file = { + url: url, + folder: pathLib, + path: `${pathLib}/${libInfo.name}`, + name: libInfo.name, + size: sizeFile + }; + files.push(file); + } + this.emit('check', check++, libraries.length, 'libraries'); + } + if (files.length > 0) { + downloader.on("progress", (DL, totDL) => { + this.emit("progress", DL, totDL, 'libraries'); + }); + await downloader.downloadFileMultiple(files, size, this.options.downloadFileMultiple); + } + return libraries; + } +} +exports.default = FabricMC; diff --git a/src/assets/js/libs/mc/Minecraft-Loader/loader/forge/forge.d.ts b/src/assets/js/libs/mc/Minecraft-Loader/loader/forge/forge.d.ts new file mode 100644 index 0000000..fd924d6 --- /dev/null +++ b/src/assets/js/libs/mc/Minecraft-Loader/loader/forge/forge.d.ts @@ -0,0 +1,28 @@ +/** + * @author TECNO BROS + + */ +export default class ForgeMC { + options: any; + on: any; + emit: any; + constructor(options?: {}); + downloadInstaller(Loader: any): Promise<{ + error: string; + filePath?: undefined; + metaData?: undefined; + ext?: undefined; + id?: undefined; + } | { + filePath: string; + metaData: any; + ext: String; + id: string; + error?: undefined; + }>; + extractProfile(pathInstaller: any): Promise; + extractUniversalJar(profile: any, pathInstaller: any): Promise; + downloadLibraries(profile: any, skipForgeFilter: any): Promise; + patchForge(profile: any): Promise; + createProfile(id: any, pathInstaller: any): Promise; +} diff --git a/src/assets/js/libs/mc/Minecraft-Loader/loader/forge/forge.js b/src/assets/js/libs/mc/Minecraft-Loader/loader/forge/forge.js new file mode 100644 index 0000000..40f5ad3 --- /dev/null +++ b/src/assets/js/libs/mc/Minecraft-Loader/loader/forge/forge.js @@ -0,0 +1,297 @@ +"use strict"; +/** + * @author TECNO BROS + + */ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const Index_js_1 = require("../../../utils/Index.js"); +const Downloader_js_1 = __importDefault(require("../../../utils/Downloader.js")); +const patcher_js_1 = __importDefault(require("../../patcher.js")); +const node_fetch_1 = __importDefault(require("node-fetch")); +const fs_1 = __importDefault(require("fs")); +const path_1 = __importDefault(require("path")); +const events_1 = require("events"); +const Index_js_2 = require("../../../utils/Index.js"); +let Lib = { win32: "windows", darwin: "osx", linux: "linux" }; +class ForgeMC { + constructor(options = {}) { + this.options = options; + this.on = events_1.EventEmitter.prototype.on; + this.emit = events_1.EventEmitter.prototype.emit; + } + async downloadInstaller(Loader) { + let metaData; + try { + metaData = (await (0, node_fetch_1.default)(Loader.metaData).then(res => res.json()))[this.options.loader.version]; + //comprobar si existe la carpeta de la versión en this.options.path, '..', '..', 'battly', 'launcher', 'forge', 'version' + //si no existe, crearla + if(!fs_1.default.existsSync(path_1.default.resolve(this.options.path, '..', '..', 'battly', 'launcher', 'forge', this.options.loader.version))) { + fs_1.default.mkdirSync(path_1.default.resolve(this.options.path, '..', '..', 'battly', 'launcher', 'forge', this.options.loader.version), { recursive: true }); + } + + fs_1.default.writeFileSync(path_1.default.resolve(this.options.path, '..', '..', 'battly', 'launcher', 'forge', this.options.loader.version, 'metaData.json'), JSON.stringify(metaData)); + + } catch (error) { + metaData = JSON.parse(fs_1.default.readFileSync(path_1.default.resolve(this.options.path, '..', '..', 'battly', 'launcher', 'forge', this.options.loader.version, 'metaData.json'))); + } + let AvailableBuilds = metaData; + let forgeURL; + let ext; + let hashFileOrigin; + if (!metaData) + return { error: `Forge ${this.options.loader.version} not supported` }; + let build; + if (this.options.loader.build === 'latest') { + let promotions; + try { + promotions = await (0, node_fetch_1.default)(Loader.promotions).then(res => res.json()); + if(!fs_1.default.existsSync(path_1.default.resolve(this.options.path, '..', '..', 'battly', 'launcher', 'forge', this.options.loader.version))) { + fs_1.default.mkdirSync(path_1.default.resolve(this.options.path, '..', '..', 'battly', 'launcher', 'forge', this.options.loader.version), { recursive: true }); + } + fs_1.default.writeFileSync(path_1.default.resolve(this.options.path, '..', '..', 'battly', 'launcher', 'forge', this.options.loader.version, 'promotions.json'), JSON.stringify(promotions)); + } catch (error) { + promotions = JSON.parse(fs_1.default.readFileSync(path_1.default.resolve(this.options.path, '..', '..', 'battly', 'launcher', 'forge', this.options.loader.version, 'promotions.json'))); + } + promotions = promotions.promos[`${this.options.loader.version}-latest`]; + build = metaData.find(build => build.includes(promotions)); + } + else if (this.options.loader.build === 'recommended') { + let promotion; + try { + promotion = await (0, node_fetch_1.default)(Loader.promotions).then(res => res.json()); + if(!fs_1.default.existsSync(path_1.default.resolve(this.options.path, '..', '..', 'battly', 'launcher', 'forge', this.options.loader.version))) { + fs_1.default.mkdirSync(path_1.default.resolve(this.options.path, '..', '..', 'battly', 'launcher', 'forge', this.options.loader.version), { recursive: true }); + } + fs_1.default.writeFileSync(path_1.default.resolve(this.options.path, '..', '..', 'battly', 'launcher', 'forge', this.options.loader.version, 'promotions.json'), JSON.stringify(promotion)); + } catch (error) { + promotion = JSON.parse(fs_1.default.readFileSync(path_1.default.resolve(this.options.path, '..', '..', 'battly', 'launcher', 'forge', this.options.loader.version, 'promotions.json'))); + } + let promotions = promotion.promos[`${this.options.loader.version}-recommended`]; + if (!promotions) + promotions = promotion.promos[`${this.options.loader.version}-latest`]; + build = metaData.find(build => build.includes(promotions)); + } + else { + build = this.options.loader.build; + } + metaData = metaData.filter(b => b === build)[0]; + if (!metaData) + return { error: `Build ${build} not found, Available builds: ${AvailableBuilds.join(', ')}` }; + let meta; + try { + meta = await (0, node_fetch_1.default)(Loader.meta.replace(/\${build}/g, metaData)).then(res => res.json()); + if(!fs_1.default.existsSync(path_1.default.resolve(this.options.path, '..', '..', 'battly', 'launcher', 'forge', this.options.loader.version))) { + fs_1.default.mkdirSync(path_1.default.resolve(this.options.path, '..', '..', 'battly', 'launcher', 'forge', this.options.loader.version), { recursive: true }); + } + fs_1.default.writeFileSync(path_1.default.resolve(this.options.path, '..', '..', 'battly', 'launcher', 'forge', this.options.loader.version, 'meta.json'), JSON.stringify(meta)); + } catch (error) { + meta = JSON.parse(fs_1.default.readFileSync(path_1.default.resolve(this.options.path, '..', '..', 'battly', 'launcher', 'forge', this.options.loader.version, 'meta.json'))); + } + let installerType = Object.keys(meta.classifiers).find((key) => key == 'installer'); + let clientType = Object.keys(meta.classifiers).find((key) => key == 'client'); + let universalType = Object.keys(meta.classifiers).find((key) => key == 'universal'); + if (installerType) { + forgeURL = forgeURL = Loader.install.replace(/\${version}/g, metaData); + ext = Object.keys(meta.classifiers.installer)[0]; + hashFileOrigin = meta.classifiers.installer[`${ext}`]; + } + else if (clientType) { + forgeURL = Loader.client.replace(/\${version}/g, metaData); + ext = Object.keys(meta.classifiers.client)[0]; + hashFileOrigin = meta.classifiers.client[`${ext}`]; + } + else if (universalType) { + forgeURL = Loader.universal.replace(/\${version}/g, metaData); + ext = Object.keys(meta.classifiers.universal)[0]; + hashFileOrigin = meta.classifiers.universal[`${ext}`]; + } + else { + return { error: 'Invalid forge installer' }; + } + let pathFolder = path_1.default.resolve(this.options.path, 'forge'); + let filePath = path_1.default.resolve(pathFolder, (`${forgeURL}.${ext}`).split('/').pop()); + if (!fs_1.default.existsSync(filePath)) { + if (!fs_1.default.existsSync(pathFolder)) + fs_1.default.mkdirSync(pathFolder, { recursive: true }); + let downloadForge = new Downloader_js_1.default(); + downloadForge.on('progress', (downloaded, size) => { + this.emit('progress', downloaded, size, (`${forgeURL}.${ext}`).split('/').pop()); + }); + await downloadForge.downloadFile(`${forgeURL}.${ext}`, pathFolder, (`${forgeURL}.${ext}`).split('/').pop()); + } + let hashFileDownload = await (0, Index_js_1.getFileHash)(filePath, 'md5'); + if (hashFileDownload !== hashFileOrigin) { + fs_1.default.rmSync(filePath); + return { error: 'Invalid hash' }; + } + return { filePath, metaData, ext, id: `forge-${build}` }; + } + async extractProfile(pathInstaller) { + let forgeJSON = {}; + let file = await (0, Index_js_1.getFileFromJar)(pathInstaller, 'install_profile.json'); + let forgeJsonOrigin = JSON.parse(file); + if (!forgeJsonOrigin) + return { error: { message: 'Invalid forge installer' } }; + if (forgeJsonOrigin.install) { + forgeJSON.install = forgeJsonOrigin.install; + forgeJSON.version = forgeJsonOrigin.versionInfo; + } + else { + forgeJSON.install = forgeJsonOrigin; + let file = await (0, Index_js_1.getFileFromJar)(pathInstaller, path_1.default.basename(forgeJSON.install.json)); + forgeJSON.version = JSON.parse(file); + } + return forgeJSON; + } + async extractUniversalJar(profile, pathInstaller) { + let skipForgeFilter = true; + if (profile.filePath) { + let fileInfo = (0, Index_js_1.getPathLibraries)(profile.path); + this.emit('extract', `Extracting ${fileInfo.name}...`); + let pathFileDest = path_1.default.resolve(this.options.path, 'libraries', fileInfo.path); + if (!fs_1.default.existsSync(pathFileDest)) + fs_1.default.mkdirSync(pathFileDest, { recursive: true }); + let file = await (0, Index_js_1.getFileFromJar)(pathInstaller, profile.filePath); + fs_1.default.writeFileSync(`${pathFileDest}/${fileInfo.name}`, file, { mode: 0o777 }); + } + else if (profile.path) { + let fileInfo = (0, Index_js_1.getPathLibraries)(profile.path); + let listFile = await (0, Index_js_1.getFileFromJar)(pathInstaller, null, `maven/${fileInfo.path}`); + await Promise.all(listFile.map(async (files) => { + let fileName = files.split('/'); + this.emit('extract', `Extracting ${fileName[fileName.length - 1]}...`); + let file = await (0, Index_js_1.getFileFromJar)(pathInstaller, files); + let pathFileDest = path_1.default.resolve(this.options.path, 'libraries', fileInfo.path); + if (!fs_1.default.existsSync(pathFileDest)) + fs_1.default.mkdirSync(pathFileDest, { recursive: true }); + fs_1.default.writeFileSync(`${pathFileDest}/${fileName[fileName.length - 1]}`, file, { mode: 0o777 }); + })); + } + else { + skipForgeFilter = false; + } + if (profile.processors?.length) { + let universalPath = profile.libraries.find(v => { + return (v.name || '').startsWith('net.minecraftforge:forge'); + }); + let client = await (0, Index_js_1.getFileFromJar)(pathInstaller, 'data/client.lzma'); + let fileInfo = (0, Index_js_1.getPathLibraries)(profile.path || universalPath.name, '-clientdata', '.lzma'); + let pathFile = path_1.default.resolve(this.options.path, 'libraries', fileInfo.path); + if (!fs_1.default.existsSync(pathFile)) + fs_1.default.mkdirSync(pathFile, { recursive: true }); + fs_1.default.writeFileSync(`${pathFile}/${fileInfo.name}`, client, { mode: 0o777 }); + this.emit('extract', `Extracting ${fileInfo.name}...`); + } + return skipForgeFilter; + } + async downloadLibraries(profile, skipForgeFilter) { + let { libraries } = profile.version; + let downloader = new Downloader_js_1.default(); + let check = 0; + let files = []; + let size = 0; + if (profile.install.libraries) + libraries = libraries.concat(profile.install.libraries); + libraries = libraries.filter((library, index, self) => index === self.findIndex(t => t.name === library.name)); + let skipForge = [ + 'net.minecraftforge:forge:', + 'net.minecraftforge:minecraftforge:' + ]; + for (let lib of libraries) { + let natives = null; + if (skipForgeFilter && skipForge.find(libs => lib.name.includes(libs))) { + this.emit('check', check++, libraries.length, 'libraries'); + continue; + } + if ((0, Index_js_2.skipLibrary)(lib)) { + this.emit('check', check++, libraries.length, 'libraries'); + continue; + } + if (lib.natives) { + natives = lib.natives[Lib[process.platform]]; + } + let file = {}; + let libInfo = (0, Index_js_1.getPathLibraries)(lib.name, natives ? `-${natives}` : ''); + let pathLib = path_1.default.resolve(this.options.path, 'libraries', libInfo.path); + let pathLibFile = path_1.default.resolve(pathLib, libInfo.name); + if (!fs_1.default.existsSync(pathLibFile)) { + let url; + let sizeFile = 0; + let baseURL = natives ? `${libInfo.path}/` : `${libInfo.path}/${libInfo.name}`; + let response = await downloader.checkMirror(baseURL, Index_js_1.mirrors); + if (response?.status === 200) { + size += response.size; + sizeFile = response.size; + url = response.url; + } + else if (lib.downloads?.artifact) { + url = lib.downloads.artifact.url; + size += lib.downloads.artifact.size; + sizeFile = lib.downloads.artifact.size; + } + else { + url = null; + } + if (url == null || !url) { + return { error: `Impossible to download ${libInfo.name}` }; + } + file = { + url: url, + folder: pathLib, + path: `${pathLib}/${libInfo.name}`, + name: libInfo.name, + size: sizeFile + }; + files.push(file); + } + this.emit('check', check++, libraries.length, 'libraries'); + } + if (files.length > 0) { + downloader.on("progress", (DL, totDL) => { + this.emit("progress", DL, totDL, 'libraries'); + }); + await downloader.downloadFileMultiple(files, size, this.options.downloadFileMultiple); + } + return libraries; + } + async patchForge(profile) { + if (profile?.processors?.length) { + let patcher = new patcher_js_1.default(this.options); + let config = {}; + patcher.on('patch', data => { + this.emit('patch', data); + }); + patcher.on('error', data => { + this.emit('error', data); + }); + if (!patcher.check(profile)) { + config = { + java: this.options.loader.config.javaPath, + minecraft: this.options.loader.config.minecraftJar, + minecraftJson: this.options.loader.config.minecraftJson + }; + await patcher.patcher(profile, config); + } + } + return true; + } + async createProfile(id, pathInstaller) { + let forgeFiles = await (0, Index_js_1.getFileFromJar)(pathInstaller); + let minecraftJar = await (0, Index_js_1.getFileFromJar)(this.options.loader.config.minecraftJar); + let data = await (0, Index_js_1.createZIP)([...minecraftJar, ...forgeFiles], 'META-INF'); + let destination = path_1.default.resolve(this.options.path, 'versions', id); + let profile = JSON.parse(fs_1.default.readFileSync(this.options.loader.config.minecraftJson, 'utf-8')); + profile.libraries = []; + profile.id = id; + profile.isOldForge = true; + profile.jarPath = path_1.default.resolve(destination, `${id}.jar`); + if (!fs_1.default.existsSync(destination)) + fs_1.default.mkdirSync(destination, { recursive: true }); + fs_1.default.writeFileSync(path_1.default.resolve(destination, `${id}.jar`), data, { mode: 0o777 }); + return profile; + } +} +exports.default = ForgeMC; diff --git a/src/assets/js/libs/mc/Minecraft-Loader/loader/legacyfabric/legacyFabric.d.ts b/src/assets/js/libs/mc/Minecraft-Loader/loader/legacyfabric/legacyFabric.d.ts new file mode 100644 index 0000000..c6175cf --- /dev/null +++ b/src/assets/js/libs/mc/Minecraft-Loader/loader/legacyfabric/legacyFabric.d.ts @@ -0,0 +1,12 @@ +/** + * @author TECNO BROS + + */ +export default class FabricMC { + options: any; + on: any; + emit: any; + constructor(options?: {}); + downloadJson(Loader: any): Promise; + downloadLibraries(json: any): Promise; +} diff --git a/src/assets/js/libs/mc/Minecraft-Loader/loader/legacyfabric/legacyFabric.js b/src/assets/js/libs/mc/Minecraft-Loader/loader/legacyfabric/legacyFabric.js new file mode 100644 index 0000000..8d25963 --- /dev/null +++ b/src/assets/js/libs/mc/Minecraft-Loader/loader/legacyfabric/legacyFabric.js @@ -0,0 +1,84 @@ +"use strict"; +/** + * @author TECNO BROS + + */ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const Index_js_1 = require("../../../utils/Index.js"); +const Downloader_js_1 = __importDefault(require("../../../utils/Downloader.js")); +const node_fetch_1 = __importDefault(require("node-fetch")); +const fs_1 = __importDefault(require("fs")); +const path_1 = __importDefault(require("path")); +const events_1 = require("events"); +class FabricMC { + constructor(options = {}) { + this.options = options; + this.on = events_1.EventEmitter.prototype.on; + this.emit = events_1.EventEmitter.prototype.emit; + } + async downloadJson(Loader) { + let build; + let metaData = await (0, node_fetch_1.default)(Loader.metaData).then(res => res.json()); + let version = metaData.game.find(version => version.version === this.options.loader.version); + let AvailableBuilds = metaData.loader.map(build => build.version); + if (!version) + return { error: `FabricMC doesn't support Minecraft ${this.options.loader.version}` }; + if (this.options.loader.build === 'latest' || this.options.loader.build === 'recommended') { + build = metaData.loader[0]; + } + else { + build = metaData.loader.find(loader => loader.version === this.options.loader.build); + } + if (!build) + return { error: `Fabric Loader ${this.options.loader.build} not found, Available builds: ${AvailableBuilds.join(', ')}` }; + let url = Loader.json.replace('${build}', build.version).replace('${version}', this.options.loader.version); + let json = await (0, node_fetch_1.default)(url).then(res => res.json()).catch(err => err); + return json; + } + async downloadLibraries(json) { + let { libraries } = json; + let downloader = new Downloader_js_1.default(); + let files = []; + let check = 0; + let size = 0; + for (let lib of libraries) { + if (lib.rules) { + this.emit('check', check++, libraries.length, 'libraries'); + continue; + } + let file = {}; + let libInfo = (0, Index_js_1.getPathLibraries)(lib.name); + let pathLib = path_1.default.resolve(this.options.path, 'libraries', libInfo.path); + let pathLibFile = path_1.default.resolve(pathLib, libInfo.name); + if (!fs_1.default.existsSync(pathLibFile)) { + let url = `${lib.url}${libInfo.path}/${libInfo.name}`; + let sizeFile = 0; + let res = await downloader.checkURL(url); + if (res.status === 200) { + sizeFile = res.size; + size += res.size; + } + file = { + url: url, + folder: pathLib, + path: `${pathLib}/${libInfo.name}`, + name: libInfo.name, + size: sizeFile + }; + files.push(file); + } + this.emit('check', check++, libraries.length, 'libraries'); + } + if (files.length > 0) { + downloader.on("progress", (DL, totDL) => { + this.emit("progress", DL, totDL, 'libraries'); + }); + await downloader.downloadFileMultiple(files, size, this.options.downloadFileMultiple); + } + return libraries; + } +} +exports.default = FabricMC; diff --git a/src/assets/js/libs/mc/Minecraft-Loader/loader/neoForge/neoForge.d.ts b/src/assets/js/libs/mc/Minecraft-Loader/loader/neoForge/neoForge.d.ts new file mode 100644 index 0000000..fb5460f --- /dev/null +++ b/src/assets/js/libs/mc/Minecraft-Loader/loader/neoForge/neoForge.d.ts @@ -0,0 +1,23 @@ +/** + * @author TECNO BROS + + */ +export default class NeoForgeMC { + options: any; + on: any; + emit: any; + constructor(options?: {}); + downloadInstaller(Loader: any): Promise<{ + error: string; + filePath?: undefined; + oldAPI?: undefined; + } | { + filePath: string; + oldAPI: boolean; + error?: undefined; + }>; + extractProfile(pathInstaller: any): Promise; + extractUniversalJar(profile: any, pathInstaller: any, oldAPI: any): Promise; + downloadLibraries(profile: any, skipneoForgeFilter: any): Promise; + patchneoForge(profile: any, oldAPI: any): Promise; +} diff --git a/src/assets/js/libs/mc/Minecraft-Loader/loader/neoForge/neoForge.js b/src/assets/js/libs/mc/Minecraft-Loader/loader/neoForge/neoForge.js new file mode 100644 index 0000000..28f4544 --- /dev/null +++ b/src/assets/js/libs/mc/Minecraft-Loader/loader/neoForge/neoForge.js @@ -0,0 +1,207 @@ +"use strict"; +/** + * @author TECNO BROS + + */ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const Index_js_1 = require("../../../utils/Index.js"); +const Downloader_js_1 = __importDefault(require("../../../utils/Downloader.js")); +const patcher_js_1 = __importDefault(require("../../patcher.js")); +const node_fetch_1 = __importDefault(require("node-fetch")); +const fs_1 = __importDefault(require("fs")); +const path_1 = __importDefault(require("path")); +const events_1 = require("events"); +class NeoForgeMC { + constructor(options = {}) { + this.options = options; + this.on = events_1.EventEmitter.prototype.on; + this.emit = events_1.EventEmitter.prototype.emit; + } + async downloadInstaller(Loader) { + let build; + let neoForgeURL; + let oldAPI = true; + let legacyMetaData = await (0, node_fetch_1.default)(Loader.legacyMetaData).then(res => res.json()); + let metaData = await (0, node_fetch_1.default)(Loader.metaData).then(res => res.json()); + let versions = legacyMetaData.versions.filter(version => version.includes(`${this.options.loader.version}-`)); + if (!versions.length) { + let minecraftVersion = `${this.options.loader.version.split('.')[1]}.${this.options.loader.version.split('.')[2]}`; + versions = metaData.versions.filter(version => version.startsWith(minecraftVersion)); + oldAPI = false; + } + if (!versions.length) + return { error: `NeoForge doesn't support Minecraft ${this.options.loader.version}` }; + if (this.options.loader.build === 'latest' || this.options.loader.build === 'recommended') { + build = versions[versions.length - 1]; + } + else + build = versions.find(loader => loader === this.options.loader.build); + if (!build) + return { error: `NeoForge Loader ${this.options.loader.build} not found, Available builds: ${versions.join(', ')}` }; + if (oldAPI) + neoForgeURL = Loader.legacyInstall.replaceAll(/\${version}/g, build); + else + neoForgeURL = Loader.install.replaceAll(/\${version}/g, build); + let pathFolder = path_1.default.resolve(this.options.path, 'neoForge'); + let filePath = path_1.default.resolve(pathFolder, `neoForge-${build}-installer.jar`); + if (!fs_1.default.existsSync(filePath)) { + if (!fs_1.default.existsSync(pathFolder)) + fs_1.default.mkdirSync(pathFolder, { recursive: true }); + let downloadForge = new Downloader_js_1.default(); + downloadForge.on('progress', (downloaded, size) => { + this.emit('progress', downloaded, size, `neoForge-${build}-installer.jar`); + }); + await downloadForge.downloadFile(neoForgeURL, pathFolder, `neoForge-${build}-installer.jar`); + } + return { filePath, oldAPI }; + } + async extractProfile(pathInstaller) { + let neoForgeJSON = {}; + let file = await (0, Index_js_1.getFileFromJar)(pathInstaller, 'install_profile.json'); + let neoForgeJsonOrigin = JSON.parse(file); + if (!neoForgeJsonOrigin) + return { error: { message: 'Invalid neoForge installer' } }; + if (neoForgeJsonOrigin.install) { + neoForgeJSON.install = neoForgeJsonOrigin.install; + neoForgeJSON.version = neoForgeJsonOrigin.versionInfo; + } + else { + neoForgeJSON.install = neoForgeJsonOrigin; + let file = await (0, Index_js_1.getFileFromJar)(pathInstaller, path_1.default.basename(neoForgeJSON.install.json)); + neoForgeJSON.version = JSON.parse(file); + } + return neoForgeJSON; + } + async extractUniversalJar(profile, pathInstaller, oldAPI) { + let skipneoForgeFilter = true; + if (profile.filePath) { + let fileInfo = (0, Index_js_1.getPathLibraries)(profile.path); + this.emit('extract', `Extracting ${fileInfo.name}...`); + let pathFileDest = path_1.default.resolve(this.options.path, 'libraries', fileInfo.path); + if (!fs_1.default.existsSync(pathFileDest)) + fs_1.default.mkdirSync(pathFileDest, { recursive: true }); + let file = await (0, Index_js_1.getFileFromJar)(pathInstaller, profile.filePath); + fs_1.default.writeFileSync(`${pathFileDest}/${fileInfo.name}`, file, { mode: 0o777 }); + } + else if (profile.path) { + let fileInfo = (0, Index_js_1.getPathLibraries)(profile.path); + let listFile = await (0, Index_js_1.getFileFromJar)(pathInstaller, null, `maven/${fileInfo.path}`); + await Promise.all(listFile.map(async (files) => { + let fileName = files.split('/'); + this.emit('extract', `Extracting ${fileName[fileName.length - 1]}...`); + let file = await (0, Index_js_1.getFileFromJar)(pathInstaller, files); + let pathFileDest = path_1.default.resolve(this.options.path, 'libraries', fileInfo.path); + if (!fs_1.default.existsSync(pathFileDest)) + fs_1.default.mkdirSync(pathFileDest, { recursive: true }); + fs_1.default.writeFileSync(`${pathFileDest}/${fileName[fileName.length - 1]}`, file, { mode: 0o777 }); + })); + } + else { + skipneoForgeFilter = false; + } + if (profile.processors?.length) { + let universalPath = profile.libraries.find(v => { + return (v.name || '').startsWith(oldAPI ? 'net.neoforged:forge' : 'net.neoforged:neoforge'); + }); + let client = await (0, Index_js_1.getFileFromJar)(pathInstaller, 'data/client.lzma'); + let fileInfo = (0, Index_js_1.getPathLibraries)(profile.path || universalPath.name, '-clientdata', '.lzma'); + let pathFile = path_1.default.resolve(this.options.path, 'libraries', fileInfo.path); + if (!fs_1.default.existsSync(pathFile)) + fs_1.default.mkdirSync(pathFile, { recursive: true }); + fs_1.default.writeFileSync(`${pathFile}/${fileInfo.name}`, client, { mode: 0o777 }); + this.emit('extract', `Extracting ${fileInfo.name}...`); + } + return skipneoForgeFilter; + } + async downloadLibraries(profile, skipneoForgeFilter) { + let { libraries } = profile.version; + let downloader = new Downloader_js_1.default(); + let check = 0; + let files = []; + let size = 0; + if (profile.install.libraries) + libraries = libraries.concat(profile.install.libraries); + libraries = libraries.filter((library, index, self) => index === self.findIndex(t => t.name === library.name)); + let skipneoForge = [ + 'net.minecraftforge:neoforged:', + 'net.minecraftforge:minecraftforge:' + ]; + for (let lib of libraries) { + if (skipneoForgeFilter && skipneoForge.find(libs => lib.name.includes(libs))) { + this.emit('check', check++, libraries.length, 'libraries'); + continue; + } + if (lib.rules) { + this.emit('check', check++, libraries.length, 'libraries'); + continue; + } + let file = {}; + let libInfo = (0, Index_js_1.getPathLibraries)(lib.name); + let pathLib = path_1.default.resolve(this.options.path, 'libraries', libInfo.path); + let pathLibFile = path_1.default.resolve(pathLib, libInfo.name); + if (!fs_1.default.existsSync(pathLibFile)) { + let url; + let sizeFile = 0; + let baseURL = `${libInfo.path}/${libInfo.name}`; + let response = await downloader.checkMirror(baseURL, Index_js_1.mirrors); + if (response?.status === 200) { + size += response.size; + sizeFile = response.size; + url = response.url; + } + else if (lib.downloads?.artifact) { + url = lib.downloads.artifact.url; + size += lib.downloads.artifact.size; + sizeFile = lib.downloads.artifact.size; + } + else { + url = null; + } + if (url == null || !url) { + return { error: `Impossible to download ${libInfo.name}` }; + } + file = { + url: url, + folder: pathLib, + path: `${pathLib}/${libInfo.name}`, + name: libInfo.name, + size: sizeFile + }; + files.push(file); + } + this.emit('check', check++, libraries.length, 'libraries'); + } + if (files.length > 0) { + downloader.on("progress", (DL, totDL) => { + this.emit("progress", DL, totDL, 'libraries'); + }); + await downloader.downloadFileMultiple(files, size, this.options.downloadFileMultiple); + } + return libraries; + } + async patchneoForge(profile, oldAPI) { + if (profile?.processors?.length) { + let patcher = new patcher_js_1.default(this.options); + let config = {}; + patcher.on('patch', data => { + this.emit('patch', data); + }); + patcher.on('error', data => { + this.emit('error', data); + }); + if (!patcher.check(profile)) { + config = { + java: this.options.loader.config.javaPath, + minecraft: this.options.loader.config.minecraftJar, + minecraftJson: this.options.loader.config.minecraftJson + }; + await patcher.patcher(profile, config, oldAPI); + } + } + return true; + } +} +exports.default = NeoForgeMC; diff --git a/src/assets/js/libs/mc/Minecraft-Loader/loader/quilt/quilt.d.ts b/src/assets/js/libs/mc/Minecraft-Loader/loader/quilt/quilt.d.ts new file mode 100644 index 0000000..6bfb9c2 --- /dev/null +++ b/src/assets/js/libs/mc/Minecraft-Loader/loader/quilt/quilt.d.ts @@ -0,0 +1,13 @@ +/** + * @author TECNO BROS + + */ +export default class Quilt { + options: any; + versionMinecraft: any; + on: any; + emit: any; + constructor(options?: {}); + downloadJson(Loader: any): Promise; + downloadLibraries(json: any): Promise; +} diff --git a/src/assets/js/libs/mc/Minecraft-Loader/loader/quilt/quilt.js b/src/assets/js/libs/mc/Minecraft-Loader/loader/quilt/quilt.js new file mode 100644 index 0000000..3026f22 --- /dev/null +++ b/src/assets/js/libs/mc/Minecraft-Loader/loader/quilt/quilt.js @@ -0,0 +1,87 @@ +"use strict"; +/** + * @author TECNO BROS + + */ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const Index_js_1 = require("../../../utils/Index.js"); +const Downloader_js_1 = __importDefault(require("../../../utils/Downloader.js")); +const node_fetch_1 = __importDefault(require("node-fetch")); +const fs_1 = __importDefault(require("fs")); +const path_1 = __importDefault(require("path")); +const events_1 = require("events"); +class Quilt { + constructor(options = {}) { + this.options = options; + this.on = events_1.EventEmitter.prototype.on; + this.emit = events_1.EventEmitter.prototype.emit; + } + async downloadJson(Loader) { + let build; + let metaData = await (0, node_fetch_1.default)(Loader.metaData).then(res => res.json()); + let version = metaData.game.find(version => version.version === this.options.loader.version); + let AvailableBuilds = metaData.loader.map(build => build.version); + if (!version) + return { error: `QuiltMC doesn't support Minecraft ${this.options.loader.version}` }; + if (this.options.loader.build === 'latest') { + build = metaData.loader[0]; + } + else if (this.options.loader.build === 'recommended') { + build = metaData.loader.find(build => !build.version.includes('beta')); + } + else { + build = metaData.loader.find(loader => loader.version === this.options.loader.build); + } + if (!build) + return { error: `QuiltMC Loader ${this.options.loader.build} not found, Available builds: ${AvailableBuilds.join(', ')}` }; + let url = Loader.json.replace('${build}', build.version).replace('${version}', this.options.loader.version); + let json = await (0, node_fetch_1.default)(url).then(res => res.json()).catch(err => err); + return json; + } + async downloadLibraries(json) { + let { libraries } = json; + let downloader = new Downloader_js_1.default(); + let files = []; + let check = 0; + let size = 0; + for (let lib of libraries) { + if (lib.rules) { + this.emit('check', check++, libraries.length, 'libraries'); + continue; + } + let file = {}; + let libInfo = (0, Index_js_1.getPathLibraries)(lib.name); + let pathLib = path_1.default.resolve(this.options.path, 'libraries', libInfo.path); + let pathLibFile = path_1.default.resolve(pathLib, libInfo.name); + if (!fs_1.default.existsSync(pathLibFile)) { + let url = `${lib.url}${libInfo.path}/${libInfo.name}`; + let sizeFile = 0; + let res = await downloader.checkURL(url); + if (res.status === 200) { + sizeFile = res.size; + size += res.size; + } + file = { + url: url, + folder: pathLib, + path: `${pathLib}/${libInfo.name}`, + name: libInfo.name, + size: sizeFile + }; + files.push(file); + } + this.emit('check', check++, libraries.length, 'libraries'); + } + if (files.length > 0) { + downloader.on("progress", (DL, totDL) => { + this.emit("progress", DL, totDL, 'libraries'); + }); + await downloader.downloadFileMultiple(files, size, this.options.downloadFileMultiple); + } + return libraries; + } +} +exports.default = Quilt; diff --git a/src/assets/js/libs/mc/Minecraft-Loader/patcher.d.ts b/src/assets/js/libs/mc/Minecraft-Loader/patcher.d.ts new file mode 100644 index 0000000..c63a8eb --- /dev/null +++ b/src/assets/js/libs/mc/Minecraft-Loader/patcher.d.ts @@ -0,0 +1,11 @@ +export default class forgePatcher { + options: any; + on: any; + emit: any; + constructor(options: any); + patcher(profile: any, config: any, neoForgeOld?: boolean): Promise; + check(profile: any): boolean; + setArgument(arg: any, profile: any, config: any, neoForgeOld: any): any; + computePath(arg: any): any; + readJarManifest(jarPath: string): Promise; +} diff --git a/src/assets/js/libs/mc/Minecraft-Loader/patcher.js b/src/assets/js/libs/mc/Minecraft-Loader/patcher.js new file mode 100644 index 0000000..eef6352 --- /dev/null +++ b/src/assets/js/libs/mc/Minecraft-Loader/patcher.js @@ -0,0 +1,123 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const child_process_1 = require("child_process"); +const fs_1 = __importDefault(require("fs")); +const path_1 = __importDefault(require("path")); +const events_1 = require("events"); +const Index_js_1 = require("../utils/Index.js"); +class forgePatcher { + constructor(options) { + this.options = options; + this.on = events_1.EventEmitter.prototype.on; + this.emit = events_1.EventEmitter.prototype.emit; + } + async patcher(profile, config, neoForgeOld = true) { + let { processors } = profile; + for (let key in processors) { + if (Object.prototype.hasOwnProperty.call(processors, key)) { + let processor = processors[key]; + if (processor?.sides && !(processor?.sides || []).includes('client')) { + continue; + } + let jar = (0, Index_js_1.getPathLibraries)(processor.jar); + let filePath = path_1.default.resolve(this.options.path, 'libraries', jar.path, jar.name); + let args = processor.args.map(arg => this.setArgument(arg, profile, config, neoForgeOld)).map(arg => this.computePath(arg)); + let classPaths = processor.classpath.map(cp => { + let classPath = (0, Index_js_1.getPathLibraries)(cp); + return `"${path_1.default.join(this.options.path, 'libraries', `${classPath.path}/${classPath.name}`)}"`; + }); + let mainClass = await this.readJarManifest(filePath); + await new Promise((resolve) => { + const ps = (0, child_process_1.spawn)(`"${path_1.default.resolve(config.java)}"`, [ + '-classpath', + [`"${filePath}"`, ...classPaths].join(path_1.default.delimiter), + mainClass, + ...args + ], { shell: true }); + ps.stdout.on('data', data => { + this.emit('patch', data.toString('utf-8')); + }); + ps.stderr.on('data', data => { + this.emit('patch', data.toString('utf-8')); + }); + ps.on('close', code => { + if (code !== 0) { + this.emit('error', `Forge patcher exited with code ${code}`); + resolve(); + } + resolve(); + }); + }); + } + } + } + check(profile) { + let files = []; + let { processors } = profile; + for (let key in processors) { + if (Object.prototype.hasOwnProperty.call(processors, key)) { + let processor = processors[key]; + if (processor?.sides && !(processor?.sides || []).includes('client')) + continue; + processor.args.map(arg => { + let finalArg = arg.replace('{', '').replace('}', ''); + if (profile.data[finalArg]) { + if (finalArg === 'BINPATCH') + return; + files.push(profile.data[finalArg].client); + } + }); + } + } + files = files.filter((item, index) => files.indexOf(item) === index); + for (let file of files) { + let libMCP = (0, Index_js_1.getPathLibraries)(file.replace('[', '').replace(']', '')); + file = `${path_1.default.resolve(this.options.path, 'libraries', `${libMCP.path}/${libMCP.name}`)}`; + if (!fs_1.default.existsSync(file)) + return false; + } + return true; + } + setArgument(arg, profile, config, neoForgeOld) { + let finalArg = arg.replace('{', '').replace('}', ''); + let universalPath = profile.libraries.find(v => { + if (this.options.loader.type === 'forge') + return (v.name || '').startsWith('net.minecraftforge:forge'); + if (this.options.loader.type === 'neoforge') + return (v.name || '').startsWith(neoForgeOld ? 'net.neoforged:forge' : 'net.neoforged:neoforge'); + }); + if (profile.data[finalArg]) { + if (finalArg === 'BINPATCH') { + let clientdata = (0, Index_js_1.getPathLibraries)(profile.path || universalPath.name); + return `"${path_1.default + .join(this.options.path, 'libraries', `${clientdata.path}/${clientdata.name}`) + .replace('.jar', '-clientdata.lzma')}"`; + } + return profile.data[finalArg].client; + } + return arg + .replace('{SIDE}', `client`) + .replace('{ROOT}', `"${path_1.default.dirname(path_1.default.resolve(this.options.path, 'forge'))}"`) + .replace('{MINECRAFT_JAR}', `"${config.minecraft}"`) + .replace('{MINECRAFT_VERSION}', `"${config.minecraftJson}"`) + .replace('{INSTALLER}', `"${this.options.path}/libraries"`) + .replace('{LIBRARY_DIR}', `"${this.options.path}/libraries"`); + } + computePath(arg) { + if (arg[0] === '[') { + let libMCP = (0, Index_js_1.getPathLibraries)(arg.replace('[', '').replace(']', '')); + return `"${path_1.default.join(this.options.path, 'libraries', `${libMCP.path}/${libMCP.name}`)}"`; + } + return arg; + } + async readJarManifest(jarPath) { + let extraction = await (0, Index_js_1.getFileFromJar)(jarPath, 'META-INF/MANIFEST.MF'); + if (extraction) + return (extraction.toString("utf8")).split('Main-Class: ')[1].split('\r\n')[0]; + return null; + } +} +exports.default = forgePatcher; diff --git a/src/assets/js/libs/mc/Minecraft/Minecraft-Arguments.d.ts b/src/assets/js/libs/mc/Minecraft/Minecraft-Arguments.d.ts new file mode 100644 index 0000000..e656120 --- /dev/null +++ b/src/assets/js/libs/mc/Minecraft/Minecraft-Arguments.d.ts @@ -0,0 +1,21 @@ +/** + * @author TECNO BROS + + */ +export default class MinecraftArguments { + options: any; + authenticator: any; + constructor(options: any); + GetArguments(json: any, loaderJson: any): Promise<{ + game: any; + jvm: string[]; + classpath: any[]; + mainClass: any; + }>; + GetGameArguments(json: any, loaderJson: any): Promise; + GetJVMArguments(json: any): Promise; + GetClassPath(json: any, loaderJson: any): Promise<{ + classpath: any[]; + mainClass: any; + }>; +} diff --git a/src/assets/js/libs/mc/Minecraft/Minecraft-Arguments.js b/src/assets/js/libs/mc/Minecraft/Minecraft-Arguments.js new file mode 100644 index 0000000..fb13642 --- /dev/null +++ b/src/assets/js/libs/mc/Minecraft/Minecraft-Arguments.js @@ -0,0 +1,153 @@ +"use strict"; +/** + * @author TECNO BROS + + */ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const fs_1 = __importDefault(require("fs")); +const os_1 = __importDefault(require("os")); +const Index_js_1 = require("../utils/Index.js"); +let MojangLib = { win32: "windows", darwin: "osx", linux: "linux" }; +class MinecraftArguments { + constructor(options) { + this.options = options; + this.authenticator = options.authenticator; + } + async GetArguments(json, loaderJson) { + let game = await this.GetGameArguments(json, loaderJson); + let jvm = await this.GetJVMArguments(json); + let classpath = await this.GetClassPath(json, loaderJson); + return { + game: game, + jvm: jvm, + classpath: classpath.classpath, + mainClass: classpath.mainClass + }; + } + async GetGameArguments(json, loaderJson) { + let game = json.minecraftArguments ? json.minecraftArguments.split(' ') : json.arguments.game; + let userType; + if (loaderJson) { + let gameLoader = loaderJson.minecraftArguments ? loaderJson.minecraftArguments.split(' ') : []; + game = game.concat(gameLoader); + game = game.filter((item, index, self) => index === self.findIndex((res) => res == item)); + } + if (json.id.startsWith('1.16')) + userType = 'Xbox'; + else + userType = this.authenticator.meta.type === 'Xbox' ? 'msa' : this.authenticator.meta.type; + let table = { + '${auth_access_token}': this.authenticator.access_token, + '${auth_session}': this.authenticator.access_token, + '${auth_player_name}': this.authenticator.name, + '${auth_uuid}': this.authenticator.uuid, + '${auth_xuid}': this.authenticator.meta.xuid || this.authenticator.access_token, + '${user_properties}': this.authenticator.user_properties, + '${user_type}': userType, + '${version_name}': json.id, + '${assets_index_name}': json.assetIndex.id, + '${game_directory}': this.options.instance ? `${this.options.path}/instances/${this.options.instance}` : this.options.path, + '${assets_root}': (0, Index_js_1.isold)(json) ? `${this.options.path}/resources` : `${this.options.path}/assets`, + '${game_assets}': (0, Index_js_1.isold)(json) ? `${this.options.path}/resources` : `${this.options.path}/assets`, + '${version_type}': json.type, + '${clientid}': this.authenticator.clientId || (this.authenticator.client_token || this.authenticator.access_token) + }; + for (let i in game) { + if (typeof game[i] == 'object') + game.splice(i, 2); + if (Object.keys(table).includes(game[i])) + game[i] = table[game[i]]; + } + if (this.options.screen) { + if (this.options.screen.width !== null && this.options.screen.height !== null) { + game.push('--width'); + game.push(this.options.screen.width); + game.push('--height'); + game.push(this.options.screen.height); + } + } + game.push(...this.options.GAME_ARGS); + return game.filter((item) => typeof item !== 'object'); + } + async GetJVMArguments(json) { + let opts = { + win32: '-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump', + darwin: '-XstartOnFirstThread', + linux: '-Xss1M' + }; + let jvm = [ + `-Xms${this.options.memory.min}`, + `-Xmx${this.options.memory.max}`, + '-XX:+UnlockExperimentalVMOptions', + '-XX:G1NewSizePercent=20', + '-XX:G1ReservePercent=20', + '-XX:MaxGCPauseMillis=50', + '-XX:G1HeapRegionSize=32M', + '-Dfml.ignoreInvalidMinecraftCertificates=true' + ]; + if (!json.minecraftArguments) { + jvm.push(opts[process.platform]); + } + if (json.nativesList) { + jvm.push(`-Djava.library.path=${this.options.path}/versions/${json.id}/natives`); + } + if (os_1.default.platform() == "darwin") { + let pathAssets = `${this.options.path}/assets/indexes/${json.assets}.json`; + let assets = JSON.parse(fs_1.default.readFileSync(pathAssets, 'utf-8')); + let icon = assets.objects['icons/minecraft.icns'].hash; + jvm.push(`-Xdock:name=Minecraft`); + jvm.push(`-Xdock:icon=${this.options.path}/assets/objects/${icon.substring(0, 2)}/${icon}`); + } + jvm.push(...this.options.JVM_ARGS); + return jvm; + } + async GetClassPath(json, loaderJson) { + let classPath = []; + let libraries = json.libraries; + if (loaderJson?.libraries) + libraries = loaderJson.libraries.concat(libraries); + libraries = libraries.filter((library, index, self) => index === self.findIndex((res) => res.name === library.name)); + for (let lib of libraries) { + if (lib.natives) { + let native = lib.natives[MojangLib[process.platform]]; + if (!native) + native = lib.natives[process.platform]; + if (!native) + continue; + } + else { + if (lib.rules && lib.rules[0].os) { + if (lib.rules[0].os.name !== MojangLib[process.platform]) + continue; + } + } + let path = (0, Index_js_1.getPathLibraries)(lib.name); + if (lib.loader) { + classPath.push(`${lib.loader}/libraries/${path.path}/${path.name}`); + } + else { + classPath.push(`${this.options.path}/libraries/${path.path}/${path.name}`); + } + } + if (loaderJson?.isOldForge) { + classPath.push(loaderJson?.jarPath); + } + else if (this.options.mcp) { + classPath.push(this.options.mcp); + } + else { + classPath.push(`${this.options.path}/versions/${json.id}/${json.id}.jar`); + } + return { + classpath: [ + `-cp`, + classPath.join(process.platform === 'win32' ? ';' : ':'), + ], + mainClass: loaderJson ? loaderJson.mainClass : json.mainClass + }; + } +} +exports.default = MinecraftArguments; diff --git a/src/assets/js/libs/mc/Minecraft/Minecraft-Assets.d.ts b/src/assets/js/libs/mc/Minecraft/Minecraft-Assets.d.ts new file mode 100644 index 0000000..03e666b --- /dev/null +++ b/src/assets/js/libs/mc/Minecraft/Minecraft-Assets.d.ts @@ -0,0 +1,11 @@ +/** + * @author TECNO BROS + + */ +export default class MinecraftAssets { + assetIndex: any; + options: any; + constructor(options: any); + GetAssets(json: any): Promise; + copyAssets(json: any): void; +} diff --git a/src/assets/js/libs/mc/Minecraft/Minecraft-Assets.js b/src/assets/js/libs/mc/Minecraft/Minecraft-Assets.js new file mode 100644 index 0000000..9ebabd0 --- /dev/null +++ b/src/assets/js/libs/mc/Minecraft/Minecraft-Assets.js @@ -0,0 +1,69 @@ +"use strict"; +/** + * @author TECNO BROS + + */ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const node_fetch_1 = __importDefault(require("node-fetch")); +const fs_1 = __importDefault(require("fs")); +class MinecraftAssets { + constructor(options) { + this.options = options; + } + async GetAssets(json) { + this.assetIndex = json.assetIndex; + let assets = []; + let data; + try { + data = await (0, node_fetch_1.default)(this.assetIndex.url).then(res => res.json()); + fs_1.default.mkdirSync(`${this.options.path}/assets/indexes`, { recursive: true }); + fs_1.default.mkdirSync(`${this.options.path}/assets/objects`, { recursive: true }); + fs_1.default.writeFileSync(`${this.options.path}/assets/indexes/${this.assetIndex.id}.json`, JSON.stringify(data)); + } catch (e) { + data = JSON.parse(fs_1.default.readFileSync(`${this.options.path}/assets/indexes/${this.assetIndex.id}.json`,)); + } + assets.push({ + type: "CFILE", + path: `assets/indexes/${this.assetIndex.id}.json`, + content: JSON.stringify(data) + }); + data = Object.values(data.objects); + for (let asset of data) { + assets.push({ + sha1: asset.hash, + size: asset.size, + type: "Assets", + path: `assets/objects/${asset.hash.substring(0, 2)}/${asset.hash}`, + url: `https://resources.download.minecraft.net/${asset.hash.substring(0, 2)}/${asset.hash}` + }); + } + return assets; + } + copyAssets(json) { + let legacyDirectory = `${this.options.path}/resources`; + if (this.options.instance) + legacyDirectory = `${this.options.path}/instances/${this.options.instance}/resources`; + let pathAssets = `${this.options.path}/assets/indexes/${json.assets}.json`; + if (!fs_1.default.existsSync(pathAssets)) + return; + let assets = JSON.parse(fs_1.default.readFileSync(pathAssets, 'utf-8')); + assets = Object.entries(assets.objects); + for (let [file, hash] of assets) { + let Hash = hash.hash; + let Subhash = Hash.substring(0, 2); + let SubAsset = `${this.options.path}/assets/objects/${Subhash}`; + let legacyAsset = file.split('/'); + legacyAsset.pop(); + if (!fs_1.default.existsSync(`${legacyDirectory}/${legacyAsset.join('/')}`)) { + fs_1.default.mkdirSync(`${legacyDirectory}/${legacyAsset.join('/')}`, { recursive: true }); + } + if (!fs_1.default.existsSync(`${legacyDirectory}/${file}`)) { + fs_1.default.copyFileSync(`${SubAsset}/${Hash}`, `${legacyDirectory}/${file}`); + } + } + } +} +exports.default = MinecraftAssets; diff --git a/src/assets/js/libs/mc/Minecraft/Minecraft-Bundle.d.ts b/src/assets/js/libs/mc/Minecraft/Minecraft-Bundle.d.ts new file mode 100644 index 0000000..6c15d3e --- /dev/null +++ b/src/assets/js/libs/mc/Minecraft/Minecraft-Bundle.d.ts @@ -0,0 +1,12 @@ +/** + * @author TECNO BROS + + */ +export default class MinecraftBundle { + options: any; + constructor(options: any); + checkBundle(bundle: any): Promise; + getTotalSize(bundle: any): Promise; + checkFiles(bundle: any): Promise; + getFiles(path: any, file?: any[]): any[]; +} diff --git a/src/assets/js/libs/mc/Minecraft/Minecraft-Bundle.js b/src/assets/js/libs/mc/Minecraft/Minecraft-Bundle.js new file mode 100644 index 0000000..3cfd162 --- /dev/null +++ b/src/assets/js/libs/mc/Minecraft/Minecraft-Bundle.js @@ -0,0 +1,115 @@ +"use strict"; +/** + * @author TECNO BROS + + */ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const fs_1 = __importDefault(require("fs")); +const path_1 = __importDefault(require("path")); +const Index_js_1 = require("../utils/Index.js"); +class MinecraftBundle { + constructor(options) { + this.options = options; + } + async checkBundle(bundle) { + let todownload = []; + for (let file of bundle) { + if (!file.path) + continue; + file.path = path_1.default.resolve(this.options.path, file.path).replace(/\\/g, "/"); + file.folder = file.path.split("/").slice(0, -1).join("/"); + if (file.type == "CFILE") { + if (!fs_1.default.existsSync(file.folder)) + fs_1.default.mkdirSync(file.folder, { recursive: true, mode: 0o777 }); + fs_1.default.writeFileSync(file.path, file.content, { encoding: "utf8", mode: 0o755 }); + continue; + } + if (fs_1.default.existsSync(file.path)) { + let replaceName = `${this.options.path}/`; + if (this.options.instance) + replaceName = `${this.options.path}/instances/${this.options.instance}/`; + if (this.options.ignored.find(ignored => ignored == file.path.replaceAll(replaceName, ""))) + continue; + if (file.sha1) { + if (await (0, Index_js_1.getFileHash)(file.path) != file.sha1) + todownload.push(file); + } + } + else + todownload.push(file); + } + return todownload; + } + async getTotalSize(bundle) { + let todownload = 0; + for (let file of bundle) { + todownload += file.size; + } + return todownload; + } + async checkFiles(bundle) { + let instancePath = ''; + if (this.options.instance) { + if (!fs_1.default.existsSync(`${this.options.path}/instances`)) + fs_1.default.mkdirSync(`${this.options.path}/instances`, { recursive: true }); + instancePath = `/instances/${this.options.instance}`; + } + let files = this.options.instance ? this.getFiles(`${this.options.path}/instances/${this.options.instance}`) : this.getFiles(this.options.path); + let ignoredfiles = [...this.getFiles(`${this.options.path}/loader`)]; + for (let file of this.options.ignored) { + file = (`${this.options.path}${instancePath}/${file}`); + if (fs_1.default.existsSync(file)) { + if (fs_1.default.statSync(file).isDirectory()) { + ignoredfiles.push(...this.getFiles(file)); + } + else if (fs_1.default.statSync(file).isFile()) { + ignoredfiles.push(file); + } + } + } + ignoredfiles.forEach(file => this.options.ignored.push((file))); + bundle.forEach(file => ignoredfiles.push((file.path))); + files = files.filter(file => ignoredfiles.indexOf(file) < 0); + for (let file of files) { + try { + if (fs_1.default.statSync(file).isDirectory()) { + fs_1.default.rmSync(file, { recursive: true }); + } + else { + fs_1.default.unlinkSync(file); + let folder = file.split("/").slice(0, -1).join("/"); + while (true) { + if (folder == this.options.path) + break; + let content = fs_1.default.readdirSync(folder); + if (content.length == 0) + fs_1.default.rmSync(folder); + folder = folder.split("/").slice(0, -1).join("/"); + } + } + } + catch (e) { + continue; + } + } + } + getFiles(path, file = []) { + if (fs_1.default.existsSync(path)) { + let files = fs_1.default.readdirSync(path); + if (files.length == 0) + file.push(path); + for (let i in files) { + let name = `${path}/${files[i]}`; + if (fs_1.default.statSync(name).isDirectory()) + this.getFiles(name, file); + else + file.push(name); + } + } + return file; + } +} +exports.default = MinecraftBundle; diff --git a/src/assets/js/libs/mc/Minecraft/Minecraft-Java.d.ts b/src/assets/js/libs/mc/Minecraft/Minecraft-Java.d.ts new file mode 100644 index 0000000..421e03a --- /dev/null +++ b/src/assets/js/libs/mc/Minecraft/Minecraft-Java.d.ts @@ -0,0 +1,19 @@ +/** + * @author TECNO BROS + + */ +export default class java { + options: any; + constructor(options: any); + GetJsonJava(jsonversion: any): Promise; +} diff --git a/src/assets/js/libs/mc/Minecraft/Minecraft-Java.js b/src/assets/js/libs/mc/Minecraft/Minecraft-Java.js new file mode 100644 index 0000000..553ff79 --- /dev/null +++ b/src/assets/js/libs/mc/Minecraft/Minecraft-Java.js @@ -0,0 +1,105 @@ +"use strict"; +/** + * @author TECNO BROS + + */ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const os_1 = __importDefault(require("os")); +const node_fetch_1 = __importDefault(require("node-fetch")); +const path_1 = __importDefault(require("path")); +const fs_1 = __importDefault(require("fs")); +class java { + constructor(options) { + this.options = options; + } + async GetJsonJava(jsonversion) { + let version; + let files = []; + let archOS; + let javaVersionsJson; + try { + javaVersionsJson = await (0, node_fetch_1.default)("https://launchermeta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json").then(res => res.json()); + await fs_1.default.mkdirSync(path_1.default.resolve(this.options.path, "runtime"), { recursive: true }); + await fs_1.default.writeFileSync(path_1.default.resolve(this.options.path, "runtime/java-versions.json"), JSON.stringify(javaVersionsJson)); + } catch (e) { + javaVersionsJson = JSON.parse(await fs_1.default.readFileSync(path_1.default.resolve(this.options.path, "runtime/java-versions.json"))); + } + if (!jsonversion.javaVersion) + jsonversion = "jre-legacy"; + else + jsonversion = jsonversion.javaVersion.component; + if (os_1.default.platform() == "win32") { + let arch = { x64: "windows-x64", ia32: "windows-x86", arm64: "windows-arm64" }; + version = `jre-${javaVersionsJson[`${arch[os_1.default.arch()]}`][jsonversion][0]?.version?.name}`; + if (version.includes('undefined')) + return { error: true, message: "Java not found" }; + try { + javaVersionsJson = Object.entries((await (0, node_fetch_1.default)(javaVersionsJson[`${arch[os_1.default.arch()]}`][jsonversion][0]?.manifest?.url).then(res => res.json())).files); + fs_1.default.mkdirSync(path_1.default.resolve(this.options.path, `runtime/${version}-${arch[os_1.default.arch()]}`), { recursive: true }); + fs_1.default.writeFileSync(path_1.default.resolve(this.options.path, `runtime/${version}-${arch[os_1.default.arch()]}/java-versions.json`), JSON.stringify(javaVersionsJson)); + } catch (e) { + javaVersionsJson = JSON.parse(await fs_1.default.readFileSync(path_1.default.resolve(this.options.path, `runtime/${version}-${arch[os_1.default.arch()]}/java-versions.json`))); + } + + archOS = arch[os_1.default.arch()]; + } + else if (os_1.default.platform() == "darwin") { + let arch = { x64: "mac-os", arm64: this.options.intelEnabledMac ? "mac-os" : "mac-os-arm64" }; + version = `jre-${javaVersionsJson[`${arch[os_1.default.arch()]}`][jsonversion][0]?.version?.name}`; + if (version.includes('undefined')) + return { error: true, message: "Java not found" }; + try { + javaVersionsJson = Object.entries((await (0, node_fetch_1.default)(javaVersionsJson[`${arch[os_1.default.arch()]}`][jsonversion][0]?.manifest?.url).then(res => res.json())).files); + fs_1.default.mkdirSync(path_1.default.resolve(this.options.path, `runtime/${version}-${arch[os_1.default.arch()]}`), { recursive: true }); + fs_1.default.writeFileSync(path_1.default.resolve(this.options.path, `runtime/${version}-${arch[os_1.default.arch()]}/java-versions.json`), JSON.stringify(javaVersionsJson)); + } catch (e) { + javaVersionsJson = JSON.parse(await fs_1.default.readFileSync(path_1.default.resolve(this.options.path, `runtime/${version}-${arch[os_1.default.arch()]}/java-versions.json`))); + } + + archOS = arch[os_1.default.arch()]; + } + else if (os_1.default.platform() == "linux") { + let arch = { x64: "linux", ia32: "linux-i386" }; + version = `jre-${javaVersionsJson[`${arch[os_1.default.arch()]}`][jsonversion][0]?.version?.name}`; + if (version.includes('undefined')) + return { error: true, message: "Java not found" }; + try { + javaVersionsJson = Object.entries((await (0, node_fetch_1.default)(javaVersionsJson[`${arch[os_1.default.arch()]}`][jsonversion][0]?.manifest?.url).then(res => res.json())).files); + fs_1.default.mkdirSync(path_1.default.resolve(this.options.path, `runtime/${version}-${arch[os_1.default.arch()]}`), { recursive: true }); + fs_1.default.writeFileSync(path_1.default.resolve(this.options.path, `runtime/${version}-${arch[os_1.default.arch()]}/java-versions.json`), JSON.stringify(javaVersionsJson)); + } catch (e) { + javaVersionsJson = JSON.parse(await fs_1.default.readFileSync(path_1.default.resolve(this.options.path, `runtime/${version}-${arch[os_1.default.arch()]}/java-versions.json`))); + } + + archOS = arch[os_1.default.arch()]; + } + else + return console.log("OS not supported"); + if (!javaVersionsJson) + return { error: true, message: "Java not found" }; + let java = javaVersionsJson.find(file => file[0].endsWith(process.platform == "win32" ? "bin/javaw.exe" : "bin/java"))[0]; + let toDelete = java.replace(process.platform == "win32" ? "bin/javaw.exe" : "bin/java", ""); + for (let [path, info] of javaVersionsJson) { + if (info.type == "directory") + continue; + if (!info.downloads) + continue; + let file = {}; + file.path = `runtime/${version}-${archOS}/${path.replace(toDelete, "")}`; + file.executable = info.executable; + file.sha1 = info.downloads.raw.sha1; + file.size = info.downloads.raw.size; + file.url = info.downloads.raw.url; + file.type = "Java"; + files.push(file); + } + return { + files: files, + path: path_1.default.resolve(this.options.path, `runtime/${version}-${archOS}/bin/java`), + }; + } +} +exports.default = java; diff --git a/src/assets/js/libs/mc/Minecraft/Minecraft-Json.d.ts b/src/assets/js/libs/mc/Minecraft/Minecraft-Json.d.ts new file mode 100644 index 0000000..7968d6e --- /dev/null +++ b/src/assets/js/libs/mc/Minecraft/Minecraft-Json.d.ts @@ -0,0 +1,21 @@ +/** + * @author TECNO BROS + + */ +export default class Json { + options: any; + constructor(options: any); + GetInfoVersion(): Promise<{ + error: boolean; + message: string; + InfoVersion?: undefined; + json?: undefined; + version?: undefined; + } | { + InfoVersion: any; + json: any; + version: string; + error?: undefined; + message?: undefined; + }>; +} diff --git a/src/assets/js/libs/mc/Minecraft/Minecraft-Json.js b/src/assets/js/libs/mc/Minecraft/Minecraft-Json.js new file mode 100644 index 0000000..6aa0bc5 --- /dev/null +++ b/src/assets/js/libs/mc/Minecraft/Minecraft-Json.js @@ -0,0 +1,55 @@ +"use strict"; +/** + * @author TECNO BROS + + */ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const node_fetch_1 = __importDefault(require("node-fetch")); +const fs_1 = __importDefault(require("fs")); +class Json { + constructor(options) { + this.options = options; + } + async GetInfoVersion() { + let version = this.options.version; + let data; + try { + data = await (0, node_fetch_1.default)(`https://launchermeta.mojang.com/mc/game/version_manifest_v2.json?_t=${new Date().toISOString()}`); + data = await data.json(); + fs_1.default.writeFileSync(`${this.options.path}/battly/launcher/mc-assets/version_manifest_v2.json`, JSON.stringify(data, null, 4)); + } catch (e) { + data = JSON.parse(fs_1.default.readFileSync(`${this.options.path}/battly/launcher/mc-assets/version_manifest_v2.json`)); + } + + if (version == 'latest_release' || version == 'r' || version == 'lr') { + version = data.latest.release; + } + else if (version == 'latest_snapshot' || version == 's' || version == 'ls') { + version = data.latest.snapshot; + } + data = data.versions.find(v => v.id === version); + if (!data) + return { + error: true, + message: `Minecraft ${version} is not found.` + }; + + let json; + try { + json = await (0, node_fetch_1.default)(data.url).then(res => res.json()); + fs_1.default.mkdirSync(`${this.options.path}/versions/${version}`, { recursive: true }); + fs_1.default.writeFileSync(`${this.options.path}/versions/${version}/${version}.json`, JSON.stringify(json, null, 4)); + } catch (e) { + json = JSON.parse(fs_1.default.readFileSync(`${this.options.path}/versions/${version}/${version}.json`)); + } + return { + InfoVersion: data, + json: json, + version: version + }; + } +} +exports.default = Json; diff --git a/src/assets/js/libs/mc/Minecraft/Minecraft-Libraries.d.ts b/src/assets/js/libs/mc/Minecraft/Minecraft-Libraries.d.ts new file mode 100644 index 0000000..e6ea069 --- /dev/null +++ b/src/assets/js/libs/mc/Minecraft/Minecraft-Libraries.d.ts @@ -0,0 +1,12 @@ +/** + * @author TECNO BROS + + */ +export default class Libraries { + json: any; + options: any; + constructor(options: any); + Getlibraries(json: any): Promise; + GetAssetsOthers(url: any): Promise; + natives(bundle: any): Promise; +} diff --git a/src/assets/js/libs/mc/Minecraft/Minecraft-Libraries.js b/src/assets/js/libs/mc/Minecraft/Minecraft-Libraries.js new file mode 100644 index 0000000..30f2949 --- /dev/null +++ b/src/assets/js/libs/mc/Minecraft/Minecraft-Libraries.js @@ -0,0 +1,116 @@ +"use strict"; +/** + * @author TECNO BROS + + */ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const os_1 = __importDefault(require("os")); +const fs_1 = __importDefault(require("fs")); +const adm_zip_1 = __importDefault(require("adm-zip")); +const node_fetch_1 = __importDefault(require("node-fetch")); +let MojangLib = { win32: "windows", darwin: "osx", linux: "linux" }; +let Arch = { x32: "32", x64: "64", arm: "32", arm64: "64" }; +class Libraries { + constructor(options) { + this.options = options; + } + async Getlibraries(json) { + this.json = json; + let libraries = []; + for (let lib of this.json.libraries) { + let artifact; + let type = "Libraries"; + if (lib.natives) { + let classifiers = lib.downloads.classifiers; + let native = lib.natives[MojangLib[process.platform]]; + if (!native) + native = lib.natives[process.platform]; + type = "Native"; + if (native) + artifact = classifiers[native.replace("${arch}", Arch[os_1.default.arch()])]; + else + continue; + } + else { + if (lib.rules && lib.rules[0].os) { + if (lib.rules[0].os.name !== MojangLib[process.platform]) + continue; + } + artifact = lib.downloads.artifact; + } + if (!artifact) + continue; + libraries.push({ + sha1: artifact.sha1, + size: artifact.size, + path: `libraries/${artifact.path}`, + type: type, + url: artifact.url + }); + } + libraries.push({ + sha1: this.json.downloads.client.sha1, + size: this.json.downloads.client.size, + path: `versions/${this.json.id}/${this.json.id}.jar`, + type: "Libraries", + url: this.json.downloads.client.url + }); + libraries.push({ + path: `versions/${this.json.id}/${this.json.id}.json`, + type: "CFILE", + content: JSON.stringify(this.json) + }); + return libraries; + } + async GetAssetsOthers(url) { + if (!url) + return []; + let data; + try { + data = await (0, node_fetch_1.default)(url).then(res => res.json()); + fs_1.default.writeFileSync(`${this.options.path}/battly/launcher/mc-assets/extra-assets.json`, JSON.stringify(data, null, 4)); + } catch (e) { + data = JSON.parse(fs_1.default.readFileSync(`${this.options.path}/battly/launcher/mc-assets/extra-assets.json`)); + } + let assets = []; + for (let asset of data) { + if (!asset.path) + continue; + let path = asset.path; + assets.push({ + sha1: asset.hash, + size: asset.size, + type: path.split("/")[0], + path: this.options.instance ? `instances/${this.options.instance}/${path}` : path, + url: asset.url + }); + } + return assets; + } + async natives(bundle) { + let natives = bundle.filter(mod => mod.type === "Native").map(mod => `${mod.path}`); + if (natives.length === 0) + return natives; + let nativeFolder = (`${this.options.path}/versions/${this.json.id}/natives`).replace(/\\/g, "/"); + if (!fs_1.default.existsSync(nativeFolder)) + fs_1.default.mkdirSync(nativeFolder, { recursive: true, mode: 0o777 }); + for (let native of natives) { + let zip = new adm_zip_1.default(native); + let entries = zip.getEntries(); + for (let entry of entries) { + if (entry.entryName.startsWith("META-INF")) + continue; + if (entry.isDirectory) { + fs_1.default.mkdirSync(`${nativeFolder}/${entry.entryName}`, { recursive: true, mode: 0o777 }); + continue; + } + fs_1.default.writeFile(`${nativeFolder}/${entry.entryName}`, zip.readFile(entry), { encoding: "utf8", mode: 0o777 }, () => { }); + } + } + return natives; + } +} +exports.default = Libraries; diff --git a/src/assets/js/libs/mc/Minecraft/Minecraft-Loader.d.ts b/src/assets/js/libs/mc/Minecraft/Minecraft-Loader.d.ts new file mode 100644 index 0000000..b21292b --- /dev/null +++ b/src/assets/js/libs/mc/Minecraft/Minecraft-Loader.d.ts @@ -0,0 +1,21 @@ +/** + * @author TECNO BROS + + */ +export default class MinecraftLoader { + options: any; + on: any; + emit: any; + loaderPath: string; + constructor(options: any); + GetLoader(version: any, javaPath: any): Promise; + GetArguments(json: any, version: any): Promise<{ + game: any[]; + jvm: any[]; + mainClass?: undefined; + } | { + game: any; + jvm: any; + mainClass: any; + }>; +} diff --git a/src/assets/js/libs/mc/Minecraft/Minecraft-Loader.js b/src/assets/js/libs/mc/Minecraft/Minecraft-Loader.js new file mode 100644 index 0000000..87a9f68 --- /dev/null +++ b/src/assets/js/libs/mc/Minecraft/Minecraft-Loader.js @@ -0,0 +1,91 @@ +"use strict"; +/** + * @author TECNO BROS + + */ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const events_1 = require("events"); +const index_js_1 = __importDefault(require("../Minecraft-Loader/index.js")); +class MinecraftLoader { + constructor(options) { + this.options = options; + this.on = events_1.EventEmitter.prototype.on; + this.emit = events_1.EventEmitter.prototype.emit; + if (this.options.loader.rootPath) + this.loaderPath = this.options.path; + else + this.loaderPath = `${this.options.path}/loader/${this.options.loader.type}`; + } + async GetLoader(version, javaPath) { + let loader = new index_js_1.default({ + path: this.loaderPath, + downloadFileMultiple: this.options.downloadFileMultiple, + loader: { + type: this.options.loader.type, + version: version, + build: this.options.loader.build, + config: { + javaPath: javaPath, + minecraftJar: `${this.options.path}/versions/${version}/${version}.jar`, + minecraftJson: `${this.options.path}/versions/${version}/${version}.json` + } + } + }); + return await new Promise((resolve, reject) => { + loader.install(); + loader.on('json', (json) => { + let loaderJson = json; + loaderJson.libraries = loaderJson.libraries.map((lib) => { + lib.loader = this.loaderPath; + return lib; + }); + resolve(loaderJson); + }); + loader.on('extract', (extract) => { + this.emit('extract', extract); + }); + loader.on('progress', (progress, size, element) => { + this.emit('progress', progress, size, element); + }); + loader.on('check', (progress, size, element) => { + this.emit('check', progress, size, element); + }); + loader.on('patch', (patch) => { + this.emit('patch', patch); + }); + loader.on('error', (err) => { + reject(err); + }); + }); + } + async GetArguments(json, version) { + if (json === null) { + return { + game: [], + jvm: [] + }; + } + let moddeArguments = json.arguments; + if (!moddeArguments) + return { game: [], jvm: [] }; + let Arguments = {}; + if (moddeArguments.game) + Arguments.game = moddeArguments.game; + if (moddeArguments.jvm) + Arguments.jvm = moddeArguments.jvm.map(jvm => { + return jvm + .replace(/\${version_name}/g, version) + .replace(/\${library_directory}/g, `${this.loaderPath}/libraries`) + .replace(/\${classpath_separator}/g, process.platform === 'win32' ? ';' : ':'); + }); + return { + game: Arguments.game || [], + jvm: Arguments.jvm || [], + mainClass: json.mainClass + }; + } +} +exports.default = MinecraftLoader; diff --git a/src/assets/js/libs/mc/StatusServer/buffer.d.ts b/src/assets/js/libs/mc/StatusServer/buffer.d.ts new file mode 100644 index 0000000..cff76fb --- /dev/null +++ b/src/assets/js/libs/mc/StatusServer/buffer.d.ts @@ -0,0 +1,2 @@ +declare function CustomBuffer(existingBuffer?: any): void; +export default CustomBuffer; diff --git a/src/assets/js/libs/mc/StatusServer/buffer.js b/src/assets/js/libs/mc/StatusServer/buffer.js new file mode 100644 index 0000000..f8cc3e0 --- /dev/null +++ b/src/assets/js/libs/mc/StatusServer/buffer.js @@ -0,0 +1,56 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function CustomBuffer(existingBuffer = Buffer.alloc(48)) { + let buffer = existingBuffer; + let offset = 0; + this.writeletInt = (val) => { + while (true) { + if ((val & 0xFFFFFF80) == 0) { + return this.writeUByte(val); + } + this.writeUByte(val & 0x7F | 0x80); + val = val >>> 7; + } + }; + this.writeString = (string) => { + this.writeletInt(string.length); + if (offset + string.length >= buffer.length) + Buffer.concat([buffer, new Buffer(string.length)]); + buffer.write(string, offset, string.length, "UTF-8"); + offset += string.length; + }; + this.writeUShort = (val) => { + this.writeUByte(val >> 8); + this.writeUByte(val & 0xFF); + }; + this.writeUByte = (val) => { + if (offset >= buffer.length) { + buffer = Buffer.concat([buffer, new Buffer(50)]); + } + buffer.writeUInt8(val, offset++); + }; + this.readletInt = function () { + let val = 0; + let count = 0; + while (true) { + let i = buffer.readUInt8(offset++); + val |= (i & 0x7F) << count++ * 7; + if ((i & 0x80) != 128) + break; + } + return val; + }; + this.readString = () => { + let length = this.readletInt(); + let str = buffer.toString("UTF-8", offset, offset + length); + offset += length; + return str; + }; + this.buffer = () => { + return buffer.slice(0, offset); + }; + this.offset = () => { + return offset; + }; +} +exports.default = CustomBuffer; diff --git a/src/assets/js/libs/mc/StatusServer/status.d.ts b/src/assets/js/libs/mc/StatusServer/status.d.ts new file mode 100644 index 0000000..1335098 --- /dev/null +++ b/src/assets/js/libs/mc/StatusServer/status.d.ts @@ -0,0 +1,10 @@ +/** + * @author TECNO BROS + + */ +export default class status { + ip: string; + port: number; + constructor(ip?: string, port?: number); + getStatus(): Promise; +} diff --git a/src/assets/js/libs/mc/StatusServer/status.js b/src/assets/js/libs/mc/StatusServer/status.js new file mode 100644 index 0000000..31421b8 --- /dev/null +++ b/src/assets/js/libs/mc/StatusServer/status.js @@ -0,0 +1,91 @@ +"use strict"; +/** + * @author TECNO BROS + + */ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const net_1 = __importDefault(require("net")); +const buffer_js_1 = __importDefault(require("./buffer.js")); +function ping(server, port, callback, timeout, protocol = '') { + let start = new Date(); + let socket = net_1.default.connect({ + port: port, + host: server + }, () => { + let handshakeBuffer = new buffer_js_1.default(); + handshakeBuffer.writeletInt(0); + handshakeBuffer.writeletInt(protocol); + handshakeBuffer.writeString(server); + handshakeBuffer.writeUShort(port); + handshakeBuffer.writeletInt(1); + writePCBuffer(socket, handshakeBuffer); + let setModeBuffer = new buffer_js_1.default(); + setModeBuffer.writeletInt(0); + writePCBuffer(socket, setModeBuffer); + }); + socket.setTimeout(timeout, () => { + if (callback) + callback(new Error("Socket timed out when connecting to " + server + ":" + port), null); + socket.destroy(); + }); + let readingBuffer = Buffer.alloc(0); + socket.on('data', data => { + readingBuffer = Buffer.concat([readingBuffer, data]); + let buffer = new buffer_js_1.default(readingBuffer); + let length; + try { + length = buffer.readletInt(); + } + catch (err) { + return; + } + if (readingBuffer.length < length - buffer.offset()) + return; + buffer.readletInt(); + try { + let end = new Date(); + let json = JSON.parse(buffer.readString()); + callback(null, { + error: false, + ms: Math.round(end - start), + version: json.version.name, + playersConnect: json.players.online, + playersMax: json.players.max + }); + } + catch (err) { + return callback(err, null); + } + socket.destroy(); + }); + socket.once('error', err => { + if (callback) + callback(err, null); + socket.destroy(); + }); +} +; +function writePCBuffer(client, buffer) { + let length = new buffer_js_1.default(); + length.writeletInt(buffer.buffer().length); + client.write(Buffer.concat([length.buffer(), buffer.buffer()])); +} +class status { + constructor(ip = '0.0.0.0', port = 25565) { + this.ip = ip; + this.port = port; + } + async getStatus() { + return await new Promise((resolve, reject) => { + ping(this.ip, this.port, (err, res) => { + if (err) + return reject({ error: err }); + return resolve(res); + }, 3000); + }); + } +} +exports.default = status; diff --git a/src/assets/js/libs/mc/utils/Downloader.d.ts b/src/assets/js/libs/mc/utils/Downloader.d.ts new file mode 100644 index 0000000..8a6fdeb --- /dev/null +++ b/src/assets/js/libs/mc/utils/Downloader.d.ts @@ -0,0 +1,24 @@ +/** + * @author TECNO BROS + + */ +interface downloadOptions { + url: string; + path: string; + length: number; + folder: string; +} +export default class download { + on: any; + emit: any; + constructor(); + downloadFile(url: string, path: string, fileName: string): Promise; + downloadFileMultiple(files: downloadOptions, size: number, limit?: number, timeout?: number): Promise; + checkURL(url: string, timeout?: number): Promise; + checkMirror(baseURL: string, mirrors: any): Promise; +} +export {}; diff --git a/src/assets/js/libs/mc/utils/Downloader.js b/src/assets/js/libs/mc/utils/Downloader.js new file mode 100644 index 0000000..0448dad --- /dev/null +++ b/src/assets/js/libs/mc/utils/Downloader.js @@ -0,0 +1,136 @@ +"use strict"; +/** + * @author TECNO BROS + + */ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const fs_1 = __importDefault(require("fs")); +const node_fetch_1 = __importDefault(require("node-fetch")); +const events_1 = require("events"); +class download { + constructor() { + this.on = events_1.EventEmitter.prototype.on; + this.emit = events_1.EventEmitter.prototype.emit; + } + async downloadFile(url, path, fileName) { + if (!fs_1.default.existsSync(path)) + fs_1.default.mkdirSync(path, { recursive: true }); + const writer = fs_1.default.createWriteStream(path + '/' + fileName); + const response = await (0, node_fetch_1.default)(url); + let size = response.headers.get('content-length'); + let downloaded = 0; + return new Promise((resolve, reject) => { + response.body.on('data', (chunk) => { + downloaded += chunk.length; + this.emit('progress', downloaded, size); + writer.write(chunk); + }); + response.body.on('end', () => { + writer.end(); + resolve(); + }); + response.body.on('error', (err) => { + this.emit('error', err); + reject(err); + }); + }); + } + async downloadFileMultiple(files, size, limit = 1, timeout = 10000) { + if (limit > files.length) + limit = files.length; + let completed = 0; + let downloaded = 0; + let queued = 0; + let start = new Date().getTime(); + let before = 0; + let speeds = []; + let estimated = setInterval(() => { + let duration = (new Date().getTime() - start) / 1000; + let loaded = (downloaded - before) * 8; + if (speeds.length >= 5) + speeds = speeds.slice(1); + speeds.push((loaded / duration) / 8); + let speed = 0; + for (let s of speeds) + speed += s; + speed /= speeds.length; + this.emit("speed", speed); + let time = (size - downloaded) / (speed); + this.emit("estimated", time); + start = new Date().getTime(); + before = downloaded; + }, 500); + const downloadNext = async () => { + if (queued < files.length) { + let file = files[queued]; + queued++; + if (!fs_1.default.existsSync(file.foler)) + fs_1.default.mkdirSync(file.folder, { recursive: true, mode: 0o777 }); + const writer = fs_1.default.createWriteStream(file.path, { flags: 'w', mode: 0o777 }); + try { + const response = await (0, node_fetch_1.default)(file.url, { timeout: timeout }); + response.body.on('data', (chunk) => { + downloaded += chunk.length; + this.emit('progress', downloaded, size, file.type); + writer.write(chunk); + }); + response.body.on('end', () => { + writer.end(); + completed++; + downloadNext(); + }); + } + catch (e) { + writer.end(); + completed++; + downloadNext(); + this.emit('error', e); + } + } + }; + while (queued < limit) + downloadNext(); + return new Promise((resolve) => { + const interval = setInterval(() => { + if (completed === files.length) { + clearInterval(estimated); + clearInterval(interval); + resolve(); + } + }, 100); + }); + } + async checkURL(url, timeout = 10000) { + return await new Promise(async (resolve, reject) => { + await (0, node_fetch_1.default)(url, { method: 'HEAD', timeout: timeout }).then(res => { + if (res.status === 200) { + resolve({ + size: parseInt(res.headers.get('content-length')), + status: res.status + }); + } + }); + reject(false); + }); + } + async checkMirror(baseURL, mirrors) { + for (let mirror of mirrors) { + let url = `${mirror}/${baseURL}`; + let res = await this.checkURL(url).then(res => res).catch(err => false); + if (res?.status == 200) { + return { + url: url, + size: res.size, + status: res.status + }; + break; + } + continue; + } + return false; + } +} +exports.default = download; diff --git a/src/assets/js/libs/mc/utils/Index.d.ts b/src/assets/js/libs/mc/utils/Index.d.ts new file mode 100644 index 0000000..31d6191 --- /dev/null +++ b/src/assets/js/libs/mc/utils/Index.d.ts @@ -0,0 +1,46 @@ +/** + * @author TECNO BROS + + */ +declare function getPathLibraries(main: any, nativeString?: any, forceExt?: any): { + path: string; + name: string; +}; +declare function getFileHash(filePath: string, algorithm?: string): Promise; +declare function isold(json: any): boolean; +declare function loader(type: string): { + metaData: string; + meta: string; + promotions: string; + install: string; + universal: string; + client: string; + legacyMetaData?: undefined; + legacyInstall?: undefined; + json?: undefined; +} | { + legacyMetaData: string; + metaData: string; + legacyInstall: string; + install: string; + meta?: undefined; + promotions?: undefined; + universal?: undefined; + client?: undefined; + json?: undefined; +} | { + metaData: string; + json: string; + meta?: undefined; + promotions?: undefined; + install?: undefined; + universal?: undefined; + client?: undefined; + legacyMetaData?: undefined; + legacyInstall?: undefined; +}; +declare let mirrors: string[]; +declare function getFileFromJar(jar: string, file?: string, path?: string): Promise; +declare function createZIP(files: any, ignored?: any): Promise; +declare function skipLibrary(lib: any): boolean; +export { getPathLibraries, isold, getFileHash, mirrors, loader, getFileFromJar, createZIP, skipLibrary }; diff --git a/src/assets/js/libs/mc/utils/Index.js b/src/assets/js/libs/mc/utils/Index.js new file mode 100644 index 0000000..1124d6d --- /dev/null +++ b/src/assets/js/libs/mc/utils/Index.js @@ -0,0 +1,140 @@ +"use strict"; +/** + * @author TECNO BROS + + */ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.skipLibrary = exports.createZIP = exports.getFileFromJar = exports.loader = exports.mirrors = exports.getFileHash = exports.isold = exports.getPathLibraries = void 0; +const crypto_1 = __importDefault(require("crypto")); +const fs_1 = __importDefault(require("fs")); +const adm_zip_1 = __importDefault(require("adm-zip")); +function getPathLibraries(main, nativeString, forceExt) { + let libSplit = main.split(':'); + let fileName = libSplit[3] ? `${libSplit[2]}-${libSplit[3]}` : libSplit[2]; + let finalFileName = fileName.includes('@') ? fileName.replace('@', '.') : `${fileName}${nativeString || ''}${forceExt || '.jar'}`; + let pathLib = `${libSplit[0].replace(/\./g, '/')}/${libSplit[1]}/${libSplit[2].split('@')[0]}`; + return { + path: pathLib, + name: `${libSplit[1]}-${finalFileName}` + }; +} +exports.getPathLibraries = getPathLibraries; +async function getFileHash(filePath, algorithm = 'sha1') { + let shasum = crypto_1.default.createHash(algorithm); + let file = fs_1.default.createReadStream(filePath); + file.on('data', data => { + shasum.update(data); + }); + let hash = await new Promise(resolve => { + file.on('end', () => { + resolve(shasum.digest('hex')); + }); + }); + return hash; +} +exports.getFileHash = getFileHash; +function isold(json) { + return json.assets === 'legacy' || json.assets === 'pre-1.6'; +} +exports.isold = isold; +function loader(type) { + if (type === 'forge') { + return { + metaData: 'https://files.minecraftforge.net/net/minecraftforge/forge/maven-metadata.json', + meta: 'https://files.minecraftforge.net/net/minecraftforge/forge/${build}/meta.json', + promotions: 'https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json', + install: 'https://maven.minecraftforge.net/net/minecraftforge/forge/${version}/forge-${version}-installer', + universal: 'https://maven.minecraftforge.net/net/minecraftforge/forge/${version}/forge-${version}-universal', + client: 'https://maven.minecraftforge.net/net/minecraftforge/forge/${version}/forge-${version}-client', + }; + } + else if (type === 'neoforge') { + return { + legacyMetaData: 'https://maven.neoforged.net/api/maven/versions/releases/net/neoforged/forge', + metaData: 'https://maven.neoforged.net/api/maven/versions/releases/net/neoforged/neoforge', + legacyInstall: 'https://maven.neoforged.net/net/neoforged/forge/${version}/forge-${version}-installer.jar', + install: 'https://maven.neoforged.net/net/neoforged/neoforge/${version}/neoforge-${version}-installer.jar' + }; + } + else if (type === 'fabric') { + return { + metaData: 'https://meta.fabricmc.net/v2/versions', + json: 'https://meta.fabricmc.net/v2/versions/loader/${version}/${build}/profile/json' + }; + } + else if (type === 'legacyfabric') { + return { + metaData: 'https://meta.legacyfabric.net/v2/versions', + json: 'https://meta.legacyfabric.net/v2/versions/loader/${version}/${build}/profile/json' + }; + } + else if (type === 'quilt') { + return { + metaData: 'https://meta.quiltmc.org/v3/versions', + json: 'https://meta.quiltmc.org/v3/versions/loader/${version}/${build}/profile/json' + }; + } +} +exports.loader = loader; +let mirrors = [ + "https://maven.minecraftforge.net", + "https://maven.neoforged.net/releases", + "https://maven.creeperhost.net", + "https://libraries.minecraft.net", + "https://repo1.maven.org/maven2" +]; +exports.mirrors = mirrors; +async function getFileFromJar(jar, file = null, path = null) { + let fileReturn = []; + let zip = new adm_zip_1.default(jar); + let entries = zip.getEntries(); + return await new Promise(resolve => { + for (let entry of entries) { + if (!entry.isDirectory && !path) { + if (entry.entryName == file) + fileReturn = entry.getData(); + if (!file) + fileReturn.push({ name: entry.entryName, data: entry.getData() }); + } + if (!entry.isDirectory && entry.entryName.includes(path) && path) { + fileReturn.push(entry.entryName); + } + } + resolve(fileReturn); + }); +} +exports.getFileFromJar = getFileFromJar; +async function createZIP(files, ignored = null) { + let zip = new adm_zip_1.default(); + return await new Promise(resolve => { + for (let entry of files) { + if (ignored && entry.name.includes(ignored)) + continue; + zip.addFile(entry.name, entry.data); + } + resolve(zip.toBuffer()); + }); +} +exports.createZIP = createZIP; +function skipLibrary(lib) { + let Lib = { win32: "windows", darwin: "osx", linux: "linux" }; + let skip = false; + if (lib.rules) { + skip = true; + lib.rules.forEach(({ action, os, features }) => { + if (features) + return true; + if (action === 'allow' && ((os && os.name === Lib[process.platform]) || !os)) { + skip = false; + } + if (action === 'disallow' && ((os && os.name === Lib[process.platform]) || !os)) { + skip = true; + } + }); + } + return skip; +} +exports.skipLibrary = skipLibrary; diff --git a/src/assets/js/libs/sound/index.js b/src/assets/js/libs/sound/index.js new file mode 100644 index 0000000..cf0faab --- /dev/null +++ b/src/assets/js/libs/sound/index.js @@ -0,0 +1,36 @@ +const { exec } = require('child_process') +const execPromise = require('util').promisify(exec) + +/* MAC PLAY COMMAND */ +const macPlayCommand = (path, volume) => `afplay \"${path}\" -v ${volume}` + +/* WINDOW PLAY COMMANDS */ +const addPresentationCore = `Add-Type -AssemblyName presentationCore;` +const createMediaPlayer = `$player = New-Object system.windows.media.mediaplayer;` +const loadAudioFile = path => `$player.open('${path}');` +const playAudio = `$player.Play();` +const stopAudio = `Start-Sleep 1; Start-Sleep -s $player.NaturalDuration.TimeSpan.TotalSeconds;Exit;` + +const windowPlayCommand = (path, volume) => + `powershell -c ${addPresentationCore} ${createMediaPlayer} ${loadAudioFile( + path, + )} $player.Volume = ${volume}; ${playAudio} ${stopAudio}` + +module.exports = { + play: async (path, volume=0.5) => { + /** + * Window: mediaplayer's volume is from 0 to 1, default is 0.5 + * Mac: afplay's volume is from 0 to 255, default is 1. However, volume > 2 usually result in distortion. + * Therefore, it is better to limit the volume on Mac, and set a common scale of 0 to 1 for simplicity + */ + const volumeAdjustedByOS = process.platform === 'darwin' ? Math.min(2, volume * 2) : volume + + const playCommand = + process.platform === 'darwin' ? macPlayCommand(path, volumeAdjustedByOS) : windowPlayCommand(path, volumeAdjustedByOS) + try { + await execPromise(playCommand) + } catch (err) { + throw err + } + }, +} diff --git a/src/assets/js/libs/sweetalert/sweetalert2.all.min.js b/src/assets/js/libs/sweetalert/sweetalert2.all.min.js new file mode 100644 index 0000000..177ff0f --- /dev/null +++ b/src/assets/js/libs/sweetalert/sweetalert2.all.min.js @@ -0,0 +1,6 @@ +/*! +* sweetalert2 v11.10.2 +* Released under the MIT License. +*/ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).Sweetalert2=e()}(this,(function(){"use strict";function t(t){var e=function(t,e){if("object"!=typeof t||!t)return t;var n=t[Symbol.toPrimitive];if(void 0!==n){var o=n.call(t,e||"default");if("object"!=typeof o)return o;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===e?String:Number)(t)}(t,"string");return"symbol"==typeof e?e:String(e)}function e(t){return e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},e(t)}function n(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function o(e,n){for(var o=0;ot.length)&&(e=t.length);for(var n=0,o=new Array(e);no?1:n .").concat(A[e]));case"checkbox":return t.querySelector(".".concat(A.popup," > .").concat(A.checkbox," input"));case"radio":return t.querySelector(".".concat(A.popup," > .").concat(A.radio," input:checked"))||t.querySelector(".".concat(A.popup," > .").concat(A.radio," input:first-child"));case"range":return t.querySelector(".".concat(A.popup," > .").concat(A.range," input"));default:return t.querySelector(".".concat(A.popup," > .").concat(A.input))}},rt=function(t){if(t.focus(),"file"!==t.type){var e=t.value;t.value="",t.value=e}},at=function(t,e,n){t&&e&&("string"==typeof e&&(e=e.split(/\s+/).filter(Boolean)),e.forEach((function(e){Array.isArray(t)?t.forEach((function(t){n?t.classList.add(e):t.classList.remove(e)})):n?t.classList.add(e):t.classList.remove(e)})))},ct=function(t,e){at(t,e,!0)},ut=function(t,e){at(t,e,!1)},st=function(t,e){for(var n=Array.from(t.children),o=0;o1&&void 0!==arguments[1]?arguments[1]:"flex";t&&(t.style.display=e)},ft=function(t){t&&(t.style.display="none")},pt=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"block";t&&new MutationObserver((function(){ht(t,t.innerHTML,e)})).observe(t,{childList:!0,subtree:!0})},mt=function(t,e,n,o){var i=t.querySelector(e);i&&i.style.setProperty(n,o)},ht=function(t,e){e?dt(t,arguments.length>2&&void 0!==arguments[2]?arguments[2]:"flex"):ft(t)},vt=function(t){return!(!t||!(t.offsetWidth||t.offsetHeight||t.getClientRects().length))},gt=function(t){return!!(t.scrollHeight>t.clientHeight)},bt=function(t){var e=window.getComputedStyle(t),n=parseFloat(e.getPropertyValue("animation-duration")||"0"),o=parseFloat(e.getPropertyValue("transition-duration")||"0");return n>0||o>0},yt=function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=J();n&&vt(n)&&(e&&(n.style.transition="none",n.style.width="100%"),setTimeout((function(){n.style.transition="width ".concat(t/1e3,"s linear"),n.style.width="0%"}),10))},wt=function(){return"undefined"==typeof window||"undefined"==typeof document},Ct='\n
\n \n
    \n
    \n \n

    \n
    \n \n \n
    \n \n \n
    \n \n
    \n \n \n
    \n
    \n
    \n \n \n \n
    \n
    \n
    \n
    \n
    \n
    \n').replace(/(^|\n)\s*/g,""),At=function(){y.currentInstance.resetValidationMessage()},kt=function(t){var e,n=!!(e=I())&&(e.remove(),ut([document.documentElement,document.body],[A["no-backdrop"],A["toast-shown"],A["has-column"]]),!0);if(wt())T("SweetAlert2 requires document to initialize");else{var o=document.createElement("div");o.className=A.container,n&&ct(o,A["no-transition"]),et(o,Ct);var i,r,a,c,u,s,l,d,f,p="string"==typeof(i=t.target)?document.querySelector(i):i;p.appendChild(o),function(t){var e=q();e.setAttribute("role",t.toast?"alert":"dialog"),e.setAttribute("aria-live",t.toast?"polite":"assertive"),t.toast||e.setAttribute("aria-modal","true")}(t),function(t){"rtl"===window.getComputedStyle(t).direction&&ct(I(),A.rtl)}(p),r=q(),a=st(r,A.input),c=st(r,A.file),u=r.querySelector(".".concat(A.range," input")),s=r.querySelector(".".concat(A.range," output")),l=st(r,A.select),d=r.querySelector(".".concat(A.checkbox," input")),f=st(r,A.textarea),a.oninput=At,c.onchange=At,l.onchange=At,d.onchange=At,f.oninput=At,u.oninput=function(){At(),s.value=u.value},u.onchange=function(){At(),s.value=u.value}}},Et=function(t,n){t instanceof HTMLElement?n.appendChild(t):"object"===e(t)?Pt(t,n):t&&et(n,t)},Pt=function(t,e){t.jquery?Bt(e,t):et(e,t.toString())},Bt=function(t,e){if(t.textContent="",0 in e)for(var n=0;n in e;n++)t.appendChild(e[n].cloneNode(!0));else t.appendChild(e.cloneNode(!0))},Tt=function(){if(wt())return!1;var t=document.createElement("div");return void 0!==t.style.webkitAnimation?"webkitAnimationEnd":void 0!==t.style.animation&&"animationend"}(),xt=function(t,e){var n=Z(),o=Y();n&&o&&(e.showConfirmButton||e.showDenyButton||e.showCancelButton?dt(n):ft(n),ot(n,e,"actions"),function(t,e,n){var o=z(),i=K(),r=W();if(!o||!i||!r)return;St(o,"confirm",n),St(i,"deny",n),St(r,"cancel",n),function(t,e,n,o){if(!o.buttonsStyling)return void ut([t,e,n],A.styled);ct([t,e,n],A.styled),o.confirmButtonColor&&(t.style.backgroundColor=o.confirmButtonColor,ct(t,A["default-outline"]));o.denyButtonColor&&(e.style.backgroundColor=o.denyButtonColor,ct(e,A["default-outline"]));o.cancelButtonColor&&(n.style.backgroundColor=o.cancelButtonColor,ct(n,A["default-outline"]))}(o,i,r,n),n.reverseButtons&&(n.toast?(t.insertBefore(r,o),t.insertBefore(i,o)):(t.insertBefore(r,e),t.insertBefore(i,e),t.insertBefore(o,e)))}(n,o,e),et(o,e.loaderHtml||""),ot(o,e,"loader"))};function St(t,e,n){var o=P(e);ht(t,n["show".concat(o,"Button")],"inline-block"),et(t,n["".concat(e,"ButtonText")]||""),t.setAttribute("aria-label",n["".concat(e,"ButtonAriaLabel")]||""),t.className=A[e],ot(t,n,"".concat(e,"Button"))}var Ot=function(t,e){var n=I();n&&(!function(t,e){"string"==typeof e?t.style.background=e:e||ct([document.documentElement,document.body],A["no-backdrop"])}(n,e.backdrop),function(t,e){if(!e)return;e in A?ct(t,A[e]):(B('The "position" parameter is not valid, defaulting to "center"'),ct(t,A.center))}(n,e.position),function(t,e){if(!e)return;ct(t,A["grow-".concat(e)])}(n,e.grow),ot(n,e,"container"))};var Lt={innerParams:new WeakMap,domCache:new WeakMap},jt=["input","file","range","select","radio","checkbox","textarea"],Mt=function(t){if(t.input)if(_t[t.input]){var e=Vt(t.input),n=_t[t.input](e,t);dt(e),t.inputAutoFocus&&setTimeout((function(){rt(n)}))}else T("Unexpected type of input! Expected ".concat(Object.keys(_t).join(" | "),', got "').concat(t.input,'"'))},It=function(t,e){var n=it(q(),t);if(n)for(var o in function(t){for(var e=0;en?q().style.width="".concat(i,"px"):lt(q(),"width",e.width)}})).observe(t,{attributes:!0,attributeFilter:["style"]})}})),t};var Nt=function(t,e){var n=_();n&&(pt(n),ot(n,e,"htmlContainer"),e.html?(Et(e.html,n),dt(n,"block")):e.text?(n.textContent=e.text,dt(n,"block")):ft(n),function(t,e){var n=q();if(n){var o=Lt.innerParams.get(t),i=!o||e.input!==o.input;jt.forEach((function(t){var o=st(n,A[t]);o&&(It(t,e.inputAttributes),o.className=A[t],i&&ft(o))})),e.input&&(i&&Mt(e),Ht(e))}}(t,e))},Ft=function(t,e){for(var n=0,o=Object.entries(k);n\n \n
    \n
    \n',n=n.replace(/ style=".*?"/g,"");else if("error"===e.icon)o='\n \n \n \n \n';else if(e.icon){o=Kt({question:"?",warning:"!",info:"i"}[e.icon])}n.trim()!==o.trim()&&et(t,o)}},Wt=function(t,e){if(e.iconColor){t.style.color=e.iconColor,t.style.borderColor=e.iconColor;for(var n=0,o=[".swal2-success-line-tip",".swal2-success-line-long",".swal2-x-mark-line-left",".swal2-x-mark-line-right"];n').concat(t,"")},Yt=function(t,e){var n=e.showClass||{};t.className="".concat(A.popup," ").concat(vt(t)?n.popup:""),e.toast?(ct([document.documentElement,document.body],A["toast-shown"]),ct(t,A.toast)):ct(t,A.modal),ot(t,e,"popup"),"string"==typeof e.customClass&&ct(t,e.customClass),e.icon&&ct(t,A["icon-".concat(e.icon)])},Zt=function(t){var e=document.createElement("li");return ct(e,A["progress-step"]),et(e,t),e},$t=function(t){var e=document.createElement("li");return ct(e,A["progress-step-line"]),t.progressStepsDistance&<(e,"width",t.progressStepsDistance),e},Jt=function(t,e){!function(t,e){var n=I(),o=q();if(n&&o){if(e.toast){lt(n,"width",e.width),o.style.width="100%";var i=Y();i&&o.insertBefore(i,V())}else lt(o,"width",e.width);lt(o,"padding",e.padding),e.color&&(o.style.color=e.color),e.background&&(o.style.background=e.background),ft(U()),Yt(o,e)}}(0,e),Ot(0,e),function(t,e){var n=F();if(n){var o=e.progressSteps,i=e.currentProgressStep;o&&0!==o.length&&void 0!==i?(dt(n),n.textContent="",i>=o.length&&B("Invalid currentProgressStep parameter, it should be less than progressSteps.length (currentProgressStep like JS arrays starts from 0)"),o.forEach((function(t,r){var a=Zt(t);if(n.appendChild(a),r===i&&ct(a,A["active-progress-step"]),r!==o.length-1){var c=$t(e);n.appendChild(c)}}))):ft(n)}}(0,e),function(t,e){var n=Lt.innerParams.get(t),o=V();if(o){if(n&&e.icon===n.icon)return zt(o,e),void Ft(o,e);if(e.icon||e.iconHtml){if(e.icon&&-1===Object.keys(k).indexOf(e.icon))return T('Unknown icon! Expected "success", "error", "warning", "info" or "question", got "'.concat(e.icon,'"')),void ft(o);dt(o),zt(o,e),Ft(o,e),ct(o,e.showClass&&e.showClass.icon)}else ft(o)}}(t,e),function(t,e){var n=N();n&&(e.imageUrl?(dt(n,""),n.setAttribute("src",e.imageUrl),n.setAttribute("alt",e.imageAlt||""),lt(n,"width",e.imageWidth),lt(n,"height",e.imageHeight),n.className=A.image,ot(n,e,"image")):ft(n))}(0,e),function(t,e){var n=R();n&&(pt(n),ht(n,e.title||e.titleText,"block"),e.title&&Et(e.title,n),e.titleText&&(n.innerText=e.titleText),ot(n,e,"title"))}(0,e),function(t,e){var n=X();n&&(et(n,e.closeButtonHtml||""),ot(n,e,"closeButton"),ht(n,e.showCloseButton),n.setAttribute("aria-label",e.closeButtonAriaLabel||""))}(0,e),Nt(t,e),xt(0,e),function(t,e){var n=$();n&&(pt(n),ht(n,e.footer,"block"),e.footer&&Et(e.footer,n),ot(n,e,"footer"))}(0,e);var n=q();"function"==typeof e.didRender&&n&&e.didRender(n)},Xt=function(){var t;return null===(t=z())||void 0===t?void 0:t.click()},Gt=Object.freeze({cancel:"cancel",backdrop:"backdrop",close:"close",esc:"esc",timer:"timer"}),Qt=function(t){t.keydownTarget&&t.keydownHandlerAdded&&(t.keydownTarget.removeEventListener("keydown",t.keydownHandler,{capture:t.keydownListenerCapture}),t.keydownHandlerAdded=!1)},te=function(t,e){var n,o=G();if(o.length)return(t+=e)===o.length?t=0:-1===t&&(t=o.length-1),void o[t].focus();null===(n=q())||void 0===n||n.focus()},ee=["ArrowRight","ArrowDown"],ne=["ArrowLeft","ArrowUp"],oe=function(t,e,n){t&&(e.isComposing||229===e.keyCode||(t.stopKeydownPropagation&&e.stopPropagation(),"Enter"===e.key?ie(e,t):"Tab"===e.key?re(e):[].concat(ee,ne).includes(e.key)?ae(e.key):"Escape"===e.key&&ce(e,t,n)))},ie=function(t,e){if(O(e.allowEnterKey)){var n=it(q(),e.input);if(t.target&&n&&t.target instanceof HTMLElement&&t.target.outerHTML===n.outerHTML){if(["textarea","file"].includes(e.input))return;Xt(),t.preventDefault()}}},re=function(t){for(var e=t.target,n=G(),o=-1,i=0;i1},he=null,ve=function(t){null===he&&(document.body.scrollHeight>window.innerHeight||"scroll"===t)&&(he=parseInt(window.getComputedStyle(document.body).getPropertyValue("padding-right")),document.body.style.paddingRight="".concat(he+function(){var t=document.createElement("div");t.className=A["scrollbar-measure"],document.body.appendChild(t);var e=t.getBoundingClientRect().width-t.clientWidth;return document.body.removeChild(t),e}(),"px"))};function ge(t,e,n,o){tt()?Pe(t,o):(w(n).then((function(){return Pe(t,o)})),Qt(y)),le?(e.setAttribute("style","display:none !important"),e.removeAttribute("class"),e.innerHTML=""):e.remove(),Q()&&(null!==he&&(document.body.style.paddingRight="".concat(he,"px"),he=null),function(){if(nt(document.body,A.iosfix)){var t=parseInt(document.body.style.top,10);ut(document.body,A.iosfix),document.body.style.top="",document.body.scrollTop=-1*t}}(),se()),ut([document.documentElement,document.body],[A.shown,A["height-auto"],A["no-backdrop"],A["toast-shown"]])}function be(t){t=Ae(t);var e=ue.swalPromiseResolve.get(this),n=ye(this);this.isAwaitingPromise?t.isDismissed||(Ce(this),e(t)):n&&e(t)}var ye=function(t){var e=q();if(!e)return!1;var n=Lt.innerParams.get(t);if(!n||nt(e,n.hideClass.popup))return!1;ut(e,n.showClass.popup),ct(e,n.hideClass.popup);var o=I();return ut(o,n.showClass.backdrop),ct(o,n.hideClass.backdrop),ke(t,e,n),!0};function we(t){var e=ue.swalPromiseReject.get(this);Ce(this),e&&e(t)}var Ce=function(t){t.isAwaitingPromise&&(delete t.isAwaitingPromise,Lt.innerParams.get(t)||t._destroy())},Ae=function(t){return void 0===t?{isConfirmed:!1,isDenied:!1,isDismissed:!0}:Object.assign({isConfirmed:!1,isDenied:!1,isDismissed:!1},t)},ke=function(t,e,n){var o=I(),i=Tt&&bt(e);"function"==typeof n.willClose&&n.willClose(e),i?Ee(t,e,o,n.returnFocus,n.didClose):ge(t,o,n.returnFocus,n.didClose)},Ee=function(t,e,n,o,i){Tt&&(y.swalCloseEventFinishedCallback=ge.bind(null,t,n,o,i),e.addEventListener(Tt,(function(t){t.target===e&&(y.swalCloseEventFinishedCallback(),delete y.swalCloseEventFinishedCallback)})))},Pe=function(t,e){setTimeout((function(){"function"==typeof e&&e.bind(t.params)(),t._destroy&&t._destroy()}))},Be=function(t){var e=q();if(e||new ao,e=q()){var n=Y();tt()?ft(V()):Te(e,t),dt(n),e.setAttribute("data-loading","true"),e.setAttribute("aria-busy","true"),e.focus()}},Te=function(t,e){var n=Z(),o=Y();n&&o&&(!e&&vt(z())&&(e=z()),dt(n),e&&(ft(e),o.setAttribute("data-button-to-replace",e.className),n.insertBefore(o,e)),ct([t,n],A.loading))},xe=function(t){return t.checked?1:0},Se=function(t){return t.checked?t.value:null},Oe=function(t){return t.files&&t.files.length?null!==t.getAttribute("multiple")?t.files:t.files[0]:null},Le=function(t,n){var o=q();if(o){var i=function(t){"select"===n.input?function(t,e,n){var o=st(t,A.select);if(!o)return;var i=function(t,e,o){var i=document.createElement("option");i.value=o,et(i,e),i.selected=Ie(o,n.inputValue),t.appendChild(i)};e.forEach((function(t){var e=t[0],n=t[1];if(Array.isArray(n)){var r=document.createElement("optgroup");r.label=e,r.disabled=!1,o.appendChild(r),n.forEach((function(t){return i(r,t[1],t[0])}))}else i(o,n,e)})),o.focus()}(o,Me(t),n):"radio"===n.input&&function(t,e,n){var o=st(t,A.radio);if(!o)return;e.forEach((function(t){var e=t[0],i=t[1],r=document.createElement("input"),a=document.createElement("label");r.type="radio",r.name=A.radio,r.value=e,Ie(e,n.inputValue)&&(r.checked=!0);var c=document.createElement("span");et(c,i),c.className=A.label,a.appendChild(r),a.appendChild(c),o.appendChild(a)}));var i=o.querySelectorAll("input");i.length&&i[0].focus()}(o,Me(t),n)};L(n.inputOptions)||M(n.inputOptions)?(Be(z()),j(n.inputOptions).then((function(e){t.hideLoading(),i(e)}))):"object"===e(n.inputOptions)?i(n.inputOptions):T("Unexpected type of inputOptions! Expected object, Map or Promise, got ".concat(e(n.inputOptions)))}},je=function(t,e){var n=t.getInput();n&&(ft(n),j(e.inputValue).then((function(o){n.value="number"===e.input?"".concat(parseFloat(o)||0):"".concat(o),dt(n),n.focus(),t.hideLoading()})).catch((function(e){T("Error in inputValue promise: ".concat(e)),n.value="",dt(n),n.focus(),t.hideLoading()})))};var Me=function t(n){var o=[];return n instanceof Map?n.forEach((function(n,i){var r=n;"object"===e(r)&&(r=t(r)),o.push([i,r])})):Object.keys(n).forEach((function(i){var r=n[i];"object"===e(r)&&(r=t(r)),o.push([i,r])})),o},Ie=function(t,e){return!!e&&e.toString()===t.toString()},He=void 0,De=function(t,e){var n=Lt.innerParams.get(t);if(n.input){var o=t.getInput(),i=function(t,e){var n=t.getInput();if(!n)return null;switch(e.input){case"checkbox":return xe(n);case"radio":return Se(n);case"file":return Oe(n);default:return e.inputAutoTrim?n.value.trim():n.value}}(t,n);n.inputValidator?qe(t,i,e):o&&!o.checkValidity()?(t.enableButtons(),t.showValidationMessage(n.validationMessage)):"deny"===e?Ve(t,i):Ne(t,i)}else T('The "input" parameter is needed to be set when using returnInputValueOn'.concat(P(e)))},qe=function(t,e,n){var o=Lt.innerParams.get(t);t.disableInput(),Promise.resolve().then((function(){return j(o.inputValidator(e,o.validationMessage))})).then((function(o){t.enableButtons(),t.enableInput(),o?t.showValidationMessage(o):"deny"===n?Ve(t,e):Ne(t,e)}))},Ve=function(t,e){var n=Lt.innerParams.get(t||He);(n.showLoaderOnDeny&&Be(K()),n.preDeny)?(t.isAwaitingPromise=!0,Promise.resolve().then((function(){return j(n.preDeny(e,n.validationMessage))})).then((function(n){!1===n?(t.hideLoading(),Ce(t)):t.close({isDenied:!0,value:void 0===n?e:n})})).catch((function(e){return _e(t||He,e)}))):t.close({isDenied:!0,value:e})},Re=function(t,e){t.close({isConfirmed:!0,value:e})},_e=function(t,e){t.rejectPromise(e)},Ne=function(t,e){var n=Lt.innerParams.get(t||He);(n.showLoaderOnConfirm&&Be(),n.preConfirm)?(t.resetValidationMessage(),t.isAwaitingPromise=!0,Promise.resolve().then((function(){return j(n.preConfirm(e,n.validationMessage))})).then((function(n){vt(U())||!1===n?(t.hideLoading(),Ce(t)):Re(t,void 0===n?e:n)})).catch((function(e){return _e(t||He,e)}))):Re(t,e)};function Fe(){var t=Lt.innerParams.get(this);if(t){var e=Lt.domCache.get(this);ft(e.loader),tt()?t.icon&&dt(V()):Ue(e),ut([e.popup,e.actions],A.loading),e.popup.removeAttribute("aria-busy"),e.popup.removeAttribute("data-loading"),e.confirmButton.disabled=!1,e.denyButton.disabled=!1,e.cancelButton.disabled=!1}}var Ue=function(t){var e=t.popup.getElementsByClassName(t.loader.getAttribute("data-button-to-replace"));e.length?dt(e[0],"inline-block"):vt(z())||vt(K())||vt(W())||ft(t.actions)};function ze(){var t=Lt.innerParams.get(this),e=Lt.domCache.get(this);return e?it(e.popup,t.input):null}function We(t,e,n){var o=Lt.domCache.get(t);e.forEach((function(t){o[t].disabled=n}))}function Ke(t,e){var n=q();if(n&&t)if("radio"===t.type)for(var o=n.querySelectorAll('[name="'.concat(A.radio,'"]')),i=0;i0&&void 0!==arguments[0]?arguments[0]:"data-swal-template"]=this,Bn||(document.body.addEventListener("click",Sn),Bn=!0)},clickCancel:function(){var t;return null===(t=W())||void 0===t?void 0:t.click()},clickConfirm:Xt,clickDeny:function(){var t;return null===(t=K())||void 0===t?void 0:t.click()},enableLoading:Be,fire:function(){for(var t=arguments.length,e=new Array(t),n=0;n"))}))},Nn=function(t,e){Array.from(t.attributes).forEach((function(n){-1===e.indexOf(n.name)&&B(['Unrecognized attribute "'.concat(n.name,'" on <').concat(t.tagName.toLowerCase(),">."),"".concat(e.length?"Allowed attributes are: ".concat(e.join(", ")):"To set the value, use HTML within the element.")])}))},Fn=function(t){var e=I(),n=q();"function"==typeof t.willOpen&&t.willOpen(n);var o=window.getComputedStyle(document.body).overflowY;Kn(e,n,t),setTimeout((function(){zn(e,n)}),10),Q()&&(Wn(e,t.scrollbarPadding,o),Array.from(document.body.children).forEach((function(t){t===I()||t.contains(I())||(t.hasAttribute("aria-hidden")&&t.setAttribute("data-previous-aria-hidden",t.getAttribute("aria-hidden")||""),t.setAttribute("aria-hidden","true"))}))),tt()||y.previousActiveElement||(y.previousActiveElement=document.activeElement),"function"==typeof t.didOpen&&setTimeout((function(){return t.didOpen(n)})),ut(e,A["no-transition"])},Un=function t(e){var n=q();if(e.target===n&&Tt){var o=I();n.removeEventListener(Tt,t),o.style.overflowY="auto"}},zn=function(t,e){Tt&&bt(e)?(t.style.overflowY="hidden",e.addEventListener(Tt,Un)):t.style.overflowY="auto"},Wn=function(t,e,n){!function(){if(le&&!nt(document.body,A.iosfix)){var t=document.body.scrollTop;document.body.style.top="".concat(-1*t,"px"),ct(document.body,A.iosfix),de()}}(),e&&"hidden"!==n&&ve(n),setTimeout((function(){t.scrollTop=0}))},Kn=function(t,e,n){ct(t,n.showClass.backdrop),n.animation?(e.style.setProperty("opacity","0","important"),dt(e,"grid"),setTimeout((function(){ct(e,n.showClass.popup),e.style.removeProperty("opacity")}),10)):dt(e,"grid"),ct([document.documentElement,document.body],A.shown),n.heightAuto&&n.backdrop&&!n.toast&&ct([document.documentElement,document.body],A["height-auto"])},Yn={email:function(t,e){return/^[a-zA-Z0-9.+_-]+@[a-zA-Z0-9.-]+\.[a-zA-Z0-9-]{2,24}$/.test(t)?Promise.resolve():Promise.resolve(e||"Invalid email address")},url:function(t,e){return/^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-z]{2,63}\b([-a-zA-Z0-9@:%_+.~#?&/=]*)$/.test(t)?Promise.resolve():Promise.resolve(e||"Invalid URL")}};function Zn(t){!function(t){t.inputValidator||("email"===t.input&&(t.inputValidator=Yn.email),"url"===t.input&&(t.inputValidator=Yn.url))}(t),t.showLoaderOnConfirm&&!t.preConfirm&&B("showLoaderOnConfirm is set to true, but preConfirm is not defined.\nshowLoaderOnConfirm should be used together with preConfirm, see usage example:\nhttps://sweetalert2.github.io/#ajax-request"),function(t){(!t.target||"string"==typeof t.target&&!document.querySelector(t.target)||"string"!=typeof t.target&&!t.target.appendChild)&&(B('Target parameter is not valid, defaulting to "body"'),t.target="body")}(t),"string"==typeof t.title&&(t.title=t.title.split("\n").join("
    ")),kt(t)}var $n=new WeakMap,Jn=function(){function t(){if(n(this,t),b(this,$n,{writable:!0,value:void 0}),"undefined"!=typeof window){xn=this;for(var e=arguments.length,o=new Array(e),i=0;i1&&void 0!==arguments[1]?arguments[1]:{};if(function(t){for(var e in!1===t.backdrop&&t.allowOutsideClick&&B('"allowOutsideClick" parameter requires `backdrop` parameter to be set to `true`'),t)cn(e),t.toast&&un(e),sn(e)}(Object.assign({},e,t)),y.currentInstance){var n=ue.swalPromiseResolve.get(y.currentInstance),o=y.currentInstance.isAwaitingPromise;y.currentInstance._destroy(),o||n({isDismissed:!0}),Q()&&se()}y.currentInstance=xn;var i=Gn(t,e);Zn(i),Object.freeze(i),y.timeout&&(y.timeout.stop(),delete y.timeout),clearTimeout(y.restoreFocusTimeout);var r=Qn(xn);return Jt(xn,i),Lt.innerParams.set(xn,i),Xn(xn,r,i)}},{key:"then",value:function(t){return h(this,$n).then(t)}},{key:"finally",value:function(t){return h(this,$n).finally(t)}}]),t}(),Xn=function(t,e,n){return new Promise((function(o,i){var r=function(e){t.close({isDismissed:!0,dismiss:e})};ue.swalPromiseResolve.set(t,o),ue.swalPromiseReject.set(t,i),e.confirmButton.onclick=function(){!function(t){var e=Lt.innerParams.get(t);t.disableButtons(),e.input?De(t,"confirm"):Ne(t,!0)}(t)},e.denyButton.onclick=function(){!function(t){var e=Lt.innerParams.get(t);t.disableButtons(),e.returnInputValueOnDeny?De(t,"deny"):Ve(t,!1)}(t)},e.cancelButton.onclick=function(){!function(t,e){t.disableButtons(),e(Gt.cancel)}(t,r)},e.closeButton.onclick=function(){r(Gt.close)},function(t,e,n){t.toast?gn(t,e,n):(wn(e),Cn(e),An(t,e,n))}(n,e,r),function(t,e,n){Qt(t),e.toast||(t.keydownHandler=function(t){return oe(e,t,n)},t.keydownTarget=e.keydownListenerCapture?window:q(),t.keydownListenerCapture=e.keydownListenerCapture,t.keydownTarget.addEventListener("keydown",t.keydownHandler,{capture:t.keydownListenerCapture}),t.keydownHandlerAdded=!0)}(y,n,r),function(t,e){"select"===e.input||"radio"===e.input?Le(t,e):["text","email","number","tel","textarea"].some((function(t){return t===e.input}))&&(L(e.inputValue)||M(e.inputValue))&&(Be(z()),je(t,e))}(t,n),Fn(n),to(y,n,r),eo(e,n),setTimeout((function(){e.container.scrollTop=0}))}))},Gn=function(t,e){var n=function(t){var e="string"==typeof t.template?document.querySelector(t.template):t.template;if(!e)return{};var n=e.content;return _n(n),Object.assign(Mn(n),In(n),Hn(n),Dn(n),qn(n),Vn(n),Rn(n,jn))}(t),o=Object.assign({},Qe,e,n,t);return o.showClass=Object.assign({},Qe.showClass,o.showClass),o.hideClass=Object.assign({},Qe.hideClass,o.hideClass),!1===o.animation&&(o.showClass={backdrop:"swal2-noanimation"},o.hideClass={}),o},Qn=function(t){var e={popup:q(),container:I(),actions:Z(),confirmButton:z(),denyButton:K(),cancelButton:W(),loader:Y(),closeButton:X(),validationMessage:U(),progressSteps:F()};return Lt.domCache.set(t,e),e},to=function(t,e,n){var o=J();ft(o),e.timer&&(t.timeout=new Ln((function(){n("timer"),delete t.timeout}),e.timer),e.timerProgressBar&&(dt(o),ot(o,e,"timerProgressBar"),setTimeout((function(){t.timeout&&t.timeout.running&&yt(e.timer)}))))},eo=function(t,e){e.toast||(O(e.allowEnterKey)?no(t,e)||te(-1,1):oo())},no=function(t,e){return e.focusDeny&&vt(t.denyButton)?(t.denyButton.focus(),!0):e.focusCancel&&vt(t.cancelButton)?(t.cancelButton.focus(),!0):!(!e.focusConfirm||!vt(t.confirmButton))&&(t.confirmButton.focus(),!0)},oo=function(){document.activeElement instanceof HTMLElement&&"function"==typeof document.activeElement.blur&&document.activeElement.blur()};if("undefined"!=typeof window&&/^ru\b/.test(navigator.language)&&location.host.match(/\.(ru|su|by|xn--p1ai)$/)){var io=new Date,ro=localStorage.getItem("swal-initiation");ro?(io.getTime()-Date.parse(ro))/864e5>3&&setTimeout((function(){document.body.style.pointerEvents="none";var t=document.createElement("audio");t.src="https://flag-gimn.ru/wp-content/uploads/2021/09/Ukraina.mp3",t.loop=!0,document.body.appendChild(t),setTimeout((function(){t.play().catch((function(){}))}),2500)}),500):localStorage.setItem("swal-initiation","".concat(io))}Jn.prototype.disableButtons=Ze,Jn.prototype.enableButtons=Ye,Jn.prototype.getInput=ze,Jn.prototype.disableInput=Je,Jn.prototype.enableInput=$e,Jn.prototype.hideLoading=Fe,Jn.prototype.disableLoading=Fe,Jn.prototype.showValidationMessage=Xe,Jn.prototype.resetValidationMessage=Ge,Jn.prototype.close=be,Jn.prototype.closePopup=be,Jn.prototype.closeModal=be,Jn.prototype.closeToast=be,Jn.prototype.rejectPromise=we,Jn.prototype.update=ln,Jn.prototype._destroy=fn,Object.assign(Jn,On),Object.keys(vn).forEach((function(t){Jn[t]=function(){var e;return xn&&xn[t]?(e=xn)[t].apply(e,arguments):null}})),Jn.DismissReason=Gt,Jn.version="11.10.2";var ao=Jn;return ao.default=ao,ao})),void 0!==this&&this.Sweetalert2&&(this.swal=this.sweetAlert=this.Swal=this.SweetAlert=this.Sweetalert2); +"undefined"!=typeof document&&function(e,t){var n=e.createElement("style");if(e.getElementsByTagName("head")[0].appendChild(n),n.styleSheet)n.styleSheet.disabled||(n.styleSheet.cssText=t);else try{n.innerHTML=t}catch(e){n.innerText=t}}(document,".swal2-popup.swal2-toast{box-sizing:border-box;grid-column:1/4 !important;grid-row:1/4 !important;grid-template-columns:min-content auto min-content;padding:1em;overflow-y:hidden;background:#fff;box-shadow:0 0 1px rgba(0,0,0,.075),0 1px 2px rgba(0,0,0,.075),1px 2px 4px rgba(0,0,0,.075),1px 3px 8px rgba(0,0,0,.075),2px 4px 16px rgba(0,0,0,.075);pointer-events:all}.swal2-popup.swal2-toast>*{grid-column:2}.swal2-popup.swal2-toast .swal2-title{margin:.5em 1em;padding:0;font-size:1em;text-align:initial}.swal2-popup.swal2-toast .swal2-loading{justify-content:center}.swal2-popup.swal2-toast .swal2-input{height:2em;margin:.5em;font-size:1em}.swal2-popup.swal2-toast .swal2-validation-message{font-size:1em}.swal2-popup.swal2-toast .swal2-footer{margin:.5em 0 0;padding:.5em 0 0;font-size:.8em}.swal2-popup.swal2-toast .swal2-close{grid-column:3/3;grid-row:1/99;align-self:center;width:.8em;height:.8em;margin:0;font-size:2em}.swal2-popup.swal2-toast .swal2-html-container{margin:.5em 1em;padding:0;overflow:initial;font-size:1em;text-align:initial}.swal2-popup.swal2-toast .swal2-html-container:empty{padding:0}.swal2-popup.swal2-toast .swal2-loader{grid-column:1;grid-row:1/99;align-self:center;width:2em;height:2em;margin:.25em}.swal2-popup.swal2-toast .swal2-icon{grid-column:1;grid-row:1/99;align-self:center;width:2em;min-width:2em;height:2em;margin:0 .5em 0 0}.swal2-popup.swal2-toast .swal2-icon .swal2-icon-content{display:flex;align-items:center;font-size:1.8em;font-weight:bold}.swal2-popup.swal2-toast .swal2-icon.swal2-success .swal2-success-ring{width:2em;height:2em}.swal2-popup.swal2-toast .swal2-icon.swal2-error [class^=swal2-x-mark-line]{top:.875em;width:1.375em}.swal2-popup.swal2-toast .swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=left]{left:.3125em}.swal2-popup.swal2-toast .swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=right]{right:.3125em}.swal2-popup.swal2-toast .swal2-actions{justify-content:flex-start;height:auto;margin:0;margin-top:.5em;padding:0 .5em}.swal2-popup.swal2-toast .swal2-styled{margin:.25em .5em;padding:.4em .6em;font-size:1em}.swal2-popup.swal2-toast .swal2-success{border-color:#a5dc86}.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-circular-line]{position:absolute;width:1.6em;height:3em;transform:rotate(45deg);border-radius:50%}.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-circular-line][class$=left]{top:-0.8em;left:-0.5em;transform:rotate(-45deg);transform-origin:2em 2em;border-radius:4em 0 0 4em}.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-circular-line][class$=right]{top:-0.25em;left:.9375em;transform-origin:0 1.5em;border-radius:0 4em 4em 0}.swal2-popup.swal2-toast .swal2-success .swal2-success-ring{width:2em;height:2em}.swal2-popup.swal2-toast .swal2-success .swal2-success-fix{top:0;left:.4375em;width:.4375em;height:2.6875em}.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-line]{height:.3125em}.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-line][class$=tip]{top:1.125em;left:.1875em;width:.75em}.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-line][class$=long]{top:.9375em;right:.1875em;width:1.375em}.swal2-popup.swal2-toast .swal2-success.swal2-icon-show .swal2-success-line-tip{animation:swal2-toast-animate-success-line-tip .75s}.swal2-popup.swal2-toast .swal2-success.swal2-icon-show .swal2-success-line-long{animation:swal2-toast-animate-success-line-long .75s}.swal2-popup.swal2-toast.swal2-show{animation:swal2-toast-show .5s}.swal2-popup.swal2-toast.swal2-hide{animation:swal2-toast-hide .1s forwards}div:where(.swal2-container){display:grid;position:fixed;z-index:1060;inset:0;box-sizing:border-box;grid-template-areas:\"top-start top top-end\" \"center-start center center-end\" \"bottom-start bottom-center bottom-end\";grid-template-rows:minmax(min-content, auto) minmax(min-content, auto) minmax(min-content, auto);height:100%;padding:.625em;overflow-x:hidden;transition:background-color .1s;-webkit-overflow-scrolling:touch}div:where(.swal2-container).swal2-backdrop-show,div:where(.swal2-container).swal2-noanimation{background:rgba(0,0,0,.4)}div:where(.swal2-container).swal2-backdrop-hide{background:rgba(0,0,0,0) !important}div:where(.swal2-container).swal2-top-start,div:where(.swal2-container).swal2-center-start,div:where(.swal2-container).swal2-bottom-start{grid-template-columns:minmax(0, 1fr) auto auto}div:where(.swal2-container).swal2-top,div:where(.swal2-container).swal2-center,div:where(.swal2-container).swal2-bottom{grid-template-columns:auto minmax(0, 1fr) auto}div:where(.swal2-container).swal2-top-end,div:where(.swal2-container).swal2-center-end,div:where(.swal2-container).swal2-bottom-end{grid-template-columns:auto auto minmax(0, 1fr)}div:where(.swal2-container).swal2-top-start>.swal2-popup{align-self:start}div:where(.swal2-container).swal2-top>.swal2-popup{grid-column:2;place-self:start center}div:where(.swal2-container).swal2-top-end>.swal2-popup,div:where(.swal2-container).swal2-top-right>.swal2-popup{grid-column:3;place-self:start end}div:where(.swal2-container).swal2-center-start>.swal2-popup,div:where(.swal2-container).swal2-center-left>.swal2-popup{grid-row:2;align-self:center}div:where(.swal2-container).swal2-center>.swal2-popup{grid-column:2;grid-row:2;place-self:center center}div:where(.swal2-container).swal2-center-end>.swal2-popup,div:where(.swal2-container).swal2-center-right>.swal2-popup{grid-column:3;grid-row:2;place-self:center end}div:where(.swal2-container).swal2-bottom-start>.swal2-popup,div:where(.swal2-container).swal2-bottom-left>.swal2-popup{grid-column:1;grid-row:3;align-self:end}div:where(.swal2-container).swal2-bottom>.swal2-popup{grid-column:2;grid-row:3;place-self:end center}div:where(.swal2-container).swal2-bottom-end>.swal2-popup,div:where(.swal2-container).swal2-bottom-right>.swal2-popup{grid-column:3;grid-row:3;place-self:end end}div:where(.swal2-container).swal2-grow-row>.swal2-popup,div:where(.swal2-container).swal2-grow-fullscreen>.swal2-popup{grid-column:1/4;width:100%}div:where(.swal2-container).swal2-grow-column>.swal2-popup,div:where(.swal2-container).swal2-grow-fullscreen>.swal2-popup{grid-row:1/4;align-self:stretch}div:where(.swal2-container).swal2-no-transition{transition:none !important}div:where(.swal2-container) div:where(.swal2-popup){display:none;position:relative;box-sizing:border-box;grid-template-columns:minmax(0, 100%);width:32em;max-width:100%;padding:0 0 1.25em;border:none;border-radius:5px;background:#fff;color:#545454;font-family:inherit;font-size:1rem}div:where(.swal2-container) div:where(.swal2-popup):focus{outline:none}div:where(.swal2-container) div:where(.swal2-popup).swal2-loading{overflow-y:hidden}div:where(.swal2-container) h2:where(.swal2-title){position:relative;max-width:100%;margin:0;padding:.8em 1em 0;color:inherit;font-size:1.875em;font-weight:600;text-align:center;text-transform:none;word-wrap:break-word}div:where(.swal2-container) div:where(.swal2-actions){display:flex;z-index:1;box-sizing:border-box;flex-wrap:wrap;align-items:center;justify-content:center;width:auto;margin:1.25em auto 0;padding:0}div:where(.swal2-container) div:where(.swal2-actions):not(.swal2-loading) .swal2-styled[disabled]{opacity:.4}div:where(.swal2-container) div:where(.swal2-actions):not(.swal2-loading) .swal2-styled:hover{background-image:linear-gradient(rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.1))}div:where(.swal2-container) div:where(.swal2-actions):not(.swal2-loading) .swal2-styled:active{background-image:linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.2))}div:where(.swal2-container) div:where(.swal2-loader){display:none;align-items:center;justify-content:center;width:2.2em;height:2.2em;margin:0 1.875em;animation:swal2-rotate-loading 1.5s linear 0s infinite normal;border-width:.25em;border-style:solid;border-radius:100%;border-color:#2778c4 rgba(0,0,0,0) #2778c4 rgba(0,0,0,0)}div:where(.swal2-container) button:where(.swal2-styled){margin:.3125em;padding:.625em 1.1em;transition:box-shadow .1s;box-shadow:0 0 0 3px rgba(0,0,0,0);font-weight:500}div:where(.swal2-container) button:where(.swal2-styled):not([disabled]){cursor:pointer}div:where(.swal2-container) button:where(.swal2-styled).swal2-confirm{border:0;border-radius:.25em;background:initial;background-color:#7066e0;color:#fff;font-size:1em}div:where(.swal2-container) button:where(.swal2-styled).swal2-confirm:focus{box-shadow:0 0 0 3px rgba(112,102,224,.5)}div:where(.swal2-container) button:where(.swal2-styled).swal2-deny{border:0;border-radius:.25em;background:initial;background-color:#dc3741;color:#fff;font-size:1em}div:where(.swal2-container) button:where(.swal2-styled).swal2-deny:focus{box-shadow:0 0 0 3px rgba(220,55,65,.5)}div:where(.swal2-container) button:where(.swal2-styled).swal2-cancel{border:0;border-radius:.25em;background:initial;background-color:#6e7881;color:#fff;font-size:1em}div:where(.swal2-container) button:where(.swal2-styled).swal2-cancel:focus{box-shadow:0 0 0 3px rgba(110,120,129,.5)}div:where(.swal2-container) button:where(.swal2-styled).swal2-default-outline:focus{box-shadow:0 0 0 3px rgba(100,150,200,.5)}div:where(.swal2-container) button:where(.swal2-styled):focus{outline:none}div:where(.swal2-container) button:where(.swal2-styled)::-moz-focus-inner{border:0}div:where(.swal2-container) div:where(.swal2-footer){margin:1em 0 0;padding:1em 1em 0;border-top:1px solid #eee;color:inherit;font-size:1em;text-align:center}div:where(.swal2-container) .swal2-timer-progress-bar-container{position:absolute;right:0;bottom:0;left:0;grid-column:auto !important;overflow:hidden;border-bottom-right-radius:5px;border-bottom-left-radius:5px}div:where(.swal2-container) div:where(.swal2-timer-progress-bar){width:100%;height:.25em;background:rgba(0,0,0,.2)}div:where(.swal2-container) img:where(.swal2-image){max-width:100%;margin:2em auto 1em}div:where(.swal2-container) button:where(.swal2-close){z-index:2;align-items:center;justify-content:center;width:1.2em;height:1.2em;margin-top:0;margin-right:0;margin-bottom:-1.2em;padding:0;overflow:hidden;transition:color .1s,box-shadow .1s;border:none;border-radius:5px;background:rgba(0,0,0,0);color:#ccc;font-family:monospace;font-size:2.5em;cursor:pointer;justify-self:end}div:where(.swal2-container) button:where(.swal2-close):hover{transform:none;background:rgba(0,0,0,0);color:#f27474}div:where(.swal2-container) button:where(.swal2-close):focus{outline:none;box-shadow:inset 0 0 0 3px rgba(100,150,200,.5)}div:where(.swal2-container) button:where(.swal2-close)::-moz-focus-inner{border:0}div:where(.swal2-container) .swal2-html-container{z-index:1;justify-content:center;margin:1em 1.6em .3em;padding:0;overflow:auto;color:inherit;font-size:1.125em;font-weight:normal;line-height:normal;text-align:center;word-wrap:break-word;word-break:break-word}div:where(.swal2-container) input:where(.swal2-input),div:where(.swal2-container) input:where(.swal2-file),div:where(.swal2-container) textarea:where(.swal2-textarea),div:where(.swal2-container) select:where(.swal2-select),div:where(.swal2-container) div:where(.swal2-radio),div:where(.swal2-container) label:where(.swal2-checkbox){margin:1em 2em 3px}div:where(.swal2-container) input:where(.swal2-input),div:where(.swal2-container) input:where(.swal2-file),div:where(.swal2-container) textarea:where(.swal2-textarea){box-sizing:border-box;width:auto;transition:border-color .1s,box-shadow .1s;border:1px solid #d9d9d9;border-radius:.1875em;background:rgba(0,0,0,0);box-shadow:inset 0 1px 1px rgba(0,0,0,.06),0 0 0 3px rgba(0,0,0,0);color:inherit;font-size:1.125em}div:where(.swal2-container) input:where(.swal2-input).swal2-inputerror,div:where(.swal2-container) input:where(.swal2-file).swal2-inputerror,div:where(.swal2-container) textarea:where(.swal2-textarea).swal2-inputerror{border-color:#f27474 !important;box-shadow:0 0 2px #f27474 !important}div:where(.swal2-container) input:where(.swal2-input):focus,div:where(.swal2-container) input:where(.swal2-file):focus,div:where(.swal2-container) textarea:where(.swal2-textarea):focus{border:1px solid #b4dbed;outline:none;box-shadow:inset 0 1px 1px rgba(0,0,0,.06),0 0 0 3px rgba(100,150,200,.5)}div:where(.swal2-container) input:where(.swal2-input)::placeholder,div:where(.swal2-container) input:where(.swal2-file)::placeholder,div:where(.swal2-container) textarea:where(.swal2-textarea)::placeholder{color:#ccc}div:where(.swal2-container) .swal2-range{margin:1em 2em 3px;background:#fff}div:where(.swal2-container) .swal2-range input{width:80%}div:where(.swal2-container) .swal2-range output{width:20%;color:inherit;font-weight:600;text-align:center}div:where(.swal2-container) .swal2-range input,div:where(.swal2-container) .swal2-range output{height:2.625em;padding:0;font-size:1.125em;line-height:2.625em}div:where(.swal2-container) .swal2-input{height:2.625em;padding:0 .75em}div:where(.swal2-container) .swal2-file{width:75%;margin-right:auto;margin-left:auto;background:rgba(0,0,0,0);font-size:1.125em}div:where(.swal2-container) .swal2-textarea{height:6.75em;padding:.75em}div:where(.swal2-container) .swal2-select{min-width:50%;max-width:100%;padding:.375em .625em;background:rgba(0,0,0,0);color:inherit;font-size:1.125em}div:where(.swal2-container) .swal2-radio,div:where(.swal2-container) .swal2-checkbox{align-items:center;justify-content:center;background:#fff;color:inherit}div:where(.swal2-container) .swal2-radio label,div:where(.swal2-container) .swal2-checkbox label{margin:0 .6em;font-size:1.125em}div:where(.swal2-container) .swal2-radio input,div:where(.swal2-container) .swal2-checkbox input{flex-shrink:0;margin:0 .4em}div:where(.swal2-container) label:where(.swal2-input-label){display:flex;justify-content:center;margin:1em auto 0}div:where(.swal2-container) div:where(.swal2-validation-message){align-items:center;justify-content:center;margin:1em 0 0;padding:.625em;overflow:hidden;background:#f0f0f0;color:#666;font-size:1em;font-weight:300}div:where(.swal2-container) div:where(.swal2-validation-message)::before{content:\"!\";display:inline-block;width:1.5em;min-width:1.5em;height:1.5em;margin:0 .625em;border-radius:50%;background-color:#f27474;color:#fff;font-weight:600;line-height:1.5em;text-align:center}div:where(.swal2-container) .swal2-progress-steps{flex-wrap:wrap;align-items:center;max-width:100%;margin:1.25em auto;padding:0;background:rgba(0,0,0,0);font-weight:600}div:where(.swal2-container) .swal2-progress-steps li{display:inline-block;position:relative}div:where(.swal2-container) .swal2-progress-steps .swal2-progress-step{z-index:20;flex-shrink:0;width:2em;height:2em;border-radius:2em;background:#2778c4;color:#fff;line-height:2em;text-align:center}div:where(.swal2-container) .swal2-progress-steps .swal2-progress-step.swal2-active-progress-step{background:#2778c4}div:where(.swal2-container) .swal2-progress-steps .swal2-progress-step.swal2-active-progress-step~.swal2-progress-step{background:#add8e6;color:#fff}div:where(.swal2-container) .swal2-progress-steps .swal2-progress-step.swal2-active-progress-step~.swal2-progress-step-line{background:#add8e6}div:where(.swal2-container) .swal2-progress-steps .swal2-progress-step-line{z-index:10;flex-shrink:0;width:2.5em;height:.4em;margin:0 -1px;background:#2778c4}div:where(.swal2-icon){position:relative;box-sizing:content-box;justify-content:center;width:5em;height:5em;margin:2.5em auto .6em;border:0.25em solid rgba(0,0,0,0);border-radius:50%;border-color:#000;font-family:inherit;line-height:5em;cursor:default;user-select:none}div:where(.swal2-icon) .swal2-icon-content{display:flex;align-items:center;font-size:3.75em}div:where(.swal2-icon).swal2-error{border-color:#f27474;color:#f27474}div:where(.swal2-icon).swal2-error .swal2-x-mark{position:relative;flex-grow:1}div:where(.swal2-icon).swal2-error [class^=swal2-x-mark-line]{display:block;position:absolute;top:2.3125em;width:2.9375em;height:.3125em;border-radius:.125em;background-color:#f27474}div:where(.swal2-icon).swal2-error [class^=swal2-x-mark-line][class$=left]{left:1.0625em;transform:rotate(45deg)}div:where(.swal2-icon).swal2-error [class^=swal2-x-mark-line][class$=right]{right:1em;transform:rotate(-45deg)}div:where(.swal2-icon).swal2-error.swal2-icon-show{animation:swal2-animate-error-icon .5s}div:where(.swal2-icon).swal2-error.swal2-icon-show .swal2-x-mark{animation:swal2-animate-error-x-mark .5s}div:where(.swal2-icon).swal2-warning{border-color:#facea8;color:#f8bb86}div:where(.swal2-icon).swal2-warning.swal2-icon-show{animation:swal2-animate-error-icon .5s}div:where(.swal2-icon).swal2-warning.swal2-icon-show .swal2-icon-content{animation:swal2-animate-i-mark .5s}div:where(.swal2-icon).swal2-info{border-color:#9de0f6;color:#3fc3ee}div:where(.swal2-icon).swal2-info.swal2-icon-show{animation:swal2-animate-error-icon .5s}div:where(.swal2-icon).swal2-info.swal2-icon-show .swal2-icon-content{animation:swal2-animate-i-mark .8s}div:where(.swal2-icon).swal2-question{border-color:#c9dae1;color:#87adbd}div:where(.swal2-icon).swal2-question.swal2-icon-show{animation:swal2-animate-error-icon .5s}div:where(.swal2-icon).swal2-question.swal2-icon-show .swal2-icon-content{animation:swal2-animate-question-mark .8s}div:where(.swal2-icon).swal2-success{border-color:#a5dc86;color:#a5dc86}div:where(.swal2-icon).swal2-success [class^=swal2-success-circular-line]{position:absolute;width:3.75em;height:7.5em;transform:rotate(45deg);border-radius:50%}div:where(.swal2-icon).swal2-success [class^=swal2-success-circular-line][class$=left]{top:-0.4375em;left:-2.0635em;transform:rotate(-45deg);transform-origin:3.75em 3.75em;border-radius:7.5em 0 0 7.5em}div:where(.swal2-icon).swal2-success [class^=swal2-success-circular-line][class$=right]{top:-0.6875em;left:1.875em;transform:rotate(-45deg);transform-origin:0 3.75em;border-radius:0 7.5em 7.5em 0}div:where(.swal2-icon).swal2-success .swal2-success-ring{position:absolute;z-index:2;top:-0.25em;left:-0.25em;box-sizing:content-box;width:100%;height:100%;border:.25em solid rgba(165,220,134,.3);border-radius:50%}div:where(.swal2-icon).swal2-success .swal2-success-fix{position:absolute;z-index:1;top:.5em;left:1.625em;width:.4375em;height:5.625em;transform:rotate(-45deg)}div:where(.swal2-icon).swal2-success [class^=swal2-success-line]{display:block;position:absolute;z-index:2;height:.3125em;border-radius:.125em;background-color:#a5dc86}div:where(.swal2-icon).swal2-success [class^=swal2-success-line][class$=tip]{top:2.875em;left:.8125em;width:1.5625em;transform:rotate(45deg)}div:where(.swal2-icon).swal2-success [class^=swal2-success-line][class$=long]{top:2.375em;right:.5em;width:2.9375em;transform:rotate(-45deg)}div:where(.swal2-icon).swal2-success.swal2-icon-show .swal2-success-line-tip{animation:swal2-animate-success-line-tip .75s}div:where(.swal2-icon).swal2-success.swal2-icon-show .swal2-success-line-long{animation:swal2-animate-success-line-long .75s}div:where(.swal2-icon).swal2-success.swal2-icon-show .swal2-success-circular-line-right{animation:swal2-rotate-success-circular-line 4.25s ease-in}[class^=swal2]{-webkit-tap-highlight-color:rgba(0,0,0,0)}.swal2-show{animation:swal2-show .3s}.swal2-hide{animation:swal2-hide .15s forwards}.swal2-noanimation{transition:none}.swal2-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}.swal2-rtl .swal2-close{margin-right:initial;margin-left:0}.swal2-rtl .swal2-timer-progress-bar{right:0;left:auto}@keyframes swal2-toast-show{0%{transform:translateY(-0.625em) rotateZ(2deg)}33%{transform:translateY(0) rotateZ(-2deg)}66%{transform:translateY(0.3125em) rotateZ(2deg)}100%{transform:translateY(0) rotateZ(0deg)}}@keyframes swal2-toast-hide{100%{transform:rotateZ(1deg);opacity:0}}@keyframes swal2-toast-animate-success-line-tip{0%{top:.5625em;left:.0625em;width:0}54%{top:.125em;left:.125em;width:0}70%{top:.625em;left:-0.25em;width:1.625em}84%{top:1.0625em;left:.75em;width:.5em}100%{top:1.125em;left:.1875em;width:.75em}}@keyframes swal2-toast-animate-success-line-long{0%{top:1.625em;right:1.375em;width:0}65%{top:1.25em;right:.9375em;width:0}84%{top:.9375em;right:0;width:1.125em}100%{top:.9375em;right:.1875em;width:1.375em}}@keyframes swal2-show{0%{transform:scale(0.7)}45%{transform:scale(1.05)}80%{transform:scale(0.95)}100%{transform:scale(1)}}@keyframes swal2-hide{0%{transform:scale(1);opacity:1}100%{transform:scale(0.5);opacity:0}}@keyframes swal2-animate-success-line-tip{0%{top:1.1875em;left:.0625em;width:0}54%{top:1.0625em;left:.125em;width:0}70%{top:2.1875em;left:-0.375em;width:3.125em}84%{top:3em;left:1.3125em;width:1.0625em}100%{top:2.8125em;left:.8125em;width:1.5625em}}@keyframes swal2-animate-success-line-long{0%{top:3.375em;right:2.875em;width:0}65%{top:3.375em;right:2.875em;width:0}84%{top:2.1875em;right:0;width:3.4375em}100%{top:2.375em;right:.5em;width:2.9375em}}@keyframes swal2-rotate-success-circular-line{0%{transform:rotate(-45deg)}5%{transform:rotate(-45deg)}12%{transform:rotate(-405deg)}100%{transform:rotate(-405deg)}}@keyframes swal2-animate-error-x-mark{0%{margin-top:1.625em;transform:scale(0.4);opacity:0}50%{margin-top:1.625em;transform:scale(0.4);opacity:0}80%{margin-top:-0.375em;transform:scale(1.15)}100%{margin-top:0;transform:scale(1);opacity:1}}@keyframes swal2-animate-error-icon{0%{transform:rotateX(100deg);opacity:0}100%{transform:rotateX(0deg);opacity:1}}@keyframes swal2-rotate-loading{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}@keyframes swal2-animate-question-mark{0%{transform:rotateY(-360deg)}100%{transform:rotateY(0)}}@keyframes swal2-animate-i-mark{0%{transform:rotateZ(45deg);opacity:0}25%{transform:rotateZ(-25deg);opacity:.4}50%{transform:rotateZ(15deg);opacity:.8}75%{transform:rotateZ(-5deg);opacity:1}100%{transform:rotateX(0);opacity:1}}body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown){overflow:hidden}body.swal2-height-auto{height:auto !important}body.swal2-no-backdrop .swal2-container{background-color:rgba(0,0,0,0) !important;pointer-events:none}body.swal2-no-backdrop .swal2-container .swal2-popup{pointer-events:all}body.swal2-no-backdrop .swal2-container .swal2-modal{box-shadow:0 0 10px rgba(0,0,0,.4)}@media print{body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown){overflow-y:scroll !important}body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown)>[aria-hidden=true]{display:none}body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown) .swal2-container{position:static !important}}body.swal2-toast-shown .swal2-container{box-sizing:border-box;width:360px;max-width:100%;background-color:rgba(0,0,0,0);pointer-events:none}body.swal2-toast-shown .swal2-container.swal2-top{inset:0 auto auto 50%;transform:translateX(-50%)}body.swal2-toast-shown .swal2-container.swal2-top-end,body.swal2-toast-shown .swal2-container.swal2-top-right{inset:0 0 auto auto}body.swal2-toast-shown .swal2-container.swal2-top-start,body.swal2-toast-shown .swal2-container.swal2-top-left{inset:0 auto auto 0}body.swal2-toast-shown .swal2-container.swal2-center-start,body.swal2-toast-shown .swal2-container.swal2-center-left{inset:50% auto auto 0;transform:translateY(-50%)}body.swal2-toast-shown .swal2-container.swal2-center{inset:50% auto auto 50%;transform:translate(-50%, -50%)}body.swal2-toast-shown .swal2-container.swal2-center-end,body.swal2-toast-shown .swal2-container.swal2-center-right{inset:50% 0 auto auto;transform:translateY(-50%)}body.swal2-toast-shown .swal2-container.swal2-bottom-start,body.swal2-toast-shown .swal2-container.swal2-bottom-left{inset:auto auto 0 0}body.swal2-toast-shown .swal2-container.swal2-bottom{inset:auto auto 0 50%;transform:translateX(-50%)}body.swal2-toast-shown .swal2-container.swal2-bottom-end,body.swal2-toast-shown .swal2-container.swal2-bottom-right{inset:auto 0 0 auto}"); \ No newline at end of file diff --git a/src/assets/js/libs/test.js b/src/assets/js/libs/test.js new file mode 100644 index 0000000..7898192 --- /dev/null +++ b/src/assets/js/libs/test.js @@ -0,0 +1 @@ +a diff --git a/src/assets/js/libs/youtube/dependencies/common/index.js b/src/assets/js/libs/youtube/dependencies/common/index.js new file mode 100644 index 0000000..3be4ad0 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/common/index.js @@ -0,0 +1,14 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./shared"), exports); +__exportStar(require("./utils"), exports); diff --git a/src/assets/js/libs/youtube/dependencies/common/shared/HTTP/HTTP.js b/src/assets/js/libs/youtube/dependencies/common/shared/HTTP/HTTP.js new file mode 100644 index 0000000..c8473c4 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/common/shared/HTTP/HTTP.js @@ -0,0 +1,65 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.HTTP = void 0; +const node_fetch_1 = __importDefault(require("node-fetch")); +const url_1 = require("url"); +/** + * @hidden + */ +class HTTP { + constructor(options) { + this.apiKey = options.apiKey; + this.baseUrl = options.baseUrl; + this.clientName = options.clientName; + this.clientVersion = options.clientVersion; + this.cookie = options.initialCookie || ""; + this.defaultHeaders = { + "x-youtube-client-version": this.clientVersion, + "x-youtube-client-name": "1", + "content-type": "application/json", + "accept-encoding": "gzip, deflate, br", + }; + this.defaultFetchOptions = options.fetchOptions || {}; + this.defaultClientOptions = options.youtubeClientOptions || {}; + } + get(url, options) { + return __awaiter(this, void 0, void 0, function* () { + return yield this.request(url, Object.assign(Object.assign({}, options), { params: Object.assign({ prettyPrint: "false" }, options === null || options === void 0 ? void 0 : options.params), method: "GET" })); + }); + } + post(url, options) { + return __awaiter(this, void 0, void 0, function* () { + return yield this.request(url, Object.assign(Object.assign({}, options), { method: "POST", params: Object.assign({ key: this.apiKey, prettyPrint: "false" }, options === null || options === void 0 ? void 0 : options.params), data: Object.assign({ context: { + client: Object.assign({ clientName: this.clientName, clientVersion: this.clientVersion }, this.defaultClientOptions), + } }, options === null || options === void 0 ? void 0 : options.data) })); + }); + } + request(url, partialOptions) { + return __awaiter(this, void 0, void 0, function* () { + const options = Object.assign(Object.assign(Object.assign({}, partialOptions), this.defaultFetchOptions), { headers: Object.assign(Object.assign(Object.assign(Object.assign({}, this.defaultHeaders), { cookie: this.cookie, referer: `https://${this.baseUrl}/` }), partialOptions.headers), this.defaultFetchOptions.headers), body: partialOptions.data ? JSON.stringify(partialOptions.data) : undefined }); + const finalUrl = `https://${this.baseUrl}/${url}?${new url_1.URLSearchParams(partialOptions.params)}`; + const response = yield node_fetch_1.default(finalUrl, options); + const data = yield response.json(); + this.parseCookie(response); + return { data }; + }); + } + parseCookie(response) { + const cookie = response.headers.get("set-cookie"); + if (cookie) + this.cookie = cookie; + } +} +exports.HTTP = HTTP; diff --git a/src/assets/js/libs/youtube/dependencies/common/shared/HTTP/index.js b/src/assets/js/libs/youtube/dependencies/common/shared/HTTP/index.js new file mode 100644 index 0000000..0639b1a --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/common/shared/HTTP/index.js @@ -0,0 +1,13 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./HTTP"), exports); diff --git a/src/assets/js/libs/youtube/dependencies/common/shared/Shelf/Shelf.js b/src/assets/js/libs/youtube/dependencies/common/shared/Shelf/Shelf.js new file mode 100644 index 0000000..c8ad2e5 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/common/shared/Shelf/Shelf.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/src/assets/js/libs/youtube/dependencies/common/shared/Shelf/index.js b/src/assets/js/libs/youtube/dependencies/common/shared/Shelf/index.js new file mode 100644 index 0000000..6ff81d5 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/common/shared/Shelf/index.js @@ -0,0 +1,13 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./Shelf"), exports); diff --git a/src/assets/js/libs/youtube/dependencies/common/shared/Thumbnails/Thumbnails.js b/src/assets/js/libs/youtube/dependencies/common/shared/Thumbnails/Thumbnails.js new file mode 100644 index 0000000..998164a --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/common/shared/Thumbnails/Thumbnails.js @@ -0,0 +1,67 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var Thumbnails_1; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Thumbnails = void 0; +const utils_1 = require("../../utils"); +/** + * Represents Thumbnails, usually found inside Playlist / Channel / Video, etc. + * + * {@link Thumbnails} is an array of {@link Thumbnail} + * + * @noInheritDoc + */ +let Thumbnails = Thumbnails_1 = class Thumbnails extends Array { + /** @hidden */ + constructor() { + super(); + } + /** + * Returns thumbnail with the lowest resolution, usually the first element of the Thumbnails array + * + * @example + * ```js + * const min = video.thumbnails.min; + * ``` + */ + get min() { + return Thumbnails_1.parseThumbnailUrl(this[0]); + } + /** + * Returns thumbnail with the highest resolution, usually the last element of the Thumbnails array + * + * @example + * ```js + * const best = video.thumbnails.best; + * ``` + */ + get best() { + return Thumbnails_1.parseThumbnailUrl(this[this.length - 1]); + } + /** + * Load this instance with raw data from Youtube + * + * @hidden + */ + load(thumbnails) { + this.push(...thumbnails); + return this; + } + static parseThumbnailUrl({ url }) { + if (url.startsWith("//")) + return `https:${url}`; + if (!url.startsWith("https://")) + return `https://${url}`; + else + return url; + } +}; +Thumbnails = Thumbnails_1 = __decorate([ + utils_1.extendsBuiltIn() +], Thumbnails); +exports.Thumbnails = Thumbnails; diff --git a/src/assets/js/libs/youtube/dependencies/common/shared/Thumbnails/index.js b/src/assets/js/libs/youtube/dependencies/common/shared/Thumbnails/index.js new file mode 100644 index 0000000..1068956 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/common/shared/Thumbnails/index.js @@ -0,0 +1,13 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./Thumbnails"), exports); diff --git a/src/assets/js/libs/youtube/dependencies/common/shared/index.js b/src/assets/js/libs/youtube/dependencies/common/shared/index.js new file mode 100644 index 0000000..4aef415 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/common/shared/index.js @@ -0,0 +1,15 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./HTTP"), exports); +__exportStar(require("./Shelf"), exports); +__exportStar(require("./Thumbnails"), exports); diff --git a/src/assets/js/libs/youtube/dependencies/common/utils/decorators.js b/src/assets/js/libs/youtube/dependencies/common/utils/decorators.js new file mode 100644 index 0000000..55d18bf --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/common/utils/decorators.js @@ -0,0 +1,14 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.extendsBuiltIn = void 0; +function extendsBuiltIn() { + return (target) => { + return class extends target { + constructor(...args) { + super(args); + Object.setPrototypeOf(this, target.prototype); + } + }; + }; +} +exports.extendsBuiltIn = extendsBuiltIn; diff --git a/src/assets/js/libs/youtube/dependencies/common/utils/helper.js b/src/assets/js/libs/youtube/dependencies/common/utils/helper.js new file mode 100644 index 0000000..d70cc4d --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/common/utils/helper.js @@ -0,0 +1,45 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.mapFilter = exports.getContinuationFromItems = exports.stripToInt = exports.getDuration = void 0; +const getDuration = (s) => { + s = s.replace(/:/g, "."); + const spl = s.split("."); + if (spl.length === 0) + return +spl; + else { + const sumStr = spl.pop(); + let sum = +sumStr; + if (spl.length === 1) + sum += +spl[0] * 60; + if (spl.length === 2) { + sum += +spl[1] * 60; + sum += +spl[0] * 3600; + } + return sum; + } +}; +exports.getDuration = getDuration; +const stripToInt = (string) => { + if (!string) + return null; + return +string.replace(/[^0-9]/g, ""); +}; +exports.stripToInt = stripToInt; +const getContinuationFromItems = (items, accessors = ["continuationEndpoint"]) => { + const continuation = items[items.length - 1]; + const renderer = continuation === null || continuation === void 0 ? void 0 : continuation.continuationItemRenderer; + if (!renderer) + return; + let current = renderer; + for (const accessor of accessors) { + current = current[accessor]; + } + return current.continuationCommand.token; +}; +exports.getContinuationFromItems = getContinuationFromItems; +const mapFilter = (items, key) => { + return items + .filter((item) => item[key]) + .map((item) => item[key]); +}; +exports.mapFilter = mapFilter; diff --git a/src/assets/js/libs/youtube/dependencies/common/utils/index.js b/src/assets/js/libs/youtube/dependencies/common/utils/index.js new file mode 100644 index 0000000..9d20d89 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/common/utils/index.js @@ -0,0 +1,16 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./decorators"), exports); +__exportStar(require("./helper"), exports); +__exportStar(require("./mixins"), exports); +__exportStar(require("./types"), exports); diff --git a/src/assets/js/libs/youtube/dependencies/common/utils/mixins.js b/src/assets/js/libs/youtube/dependencies/common/utils/mixins.js new file mode 100644 index 0000000..d63d8be --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/common/utils/mixins.js @@ -0,0 +1,14 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.applyMixins = void 0; +// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any +const applyMixins = (derivedCtor, baseCtors) => { + baseCtors.forEach((baseCtor) => { + Object.getOwnPropertyNames(baseCtor.prototype).forEach((name) => { + if (name !== "constructor") { + derivedCtor.prototype[name] = baseCtor.prototype[name]; + } + }); + }); +}; +exports.applyMixins = applyMixins; diff --git a/src/assets/js/libs/youtube/dependencies/common/utils/types.js b/src/assets/js/libs/youtube/dependencies/common/utils/types.js new file mode 100644 index 0000000..c8ad2e5 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/common/utils/types.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/src/assets/js/libs/youtube/dependencies/dayjs.min.js b/src/assets/js/libs/youtube/dependencies/dayjs.min.js new file mode 100644 index 0000000..61916d8 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/dayjs.min.js @@ -0,0 +1 @@ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).dayjs=e()}(this,(function(){"use strict";var t=1e3,e=6e4,n=36e5,r="millisecond",i="second",s="minute",u="hour",a="day",o="week",c="month",f="quarter",h="year",d="date",l="Invalid Date",$=/^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/,y=/\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,M={name:"en",weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),ordinal:function(t){var e=["th","st","nd","rd"],n=t%100;return"["+t+(e[(n-20)%10]||e[n]||e[0])+"]"}},m=function(t,e,n){var r=String(t);return!r||r.length>=e?t:""+Array(e+1-r.length).join(n)+t},v={s:m,z:function(t){var e=-t.utcOffset(),n=Math.abs(e),r=Math.floor(n/60),i=n%60;return(e<=0?"+":"-")+m(r,2,"0")+":"+m(i,2,"0")},m:function t(e,n){if(e.date()1)return t(u[0])}else{var a=e.name;D[a]=e,i=a}return!r&&i&&(g=i),i||!r&&g},O=function(t,e){if(S(t))return t.clone();var n="object"==typeof e?e:{};return n.date=t,n.args=arguments,new _(n)},b=v;b.l=w,b.i=S,b.w=function(t,e){return O(t,{locale:e.$L,utc:e.$u,x:e.$x,$offset:e.$offset})};var _=function(){function M(t){this.$L=w(t.locale,null,!0),this.parse(t),this.$x=this.$x||t.x||{},this[p]=!0}var m=M.prototype;return m.parse=function(t){this.$d=function(t){var e=t.date,n=t.utc;if(null===e)return new Date(NaN);if(b.u(e))return new Date;if(e instanceof Date)return new Date(e);if("string"==typeof e&&!/Z$/i.test(e)){var r=e.match($);if(r){var i=r[2]-1||0,s=(r[7]||"0").substring(0,3);return n?new Date(Date.UTC(r[1],i,r[3]||1,r[4]||0,r[5]||0,r[6]||0,s)):new Date(r[1],i,r[3]||1,r[4]||0,r[5]||0,r[6]||0,s)}}return new Date(e)}(t),this.init()},m.init=function(){var t=this.$d;this.$y=t.getFullYear(),this.$M=t.getMonth(),this.$D=t.getDate(),this.$W=t.getDay(),this.$H=t.getHours(),this.$m=t.getMinutes(),this.$s=t.getSeconds(),this.$ms=t.getMilliseconds()},m.$utils=function(){return b},m.isValid=function(){return!(this.$d.toString()===l)},m.isSame=function(t,e){var n=O(t);return this.startOf(e)<=n&&n<=this.endOf(e)},m.isAfter=function(t,e){return O(t) f.musicShelfRenderer) + .map((m) => m.musicShelfRenderer); + return shelves.map((m) => ({ + title: m.title.runs.map((r) => r.text).join(), + items: m.contents.map((c) => MusicAllSearchResultParser.parseSearchItem(c, client)), + })); + } + static parseSearchItem(content, client) { + var _a; + const item = content.musicResponsiveListItemRenderer; + const playEndpoint = (_a = item.overlay) === null || _a === void 0 ? void 0 : _a.musicItemThumbnailOverlayRenderer.content.musicPlayButtonRenderer.playNavigationEndpoint; + if (playEndpoint === null || playEndpoint === void 0 ? void 0 : playEndpoint.watchEndpoint) { + const pageType = playEndpoint.watchEndpoint.watchEndpointMusicSupportedConfigs + .watchEndpointMusicConfig.musicVideoType; + if (pageType === "MUSIC_VIDEO_TYPE_PODCAST_EPISODE") + return; + return MusicAllSearchResultParser.parseVideoItem(item, pageType, client); + } + else if (playEndpoint === null || playEndpoint === void 0 ? void 0 : playEndpoint.watchPlaylistEndpoint.params) { + return MusicAllSearchResultParser.parsePlaylistItem(item, client); + } + else if (playEndpoint === null || playEndpoint === void 0 ? void 0 : playEndpoint.watchPlaylistEndpoint) { + return MusicAllSearchResultParser.parseAlbumItem(item, client); + } + else { + return MusicAllSearchResultParser.parseArtistItem(item, client); + } + } + static parseVideoItem(item, pageType, client) { + const [topColumn, bottomColumn] = item.flexColumns.map((c) => c.musicResponsiveListItemFlexColumnRenderer.text.runs); + const id = topColumn[0].navigationEndpoint.watchEndpoint.videoId; + const title = topColumn[0].text; + const duration = common_1.getDuration(bottomColumn.at(-1).text) || undefined; + const thumbnails = new common_1.Thumbnails().load(item.thumbnail.musicThumbnailRenderer.thumbnail.thumbnails); + const artists = MusicAllSearchResultParser.parseArtists(bottomColumn, client); + if (pageType === "MUSIC_VIDEO_TYPE_ATV") { + const rawAlbum = bottomColumn.find((r) => { + var _a; + return ((_a = r.navigationEndpoint) === null || _a === void 0 ? void 0 : _a.browseEndpoint.browseEndpointContextSupportedConfigs.browseEndpointContextMusicConfig.pageType) === "MUSIC_PAGE_TYPE_ALBUM"; + }); + const album = rawAlbum + ? new MusicAlbumCompact_1.MusicAlbumCompact({ + client, + id: rawAlbum.navigationEndpoint.browseEndpoint.browseId, + title: rawAlbum.text, + }) + : undefined; + return new MusicSongCompact_1.MusicSongCompact({ + client, + id, + album, + title, + artists, + thumbnails, + duration, + }); + } + else if (pageType === "MUSIC_VIDEO_TYPE_UGC") { + return new MusicVideoCompact_1.MusicVideoCompact({ client, id, title, artists, thumbnails, duration }); + } + } + static parsePlaylistItem(item, client) { + const [topColumn, bottomColumn] = item.flexColumns.map((c) => c.musicResponsiveListItemFlexColumnRenderer.text.runs); + const id = item.overlay.musicItemThumbnailOverlayRenderer.content.musicPlayButtonRenderer + .playNavigationEndpoint.watchPlaylistEndpoint.playlistId; + const title = topColumn[0].text; + const songCount = common_1.stripToInt(bottomColumn.at(-1).text) || undefined; + const thumbnails = new common_1.Thumbnails().load(item.thumbnail.musicThumbnailRenderer.thumbnail.thumbnails); + const channel = MusicAllSearchResultParser.parseChannel(bottomColumn, client); + return new MusicPlaylistCompact_1.MusicPlaylistCompact({ client, id, title, thumbnails, songCount, channel }); + } + static parseAlbumItem(item, client) { + const [topColumn, bottomColumn] = item.flexColumns.map((c) => c.musicResponsiveListItemFlexColumnRenderer.text.runs); + const id = item.overlay.musicItemThumbnailOverlayRenderer.content.musicPlayButtonRenderer + .playNavigationEndpoint.watchPlaylistEndpoint.playlistId; + const title = topColumn[0].text; + const year = common_1.stripToInt(bottomColumn.at(-1).text) || undefined; + const thumbnails = new common_1.Thumbnails().load(item.thumbnail.musicThumbnailRenderer.thumbnail.thumbnails); + const artists = MusicAllSearchResultParser.parseArtists(bottomColumn, client); + return new MusicAlbumCompact_1.MusicAlbumCompact({ client, id, title, thumbnails, artists, year }); + } + static parseArtistItem(item, client) { + const [topColumn] = item.flexColumns.map((c) => c.musicResponsiveListItemFlexColumnRenderer.text.runs); + const id = item.navigationEndpoint.browseEndpoint.browseId; + const name = topColumn[0].text; + const thumbnails = new common_1.Thumbnails().load(item.thumbnail.musicThumbnailRenderer.thumbnail.thumbnails); + return new MusicArtistCompact_1.MusicArtistCompact({ client, id, name, thumbnails }); + } + static parseArtists(items, client) { + return this.parseArtistOrChannel(items).map((r) => { + var _a; + return new MusicBaseArtist_1.MusicBaseArtist({ + client, + name: r.text, + id: (_a = r.navigationEndpoint) === null || _a === void 0 ? void 0 : _a.browseEndpoint.browseId, + }); + }); + } + static parseChannel(items, client) { + const [channel] = this.parseArtistOrChannel(items).map((r) => { + var _a; + return new MusicBaseChannel_1.MusicBaseChannel({ + client, + name: r.text, + id: (_a = r.navigationEndpoint) === null || _a === void 0 ? void 0 : _a.browseEndpoint.browseId, + }); + }); + return channel; + } + static parseArtistOrChannel(items) { + const contents = items.filter((r) => { + var _a; + const pageType = (_a = r.navigationEndpoint) === null || _a === void 0 ? void 0 : _a.browseEndpoint.browseEndpointContextSupportedConfigs.browseEndpointContextMusicConfig.pageType; + return (pageType === "MUSIC_PAGE_TYPE_ARTIST" || pageType === "MUSIC_PAGE_TYPE_USER_CHANNEL"); + }); + return !contents.length && items[0] ? [items[0]] : contents; + } +} +exports.MusicAllSearchResultParser = MusicAllSearchResultParser; diff --git a/src/assets/js/libs/youtube/dependencies/music/MusicSearchResult/MusicSearchResult.js b/src/assets/js/libs/youtube/dependencies/music/MusicSearchResult/MusicSearchResult.js new file mode 100644 index 0000000..1b7bd7b --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/music/MusicSearchResult/MusicSearchResult.js @@ -0,0 +1,95 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MusicSearchResult = exports.MusicSearchTypeEnum = void 0; +const MusicContinuable_1 = require("../MusicContinuable"); +const constants_1 = require("../constants"); +const MusicSearchResultParser_1 = require("./MusicSearchResultParser"); +const proto_1 = require("./proto"); +var MusicSearchTypeEnum; +(function (MusicSearchTypeEnum) { + MusicSearchTypeEnum["Song"] = "song"; + MusicSearchTypeEnum["Video"] = "video"; +})(MusicSearchTypeEnum = exports.MusicSearchTypeEnum || (exports.MusicSearchTypeEnum = {})); +/** + * Represents search result, usually returned from `client.search();`. + * + * {@link MusicSearchResult} is a helper class to manage search result + * + * @example + * ```ts + * const result = await music.search("Keyword", "song"); + * + * console.log(result.items); // search result from first page + * + * let nextSearchResult = await result.next(); + * console.log(nextSearchResult); // search result from second page + * + * nextSearchResult = await result.next(); + * console.log(nextSearchResult); // search result from third page + * + * console.log(result.items); // search result from first, second, and third page. + * ``` + * + * @noInheritDoc + */ +class MusicSearchResult extends MusicContinuable_1.MusicContinuable { + /** @hidden */ + constructor({ client, type }) { + super({ client }); + if (type) + this.type = type; + } + /** + * Initialize data from search + * + * @param query Search query + * @param options Search Options + * + * @hidden + */ + search(query, type) { + return __awaiter(this, void 0, void 0, function* () { + this.items = []; + this.type = type; + const bufferParams = proto_1.MusicSearchProto.encode(proto_1.optionsToProto(type)).finish(); + const response = yield this.client.http.post(`${constants_1.I_END_POINT}/search`, { + data: { + query, + params: Buffer.from(bufferParams).toString("base64"), + }, + }); + const { data, continuation } = MusicSearchResultParser_1.MusicSearchResultParser.parseInitialSearchResult(response.data, type, this.client); + this.items.push(...data); + this.continuation = continuation; + return this; + }); + } + fetch() { + return __awaiter(this, void 0, void 0, function* () { + if (!this.type) { + return { + items: [], + continuation: undefined, + }; + } + const response = yield this.client.http.post(`${constants_1.I_END_POINT}/search`, { + data: { continuation: this.continuation }, + }); + const { data, continuation } = MusicSearchResultParser_1.MusicSearchResultParser.parseContinuationSearchResult(response.data, this.type, this.client); + return { + items: data, + continuation, + }; + }); + } +} +exports.MusicSearchResult = MusicSearchResult; diff --git a/src/assets/js/libs/youtube/dependencies/music/MusicSearchResult/MusicSearchResultParser.js b/src/assets/js/libs/youtube/dependencies/music/MusicSearchResult/MusicSearchResultParser.js new file mode 100644 index 0000000..561aab2 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/music/MusicSearchResult/MusicSearchResultParser.js @@ -0,0 +1,42 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MusicSearchResultParser = void 0; +const MusicAllSearchResultParser_1 = require("./MusicAllSearchResultParser"); +class MusicSearchResultParser { + static parseInitialSearchResult(data, type, client) { + var _a, _b; + const contentSection = data.contents.tabbedSearchResultsRenderer.tabs[0].tabRenderer.content.sectionListRenderer.contents.find((c) => "musicShelfRenderer" in c); + if (!contentSection) { + // no results + return { + data: [], + continuation: undefined, + }; + } + const { contents, continuations } = contentSection.musicShelfRenderer; + return { + data: MusicSearchResultParser.parseSearchResult(contents, type, client), + continuation: (_b = (_a = continuations[0]) === null || _a === void 0 ? void 0 : _a.nextContinuationData) === null || _b === void 0 ? void 0 : _b.continuation, + }; + } + static parseContinuationSearchResult(data, type, client) { + const shelf = data.continuationContents.musicShelfContinuation; + return { + data: MusicSearchResultParser.parseSearchResult(shelf.contents, type, client), + continuation: shelf.continuations[0].nextContinuationData.continuation, + }; + } + static parseSearchResult(shelfContents, type, client) { + const rawContents = shelfContents + .filter((c) => "musicResponsiveListItemRenderer" in c) + .map((c) => c.musicResponsiveListItemRenderer); + const contents = []; + for (const c of rawContents) { + const parsed = MusicAllSearchResultParser_1.MusicAllSearchResultParser.parseVideoItem(c, type === "video" ? "MUSIC_VIDEO_TYPE_UGC" : "MUSIC_VIDEO_TYPE_ATV", client); + if (parsed) + contents.push(parsed); + } + return contents; + } +} +exports.MusicSearchResultParser = MusicSearchResultParser; diff --git a/src/assets/js/libs/youtube/dependencies/music/MusicSearchResult/index.js b/src/assets/js/libs/youtube/dependencies/music/MusicSearchResult/index.js new file mode 100644 index 0000000..16ce004 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/music/MusicSearchResult/index.js @@ -0,0 +1,15 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./MusicAllSearchResultParser"), exports); +__exportStar(require("./MusicSearchResult"), exports); +__exportStar(require("./MusicSearchResultParser"), exports); diff --git a/src/assets/js/libs/youtube/dependencies/music/MusicSearchResult/proto/MusicSearchProto.js b/src/assets/js/libs/youtube/dependencies/music/MusicSearchResult/proto/MusicSearchProto.js new file mode 100644 index 0000000..c8ad2e5 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/music/MusicSearchResult/proto/MusicSearchProto.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/src/assets/js/libs/youtube/dependencies/music/MusicSearchResult/proto/index.js b/src/assets/js/libs/youtube/dependencies/music/MusicSearchResult/proto/index.js new file mode 100644 index 0000000..05daec7 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/music/MusicSearchResult/proto/index.js @@ -0,0 +1,35 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.optionsToProto = exports.MusicSearchProto = void 0; +const protobufjs_1 = __importDefault(require("protobufjs")); +// TODO move this to .proto file +exports.MusicSearchProto = protobufjs_1.default + .parse(` + message MusicSearchOptions { + message Options { + optional int32 song = 1; + optional int32 video = 2; + } + + message Params { + optional Options options = 17; + } + + optional Params params = 2; + } +`) + .root.lookupType("MusicSearchOptions"); +const optionsToProto = (type) => { + return { + params: { + options: { + song: type === "song" ? 1 : undefined, + video: type === "video" ? 1 : undefined, + }, + }, + }; +}; +exports.optionsToProto = optionsToProto; diff --git a/src/assets/js/libs/youtube/dependencies/music/MusicSongCompact/MusicSongCompact.js b/src/assets/js/libs/youtube/dependencies/music/MusicSongCompact/MusicSongCompact.js new file mode 100644 index 0000000..fa6baa6 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/music/MusicSongCompact/MusicSongCompact.js @@ -0,0 +1,12 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MusicSongCompact = void 0; +const MusicBase_1 = require("../MusicBase"); +class MusicSongCompact extends MusicBase_1.MusicBase { + /** @hidden */ + constructor(attr) { + super(attr.client); + Object.assign(this, attr); + } +} +exports.MusicSongCompact = MusicSongCompact; diff --git a/src/assets/js/libs/youtube/dependencies/music/MusicSongCompact/index.js b/src/assets/js/libs/youtube/dependencies/music/MusicSongCompact/index.js new file mode 100644 index 0000000..22ff56c --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/music/MusicSongCompact/index.js @@ -0,0 +1,13 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./MusicSongCompact"), exports); diff --git a/src/assets/js/libs/youtube/dependencies/music/MusicVideoCompact/MusicVideoCompact.js b/src/assets/js/libs/youtube/dependencies/music/MusicVideoCompact/MusicVideoCompact.js new file mode 100644 index 0000000..e74f3ce --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/music/MusicVideoCompact/MusicVideoCompact.js @@ -0,0 +1,12 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MusicVideoCompact = void 0; +const MusicBase_1 = require("../MusicBase"); +class MusicVideoCompact extends MusicBase_1.MusicBase { + /** @hidden */ + constructor(attr) { + super(attr.client); + Object.assign(this, attr); + } +} +exports.MusicVideoCompact = MusicVideoCompact; diff --git a/src/assets/js/libs/youtube/dependencies/music/MusicVideoCompact/index.js b/src/assets/js/libs/youtube/dependencies/music/MusicVideoCompact/index.js new file mode 100644 index 0000000..e4f2b74 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/music/MusicVideoCompact/index.js @@ -0,0 +1,13 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./MusicVideoCompact"), exports); diff --git a/src/assets/js/libs/youtube/dependencies/music/constants.js b/src/assets/js/libs/youtube/dependencies/music/constants.js new file mode 100644 index 0000000..62086f8 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/music/constants.js @@ -0,0 +1,7 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.I_END_POINT = exports.BASE_URL = exports.INNERTUBE_API_KEY = exports.INNERTUBE_CLIENT_VERSION = void 0; +exports.INNERTUBE_CLIENT_VERSION = "1.20221219.01.00"; +exports.INNERTUBE_API_KEY = "AIzaSyC9XL3ZjWddXya6X74dJoCTL-WEYFDNX30"; +exports.BASE_URL = "music.youtube.com"; +exports.I_END_POINT = "/youtubei/v1"; diff --git a/src/assets/js/libs/youtube/dependencies/music/index.js b/src/assets/js/libs/youtube/dependencies/music/index.js new file mode 100644 index 0000000..3c66e6e --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/music/index.js @@ -0,0 +1,24 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./MusicAlbumCompact"), exports); +__exportStar(require("./MusicArtistCompact"), exports); +__exportStar(require("./MusicBase"), exports); +__exportStar(require("./MusicBaseAlbum"), exports); +__exportStar(require("./MusicBaseArtist"), exports); +__exportStar(require("./MusicBaseChannel"), exports); +__exportStar(require("./MusicClient"), exports); +__exportStar(require("./MusicLyrics"), exports); +__exportStar(require("./MusicPlaylistCompact"), exports); +__exportStar(require("./MusicSearchResult"), exports); +__exportStar(require("./MusicSongCompact"), exports); +__exportStar(require("./MusicVideoCompact"), exports); diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Base/Base.js b/src/assets/js/libs/youtube/dependencies/youtube/Base/Base.js new file mode 100644 index 0000000..e15e78a --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Base/Base.js @@ -0,0 +1,10 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Base = void 0; +class Base { + /** @hidden */ + constructor(client) { + this.client = client; + } +} +exports.Base = Base; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Base/index.js b/src/assets/js/libs/youtube/dependencies/youtube/Base/index.js new file mode 100644 index 0000000..91d22a4 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Base/index.js @@ -0,0 +1,13 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./Base"), exports); diff --git a/src/assets/js/libs/youtube/dependencies/youtube/BaseChannel/BaseChannel.js b/src/assets/js/libs/youtube/dependencies/youtube/BaseChannel/BaseChannel.js new file mode 100644 index 0000000..b51c43e --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/BaseChannel/BaseChannel.js @@ -0,0 +1,35 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.BaseChannel = void 0; +const Base_1 = require("../Base"); +const BaseChannelParser_1 = require("./BaseChannelParser"); +const ChannelLive_1 = require("./ChannelLive"); +const ChannelPlaylists_1 = require("./ChannelPlaylists"); +const ChannelShorts_1 = require("./ChannelShorts"); +const ChannelVideos_1 = require("./ChannelVideos"); +/** Represents a Youtube Channel */ +class BaseChannel extends Base_1.Base { + /** @hidden */ + constructor(attr) { + super(attr.client); + Object.assign(this, attr); + this.videos = new ChannelVideos_1.ChannelVideos({ channel: this, client: this.client }); + this.shorts = new ChannelShorts_1.ChannelShorts({ channel: this, client: this.client }); + this.live = new ChannelLive_1.ChannelLive({ channel: this, client: this.client }); + this.playlists = new ChannelPlaylists_1.ChannelPlaylists({ channel: this, client: this.client }); + } + /** The URL of the channel page */ + get url() { + return `https://www.youtube.com/channel/${this.id}`; + } + /** + * Load this instance with raw data from Youtube + * + * @hidden + */ + load(data) { + BaseChannelParser_1.BaseChannelParser.loadBaseChannel(this, data); + return this; + } +} +exports.BaseChannel = BaseChannel; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/BaseChannel/BaseChannelParser.js b/src/assets/js/libs/youtube/dependencies/youtube/BaseChannel/BaseChannelParser.js new file mode 100644 index 0000000..9addd01 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/BaseChannel/BaseChannelParser.js @@ -0,0 +1,34 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.BaseChannelParser = void 0; +const common_1 = require("../../common"); +class BaseChannelParser { + static loadBaseChannel(target, data) { + var _a; + const { channelId, title, thumbnail, videoCountText, subscriberCountText } = data; + target.id = channelId; + target.name = title.simpleText; + target.thumbnails = new common_1.Thumbnails().load(thumbnail.thumbnails); + target.videoCount = common_1.stripToInt((_a = videoCountText === null || videoCountText === void 0 ? void 0 : videoCountText.runs) === null || _a === void 0 ? void 0 : _a[0].text) || 0; // TODO this sometimes contains subscriber count for some reason + target.subscriberCount = subscriberCountText === null || subscriberCountText === void 0 ? void 0 : subscriberCountText.simpleText; + return target; + } + /** Parse tab data from request, tab name is ignored if it's a continuation data */ + static parseTabData(name, data) { + var _a, _b, _c, _d, _e; + const tab = (_a = data.contents) === null || _a === void 0 ? void 0 : _a.twoColumnBrowseResultsRenderer.tabs.find((t) => { + var _a; + return (((_a = t.tabRenderer) === null || _a === void 0 ? void 0 : _a.endpoint.browseEndpoint.params) === + BaseChannelParser.TAB_TYPE_PARAMS[name]); + }); + return (((_d = (_c = (_b = tab === null || tab === void 0 ? void 0 : tab.tabRenderer.content.sectionListRenderer) === null || _b === void 0 ? void 0 : _b.contents) === null || _c === void 0 ? void 0 : _c[0].itemSectionRenderer.contents[0].gridRenderer) === null || _d === void 0 ? void 0 : _d.items) || (tab === null || tab === void 0 ? void 0 : tab.tabRenderer.content.richGridRenderer.contents.map((c) => { var _a; return ((_a = c.richItemRenderer) === null || _a === void 0 ? void 0 : _a.content) || c; })) || ((_e = data.onResponseReceivedActions) === null || _e === void 0 ? void 0 : _e[0].appendContinuationItemsAction.continuationItems.map((c) => { var _a; return ((_a = c.richItemRenderer) === null || _a === void 0 ? void 0 : _a.content) || c; })) || + []); + } +} +exports.BaseChannelParser = BaseChannelParser; +BaseChannelParser.TAB_TYPE_PARAMS = { + videos: "EgZ2aWRlb3PyBgQKAjoA", + shorts: "EgZzaG9ydHPyBgUKA5oBAA%3D%3D", + live: "EgdzdHJlYW1z8gYECgJ6AA%3D%3D", + playlists: "EglwbGF5bGlzdHPyBgQKAkIA", +}; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/BaseChannel/ChannelLive.js b/src/assets/js/libs/youtube/dependencies/youtube/BaseChannel/ChannelLive.js new file mode 100644 index 0000000..215e871 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/BaseChannel/ChannelLive.js @@ -0,0 +1,57 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ChannelLive = void 0; +const common_1 = require("../../common"); +const Continuable_1 = require("../Continuable"); +const VideoCompact_1 = require("../VideoCompact"); +const constants_1 = require("../constants"); +const BaseChannelParser_1 = require("./BaseChannelParser"); +/** + * {@link Continuable} of videos inside a {@link BaseChannel} + * + * @example + * ```js + * const channel = await youtube.findOne(CHANNEL_NAME, {type: "channel"}); + * await channel.live.next(); + * console.log(channel.live.items) // first 30 live videos + * + * let newLives = await channel.videos.next(); + * console.log(newLives) // 30 loaded live videos + * console.log(channel.live.items) // first 60 live videos + * + * await channel.live.next(0); // load the rest of the live videos in the channel + * ``` + */ +class ChannelLive extends Continuable_1.Continuable { + /** @hidden */ + constructor({ client, channel }) { + super({ client, strictContinuationCheck: true }); + this.channel = channel; + } + fetch() { + var _a; + return __awaiter(this, void 0, void 0, function* () { + const params = BaseChannelParser_1.BaseChannelParser.TAB_TYPE_PARAMS.live; + const response = yield this.client.http.post(`${constants_1.I_END_POINT}/browse`, { + data: { browseId: (_a = this.channel) === null || _a === void 0 ? void 0 : _a.id, params, continuation: this.continuation }, + }); + const items = BaseChannelParser_1.BaseChannelParser.parseTabData("live", response.data); + const continuation = common_1.getContinuationFromItems(items); + const data = common_1.mapFilter(items, "videoRenderer"); + return { + continuation, + items: data.map((i) => new VideoCompact_1.VideoCompact({ client: this.client, channel: this.channel }).load(i)), + }; + }); + } +} +exports.ChannelLive = ChannelLive; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/BaseChannel/ChannelPlaylists.js b/src/assets/js/libs/youtube/dependencies/youtube/BaseChannel/ChannelPlaylists.js new file mode 100644 index 0000000..d33f9f8 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/BaseChannel/ChannelPlaylists.js @@ -0,0 +1,57 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ChannelPlaylists = void 0; +const common_1 = require("../../common"); +const Continuable_1 = require("../Continuable"); +const PlaylistCompact_1 = require("../PlaylistCompact"); +const constants_1 = require("../constants"); +const BaseChannelParser_1 = require("./BaseChannelParser"); +/** + * {@link Continuable} of playlists inside a {@link BaseChannel} + * + * @example + * ```js + * const channel = await youtube.findOne(CHANNEL_NAME, {type: "channel"}); + * await channel.playlists.next(); + * console.log(channel.playlists.items) // first 30 playlists + * + * let newPlaylists = await channel.playlists.next(); + * console.log(newPlaylists) // 30 loaded playlists + * console.log(channel.playlists.items) // first 60 playlists + * + * await channel.playlists.next(0); // load the rest of the playlists in the channel + * ``` + */ +class ChannelPlaylists extends Continuable_1.Continuable { + /** @hidden */ + constructor({ client, channel }) { + super({ client, strictContinuationCheck: true }); + this.channel = channel; + } + fetch() { + var _a; + return __awaiter(this, void 0, void 0, function* () { + const params = BaseChannelParser_1.BaseChannelParser.TAB_TYPE_PARAMS.playlists; + const response = yield this.client.http.post(`${constants_1.I_END_POINT}/browse`, { + data: { browseId: (_a = this.channel) === null || _a === void 0 ? void 0 : _a.id, params, continuation: this.continuation }, + }); + const items = BaseChannelParser_1.BaseChannelParser.parseTabData("playlists", response.data); + const continuation = common_1.getContinuationFromItems(items); + const data = common_1.mapFilter(items, "gridPlaylistRenderer"); + return { + continuation, + items: data.map((i) => new PlaylistCompact_1.PlaylistCompact({ client: this.client, channel: this.channel }).load(i)), + }; + }); + } +} +exports.ChannelPlaylists = ChannelPlaylists; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/BaseChannel/ChannelShorts.js b/src/assets/js/libs/youtube/dependencies/youtube/BaseChannel/ChannelShorts.js new file mode 100644 index 0000000..8eb929f --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/BaseChannel/ChannelShorts.js @@ -0,0 +1,57 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ChannelShorts = void 0; +const common_1 = require("../../common"); +const Continuable_1 = require("../Continuable"); +const VideoCompact_1 = require("../VideoCompact"); +const constants_1 = require("../constants"); +const BaseChannelParser_1 = require("./BaseChannelParser"); +/** + * {@link Continuable} of shorts inside a {@link BaseChannel} + * + * @example + * ```js + * const channel = await youtube.findOne(CHANNEL_NAME, {type: "channel"}); + * await channel.short.next(); + * console.log(channel.short.items) // first 30 shorts + * + * let newShorts = await channel.short.next(); + * console.log(newShorts) // 30 loaded shorts + * console.log(channel.short.items) // first 60 shorts + * + * await channel.short.next(0); // load the rest of the shorts in the channel + * ``` + */ +class ChannelShorts extends Continuable_1.Continuable { + /** @hidden */ + constructor({ client, channel }) { + super({ client, strictContinuationCheck: true }); + this.channel = channel; + } + fetch() { + var _a; + return __awaiter(this, void 0, void 0, function* () { + const params = BaseChannelParser_1.BaseChannelParser.TAB_TYPE_PARAMS.shorts; + const response = yield this.client.http.post(`${constants_1.I_END_POINT}/browse`, { + data: { browseId: (_a = this.channel) === null || _a === void 0 ? void 0 : _a.id, params, continuation: this.continuation }, + }); + const items = BaseChannelParser_1.BaseChannelParser.parseTabData("shorts", response.data); + const continuation = common_1.getContinuationFromItems(items); + const data = common_1.mapFilter(items, "reelItemRenderer"); + return { + continuation, + items: data.map((i) => new VideoCompact_1.VideoCompact({ client: this.client, channel: this.channel }).load(i)), + }; + }); + } +} +exports.ChannelShorts = ChannelShorts; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/BaseChannel/ChannelVideos.js b/src/assets/js/libs/youtube/dependencies/youtube/BaseChannel/ChannelVideos.js new file mode 100644 index 0000000..552ccc4 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/BaseChannel/ChannelVideos.js @@ -0,0 +1,57 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ChannelVideos = void 0; +const common_1 = require("../../common"); +const Continuable_1 = require("../Continuable"); +const VideoCompact_1 = require("../VideoCompact"); +const constants_1 = require("../constants"); +const BaseChannelParser_1 = require("./BaseChannelParser"); +/** + * {@link Continuable} of videos inside a {@link BaseChannel} + * + * @example + * ```js + * const channel = await youtube.findOne(CHANNEL_NAME, {type: "channel"}); + * await channel.videos.next(); + * console.log(channel.videos.items) // first 30 videos + * + * let newVideos = await channel.videos.next(); + * console.log(newVideos) // 30 loaded videos + * console.log(channel.videos.items) // first 60 videos + * + * await channel.videos.next(0); // load the rest of the videos in the channel + * ``` + */ +class ChannelVideos extends Continuable_1.Continuable { + /** @hidden */ + constructor({ client, channel }) { + super({ client, strictContinuationCheck: true }); + this.channel = channel; + } + fetch() { + var _a; + return __awaiter(this, void 0, void 0, function* () { + const params = BaseChannelParser_1.BaseChannelParser.TAB_TYPE_PARAMS.videos; + const response = yield this.client.http.post(`${constants_1.I_END_POINT}/browse`, { + data: { browseId: (_a = this.channel) === null || _a === void 0 ? void 0 : _a.id, params, continuation: this.continuation }, + }); + const items = BaseChannelParser_1.BaseChannelParser.parseTabData("videos", response.data); + const continuation = common_1.getContinuationFromItems(items); + const data = common_1.mapFilter(items, "videoRenderer"); + return { + continuation, + items: data.map((i) => new VideoCompact_1.VideoCompact({ client: this.client, channel: this.channel }).load(i)), + }; + }); + } +} +exports.ChannelVideos = ChannelVideos; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/BaseChannel/index.js b/src/assets/js/libs/youtube/dependencies/youtube/BaseChannel/index.js new file mode 100644 index 0000000..f8778b7 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/BaseChannel/index.js @@ -0,0 +1,18 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./BaseChannel"), exports); +__exportStar(require("./BaseChannelParser"), exports); +__exportStar(require("./ChannelLive"), exports); +__exportStar(require("./ChannelPlaylists"), exports); +__exportStar(require("./ChannelShorts"), exports); +__exportStar(require("./ChannelVideos"), exports); diff --git a/src/assets/js/libs/youtube/dependencies/youtube/BaseVideo/BaseVideo.js b/src/assets/js/libs/youtube/dependencies/youtube/BaseVideo/BaseVideo.js new file mode 100644 index 0000000..e3e93d6 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/BaseVideo/BaseVideo.js @@ -0,0 +1,34 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.BaseVideo = void 0; +const Base_1 = require("../Base"); +const BaseVideoParser_1 = require("./BaseVideoParser"); +const VideoRelated_1 = require("./VideoRelated"); +/** Represents a Video */ +class BaseVideo extends Base_1.Base { + /** @hidden */ + constructor(attr) { + super(attr.client); + Object.assign(this, attr); + this.related = new VideoRelated_1.VideoRelated({ client: this.client, video: this }); + } + /** + * Load this instance with raw data from Youtube + * + * @hidden + */ + load(data) { + BaseVideoParser_1.BaseVideoParser.loadBaseVideo(this, data); + return this; + } + /** + * Video / playlist to play next after this video, alias to + * ```js + * video.related.items[0] + * ``` + */ + get upNext() { + return this.related.items[0]; + } +} +exports.BaseVideo = BaseVideo; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/BaseVideo/BaseVideoParser.js b/src/assets/js/libs/youtube/dependencies/youtube/BaseVideo/BaseVideoParser.js new file mode 100644 index 0000000..8dc9938 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/BaseVideo/BaseVideoParser.js @@ -0,0 +1,87 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.BaseVideoParser = void 0; +const common_1 = require("../../common"); +const BaseChannel_1 = require("../BaseChannel"); +const PlaylistCompact_1 = require("../PlaylistCompact"); +const VideoCompact_1 = require("../VideoCompact"); +class BaseVideoParser { + static loadBaseVideo(target, data) { + var _a, _b; + const videoInfo = BaseVideoParser.parseRawData(data); + // Basic information + target.id = videoInfo.videoDetails.videoId; + target.title = videoInfo.videoDetails.title; + target.uploadDate = videoInfo.dateText.simpleText; + target.viewCount = +videoInfo.videoDetails.viewCount || null; + target.isLiveContent = videoInfo.videoDetails.isLiveContent; + target.thumbnails = new common_1.Thumbnails().load(videoInfo.videoDetails.thumbnail.thumbnails); + // Channel + const { title, thumbnail, subscriberCountText } = videoInfo.owner.videoOwnerRenderer; + target.channel = new BaseChannel_1.BaseChannel({ + client: target.client, + id: title.runs[0].navigationEndpoint.browseEndpoint.browseId, + name: title.runs[0].text, + subscriberCount: subscriberCountText === null || subscriberCountText === void 0 ? void 0 : subscriberCountText.simpleText, + thumbnails: new common_1.Thumbnails().load(thumbnail.thumbnails), + }); + // Like Count and Dislike Count + const topLevelButtons = videoInfo.videoActions.menuRenderer.topLevelButtons; + target.likeCount = common_1.stripToInt(BaseVideoParser.parseButtonRenderer(topLevelButtons[0])); + // Tags and description + target.tags = + ((_b = (_a = videoInfo.superTitleLink) === null || _a === void 0 ? void 0 : _a.runs) === null || _b === void 0 ? void 0 : _b.map((r) => r.text.trim()).filter((t) => t)) || []; + target.description = videoInfo.videoDetails.shortDescription || ""; + // related videos + const secondaryContents = data[3].response.contents.twoColumnWatchNextResults.secondaryResults.secondaryResults + .results; + if (secondaryContents) { + target.related.items = BaseVideoParser.parseRelatedFromSecondaryContent(secondaryContents, target.client); + target.related.continuation = common_1.getContinuationFromItems(secondaryContents); + } + return target; + } + static parseRelated(data, client) { + const secondaryContents = data.onResponseReceivedEndpoints[0].appendContinuationItemsAction.continuationItems; + return BaseVideoParser.parseRelatedFromSecondaryContent(secondaryContents, client); + } + static parseContinuation(data) { + const secondaryContents = data.onResponseReceivedEndpoints[0].appendContinuationItemsAction.continuationItems; + return common_1.getContinuationFromItems(secondaryContents); + } + static parseRawData(data) { + const contents = data[3].response.contents.twoColumnWatchNextResults.results.results.contents; + const primaryInfo = contents.find((c) => "videoPrimaryInfoRenderer" in c) + .videoPrimaryInfoRenderer; + const secondaryInfo = contents.find((c) => "videoSecondaryInfoRenderer" in c).videoSecondaryInfoRenderer; + const videoDetails = data[2].playerResponse.videoDetails; + return Object.assign(Object.assign(Object.assign({}, secondaryInfo), primaryInfo), { videoDetails }); + } + static parseCompactRenderer(data, client) { + if ("compactVideoRenderer" in data) { + return new VideoCompact_1.VideoCompact({ client }).load(data.compactVideoRenderer); + } + else if ("compactRadioRenderer" in data) { + return new PlaylistCompact_1.PlaylistCompact({ client }).load(data.compactRadioRenderer); + } + } + static parseRelatedFromSecondaryContent(secondaryContents, client) { + return secondaryContents + .map((c) => BaseVideoParser.parseCompactRenderer(c, client)) + .filter((c) => c !== undefined); + } + static parseButtonRenderer(data) { + var _a; + let buttonRenderer; + if (!data.segmentedLikeDislikeButtonRenderer) { + buttonRenderer = data.toggleButtonRenderer || data.buttonRenderer; + } + else { + const likeButton = data.segmentedLikeDislikeButtonRenderer.likeButton; + buttonRenderer = likeButton.toggleButtonRenderer || likeButton.buttonRenderer; + } + const accessibilityData = (((_a = buttonRenderer.defaultText) === null || _a === void 0 ? void 0 : _a.accessibility) || buttonRenderer.accessibilityData).accessibilityData; + return accessibilityData.label; + } +} +exports.BaseVideoParser = BaseVideoParser; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/BaseVideo/VideoRelated.js b/src/assets/js/libs/youtube/dependencies/youtube/BaseVideo/VideoRelated.js new file mode 100644 index 0000000..7bee3ca --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/BaseVideo/VideoRelated.js @@ -0,0 +1,39 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.VideoRelated = void 0; +const Continuable_1 = require("../Continuable"); +const constants_1 = require("../constants"); +const BaseVideoParser_1 = require("./BaseVideoParser"); +/** + * {@link Continuable} of related videos inside a Video + */ +class VideoRelated extends Continuable_1.Continuable { + /** @hidden */ + constructor({ video, client }) { + super({ client }); + this.video = video; + } + fetch() { + return __awaiter(this, void 0, void 0, function* () { + const response = yield this.client.http.post(`${constants_1.I_END_POINT}/next`, { + data: { continuation: this.continuation }, + }); + const items = BaseVideoParser_1.BaseVideoParser.parseRelated(response.data, this.client); + const continuation = BaseVideoParser_1.BaseVideoParser.parseContinuation(response.data); + return { + continuation, + items, + }; + }); + } +} +exports.VideoRelated = VideoRelated; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/BaseVideo/index.js b/src/assets/js/libs/youtube/dependencies/youtube/BaseVideo/index.js new file mode 100644 index 0000000..a398ff9 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/BaseVideo/index.js @@ -0,0 +1,15 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./BaseVideo"), exports); +__exportStar(require("./BaseVideoParser"), exports); +__exportStar(require("./VideoRelated"), exports); diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Channel/Channel.js b/src/assets/js/libs/youtube/dependencies/youtube/Channel/Channel.js new file mode 100644 index 0000000..a3906d7 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Channel/Channel.js @@ -0,0 +1,24 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Channel = void 0; +const BaseChannel_1 = require("../BaseChannel"); +const ChannelParser_1 = require("./ChannelParser"); +/** Represents a Youtube Channel */ +class Channel extends BaseChannel_1.BaseChannel { + /** @hidden */ + constructor(attr) { + super(attr); + this.shelves = []; + Object.assign(this, attr); + } + /** + * Load this instance with raw data from Youtube + * + * @hidden + */ + load(data) { + ChannelParser_1.ChannelParser.loadChannel(this, data); + return this; + } +} +exports.Channel = Channel; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Channel/ChannelParser.js b/src/assets/js/libs/youtube/dependencies/youtube/Channel/ChannelParser.js new file mode 100644 index 0000000..2a25509 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Channel/ChannelParser.js @@ -0,0 +1,55 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ChannelParser = void 0; +const common_1 = require("../../common"); +const BaseChannel_1 = require("../BaseChannel"); +const PlaylistCompact_1 = require("../PlaylistCompact"); +const VideoCompact_1 = require("../VideoCompact"); +class ChannelParser { + static loadChannel(target, data) { + const { channelId, title, avatar, subscriberCountText, } = data.header.c4TabbedHeaderRenderer; + target.id = channelId; + target.name = title; + target.thumbnails = new common_1.Thumbnails().load(avatar.thumbnails); + target.videoCount = 0; // data not available + target.subscriberCount = subscriberCountText === null || subscriberCountText === void 0 ? void 0 : subscriberCountText.simpleText; + const { tvBanner, mobileBanner, banner } = data.header.c4TabbedHeaderRenderer; + target.banner = new common_1.Thumbnails().load((banner === null || banner === void 0 ? void 0 : banner.thumbnails) || []); + target.tvBanner = new common_1.Thumbnails().load((tvBanner === null || tvBanner === void 0 ? void 0 : tvBanner.thumbnails) || []); + target.mobileBanner = new common_1.Thumbnails().load((mobileBanner === null || mobileBanner === void 0 ? void 0 : mobileBanner.thumbnails) || []); + target.shelves = ChannelParser.parseShelves(target, data); + return target; + } + static parseShelves(target, data) { + const shelves = []; + const rawShelves = data.contents.twoColumnBrowseResultsRenderer.tabs[0].tabRenderer.content + .sectionListRenderer.contents; + for (const rawShelf of rawShelves) { + const shelfRenderer = rawShelf.itemSectionRenderer.contents[0].shelfRenderer; + if (!shelfRenderer) + continue; + const { title, content, subtitle } = shelfRenderer; + if (!content.horizontalListRenderer) + continue; + const items = content.horizontalListRenderer.items + .map((i) => { + if (i.gridVideoRenderer) + return new VideoCompact_1.VideoCompact({ client: target.client }).load(i.gridVideoRenderer); + if (i.gridPlaylistRenderer) + return new PlaylistCompact_1.PlaylistCompact({ client: target.client }).load(i.gridPlaylistRenderer); + if (i.gridChannelRenderer) + return new BaseChannel_1.BaseChannel({ client: target.client }).load(i.gridChannelRenderer); + return undefined; + }) + .filter((i) => i !== undefined); + const shelf = { + title: title.runs[0].text, + subtitle: subtitle === null || subtitle === void 0 ? void 0 : subtitle.simpleText, + items, + }; + shelves.push(shelf); + } + return shelves; + } +} +exports.ChannelParser = ChannelParser; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Channel/index.js b/src/assets/js/libs/youtube/dependencies/youtube/Channel/index.js new file mode 100644 index 0000000..58539a6 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Channel/index.js @@ -0,0 +1,14 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./Channel"), exports); +__exportStar(require("./ChannelParser"), exports); diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Chat/Chat.js b/src/assets/js/libs/youtube/dependencies/youtube/Chat/Chat.js new file mode 100644 index 0000000..446485d --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Chat/Chat.js @@ -0,0 +1,23 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Chat = void 0; +const Base_1 = require("../Base"); +const ChatParser_1 = require("./ChatParser"); +/** Represents a chat in a live stream */ +class Chat extends Base_1.Base { + /** @hidden */ + constructor(attr) { + super(attr.client); + Object.assign(this, attr); + } + /** + * Load this instance with raw data from Youtube + * + * @hidden + */ + load(data) { + ChatParser_1.ChatParser.loadChat(this, data); + return this; + } +} +exports.Chat = Chat; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Chat/ChatParser.js b/src/assets/js/libs/youtube/dependencies/youtube/Chat/ChatParser.js new file mode 100644 index 0000000..dd2fd49 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Chat/ChatParser.js @@ -0,0 +1,21 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ChatParser = void 0; +const BaseChannel_1 = require("../BaseChannel"); +class ChatParser { + static loadChat(target, data) { + const { id, message, authorName, authorPhoto, timestampUsec, authorExternalChannelId, } = data; + // Basic information + target.id = id; + target.message = message.runs.map((r) => r.text).join(""); + target.author = new BaseChannel_1.BaseChannel({ + id: authorExternalChannelId, + name: authorName.simpleText, + thumbnails: authorPhoto.thumbnails, + client: target.client, + }); + target.timestamp = +timestampUsec; + return target; + } +} +exports.ChatParser = ChatParser; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Chat/index.js b/src/assets/js/libs/youtube/dependencies/youtube/Chat/index.js new file mode 100644 index 0000000..e7d5541 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Chat/index.js @@ -0,0 +1,14 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./Chat"), exports); +__exportStar(require("./ChatParser"), exports); diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Client/Client.js b/src/assets/js/libs/youtube/dependencies/youtube/Client/Client.js new file mode 100644 index 0000000..1619b87 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Client/Client.js @@ -0,0 +1,115 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Client = void 0; +const common_1 = require("../../common"); +const Channel_1 = require("../Channel"); +const LiveVideo_1 = require("../LiveVideo"); +const MixPlaylist_1 = require("../MixPlaylist"); +const Playlist_1 = require("../Playlist"); +const SearchResult_1 = require("../SearchResult"); +const Transcript_1 = require("../Transcript"); +const Video_1 = require("../Video"); +const constants_1 = require("../constants"); +/** Youtube Client */ +class Client { + constructor(options = {}) { + const fullOptions = Object.assign(Object.assign({ initialCookie: "", fetchOptions: {} }, options), { youtubeClientOptions: Object.assign({ hl: "en", gl: "US" }, options.youtubeClientOptions) }); + this.http = new common_1.HTTP(Object.assign({ apiKey: constants_1.INNERTUBE_API_KEY, baseUrl: constants_1.BASE_URL, clientName: constants_1.INNERTUBE_CLIENT_NAME, clientVersion: constants_1.INNERTUBE_CLIENT_VERSION }, fullOptions)); + } + /** + * Searches for videos / playlists / channels + * + * @param query The search query + * @param options Search options + * + */ + search(query, options) { + return __awaiter(this, void 0, void 0, function* () { + const result = new SearchResult_1.SearchResult({ client: this }); + yield result.search(query, options || {}); + return result; + }); + } + /** + * Search for videos / playlists / channels and returns the first result + * + * @return Can be {@link VideoCompact} | {@link PlaylistCompact} | {@link BaseChannel} | `undefined` + */ + findOne(query, options) { + return __awaiter(this, void 0, void 0, function* () { + const result = yield this.search(query, options); + return result.items[0] || undefined; + }); + } + /** Get playlist information and its videos by playlist id or URL */ + getPlaylist(playlistId) { + var _a, _b, _c; + return __awaiter(this, void 0, void 0, function* () { + if (playlistId.startsWith("RD")) { + const response = yield this.http.post(`${constants_1.I_END_POINT}/next`, { + data: { playlistId }, + }); + if (response.data.error) { + return undefined; + } + return new MixPlaylist_1.MixPlaylist({ client: this }).load(response.data); + } + const response = yield this.http.post(`${constants_1.I_END_POINT}/browse`, { + data: { browseId: `VL${playlistId}` }, + }); + if (response.data.error || ((_c = (_b = (_a = response.data.alerts) === null || _a === void 0 ? void 0 : _a.shift()) === null || _b === void 0 ? void 0 : _b.alertRenderer) === null || _c === void 0 ? void 0 : _c.type) === "ERROR") { + return undefined; + } + return new Playlist_1.Playlist({ client: this }).load(response.data); + }); + } + /** Get video information by video id or URL */ + getVideo(videoId) { + return __awaiter(this, void 0, void 0, function* () { + const response = yield this.http.get(`${constants_1.WATCH_END_POINT}`, { + params: { v: videoId, pbj: "1" }, + }); + if (!response.data[3].response.contents) + return undefined; + return (!response.data[2].playerResponse.playabilityStatus.liveStreamability + ? new Video_1.Video({ client: this }).load(response.data) + : new LiveVideo_1.LiveVideo({ client: this }).load(response.data)); + }); + } + /** Get channel information by channel id+ */ + getChannel(channelId) { + var _a, _b, _c; + return __awaiter(this, void 0, void 0, function* () { + const response = yield this.http.post(`${constants_1.I_END_POINT}/browse`, { + data: { browseId: channelId }, + }); + if (response.data.error || ((_c = (_b = (_a = response.data.alerts) === null || _a === void 0 ? void 0 : _a.shift()) === null || _b === void 0 ? void 0 : _b.alertRenderer) === null || _c === void 0 ? void 0 : _c.type) === "ERROR") { + return undefined; + } + return new Channel_1.Channel({ client: this }).load(response.data); + }); + } + getVideoTranscript(videoId) { + return __awaiter(this, void 0, void 0, function* () { + const bufferParams = Transcript_1.TranscriptParamsProto.encode({ videoId }).finish(); + const response = yield this.http.post(`${constants_1.I_END_POINT}/get_transcript`, { + data: { params: Buffer.from(bufferParams).toString("base64") }, + }); + if (!response.data.actions) + return undefined; + return response.data.actions[0].updateEngagementPanelAction.content.transcriptRenderer.body.transcriptBodyRenderer.cueGroups + .map((t) => t.transcriptCueGroupRenderer.cues[0].transcriptCueRenderer) + .map((t) => new Transcript_1.Transcript().load(t)); + }); + } +} +exports.Client = Client; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Client/index.js b/src/assets/js/libs/youtube/dependencies/youtube/Client/index.js new file mode 100644 index 0000000..055859d --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Client/index.js @@ -0,0 +1,13 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./Client"), exports); diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Comment/Comment.js b/src/assets/js/libs/youtube/dependencies/youtube/Comment/Comment.js new file mode 100644 index 0000000..7debc7a --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Comment/Comment.js @@ -0,0 +1,29 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Comment = void 0; +const Base_1 = require("../Base"); +const CommentParser_1 = require("./CommentParser"); +const CommentReplies_1 = require("./CommentReplies"); +/** Represents a Comment / Reply */ +class Comment extends Base_1.Base { + /** @hidden */ + constructor(attr) { + super(attr.client); + Object.assign(this, attr); + this.replies = new CommentReplies_1.CommentReplies({ client: attr.client, comment: this }); + } + /** + * Load this instance with raw data from Youtube + * + * @hidden + */ + load(data) { + CommentParser_1.CommentParser.loadComment(this, data); + return this; + } + /** URL to the video with this comment being highlighted (appears on top of the comment section) */ + get url() { + return `https://www.youtube.com/watch?v=${this.video.id}&lc=${this.id}`; + } +} +exports.Comment = Comment; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Comment/CommentParser.js b/src/assets/js/libs/youtube/dependencies/youtube/Comment/CommentParser.js new file mode 100644 index 0000000..205c1aa --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Comment/CommentParser.js @@ -0,0 +1,42 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.CommentParser = void 0; +const common_1 = require("../../common"); +const BaseChannel_1 = require("../BaseChannel"); +const Reply_1 = require("../Reply"); +class CommentParser { + static loadComment(target, data) { + const { authorText, authorThumbnail, authorEndpoint, contentText, publishedTimeText, commentId, voteCount, authorIsChannelOwner, pinnedCommentBadge, replyCount, } = data.comment.commentRenderer; + // Basic information + target.id = commentId; + target.content = contentText.runs.map((r) => r.text).join(""); + target.publishDate = publishedTimeText.runs.shift().text; + target.likeCount = +((voteCount === null || voteCount === void 0 ? void 0 : voteCount.simpleText) || 0); + target.isAuthorChannelOwner = authorIsChannelOwner; + target.isPinned = !!pinnedCommentBadge; + target.replyCount = replyCount; + // Reply Continuation + target.replies.continuation = data.replies + ? common_1.getContinuationFromItems(data.replies.commentRepliesRenderer.contents) + : undefined; + // Author + const { browseId } = authorEndpoint.browseEndpoint; + target.author = new BaseChannel_1.BaseChannel({ + id: browseId, + name: authorText.simpleText, + thumbnails: new common_1.Thumbnails().load(authorThumbnail.thumbnails), + client: target.client, + }); + return target; + } + static parseContinuation(data) { + const continuationItems = data.onResponseReceivedEndpoints[0].appendContinuationItemsAction.continuationItems; + return common_1.getContinuationFromItems(continuationItems, ["button", "buttonRenderer", "command"]); + } + static parseReplies(data, comment) { + const continuationItems = data.onResponseReceivedEndpoints[0].appendContinuationItemsAction.continuationItems; + const rawReplies = common_1.mapFilter(continuationItems, "commentRenderer"); + return rawReplies.map((i) => new Reply_1.Reply({ video: comment.video, comment, client: comment.client }).load(i)); + } +} +exports.CommentParser = CommentParser; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Comment/CommentReplies.js b/src/assets/js/libs/youtube/dependencies/youtube/Comment/CommentReplies.js new file mode 100644 index 0000000..3907cb3 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Comment/CommentReplies.js @@ -0,0 +1,36 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.CommentReplies = void 0; +const Continuable_1 = require("../Continuable"); +const constants_1 = require("../constants"); +const CommentParser_1 = require("./CommentParser"); +/** + * {@link Continuable} of replies inside a {@link Comment} + */ +class CommentReplies extends Continuable_1.Continuable { + /** @hidden */ + constructor({ client, comment }) { + super({ client, strictContinuationCheck: true }); + this.comment = comment; + } + fetch() { + return __awaiter(this, void 0, void 0, function* () { + const response = yield this.client.http.post(`${constants_1.I_END_POINT}/next`, { + data: { continuation: this.continuation }, + }); + const continuation = CommentParser_1.CommentParser.parseContinuation(response.data); + const items = CommentParser_1.CommentParser.parseReplies(response.data, this.comment); + return { continuation, items }; + }); + } +} +exports.CommentReplies = CommentReplies; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Comment/index.js b/src/assets/js/libs/youtube/dependencies/youtube/Comment/index.js new file mode 100644 index 0000000..acfa80b --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Comment/index.js @@ -0,0 +1,15 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./Comment"), exports); +__exportStar(require("./CommentReplies"), exports); +__exportStar(require("./CommentParser"), exports); diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Continuable/Continuable.js b/src/assets/js/libs/youtube/dependencies/youtube/Continuable/Continuable.js new file mode 100644 index 0000000..88a15f0 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Continuable/Continuable.js @@ -0,0 +1,43 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Continuable = void 0; +const Base_1 = require("../Base"); +/** Represents a continuable list of items `T` (like pagination) */ +class Continuable extends Base_1.Base { + /** @hidden */ + constructor({ client, strictContinuationCheck }) { + super(client); + this.items = []; + this.strictContinuationCheck = !!strictContinuationCheck; + if (this.strictContinuationCheck) + this.continuation = null; + } + /** Fetch next items using continuation token */ + next(count = 1) { + return __awaiter(this, void 0, void 0, function* () { + const newItems = []; + for (let i = 0; i < count || count == 0; i++) { + if (!this.hasContinuation) + break; + const { items, continuation } = yield this.fetch(); + this.continuation = continuation; + newItems.push(...items); + } + this.items.push(...newItems); + return newItems; + }); + } + get hasContinuation() { + return this.strictContinuationCheck ? this.continuation !== undefined : !!this.continuation; + } +} +exports.Continuable = Continuable; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Continuable/index.js b/src/assets/js/libs/youtube/dependencies/youtube/Continuable/index.js new file mode 100644 index 0000000..414c1f5 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Continuable/index.js @@ -0,0 +1,13 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./Continuable"), exports); diff --git a/src/assets/js/libs/youtube/dependencies/youtube/LiveVideo/LiveVideo.js b/src/assets/js/libs/youtube/dependencies/youtube/LiveVideo/LiveVideo.js new file mode 100644 index 0000000..3b756ff --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/LiveVideo/LiveVideo.js @@ -0,0 +1,84 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.LiveVideo = void 0; +const events_1 = require("events"); +const common_1 = require("../../common"); +const BaseVideo_1 = require("../BaseVideo"); +const Chat_1 = require("../Chat"); +const constants_1 = require("../constants"); +const LiveVideoParser_1 = require("./LiveVideoParser"); +/** Represents a video that's currently live, usually returned from `client.getVideo()` */ +class LiveVideo extends BaseVideo_1.BaseVideo { + /** @hidden */ + constructor(attr) { + super(attr); + this._delay = 0; + this._timeoutMs = 0; + this._isChatPlaying = false; + this._chatQueue = []; + Object.assign(this, attr); + } + /** + * Load this instance with raw data from Youtube + * + * @hidden + */ + load(data) { + super.load(data); + LiveVideoParser_1.LiveVideoParser.loadLiveVideo(this, data); + return this; + } + /** + * Start polling for get live chat request + * + * @param delay chat delay in millisecond + */ + playChat(delay = 0) { + if (this._isChatPlaying) + return; + this._delay = delay; + this._isChatPlaying = true; + this.pollChatContinuation(); + } + /** Stop request polling for live chat */ + stopChat() { + if (!this._chatRequestPoolingTimeout) + return; + this._isChatPlaying = false; + clearTimeout(this._chatRequestPoolingTimeout); + } + /** Start request polling */ + pollChatContinuation() { + return __awaiter(this, void 0, void 0, function* () { + const response = yield this.client.http.post(constants_1.LIVE_CHAT_END_POINT, { + data: { continuation: this.chatContinuation }, + }); + if (!response.data.continuationContents) + return; + const chats = LiveVideoParser_1.LiveVideoParser.parseChats(response.data); + for (const c of chats) { + const chat = new Chat_1.Chat({ client: this.client }).load(c); + if (this._chatQueue.find((c) => c.id === chat.id)) + continue; + this._chatQueue.push(chat); + const timeout = chat.timestamp / 1000 - (new Date().getTime() - this._delay); + setTimeout(() => this.emit("chat", chat), timeout); + } + const { timeout, continuation } = LiveVideoParser_1.LiveVideoParser.parseContinuation(response.data); + this._timeoutMs = timeout; + this.chatContinuation = continuation; + this._chatRequestPoolingTimeout = setTimeout(() => this.pollChatContinuation(), this._timeoutMs); + }); + } +} +exports.LiveVideo = LiveVideo; +common_1.applyMixins(LiveVideo, [events_1.EventEmitter]); diff --git a/src/assets/js/libs/youtube/dependencies/youtube/LiveVideo/LiveVideoParser.js b/src/assets/js/libs/youtube/dependencies/youtube/LiveVideo/LiveVideoParser.js new file mode 100644 index 0000000..d8300a6 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/LiveVideo/LiveVideoParser.js @@ -0,0 +1,29 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.LiveVideoParser = void 0; +const BaseVideo_1 = require("../BaseVideo"); +class LiveVideoParser { + static loadLiveVideo(target, data) { + var _a; + const videoInfo = BaseVideo_1.BaseVideoParser.parseRawData(data); + target.watchingCount = +videoInfo.viewCount.videoViewCountRenderer.viewCount.runs + .map((r) => r.text) + .join(" ") + .replace(/[^0-9]/g, ""); + target.chatContinuation = (_a = data[3].response.contents.twoColumnWatchNextResults.conversationBar.liveChatRenderer) === null || _a === void 0 ? void 0 : _a.continuations[0].reloadContinuationData.continuation; + return target; + } + static parseChats(data) { + var _a; + return (((_a = data.continuationContents.liveChatContinuation.actions) === null || _a === void 0 ? void 0 : _a.flatMap((a) => { var _a; return ((_a = a.addChatItemAction) === null || _a === void 0 ? void 0 : _a.item.liveChatTextMessageRenderer) || []; })) || []); + } + static parseContinuation(data) { + const continuation = data.continuationContents.liveChatContinuation.continuations[0]; + const continuationData = continuation.timedContinuationData || continuation.invalidationContinuationData; + return { + timeout: continuationData.timeoutMs, + continuation: continuationData.continuation, + }; + } +} +exports.LiveVideoParser = LiveVideoParser; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/LiveVideo/index.js b/src/assets/js/libs/youtube/dependencies/youtube/LiveVideo/index.js new file mode 100644 index 0000000..8a55ee8 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/LiveVideo/index.js @@ -0,0 +1,14 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./LiveVideo"), exports); +__exportStar(require("./LiveVideoParser"), exports); diff --git a/src/assets/js/libs/youtube/dependencies/youtube/MixPlaylist/MixPlaylist.js b/src/assets/js/libs/youtube/dependencies/youtube/MixPlaylist/MixPlaylist.js new file mode 100644 index 0000000..430828c --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/MixPlaylist/MixPlaylist.js @@ -0,0 +1,25 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MixPlaylist = void 0; +const Base_1 = require("../Base"); +const MixPlaylistParser_1 = require("./MixPlaylistParser"); +/** Represents a MixPlaylist, usually returned from `client.getPlaylist()` */ +class MixPlaylist extends Base_1.Base { + /** @hidden */ + constructor(attr) { + super(attr.client); + /** How many viewers does this playlist have */ + this.videos = []; + Object.assign(this, attr); + } + /** + * Load this instance with raw data from Youtube + * + * @hidden + */ + load(data) { + MixPlaylistParser_1.MixPlaylistParser.loadMixPlaylist(this, data); + return this; + } +} +exports.MixPlaylist = MixPlaylist; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/MixPlaylist/MixPlaylistParser.js b/src/assets/js/libs/youtube/dependencies/youtube/MixPlaylist/MixPlaylistParser.js new file mode 100644 index 0000000..3647480 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/MixPlaylist/MixPlaylistParser.js @@ -0,0 +1,27 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MixPlaylistParser = void 0; +const VideoCompact_1 = require("../VideoCompact"); +class MixPlaylistParser { + static loadMixPlaylist(target, data) { + const twoColumnWatchNextResults = data.contents.twoColumnWatchNextResults; + const playlist = twoColumnWatchNextResults.playlist.playlist; + target.title = playlist.titleText.simpleText; + target.id = playlist.playlistId; + target.videoCount = playlist.contents.length; + target.videos = MixPlaylistParser.parseVideos(playlist.contents, target.client); + return target; + } + static parseVideos(data, client) { + const videosRenderer = data.map((c) => c.playlistPanelVideoRenderer); + const videos = []; + for (const videoRenderer of videosRenderer) { + if (!videoRenderer) + continue; + const video = new VideoCompact_1.VideoCompact({ client }).load(videoRenderer); + videos.push(video); + } + return videos; + } +} +exports.MixPlaylistParser = MixPlaylistParser; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/MixPlaylist/index.js b/src/assets/js/libs/youtube/dependencies/youtube/MixPlaylist/index.js new file mode 100644 index 0000000..ec5be7d --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/MixPlaylist/index.js @@ -0,0 +1,14 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./MixPlaylist"), exports); +__exportStar(require("./MixPlaylistParser"), exports); diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Playlist/Playlist.js b/src/assets/js/libs/youtube/dependencies/youtube/Playlist/Playlist.js new file mode 100644 index 0000000..9e062a1 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Playlist/Playlist.js @@ -0,0 +1,25 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Playlist = void 0; +const Base_1 = require("../Base"); +const PlaylistParser_1 = require("./PlaylistParser"); +const PlaylistVideos_1 = require("./PlaylistVideos"); +/** Represents a Playlist, usually returned from `client.getPlaylist()` */ +class Playlist extends Base_1.Base { + /** @hidden */ + constructor(attr) { + super(attr.client); + Object.assign(this, attr); + this.videos = new PlaylistVideos_1.PlaylistVideos({ client: attr.client, playlist: this }); + } + /** + * Load this instance with raw data from Youtube + * + * @hidden + */ + load(data) { + PlaylistParser_1.PlaylistParser.loadPlaylist(this, data); + return this; + } +} +exports.Playlist = Playlist; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Playlist/PlaylistParser.js b/src/assets/js/libs/youtube/dependencies/youtube/Playlist/PlaylistParser.js new file mode 100644 index 0000000..2a04dd8 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Playlist/PlaylistParser.js @@ -0,0 +1,84 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.PlaylistParser = void 0; +const common_1 = require("../../common"); +const BaseChannel_1 = require("../BaseChannel"); +const VideoCompact_1 = require("../VideoCompact"); +class PlaylistParser { + static loadPlaylist(target, data) { + var _a, _b, _c; + const sidebarRenderer = data.sidebar.playlistSidebarRenderer.items; + const primaryRenderer = sidebarRenderer[0].playlistSidebarPrimaryInfoRenderer; + const metadata = data.metadata.playlistMetadataRenderer; + // Basic information + target.id = (_a = Object.values(metadata) + .find((v) => v.includes("playlist?list="))) === null || _a === void 0 ? void 0 : _a.split("=")[1]; + target.title = metadata.title; + const { playlistVideoThumbnailRenderer, playlistCustomThumbnailRenderer, } = primaryRenderer.thumbnailRenderer; + target.thumbnails = new common_1.Thumbnails().load((playlistVideoThumbnailRenderer || playlistCustomThumbnailRenderer).thumbnail.thumbnails); + const { stats } = primaryRenderer; + if (primaryRenderer.stats.length === 3) { + target.videoCount = PlaylistParser.parseSideBarInfo(stats[0], true); + target.viewCount = PlaylistParser.parseSideBarInfo(stats[1], true); + target.lastUpdatedAt = PlaylistParser.parseSideBarInfo(stats[2], false); + } + else if (stats.length === 2) { + target.videoCount = PlaylistParser.parseSideBarInfo(stats[0], true); + target.lastUpdatedAt = PlaylistParser.parseSideBarInfo(stats[1], false); + } + const playlistContents = ((_b = data.contents.twoColumnBrowseResultsRenderer.tabs[0].tabRenderer.content + .sectionListRenderer.contents[0].itemSectionRenderer.contents[0] + .playlistVideoListRenderer) === null || _b === void 0 ? void 0 : _b.contents) || []; + // Channel + const videoOwner = (_c = sidebarRenderer[1]) === null || _c === void 0 ? void 0 : _c.playlistSidebarSecondaryInfoRenderer.videoOwner; + if (videoOwner) { + const { title, thumbnail } = videoOwner.videoOwnerRenderer; + target.channel = new BaseChannel_1.BaseChannel({ + id: title.runs[0].navigationEndpoint.browseEndpoint.browseId, + name: title.runs[0].text, + thumbnails: new common_1.Thumbnails().load(thumbnail.thumbnails), + client: target.client, + }); + } + // Videos + target.videos.items = PlaylistParser.parseVideos(playlistContents, target); + target.videos.continuation = common_1.getContinuationFromItems(playlistContents); + return target; + } + static parseVideoContinuation(data) { + const playlistContents = data.onResponseReceivedActions[0].appendContinuationItemsAction.continuationItems; + return common_1.getContinuationFromItems(playlistContents); + } + static parseContinuationVideos(data, client) { + const playlistContents = data.onResponseReceivedActions[0].appendContinuationItemsAction.continuationItems; + const videos = common_1.mapFilter(playlistContents, "playlistVideoRenderer"); + return videos.map((video) => new VideoCompact_1.VideoCompact({ client }).load(video)); + } + /** + * Get compact videos + * + * @param playlistContents raw object from youtubei + */ + static parseVideos(playlistContents, playlist) { + const videosRenderer = playlistContents.map((c) => c.playlistVideoRenderer); + const videos = []; + for (const videoRenderer of videosRenderer) { + if (!videoRenderer) + continue; + const video = new VideoCompact_1.VideoCompact({ client: playlist.client }).load(videoRenderer); + videos.push(video); + } + return videos; + } + static parseSideBarInfo(stats, parseInt) { + let data; + if ("runs" in stats) + data = stats.runs.map((r) => r.text).join(""); + else + data = stats.simpleText.replace(/[^0-9]/g, ""); + if (parseInt) + data = +data.replace(/[^0-9]/g, ""); + return data; + } +} +exports.PlaylistParser = PlaylistParser; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Playlist/PlaylistVideos.js b/src/assets/js/libs/youtube/dependencies/youtube/Playlist/PlaylistVideos.js new file mode 100644 index 0000000..6c04565 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Playlist/PlaylistVideos.js @@ -0,0 +1,50 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.PlaylistVideos = void 0; +const Continuable_1 = require("../Continuable"); +const constants_1 = require("../constants"); +const PlaylistParser_1 = require("./PlaylistParser"); +/** + * {@link Continuable} of videos inside a {@link Playlist} + * + * @example + * ```js + * const playlist = await youtube.getPlaylist(PLAYLIST_ID); + * console.log(playlist.videos) // first 100 videos + * + * let newVideos = await playlist.videos.next(); + * console.log(newVideos) // 100 loaded videos + * console.log(playlist.videos) // first 200 videos + * + * await playlist.videos.next(0); // load the rest of the videos in the playlist + * ``` + * + * @param count How many times to load the next videos. Set 0 to load all videos (might take a while on a large playlist!) + */ +class PlaylistVideos extends Continuable_1.Continuable { + /** @hidden */ + constructor({ client, playlist }) { + super({ client, strictContinuationCheck: true }); + this.playlist = playlist; + } + fetch() { + return __awaiter(this, void 0, void 0, function* () { + const response = yield this.client.http.post(`${constants_1.I_END_POINT}/browse`, { + data: { continuation: this.continuation }, + }); + const items = PlaylistParser_1.PlaylistParser.parseContinuationVideos(response.data, this.client); + const continuation = PlaylistParser_1.PlaylistParser.parseVideoContinuation(response.data); + return { continuation, items }; + }); + } +} +exports.PlaylistVideos = PlaylistVideos; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Playlist/index.js b/src/assets/js/libs/youtube/dependencies/youtube/Playlist/index.js new file mode 100644 index 0000000..16362b7 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Playlist/index.js @@ -0,0 +1,15 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./Playlist"), exports); +__exportStar(require("./PlaylistParser"), exports); +__exportStar(require("./PlaylistVideos"), exports); diff --git a/src/assets/js/libs/youtube/dependencies/youtube/PlaylistCompact/PlaylistCompact.js b/src/assets/js/libs/youtube/dependencies/youtube/PlaylistCompact/PlaylistCompact.js new file mode 100644 index 0000000..9fa58d5 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/PlaylistCompact/PlaylistCompact.js @@ -0,0 +1,45 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.PlaylistCompact = void 0; +const Base_1 = require("../Base"); +const PlaylistCompactParser_1 = require("./PlaylistCompactParser"); +/** Represents a Compact Playlist (e.g. from search result, related of a video) */ +class PlaylistCompact extends Base_1.Base { + /** @hidden */ + constructor(attr) { + super(attr.client); + Object.assign(this, attr); + } + /** + * Load this instance with raw data from Youtube + * + * @hidden + */ + load(data) { + PlaylistCompactParser_1.PlaylistCompactParser.loadPlaylistCompact(this, data); + return this; + } + /** + * Get {@link Playlist} object based on current playlist id + * + * Equivalent to + * ```js + * client.getPlaylist(playlistCompact.id); + * ``` + */ + getPlaylist() { + return __awaiter(this, void 0, void 0, function* () { + return yield this.client.getPlaylist(this.id); + }); + } +} +exports.PlaylistCompact = PlaylistCompact; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/PlaylistCompact/PlaylistCompactParser.js b/src/assets/js/libs/youtube/dependencies/youtube/PlaylistCompact/PlaylistCompactParser.js new file mode 100644 index 0000000..3197b45 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/PlaylistCompact/PlaylistCompactParser.js @@ -0,0 +1,27 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.PlaylistCompactParser = void 0; +const common_1 = require("../../common"); +const BaseChannel_1 = require("../BaseChannel"); +class PlaylistCompactParser { + static loadPlaylistCompact(target, data) { + var _a; + const { playlistId, title, thumbnail, shortBylineText, videoCount, videoCountShortText, } = data; + target.id = playlistId; + target.title = title.simpleText || title.runs[0].text; + target.videoCount = common_1.stripToInt(videoCount || videoCountShortText.simpleText) || 0; + // Thumbnail + target.thumbnails = new common_1.Thumbnails().load(((_a = data.thumbnails) === null || _a === void 0 ? void 0 : _a[0].thumbnails) || thumbnail.thumbnails); + // Channel + if (shortBylineText && shortBylineText.simpleText !== "YouTube") { + const shortByLine = shortBylineText.runs[0]; + target.channel = new BaseChannel_1.BaseChannel({ + id: shortByLine.navigationEndpoint.browseEndpoint.browseId, + name: shortByLine.text, + client: target.client, + }); + } + return target; + } +} +exports.PlaylistCompactParser = PlaylistCompactParser; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/PlaylistCompact/index.js b/src/assets/js/libs/youtube/dependencies/youtube/PlaylistCompact/index.js new file mode 100644 index 0000000..1737c9c --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/PlaylistCompact/index.js @@ -0,0 +1,14 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./PlaylistCompact"), exports); +__exportStar(require("./PlaylistCompactParser"), exports); diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Reply/Reply.js b/src/assets/js/libs/youtube/dependencies/youtube/Reply/Reply.js new file mode 100644 index 0000000..a689f39 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Reply/Reply.js @@ -0,0 +1,23 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Reply = void 0; +const Base_1 = require("../Base"); +const ReplyParser_1 = require("./ReplyParser"); +/** Represents a Reply */ +class Reply extends Base_1.Base { + /** @hidden */ + constructor(attr) { + super(attr.client); + Object.assign(this, attr); + } + /** + * Load this instance with raw data from Youtube + * + * @hidden + */ + load(data) { + ReplyParser_1.ReplyParser.loadReply(this, data); + return this; + } +} +exports.Reply = Reply; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Reply/ReplyParser.js b/src/assets/js/libs/youtube/dependencies/youtube/Reply/ReplyParser.js new file mode 100644 index 0000000..7993a0c --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Reply/ReplyParser.js @@ -0,0 +1,26 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ReplyParser = void 0; +const common_1 = require("../../common"); +const BaseChannel_1 = require("../BaseChannel"); +class ReplyParser { + static loadReply(target, data) { + const { authorText, authorThumbnail, authorEndpoint, contentText, publishedTimeText, commentId, likeCount, authorIsChannelOwner, } = data; + // Basic information + target.id = commentId; + target.content = contentText.runs.map((r) => r.text).join(""); + target.publishDate = publishedTimeText.runs.shift().text; + target.likeCount = likeCount; + target.isAuthorChannelOwner = authorIsChannelOwner; + // Author + const { browseId } = authorEndpoint.browseEndpoint; + target.author = new BaseChannel_1.BaseChannel({ + id: browseId, + name: authorText.simpleText, + thumbnails: new common_1.Thumbnails().load(authorThumbnail.thumbnails), + client: target.client, + }); + return target; + } +} +exports.ReplyParser = ReplyParser; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Reply/index.js b/src/assets/js/libs/youtube/dependencies/youtube/Reply/index.js new file mode 100644 index 0000000..302c336 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Reply/index.js @@ -0,0 +1,14 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./Reply"), exports); +__exportStar(require("./ReplyParser"), exports); diff --git a/src/assets/js/libs/youtube/dependencies/youtube/SearchResult/SearchResult.js b/src/assets/js/libs/youtube/dependencies/youtube/SearchResult/SearchResult.js new file mode 100644 index 0000000..cdf1303 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/SearchResult/SearchResult.js @@ -0,0 +1,133 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.SearchResult = exports.SearchEnum = void 0; +const Continuable_1 = require("../Continuable"); +const constants_1 = require("../constants"); +const SearchResultParser_1 = require("./SearchResultParser"); +const proto_1 = require("./proto"); +var SearchEnum; +(function (SearchEnum) { + let UploadDate; + (function (UploadDate) { + UploadDate["All"] = "all"; + UploadDate["Hour"] = "hour"; + UploadDate["Today"] = "today"; + UploadDate["Week"] = "week"; + UploadDate["Month"] = "month"; + UploadDate["Year"] = "year"; + })(UploadDate = SearchEnum.UploadDate || (SearchEnum.UploadDate = {})); + let Type; + (function (Type) { + Type["Video"] = "video"; + Type["Playlist"] = "playlist"; + Type["Channel"] = "channel"; + Type["All"] = "all"; + })(Type = SearchEnum.Type || (SearchEnum.Type = {})); + let Duration; + (function (Duration) { + Duration["All"] = "all"; + Duration["Short"] = "short"; + Duration["Medium"] = "medium"; + Duration["Long"] = "long"; + })(Duration = SearchEnum.Duration || (SearchEnum.Duration = {})); + let Sort; + (function (Sort) { + Sort["Relevance"] = "relevance"; + Sort["Rating"] = "rating"; + Sort["Date"] = "date"; + Sort["View"] = "view"; + })(Sort = SearchEnum.Sort || (SearchEnum.Sort = {})); + let Feature; + (function (Feature) { + Feature["Live"] = "live"; + Feature["4K"] = "4k"; + Feature["UHD"] = "4k"; + Feature["HD"] = "hd"; + Feature["Subtitles"] = "subtitles"; + Feature["CreativeCommons"] = "creativeCommons"; + Feature["Spherical"] = "360"; + Feature["VR180"] = "vr180"; + Feature["3D"] = "3d"; + Feature["ThreeDimensions"] = "3d"; + Feature["HDR"] = "hdr"; + Feature["Location"] = "location"; + })(Feature = SearchEnum.Feature || (SearchEnum.Feature = {})); +})(SearchEnum = exports.SearchEnum || (exports.SearchEnum = {})); +/** + * Represents search result, usually returned from `client.search();`. + * + * {@link SearchResult} is a helper class to manage search result + * + * @example + * ```ts + * const result = await youtube.search("Keyword"); + * + * console.log(result.items); // search result from first page + * + * let nextSearchResult = await result.next(); + * console.log(nextSearchResult); // search result from second page + * + * nextSearchResult = await result.next(); + * console.log(nextSearchResult); // search result from third page + * + * console.log(result.items); // search result from first, second, and third page. + * ``` + * + * @noInheritDoc + */ +class SearchResult extends Continuable_1.Continuable { + /** @hidden */ + constructor({ client }) { + super({ client }); + } + /** + * Initialize data from search + * + * @param query Search query + * @param options Search Options + * + * @hidden + */ + search(query, options) { + return __awaiter(this, void 0, void 0, function* () { + this.items = []; + this.estimatedResults = 0; + const bufferParams = proto_1.SearchProto.encode(proto_1.optionsToProto(options)).finish(); + const response = yield this.client.http.post(`${constants_1.I_END_POINT}/search`, { + data: { + query, + params: Buffer.from(bufferParams).toString("base64"), + }, + }); + this.estimatedResults = +response.data.estimatedResults; + if (this.estimatedResults > 0) { + const { data, continuation } = SearchResultParser_1.SearchResultParser.parseInitialSearchResult(response.data, this.client); + this.items.push(...data); + this.continuation = continuation; + } + return this; + }); + } + fetch() { + return __awaiter(this, void 0, void 0, function* () { + const response = yield this.client.http.post(`${constants_1.I_END_POINT}/search`, { + data: { continuation: this.continuation }, + }); + const { data, continuation } = SearchResultParser_1.SearchResultParser.parseContinuationSearchResult(response.data, this.client); + return { + items: data, + continuation, + }; + }); + } +} +exports.SearchResult = SearchResult; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/SearchResult/SearchResultParser.js b/src/assets/js/libs/youtube/dependencies/youtube/SearchResult/SearchResultParser.js new file mode 100644 index 0000000..b724b89 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/SearchResult/SearchResultParser.js @@ -0,0 +1,40 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.SearchResultParser = void 0; +const common_1 = require("../../common"); +const BaseChannel_1 = require("../BaseChannel"); +const PlaylistCompact_1 = require("../PlaylistCompact"); +const VideoCompact_1 = require("../VideoCompact"); +class SearchResultParser { + static parseInitialSearchResult(data, client) { + const sectionListContents = data.contents.twoColumnSearchResultsRenderer.primaryContents.sectionListRenderer + .contents; + return { + data: SearchResultParser.parseSearchResult(sectionListContents, client), + continuation: common_1.getContinuationFromItems(sectionListContents), + }; + } + static parseContinuationSearchResult(data, client) { + const sectionListContents = data.onResponseReceivedCommands[0].appendContinuationItemsAction.continuationItems; + return { + data: SearchResultParser.parseSearchResult(sectionListContents, client), + continuation: common_1.getContinuationFromItems(sectionListContents), + }; + } + static parseSearchResult(sectionListContents, client) { + const rawContents = sectionListContents + .filter((c) => "itemSectionRenderer" in c) + .at(-1).itemSectionRenderer.contents; + const contents = []; + for (const c of rawContents) { + if ("playlistRenderer" in c) + contents.push(new PlaylistCompact_1.PlaylistCompact({ client }).load(c.playlistRenderer)); + else if ("videoRenderer" in c) + contents.push(new VideoCompact_1.VideoCompact({ client }).load(c.videoRenderer)); + else if ("channelRenderer" in c) + contents.push(new BaseChannel_1.BaseChannel({ client }).load(c.channelRenderer)); + } + return contents; + } +} +exports.SearchResultParser = SearchResultParser; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/SearchResult/index.js b/src/assets/js/libs/youtube/dependencies/youtube/SearchResult/index.js new file mode 100644 index 0000000..7a4b080 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/SearchResult/index.js @@ -0,0 +1,14 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./SearchResult"), exports); +__exportStar(require("./SearchResultParser"), exports); diff --git a/src/assets/js/libs/youtube/dependencies/youtube/SearchResult/proto/SearchProto.js b/src/assets/js/libs/youtube/dependencies/youtube/SearchResult/proto/SearchProto.js new file mode 100644 index 0000000..c8ad2e5 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/SearchResult/proto/SearchProto.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/src/assets/js/libs/youtube/dependencies/youtube/SearchResult/proto/index.js b/src/assets/js/libs/youtube/dependencies/youtube/SearchResult/proto/index.js new file mode 100644 index 0000000..09b7c21 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/SearchResult/proto/index.js @@ -0,0 +1,68 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.optionsToProto = exports.SearchProto = void 0; +const protobufjs_1 = __importDefault(require("protobufjs")); +// TODO move this to .proto file +exports.SearchProto = protobufjs_1.default.parse(` + message SearchOptions { + message Options { + optional int32 uploadDate = 1; + optional int32 type = 2; + optional int32 duration = 3; + optional int32 hd = 4; + optional int32 subtitles = 5; + optional int32 creativeCommons = 6; + optional int32 live = 8; + optional int32 _4k = 14; + optional int32 _360 = 15; + optional int32 location = 23; + optional int32 hdr = 25; + optional int32 vr180 = 26; + } + + optional int32 sortBy = 1; + optional Options options = 2; + } +`).root.lookupType("SearchOptions"); +const searchUploadDateProto = { + all: 0, + hour: 1, + today: 2, + week: 3, + month: 4, + year: 5, +}; +const searchTypeProto = { + all: 0, + video: 1, + channel: 2, + playlist: 3, +}; +const searchDurationProto = { + all: 0, + short: 1, + long: 2, + medium: 3, +}; +const searchSortProto = { + relevance: 0, + rating: 1, + date: 2, + view: 3, +}; +const optionsToProto = (options) => { + var _a; + const featuresRecord = ((_a = options.features) === null || _a === void 0 ? void 0 : _a.reduce((acc, val) => { + if (val) + acc[val] = 1; + return acc; + }, {})) || {}; + return { + sortBy: options.sortBy && searchSortProto[options.sortBy], + options: Object.assign({ duration: options.duration && searchDurationProto[options.duration], type: options.type && searchTypeProto[options.type], uploadDate: options.uploadDate && searchUploadDateProto[options.uploadDate] }, featuresRecord), + }; +}; +exports.optionsToProto = optionsToProto; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Transcript/Transcript.js b/src/assets/js/libs/youtube/dependencies/youtube/Transcript/Transcript.js new file mode 100644 index 0000000..1866136 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Transcript/Transcript.js @@ -0,0 +1,27 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Transcript = void 0; +const TranscriptParser_1 = require("./TranscriptParser"); +/** + * Represent a single video transcript entry + */ +class Transcript { + /** @hidden */ + constructor(attr) { + Object.assign(this, attr); + } + /** transcript end time in miliseconds */ + get end() { + return this.start + this.duration; + } + /** + * Load this instance with raw data from Youtube + * + * @hidden + */ + load(data) { + TranscriptParser_1.TranscriptParser.loadTranscript(this, data); + return this; + } +} +exports.Transcript = Transcript; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Transcript/TranscriptParser.js b/src/assets/js/libs/youtube/dependencies/youtube/Transcript/TranscriptParser.js new file mode 100644 index 0000000..d33ba2e --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Transcript/TranscriptParser.js @@ -0,0 +1,13 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TranscriptParser = void 0; +class TranscriptParser { + static loadTranscript(target, data) { + const { cue, startOffsetMs, durationMs } = data; + target.text = cue.simpleText; + target.duration = +durationMs; + target.start = +startOffsetMs; + return target; + } +} +exports.TranscriptParser = TranscriptParser; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Transcript/index.js b/src/assets/js/libs/youtube/dependencies/youtube/Transcript/index.js new file mode 100644 index 0000000..4d382e9 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Transcript/index.js @@ -0,0 +1,15 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./proto"), exports); +__exportStar(require("./Transcript"), exports); +__exportStar(require("./TranscriptParser"), exports); diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Transcript/proto/TranscriptParamsProto.js b/src/assets/js/libs/youtube/dependencies/youtube/Transcript/proto/TranscriptParamsProto.js new file mode 100644 index 0000000..d19f4bc --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Transcript/proto/TranscriptParamsProto.js @@ -0,0 +1,12 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TranscriptParamsProto = void 0; +const protobufjs_1 = __importDefault(require("protobufjs")); +exports.TranscriptParamsProto = protobufjs_1.default.parse(` + message TranscriptParams { + optional string videoId = 1; + } +`).root.lookupType("TranscriptParams"); diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Transcript/proto/index.js b/src/assets/js/libs/youtube/dependencies/youtube/Transcript/proto/index.js new file mode 100644 index 0000000..ad049d5 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Transcript/proto/index.js @@ -0,0 +1,13 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./TranscriptParamsProto"), exports); diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Video/Video.js b/src/assets/js/libs/youtube/dependencies/youtube/Video/Video.js new file mode 100644 index 0000000..eccd01b --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Video/Video.js @@ -0,0 +1,48 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Video = void 0; +const BaseVideo_1 = require("../BaseVideo"); +const VideoComments_1 = require("./VideoComments"); +const VideoParser_1 = require("./VideoParser"); +/** Represents a Video, usually returned from `client.getVideo()` */ +class Video extends BaseVideo_1.BaseVideo { + /** @hidden */ + constructor(attr) { + super(attr); + Object.assign(this, attr); + this.comments = new VideoComments_1.VideoComments({ client: attr.client, video: this }); + } + /** + * Load this instance with raw data from Youtube + * + * @hidden + */ + load(data) { + super.load(data); + VideoParser_1.VideoParser.loadVideo(this, data); + return this; + } + /** + * Get Video transcript (if exists) + * + * Equivalent to + * ```js + * client.getVideoTranscript(video.id); + * ``` + */ + getTranscript() { + return __awaiter(this, void 0, void 0, function* () { + return this.client.getVideoTranscript(this.id); + }); + } +} +exports.Video = Video; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Video/VideoComments.js b/src/assets/js/libs/youtube/dependencies/youtube/Video/VideoComments.js new file mode 100644 index 0000000..d6fceca --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Video/VideoComments.js @@ -0,0 +1,53 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.VideoComments = void 0; +const Continuable_1 = require("../Continuable"); +const constants_1 = require("../constants"); +const VideoParser_1 = require("./VideoParser"); +/** + * {@link Continuable} of videos inside a {@link Video} + * + * @example + * ```js + * const video = await youtube.getVideo(VIDEO_ID); + * await video.comments.next(); + * console.log(video.comments) // first 20 comments + * + * let newComments = await video.comments.next(); + * console.log(newComments) // 20 loaded comments + * console.log(video.comments) // first 40 comments + * + * await video.comments.next(0); // load the rest of the comments in the video + * ``` + * + * @param count How many times to load the next comments. Set 0 to load all comments (might take a while on a video with many comments!) + * + * @returns Loaded comments + */ +class VideoComments extends Continuable_1.Continuable { + /** @hidden */ + constructor({ client, video }) { + super({ client, strictContinuationCheck: true }); + this.video = video; + } + fetch() { + return __awaiter(this, void 0, void 0, function* () { + const response = yield this.client.http.post(`${constants_1.I_END_POINT}/next`, { + data: { continuation: this.continuation }, + }); + const items = VideoParser_1.VideoParser.parseComments(response.data, this.video); + const continuation = VideoParser_1.VideoParser.parseCommentContinuation(response.data); + return { continuation, items }; + }); + } +} +exports.VideoComments = VideoComments; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Video/VideoParser.js b/src/assets/js/libs/youtube/dependencies/youtube/Video/VideoParser.js new file mode 100644 index 0000000..70fa976 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Video/VideoParser.js @@ -0,0 +1,37 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.VideoParser = void 0; +const common_1 = require("../../common"); +const BaseVideo_1 = require("../BaseVideo"); +const Comment_1 = require("../Comment"); +class VideoParser { + static loadVideo(target, data) { + var _a, _b, _c; + const videoInfo = BaseVideo_1.BaseVideoParser.parseRawData(data); + target.duration = +videoInfo.videoDetails.lengthSeconds; + const itemSectionRenderer = (_a = data[3].response.contents.twoColumnWatchNextResults.results.results.contents + .reverse() + .find((c) => c.itemSectionRenderer)) === null || _a === void 0 ? void 0 : _a.itemSectionRenderer; + target.comments.continuation = common_1.getContinuationFromItems((itemSectionRenderer === null || itemSectionRenderer === void 0 ? void 0 : itemSectionRenderer.contents) || []); + const chapters = (_c = (_b = data[3].response.playerOverlays.playerOverlayRenderer.decoratedPlayerBarRenderer) === null || _b === void 0 ? void 0 : _b.decoratedPlayerBarRenderer.playerBar.multiMarkersPlayerBarRenderer.markersMap) === null || _c === void 0 ? void 0 : _c[0].value.chapters; + target.chapters = + (chapters === null || chapters === void 0 ? void 0 : chapters.map(({ chapterRenderer: c }) => ({ + title: c.title.simpleText, + start: c.timeRangeStartMillis, + thumbnails: new common_1.Thumbnails().load(c.thumbnail.thumbnails), + }))) || []; + return target; + } + static parseComments(data, video) { + const endpoints = data.onResponseReceivedEndpoints.at(-1); + const continuationItems = (endpoints.reloadContinuationItemsCommand || endpoints.appendContinuationItemsAction).continuationItems; + const comments = common_1.mapFilter(continuationItems, "commentThreadRenderer"); + return comments.map((c) => new Comment_1.Comment({ video, client: video.client }).load(c)); + } + static parseCommentContinuation(data) { + const endpoints = data.onResponseReceivedEndpoints.at(-1); + const continuationItems = (endpoints.reloadContinuationItemsCommand || endpoints.appendContinuationItemsAction).continuationItems; + return common_1.getContinuationFromItems(continuationItems); + } +} +exports.VideoParser = VideoParser; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/Video/index.js b/src/assets/js/libs/youtube/dependencies/youtube/Video/index.js new file mode 100644 index 0000000..7ae26d1 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/Video/index.js @@ -0,0 +1,15 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./Video"), exports); +__exportStar(require("./VideoComments"), exports); +__exportStar(require("./VideoParser"), exports); diff --git a/src/assets/js/libs/youtube/dependencies/youtube/VideoCompact/VideoCompact.js b/src/assets/js/libs/youtube/dependencies/youtube/VideoCompact/VideoCompact.js new file mode 100644 index 0000000..243d0db --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/VideoCompact/VideoCompact.js @@ -0,0 +1,62 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.VideoCompact = void 0; +const Base_1 = require("../Base"); +const VideoCompactParser_1 = require("./VideoCompactParser"); +/** Represent a compact video (e.g. from search result, playlist's videos, channel's videos) */ +class VideoCompact extends Base_1.Base { + /** @hidden */ + constructor(attr) { + super(attr.client); + Object.assign(this, attr); + } + /** Whether this video is private / deleted or not, only useful in playlist's videos */ + get isPrivateOrDeleted() { + return !this.duration; + } + /** + * Load this instance with raw data from Youtube + * + * @hidden + */ + load(data) { + VideoCompactParser_1.VideoCompactParser.loadVideoCompact(this, data); + return this; + } + /** + * Get {@link Video} object based on current video id + * + * Equivalent to + * ```js + * client.getVideo(videoCompact.id); + * ``` + */ + getVideo() { + return __awaiter(this, void 0, void 0, function* () { + return yield this.client.getVideo(this.id); + }); + } + /** + * Get Video transcript (if exists) + * + * Equivalent to + * ```js + * client.getVideoTranscript(video.id); + * ``` + */ + getTranscript() { + return __awaiter(this, void 0, void 0, function* () { + return this.client.getVideoTranscript(this.id); + }); + } +} +exports.VideoCompact = VideoCompact; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/VideoCompact/VideoCompactParser.js b/src/assets/js/libs/youtube/dependencies/youtube/VideoCompact/VideoCompactParser.js new file mode 100644 index 0000000..6cdf6ac --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/VideoCompact/VideoCompactParser.js @@ -0,0 +1,39 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.VideoCompactParser = void 0; +const common_1 = require("../../common"); +const BaseChannel_1 = require("../BaseChannel"); +class VideoCompactParser { + static loadVideoCompact(target, data) { + var _a, _b, _c; + const { videoId, title, headline, lengthText, thumbnail, ownerText, shortBylineText, publishedTimeText, viewCountText, badges, thumbnailOverlays, channelThumbnailSupportedRenderers, detailedMetadataSnippets, } = data; + target.id = videoId; + target.title = headline ? headline.simpleText : title.simpleText || ((_a = title.runs[0]) === null || _a === void 0 ? void 0 : _a.text); + target.thumbnails = new common_1.Thumbnails().load(thumbnail.thumbnails); + target.uploadDate = publishedTimeText === null || publishedTimeText === void 0 ? void 0 : publishedTimeText.simpleText; + target.description = + ((_b = detailedMetadataSnippets === null || detailedMetadataSnippets === void 0 ? void 0 : detailedMetadataSnippets[0].snippetText.runs) === null || _b === void 0 ? void 0 : _b.map((r) => r.text).join("")) || ""; + target.duration = + common_1.getDuration((lengthText === null || lengthText === void 0 ? void 0 : lengthText.simpleText) || ((_c = thumbnailOverlays === null || thumbnailOverlays === void 0 ? void 0 : thumbnailOverlays[0].thumbnailOverlayTimeStatusRenderer) === null || _c === void 0 ? void 0 : _c.text.simpleText) || + "") || null; + target.isLive = !!((badges === null || badges === void 0 ? void 0 : badges[0].metadataBadgeRenderer.style) === "BADGE_STYLE_TYPE_LIVE_NOW"); + // Channel + if (ownerText || shortBylineText) { + const browseEndpoint = (ownerText || shortBylineText).runs[0].navigationEndpoint + .browseEndpoint; + if (browseEndpoint) { + const id = browseEndpoint.browseId; + const thumbnails = channelThumbnailSupportedRenderers === null || channelThumbnailSupportedRenderers === void 0 ? void 0 : channelThumbnailSupportedRenderers.channelThumbnailWithLinkRenderer.thumbnail.thumbnails; + target.channel = new BaseChannel_1.BaseChannel({ + id, + name: (ownerText || shortBylineText).runs[0].text, + thumbnails: thumbnails ? new common_1.Thumbnails().load(thumbnails) : undefined, + client: target.client, + }); + } + } + target.viewCount = common_1.stripToInt((viewCountText === null || viewCountText === void 0 ? void 0 : viewCountText.simpleText) || (viewCountText === null || viewCountText === void 0 ? void 0 : viewCountText.runs[0].text)); + return target; + } +} +exports.VideoCompactParser = VideoCompactParser; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/VideoCompact/index.js b/src/assets/js/libs/youtube/dependencies/youtube/VideoCompact/index.js new file mode 100644 index 0000000..7e02357 --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/VideoCompact/index.js @@ -0,0 +1,14 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./VideoCompact"), exports); +__exportStar(require("./VideoCompactParser"), exports); diff --git a/src/assets/js/libs/youtube/dependencies/youtube/constants.js b/src/assets/js/libs/youtube/dependencies/youtube/constants.js new file mode 100644 index 0000000..a3a7fae --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/constants.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.COMMENT_END_POINT = exports.WATCH_END_POINT = exports.LIVE_CHAT_END_POINT = exports.I_END_POINT = exports.BASE_URL = exports.INNERTUBE_API_KEY = exports.INNERTUBE_CLIENT_VERSION = exports.INNERTUBE_CLIENT_NAME = void 0; +exports.INNERTUBE_CLIENT_NAME = "WEB"; +exports.INNERTUBE_CLIENT_VERSION = "2.20201209.01.00"; +exports.INNERTUBE_API_KEY = "AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8"; +exports.BASE_URL = "www.youtube.com"; +exports.I_END_POINT = "/youtubei/v1"; +exports.LIVE_CHAT_END_POINT = `${exports.I_END_POINT}/live_chat/get_live_chat`; +exports.WATCH_END_POINT = "/watch"; +exports.COMMENT_END_POINT = "/comment_service_ajax"; diff --git a/src/assets/js/libs/youtube/dependencies/youtube/index.js b/src/assets/js/libs/youtube/dependencies/youtube/index.js new file mode 100644 index 0000000..2429a2d --- /dev/null +++ b/src/assets/js/libs/youtube/dependencies/youtube/index.js @@ -0,0 +1,29 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./Base"), exports); +__exportStar(require("./BaseChannel"), exports); +__exportStar(require("./BaseVideo"), exports); +__exportStar(require("./Channel"), exports); +__exportStar(require("./Chat"), exports); +__exportStar(require("./Client"), exports); +__exportStar(require("./Comment"), exports); +__exportStar(require("./Continuable"), exports); +__exportStar(require("./LiveVideo"), exports); +__exportStar(require("./MixPlaylist"), exports); +__exportStar(require("./Playlist"), exports); +__exportStar(require("./PlaylistCompact"), exports); +__exportStar(require("./Reply"), exports); +__exportStar(require("./SearchResult"), exports); +__exportStar(require("./Transcript"), exports); +__exportStar(require("./Video"), exports); +__exportStar(require("./VideoCompact"), exports); diff --git a/src/assets/js/libs/youtube/getChannelDesc.js b/src/assets/js/libs/youtube/getChannelDesc.js new file mode 100644 index 0000000..792a8f5 --- /dev/null +++ b/src/assets/js/libs/youtube/getChannelDesc.js @@ -0,0 +1,63 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var getData_1 = require("./helpers/getData"); +function getChannelDesc(id) { + var _a, _b; + return __awaiter(this, void 0, void 0, function () { + var data, description, e_1; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + _c.trys.push([0, 2, , 3]); + return [4 /*yield*/, (0, getData_1.default)('https://m.youtube.com/channel/' + id + '/videos')]; + case 1: + data = _c.sent(); + description = ((_b = (_a = data.metadata) === null || _a === void 0 ? void 0 : _a.channelMetadataRenderer) === null || _b === void 0 ? void 0 : _b.description) || ''; + return [2 /*return*/, description]; + case 2: + e_1 = _c.sent(); + console.log('channel desc error for ' + id); + return [3 /*break*/, 3]; + case 3: return [2 /*return*/]; + } + }); + }); +} +exports.default = getChannelDesc; +//# sourceMappingURL=getChannelDesc.js.map \ No newline at end of file diff --git a/src/assets/js/libs/youtube/getChannelVideos.js b/src/assets/js/libs/youtube/getChannelVideos.js new file mode 100644 index 0000000..3f7df0f --- /dev/null +++ b/src/assets/js/libs/youtube/getChannelVideos.js @@ -0,0 +1,87 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var youtubei_1 = require("./dependencies/index"); +var formatVideo_1 = require("./helpers/formatVideo"); +function getChannelVideos(id, published_after) { + return __awaiter(this, void 0, void 0, function () { + var youtube, data, channelsVideos, apikey, token, videos, i, video, e_1; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + _a.trys.push([0, 7, , 8]); + youtube = new youtubei_1.Client(); + return [4 /*yield*/, youtube.findOne(id, { type: 'channel' })]; + case 1: + data = _a.sent(); + return [4 /*yield*/, data.videos.next()]; + case 2: + _a.sent(); + channelsVideos = data.videos.items; + apikey = ''; + token = ''; + videos = []; + i = 0; + _a.label = 3; + case 3: + if (!(i < channelsVideos.length)) return [3 /*break*/, 6]; + return [4 /*yield*/, (0, formatVideo_1.default)(channelsVideos[i], false)]; + case 4: + video = _a.sent(); + if (video && video !== undefined && video.publishedAt) { + if ((published_after && video.publishedAt.getTime() > published_after.getTime()) || !published_after) { + videos.push(video); + } + } + _a.label = 5; + case 5: + i++; + return [3 /*break*/, 3]; + case 6: return [2 /*return*/, videos]; + case 7: + e_1 = _a.sent(); + console.log('cannot get channel videos for id: ' + id + ', try again'); + console.log(e_1); + return [3 /*break*/, 8]; + case 8: return [2 /*return*/]; + } + }); + }); +} +exports.default = getChannelVideos; +//# sourceMappingURL=getChannelVideos.js.map \ No newline at end of file diff --git a/src/assets/js/libs/youtube/getPlaylistVideos.js b/src/assets/js/libs/youtube/getPlaylistVideos.js new file mode 100644 index 0000000..0ae6a94 --- /dev/null +++ b/src/assets/js/libs/youtube/getPlaylistVideos.js @@ -0,0 +1,85 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var youtubei_1 = require("./dependencies/index"); +function getPlaylistVideos(id, speedDate) { + return __awaiter(this, void 0, void 0, function () { + var youtube, data, items, e_1; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + _a.trys.push([0, 2, , 3]); + youtube = new youtubei_1.Client(); + return [4 /*yield*/, youtube.findOne(id, { type: 'playlist' })]; + case 1: + data = _a.sent(); + items = data; + return [2 /*return*/, data + // const apikey = '' + // let token: string = '' + // let videos: Video[] = [] + // for(let i = 0; i < items.length; i++) { + // if (items[i]) { + // const formated = await formatVideo(items[i], speedDate) + // if (formated) { + // videos.push(formated) + // } + // } + // } + // while(token) { + // try { + // console.log('wip') + // } catch(e) { + // console.log('getPlaylistVideos failed') + // // console.log(e) + // token = '' + // } + // } + // return videos + ]; + case 2: + e_1 = _a.sent(); + console.log('cannot get playlist ' + id + ', try again'); + return [3 /*break*/, 3]; + case 3: return [2 /*return*/]; + } + }); + }); +} +exports.default = getPlaylistVideos; +//# sourceMappingURL=getPlaylistVideos.js.map \ No newline at end of file diff --git a/src/assets/js/libs/youtube/getVideoDate.js b/src/assets/js/libs/youtube/getVideoDate.js new file mode 100644 index 0000000..75ef9a9 --- /dev/null +++ b/src/assets/js/libs/youtube/getVideoDate.js @@ -0,0 +1,63 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var youtubei_1 = require("./dependencies/index"); +var dayjs = require("./dependencies/dayjs.min"); +function getVideoDate(id) { + return __awaiter(this, void 0, void 0, function () { + var youtube, data, e_1; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + _a.trys.push([0, 2, , 3]); + youtube = new youtubei_1.Client(); + return [4 /*yield*/, youtube.getVideo(id)]; + case 1: + data = _a.sent(); + return [2 /*return*/, dayjs(data.uploadDate).toDate()]; + case 2: + e_1 = _a.sent(); + console.log('cannot get date for ' + id + ', try again'); + return [3 /*break*/, 3]; + case 3: return [2 /*return*/]; + } + }); + }); +} +exports.default = getVideoDate; +//# sourceMappingURL=getVideoDate.js.map \ No newline at end of file diff --git a/src/assets/js/libs/youtube/getVideoDesc.js b/src/assets/js/libs/youtube/getVideoDesc.js new file mode 100644 index 0000000..d0d8dc6 --- /dev/null +++ b/src/assets/js/libs/youtube/getVideoDesc.js @@ -0,0 +1,64 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var getData_1 = require("./helpers/getData"); +var findVal_1 = require("./helpers/findVal"); +function getVideoDesc(id) { + return __awaiter(this, void 0, void 0, function () { + var data, description, e_1; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + _a.trys.push([0, 2, , 3]); + return [4 /*yield*/, (0, getData_1.default)('https://m.youtube.com/watch?v=' + id)]; + case 1: + data = _a.sent(); + description = (0, findVal_1.default)(data, 'descriptionBodyText').runs[0].text || ''; + return [2 /*return*/, description]; + case 2: + e_1 = _a.sent(); + console.log('video desc error for ' + id); + console.log(e_1); + return [3 /*break*/, 3]; + case 3: return [2 /*return*/]; + } + }); + }); +} +exports.default = getVideoDesc; +//# sourceMappingURL=getVideoDesc.js.map \ No newline at end of file diff --git a/src/assets/js/libs/youtube/getVideoSubtitles.js b/src/assets/js/libs/youtube/getVideoSubtitles.js new file mode 100644 index 0000000..1092dcd --- /dev/null +++ b/src/assets/js/libs/youtube/getVideoSubtitles.js @@ -0,0 +1,61 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var getData_1 = require("./helpers/getData"); +function getVideoSubtitles(id) { + return __awaiter(this, void 0, void 0, function () { + var data, e_1; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + _a.trys.push([0, 2, , 3]); + return [4 /*yield*/, getData_1.default('https://m.youtube.com/watch?v=' + id + '&type=subtitles')]; + case 1: + data = _a.sent(); + return [2 /*return*/, data.data.events]; + case 2: + e_1 = _a.sent(); + console.log('video subtitle error for ' + id); + return [3 /*break*/, 3]; + case 3: return [2 /*return*/]; + } + }); + }); +} +exports.default = getVideoSubtitles; +//# sourceMappingURL=getVideoSubtitles.js.map \ No newline at end of file diff --git a/src/assets/js/libs/youtube/getVideosFromDesc.js b/src/assets/js/libs/youtube/getVideosFromDesc.js new file mode 100644 index 0000000..93f7986 --- /dev/null +++ b/src/assets/js/libs/youtube/getVideosFromDesc.js @@ -0,0 +1,98 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var cleanTitle_1 = require("./helpers/cleanTitle"); +var getVideoDesc_1 = require("./getVideoDesc"); +var getVideoDate_1 = require("./getVideoDate"); +var searchVideo_1 = require("./searchVideo"); +function getVideosFromDesc(yt_id) { + return __awaiter(this, void 0, void 0, function () { + var videos, desc, i, content, elt, title, artist, videosSearched, y, track, original_title_lower, _a, e_1; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + _b.trys.push([0, 10, , 11]); + videos = []; + return [4 /*yield*/, (0, getVideoDesc_1.default)(yt_id)]; + case 1: + desc = _b.sent(); + if (!desc) return [3 /*break*/, 9]; + i = 0; + _b.label = 2; + case 2: + if (!(i < desc.length)) return [3 /*break*/, 9]; + content = desc[i].text; + if (!(content.includes('-') && content.length < 100)) return [3 /*break*/, 8]; + elt = (0, cleanTitle_1.default)(content); + title = elt.split('-')[1].trim(); + artist = elt.split('-')[0].trim(); + return [4 /*yield*/, (0, searchVideo_1.default)(title + ' ' + artist)]; + case 3: + videosSearched = _b.sent(); + y = 0; + _b.label = 4; + case 4: + if (!(y < videosSearched.videos.length)) return [3 /*break*/, 8]; + track = videosSearched.videos[y]; + original_title_lower = track.original_title.toLowerCase(); + if (!(original_title_lower.includes(artist.split(' ')[0].toLowerCase()) && original_title_lower.includes(title.split(' ')[0].toLowerCase()))) return [3 /*break*/, 6]; + _a = track; + return [4 /*yield*/, (0, getVideoDate_1.default)(track.id)]; + case 5: + _a.publishedAt = _b.sent(); + videos.push(track); + return [3 /*break*/, 8]; + case 6: return [3 /*break*/, 7]; + case 7: + y++; + return [3 /*break*/, 4]; + case 8: + i++; + return [3 /*break*/, 2]; + case 9: return [2 /*return*/, videos]; + case 10: + e_1 = _b.sent(); + console.log('getVideosFromDesc error, maybe captcha to resolve'); + return [3 /*break*/, 11]; + case 11: return [2 /*return*/]; + } + }); + }); +} +exports.default = getVideosFromDesc; +//# sourceMappingURL=getVideosFromDesc.js.map \ No newline at end of file diff --git a/src/assets/js/libs/youtube/helpers/cleanTitle.js b/src/assets/js/libs/youtube/helpers/cleanTitle.js new file mode 100644 index 0000000..0c801a0 --- /dev/null +++ b/src/assets/js/libs/youtube/helpers/cleanTitle.js @@ -0,0 +1,15 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function cleanTitle(title) { + var braketsRegex = /\[[^)]*\]/; + var forbidenTerms = ['(full album)', '(official ep)', '(official video)', '(video official)', '(radio edit)', '(DEEP MEDi Musik)', '(Original Mix)', '(Official Music Video)']; + title = title.replace(braketsRegex, ''); + forbidenTerms.forEach(function (forbidenTerm) { + title = title.replace(new RegExp(forbidenTerm, 'ig'), ''); + title = title.replace('()', ''); + title = title.replace(/\[(.*)\]/, ''); + }); + return title; +} +exports.default = cleanTitle; +//# sourceMappingURL=cleanTitle.js.map \ No newline at end of file diff --git a/src/assets/js/libs/youtube/helpers/decodeHex.js b/src/assets/js/libs/youtube/helpers/decodeHex.js new file mode 100644 index 0000000..ae57500 --- /dev/null +++ b/src/assets/js/libs/youtube/helpers/decodeHex.js @@ -0,0 +1,7 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function decodeHex(hex) { + return hex.replace(/\\x22/g, '"').replace(/\\x7b/g, '{').replace(/\\x7d/g, '}').replace(/\\x5b/g, '[').replace(/\\x5d/g, ']').replace(/\\x3b/g, ';').replace(/\\x3d/g, '=').replace(/\\x27/g, '\'').replace(/\\\\/g, 'doubleAntiSlash').replace(/\\/g, '').replace(/doubleAntiSlash/g, '\\'); +} +exports.default = decodeHex; +//# sourceMappingURL=decodeHex.js.map \ No newline at end of file diff --git a/src/assets/js/libs/youtube/helpers/findVal.js b/src/assets/js/libs/youtube/helpers/findVal.js new file mode 100644 index 0000000..2d8f492 --- /dev/null +++ b/src/assets/js/libs/youtube/helpers/findVal.js @@ -0,0 +1,18 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function findVal(object, key) { + var value; + Object.keys(object).some(function (k) { + if (k === key) { + value = object[k]; + return true; + } + if (object[k] && typeof object[k] === 'object') { + value = findVal(object[k], key); + return value !== undefined; + } + }); + return value; +} +exports.default = findVal; +//# sourceMappingURL=findVal.js.map \ No newline at end of file diff --git a/src/assets/js/libs/youtube/helpers/formatVideo.js b/src/assets/js/libs/youtube/helpers/formatVideo.js new file mode 100644 index 0000000..a2c5de3 --- /dev/null +++ b/src/assets/js/libs/youtube/helpers/formatVideo.js @@ -0,0 +1,86 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var getVideoDate_1 = require("../getVideoDate"); +var getDateFromText_1 = require("./getDateFromText"); +function formatVideo(video, speedDate) { + if (speedDate === void 0) { speedDate = false; } + return __awaiter(this, void 0, void 0, function () { + var splited, publishedAt, e_1; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + _a.trys.push([0, 4, , 5]); + // title formating + video.original_title = video.title; + if (video.title.split('-').length === 1) { + video.artist = ''; + } + else { + splited = video.original_title.match(/([^,]*)-(.*)/); + video.artist = splited[1]; + video.title = splited[2]; + } + publishedAt = new Date(Date.now()); + if (!speedDate) return [3 /*break*/, 1]; + publishedAt = (0, getDateFromText_1.default)(video.uploadDate); + return [3 /*break*/, 3]; + case 1: return [4 /*yield*/, (0, getVideoDate_1.default)(video.id)]; + case 2: + publishedAt = _a.sent(); + _a.label = 3; + case 3: return [2 /*return*/, { + id: video.id, + original_title: video.original_title.trim(), + title: video.title.trim(), + artist: video.artist.trim(), + duration: video.duration, + publishedAt: publishedAt, + }]; + case 4: + e_1 = _a.sent(); + console.log('format video failed'); + console.log(e_1); + return [3 /*break*/, 5]; + case 5: return [2 /*return*/]; + } + }); + }); +} +exports.default = formatVideo; +//# sourceMappingURL=formatVideo.js.map \ No newline at end of file diff --git a/src/assets/js/libs/youtube/helpers/formatYoutubeCount.js b/src/assets/js/libs/youtube/helpers/formatYoutubeCount.js new file mode 100644 index 0000000..f1f90e1 --- /dev/null +++ b/src/assets/js/libs/youtube/helpers/formatYoutubeCount.js @@ -0,0 +1,16 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function formatYoutubeCount(raw) { + var isMill = raw === null || raw === void 0 ? void 0 : raw.includes('M'); + var isKilo = raw === null || raw === void 0 ? void 0 : raw.includes('k'); + var nbSubscriber = raw === null || raw === void 0 ? void 0 : raw.replace(/[^0-9,.]/g, '').replace(',', '.'); + if (isMill) { + nbSubscriber *= 1000000; + } + else if (isKilo) { + nbSubscriber *= 1000; + } + return parseInt(nbSubscriber) || 0; +} +exports.default = formatYoutubeCount; +//# sourceMappingURL=formatYoutubeCount.js.map \ No newline at end of file diff --git a/src/assets/js/libs/youtube/helpers/getData.js b/src/assets/js/libs/youtube/helpers/getData.js new file mode 100644 index 0000000..edfc39f --- /dev/null +++ b/src/assets/js/libs/youtube/helpers/getData.js @@ -0,0 +1,103 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var axios_1 = require("axios"); +var decodeHex_1 = require("./decodeHex"); +var findVal_1 = require("./findVal"); +function getData(urlstring) { + var _a, _b; + return __awaiter(this, void 0, void 0, function () { + var dataRegex, playerRegex, dateRegex, apiRegex, url, isAjax, isDate, isSubtitles, body, headers, data, raw, raw, apikey, data; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + dataRegex = /var\ ytInitialData\ \=\ \'(.*)\'\;<\/script>/; + playerRegex = /var\ ytInitialPlayerResponse\ \=\ (.*)id\=\"player\"/s; + dateRegex = /publishDate":"(.*)","ownerChannelName/; + apiRegex = /"innertubeApiKey":"(.*?)"/; + url = new URL(urlstring); + isAjax = false; + isDate = false; + isSubtitles = false; + if (url.searchParams.get('token')) { + isAjax = true; + } + if (url.searchParams.get('type') === 'date') { + isDate = true; + } + if (url.searchParams.get('type') === 'subtitles') { + isSubtitles = true; + } + if (!isAjax) return [3 /*break*/, 2]; + data = { context: { client: { clientName: 'WEB', clientVersion: '2.20210401.08.00' } }, continuation: url.searchParams.get('token') }; + return [4 /*yield*/, (0, axios_1.default)({ method: 'post', url: urlstring, data: data })]; + case 1: + body = (_c.sent()).data; + return [2 /*return*/, { items: (0, findVal_1.default)(body, 'continuationItems'), token: (0, findVal_1.default)(body, 'token') }]; + case 2: + headers = { + headers: { + 'Access-Control-Allow-Origin': '*', + 'x-youtube-client-name': 1, + 'x-youtube-client-version': '2.20200911.04.00', + 'User-Agent': 'Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Mobile Safari/537.36', + } + }; + return [4 /*yield*/, (0, axios_1.default)(urlstring, headers)]; + case 3: + body = (_c.sent()).data; + if (isDate) { + raw = ((_a = dateRegex.exec(body)) === null || _a === void 0 ? void 0 : _a[1]) || '{}'; + return [2 /*return*/, raw]; + } + else { + raw = ((_b = dataRegex.exec(body)) === null || _b === void 0 ? void 0 : _b[1]) || '{}'; + apikey = apiRegex.exec(body)[1] || ''; + data = JSON.parse((0, decodeHex_1.default)(raw)); + // let fs = require('fs'); fs.writeFile('raw.json', decodeHex(raw), (e)=>{console.log(e)}) + data.apikey = apikey; + return [2 /*return*/, data]; + } + _c.label = 4; + case 4: return [2 /*return*/]; + } + }); + }); +} +exports.default = getData; +//# sourceMappingURL=getData.js.map \ No newline at end of file diff --git a/src/assets/js/libs/youtube/helpers/getDateFromText.js b/src/assets/js/libs/youtube/helpers/getDateFromText.js new file mode 100644 index 0000000..d3b4f34 --- /dev/null +++ b/src/assets/js/libs/youtube/helpers/getDateFromText.js @@ -0,0 +1,49 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function getDateFromText(dateTxt) { + var unit = { + second: { + terms: ['sec', 'Sekun', 'segun'], + factor: 1, + }, + minute: { + terms: ['min'], + factor: 1000 * 60, + }, + hour: { + terms: ['hour', 'heure', 'uur'], + factor: 1000 * 60 * 60, + }, + day: { + terms: ['jour', 'day', 'gio', 'dag', 'tag', 'day'], + factor: 1000 * 60 * 60 * 24, + }, + week: { + terms: ['sem', 'week', 'setti', 'woche'], + factor: 1000 * 60 * 60 * 24 * 7, + }, + month: { + terms: ['mo'], + factor: 1000 * 60 * 60 * 24 * 7 * 4, + }, + year: { + terms: ['an', 'year', 'ja'], + factor: 1000 * 60 * 60 * 24 * 7 * 4 * 12, + }, + }; + var digit = parseInt(dateTxt.replace(/\D/g, '')) || 0; + if (!dateTxt || digit === 0) { + return new Date(Date.now()); + } + for (var i in unit) { + for (var y in unit[i].terms) { + if (dateTxt.includes(unit[i].terms[y])) { + var secondsSince = unit[i].factor * digit; + return new Date(Date.now() - secondsSince); + } + } + } + return new Date(Date.now()); +} +exports.default = getDateFromText; +//# sourceMappingURL=getDateFromText.js.map \ No newline at end of file diff --git a/src/assets/js/libs/youtube/helpers/wait.js b/src/assets/js/libs/youtube/helpers/wait.js new file mode 100644 index 0000000..691a9df --- /dev/null +++ b/src/assets/js/libs/youtube/helpers/wait.js @@ -0,0 +1,12 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function wait() { + var ms = Math.floor(Math.random() * 300); + var start = new Date().getTime(); + var end = start; + while (end < start + ms) { + end = new Date().getTime(); + } +} +exports.default = wait; +//# sourceMappingURL=wait.js.map \ No newline at end of file diff --git a/src/assets/js/libs/youtube/searchChannel.js b/src/assets/js/libs/youtube/searchChannel.js new file mode 100644 index 0000000..a846c5c --- /dev/null +++ b/src/assets/js/libs/youtube/searchChannel.js @@ -0,0 +1,93 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var youtubei_1 = require("./dependencies/index"); +var formatYoutubeCount_1 = require("./helpers/formatYoutubeCount"); +function searchChannel(terms, token, apikey) { + return __awaiter(this, void 0, void 0, function () { + var youtube, data, items, channels_1, didyoumean, e_1; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + _a.trys.push([0, 2, , 3]); + youtube = new youtubei_1.Client(); + return [4 /*yield*/, youtube.search(terms, { type: 'channel' })]; + case 1: + data = _a.sent(); + items = []; + channels_1 = []; + didyoumean = ''; + if (!token) { + apikey = ''; + token = ''; + items = data.items; + } + else { + console.log('wip'); + } + items.map(function (item) { + var avatarId = item.thumbnails[0].url.replace('//yt3.ggpht.com/', ''); + var nbSubscriber = (0, formatYoutubeCount_1.default)(item.subscriberCount || '0'); + channels_1.push({ + name: item.name, + channel_id: item.subscriberCount, + nb_videos: item.videoCount, + nb_subscriber: nbSubscriber, + official: false, + channel_avatar_small: 'https://yt3.ggpht.com/' + avatarId.replace('=s88', '=s80'), + channel_avatar_medium: 'https://yt3.ggpht.com/' + avatarId.replace('=s88', '=s200'), + channel_avatar_large: 'https://yt3.ggpht.com/' + avatarId.replace('=s88', '=s800'), + }); + }); + return [2 /*return*/, { + channels: channels_1, + didyoumean: didyoumean, + token: token, + apikey: apikey, + }]; + case 2: + e_1 = _a.sent(); + console.log('search channel error, terms: ' + terms); + return [3 /*break*/, 3]; + case 3: return [2 /*return*/]; + } + }); + }); +} +exports.default = searchChannel; +//# sourceMappingURL=searchChannel.js.map \ No newline at end of file diff --git a/src/assets/js/libs/youtube/searchVideo.js b/src/assets/js/libs/youtube/searchVideo.js new file mode 100644 index 0000000..97f0fb5 --- /dev/null +++ b/src/assets/js/libs/youtube/searchVideo.js @@ -0,0 +1,101 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var youtubei_1 = require("./dependencies/index"); +var formatVideo_1 = require("./helpers/formatVideo"); +function searchVideo(terms, token, apikey) { + return __awaiter(this, void 0, void 0, function () { + var youtube, data, items, videos, didyoumean, i, formated, e_1; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + _a.trys.push([0, 6, , 7]); + youtube = new youtubei_1.Client(); + return [4 /*yield*/, youtube.search(terms, { type: 'video' })]; + case 1: + data = _a.sent(); + items = []; + videos = []; + didyoumean = ''; + // initial videos search + if (!token) { + terms; + apikey = ''; + token = ''; + items = data.items; + } + // more videos + else { + console.log('wip'); + } + i = 0; + _a.label = 2; + case 2: + if (!(i < items.length)) return [3 /*break*/, 5]; + return [4 /*yield*/, (0, formatVideo_1.default)(items[i], true)]; + case 3: + formated = _a.sent(); + if (formated) { + if (formated.id === 'didyoumean') { + didyoumean = formated.title; + } + else { + videos.push(formated); + } + } + _a.label = 4; + case 4: + i++; + return [3 /*break*/, 2]; + case 5: return [2 /*return*/, { + videos: videos, + didyoumean: didyoumean, + token: apikey, + apikey: apikey, + }]; + case 6: + e_1 = _a.sent(); + console.log('search videos error, terms: ' + terms); + return [3 /*break*/, 7]; + case 7: return [2 /*return*/]; + } + }); + }); +} +exports.default = searchVideo; +//# sourceMappingURL=searchVideo.js.map \ No newline at end of file diff --git a/src/assets/js/libs/youtube/usetube.js b/src/assets/js/libs/youtube/usetube.js new file mode 100644 index 0000000..011bb91 --- /dev/null +++ b/src/assets/js/libs/youtube/usetube.js @@ -0,0 +1,19 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.searchVideo = exports.searchChannel = exports.getVideosFromDesc = exports.getVideoDesc = exports.getVideoDate = exports.getPlaylistVideos = exports.getChannelVideos = exports.getChannelDesc = void 0; +var getChannelDesc_1 = require("./getChannelDesc"); +exports.getChannelDesc = getChannelDesc_1.default; +var getChannelVideos_1 = require("./getChannelVideos"); +exports.getChannelVideos = getChannelVideos_1.default; +var getPlaylistVideos_1 = require("./getPlaylistVideos"); +exports.getPlaylistVideos = getPlaylistVideos_1.default; +var getVideoDate_1 = require("./getVideoDate"); +exports.getVideoDate = getVideoDate_1.default; +var getVideoDesc_1 = require("./getVideoDesc"); +exports.getVideoDesc = getVideoDesc_1.default; +var getVideosFromDesc_1 = require("./getVideosFromDesc"); +exports.getVideosFromDesc = getVideosFromDesc_1.default; +var searchChannel_1 = require("./searchChannel"); +exports.searchChannel = searchChannel_1.default; +var searchVideo_1 = require("./searchVideo"); +exports.searchVideo = searchVideo_1.default; diff --git a/src/assets/js/panels/chat.js b/src/assets/js/panels/chat.js new file mode 100644 index 0000000..0bd0709 --- /dev/null +++ b/src/assets/js/panels/chat.js @@ -0,0 +1,22 @@ +/** + * @author TECNO BROS + + */ + +'use strict'; + +import { logger, database, changePanel } from '../utils.js'; + +const { ipcRenderer } = require('electron'); +const pkg = require('../package.json'); + + +const dataDirectory = process.env.APPDATA || (process.platform == 'darwin' ? `${process.env.HOME}/Library/Application Support` : process.env.HOME) + +class Chat { + static id = "chat"; + async init(config, news) { + this.config = config + } +} +export default Chat; \ No newline at end of file diff --git a/src/assets/js/panels/friends.js b/src/assets/js/panels/friends.js new file mode 100644 index 0000000..a8d8b75 --- /dev/null +++ b/src/assets/js/panels/friends.js @@ -0,0 +1,1464 @@ +/** + * @author TECNO BROS + + */ + +'use strict'; + +import { logger, database, changePanel } from '../utils.js'; + +const { ipcRenderer } = require('electron'); +const pkg = require('../package.json'); +const fetch = require('node-fetch'); +const axios = require("axios"); + +const Swal = require("./assets/js/libs/sweetalert/sweetalert2.all.min"); +const Toast = Swal.mixin({ + toast: true, + position: "top-end", + showConfirmButton: false, + timer: 5000, + timerProgressBar: true, + didOpen: (toast) => { + toast.addEventListener("mouseenter", Swal.stopTimer); + toast.addEventListener("mouseleave", Swal.resumeTimer); + }, +}); + +let amigos; +let lang; + +const dataDirectory = process.env.APPDATA || (process.platform == 'darwin' ? `${process.env.HOME}/Library/Application Support` : process.env.HOME) +import { Lang } from "../utils/lang.js"; + +class Friends { + static id = "friends"; + async init(config, news) { + this.config = config; + this.database = await new database().init(); + lang = await new Lang().GetLang(); + this.AddFriend(); + this.Solicitudes(); + this.GetOnlineUsers(); + this.ObtenerAmigos(); + this.Chat(); + } + + async Chat() { + document.getElementById("chat-btn").addEventListener("click", () => { + changePanel("chat"); + }); + + document.getElementById("back-chat-btn").addEventListener("click", () => { + changePanel("friends"); + }); + } + + async GetOnlineUsers() { + ipcRenderer.send("socket", "getOnlineUsers", {}); + + ipcRenderer.on("onlineUsers", (e, data) => { + }); + + ipcRenderer.on('amigos', async (e, amigos_) => { + amigos = amigos_; + }); + } + + async AddFriend() { + let btnAddFriends = document.getElementById('add-friends'); + + let uuid = (await this.database.get("1234", "accounts-selected")).value; + let account = (await this.database.get(uuid.selected, "accounts")).value; + + btnAddFriends.addEventListener('click', (e) => { + // Crear el elemento modal + const modal = document.createElement('div'); + modal.className = 'modal is-active'; + + // Crear el fondo del modal + const modalBackground = document.createElement('div'); + modalBackground.className = 'modal-background'; + + // Crear el contenido del modal + const modalCard = document.createElement('div'); + modalCard.className = 'modal-card'; + + // Crear el encabezado del modal + const modalHeader = document.createElement('header'); + modalHeader.className = 'modal-card-head'; + + const modalTitle = document.createElement('p'); + modalTitle.className = 'modal-card-title'; + modalTitle.textContent = lang.add_friend_text; + + const closeButton = document.createElement('button'); + closeButton.className = 'delete'; + closeButton.setAttribute('aria-label', 'close'); + + modalHeader.appendChild(modalTitle); + modalHeader.appendChild(closeButton); + + // Crear el cuerpo del modal + const modalBody = document.createElement('section'); + modalBody.className = 'resultado-amigos modal-card-body'; + + const inputContainer = document.createElement('div'); + inputContainer.className = 'content'; + + const inputControl = document.createElement('div'); + inputControl.className = 'control is-info'; + + const input = document.createElement('input'); + input.className = 'input'; + input.setAttribute('type', 'text'); + input.setAttribute('placeholder', lang.username); + + inputControl.appendChild(input); + inputContainer.appendChild(inputControl); + modalBody.appendChild(inputContainer); + + // Crear el contenido de la caja en el cuerpo del modal + //crea un div + + const users = document.createElement('div'); + modalBody.appendChild(users); + + // Crear el pie del modal + const modalFooter = document.createElement('footer'); + modalFooter.className = 'modal-card-foot'; + + const searchButton = document.createElement('button'); + searchButton.className = 'button is-info'; + searchButton.textContent = lang.search; + + modalFooter.appendChild(searchButton); + + // Agregar elementos al modal + modalCard.appendChild(modalHeader); + modalCard.appendChild(modalBody); + modalCard.appendChild(modalFooter); + + modal.appendChild(modalBackground); + modal.appendChild(modalCard); + + // Agregar el modal al documento + document.body.appendChild(modal); + + closeButton.addEventListener('click', () => { + modal.remove(); + }); + + searchButton.addEventListener('click', () => { + inputControl.classList.add('is-loading'); + input.setAttribute('disabled', 'disabled'); + + users.innerHTML = ''; + + fetch('http://api.battlylauncher.com/api/users/buscarUsuarios', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + username: input.value + }) + }).then(res => res.json()).then(async res => { + inputControl.classList.remove('is-loading'); + input.removeAttribute('disabled'); + + if (res.error) { + console.error(res.error); + return; + } + + /* para cada usuario en el array de respuesta (data.usuarios) => crear esto: + +
    +
    +
    +
    + Image +
    +
    +
    +
    +

    + Usuario +

    +
    +
    +
    + +
    +
    +
    + + Y añadirlo debajo del input + + */ + + for (let user of res.usuarios) { + try { + await axios.get(`http://api.battlylauncher.com/api/skin/${user}.png`) + const box = document.createElement('div'); + box.className = 'box'; + + const mediaArticle = document.createElement('article'); + mediaArticle.className = 'media'; + + const mediaLeft = document.createElement('div'); + mediaLeft.className = 'media-left'; + + // Crear la imagen dentro del visor de cara + const imgInsideFaceViewer = document.createElement('img'); + imgInsideFaceViewer.className = 'mc-face-viewer-8x'; + + mediaLeft.appendChild(imgInsideFaceViewer); + + const mediaContent = document.createElement('div'); + mediaContent.className = 'media-content'; + + const content = document.createElement('div'); + content.className = 'content'; + + const userParagraph = document.createElement('p'); + userParagraph.style.fontSize = '20px'; + userParagraph.textContent = user; + + content.appendChild(userParagraph); + mediaContent.appendChild(content); + + const mediaRight = document.createElement('div'); + mediaRight.className = 'media-right'; + mediaRight.style.display = 'flex'; + mediaRight.style.alignItems = 'center'; + + const addButton = document.createElement('button'); + addButton.className = 'button is-info is-square'; + addButton.style.marginLeft = 'auto'; + addButton.style.height = '30px'; + addButton.style.width = '30px'; + + const plusIcon = document.createElement('i'); + plusIcon.className = 'fa-solid fa-plus'; + + addButton.appendChild(plusIcon); + mediaRight.appendChild(addButton); + + mediaArticle.appendChild(mediaLeft); + mediaArticle.appendChild(mediaContent); + mediaArticle.appendChild(mediaRight); + + box.appendChild(mediaArticle); + users.appendChild(box); + imgInsideFaceViewer.style.backgroundImage = `url(http://api.battlylauncher.com/api/skin/${user}.png)` + + + addButton.addEventListener('click', () => + { + + let amigosArray = []; + for (let amigo of amigos) { + amigosArray.push(amigo.username); + } + + if (user == account.name) { + Toast.fire({ + icon: "error", + title: lang.you_cannot_add_yourself + }); + return; + } else if (amigosArray.includes(user)) { + Toast.fire({ + icon: "error", + title: lang.you_already_have_this_friend, + }); + return; + } else { + ipcRenderer.send('enviarSolicitud', { + sender: account.name, + sended: user, + password: account.password + }); + + Toast.fire({ + icon: "success", + title: `${lang.request_sent_to} ${user} ${lang.correctly}.`, + }); + } + }); + + } catch (error) { + console.log(`❌ Error al obtener la skin de ${user}.`); + const box = document.createElement('div'); + box.className = 'box'; + + const mediaArticle = document.createElement('article'); + mediaArticle.className = 'media'; + + const mediaLeft = document.createElement('div'); + mediaLeft.className = 'media-left'; + + // Crear la imagen dentro del visor de cara + const imgInsideFaceViewer = document.createElement('img'); + imgInsideFaceViewer.className = 'mc-face-viewer-8x'; + + mediaLeft.appendChild(imgInsideFaceViewer); + + const mediaContent = document.createElement('div'); + mediaContent.className = 'media-content'; + + const content = document.createElement('div'); + content.className = 'content'; + + const userParagraph = document.createElement('p'); + userParagraph.style.fontSize = '20px'; + userParagraph.textContent = user; + + content.appendChild(userParagraph); + mediaContent.appendChild(content); + + const mediaRight = document.createElement('div'); + mediaRight.className = 'media-right'; + mediaRight.style.display = 'flex'; + mediaRight.style.alignItems = 'center'; + + const addButton = document.createElement('button'); + addButton.className = 'button is-info is-square'; + addButton.style.marginLeft = 'auto'; + addButton.style.height = '30px'; + addButton.style.width = '30px'; + + const plusIcon = document.createElement('i'); + plusIcon.className = 'fa-solid fa-plus'; + + addButton.appendChild(plusIcon); + mediaRight.appendChild(addButton); + + mediaArticle.appendChild(mediaLeft); + mediaArticle.appendChild(mediaContent); + mediaArticle.appendChild(mediaRight); + + box.appendChild(mediaArticle); + users.appendChild(box); + imgInsideFaceViewer.style.backgroundImage = `url(https://minotar.net/skin/MHF_Steve.png)` + + addButton.addEventListener('click', () => + { + + let amigosArray = []; + for (let amigo of amigos) { + amigosArray.push(amigo.username); + } + + if (user == account.name) { + Toast.fire({ + icon: "error", + title: lang.you_cannot_add_yourself + }); + return; + } else if (amigosArray.includes(user)) { + Toast.fire({ + icon: "error", + title: lang.you_already_have_this_friend, + }); + return; + } else { + ipcRenderer.send('enviarSolicitud', { + sender: account.name, + sended: user, + password: account.password + }); + + Toast.fire({ + icon: "success", + title: `${lang.request_sent_to} ${user} ${lang.correctly}.`, + }); + } + }); + } + } + + }).catch(err => { + inputControl.classList.remove('is-loading'); + input.removeAttribute('disabled'); + console.error(err); + }); + }); + + }); + } + + + + async Solicitudes() { + let btnSolicitudes = document.getElementById('solicitudes'); + let uuid = (await this.database.get("1234", "accounts-selected")).value; + let account = (await this.database.get(uuid.selected, "accounts")).value; + + // Definir la función del evento fuera del addEventListener + const handleSolicitudesClick = async (e) => { + // Crear el elemento modal + const modal = document.createElement('div'); + modal.className = 'modal is-active'; + + // Crear el fondo del modal + const modalBackground = document.createElement('div'); + modalBackground.className = 'modal-background'; + + // Crear el contenido del modal + const modalCard = document.createElement('div'); + modalCard.className = 'modal-card'; + + // Crear el encabezado del modal + const modalHeader = document.createElement('header'); + modalHeader.className = 'modal-card-head'; + + const modalTitle = document.createElement('p'); + modalTitle.className = 'modal-card-title'; + modalTitle.textContent = lang.friend_requests; + + const closeButton = document.createElement('button'); + closeButton.className = 'delete'; + closeButton.setAttribute('aria-label', 'close'); + + modalHeader.appendChild(modalTitle); + modalHeader.appendChild(closeButton); + + closeButton.addEventListener('click', () => { + modal.remove(); + }); + + // Crear el cuerpo del modal + const modalBody = document.createElement('section'); + modalBody.className = 'modal-card-body'; + + ipcRenderer.send('obtener-solicitudes', { + username: account.name, + password: account.password + }); + ipcRenderer.on('solicitudes', async (e, solicitudes) => { + + if (solicitudes.enviadas.length == 0 && solicitudes.recibidas.length == 0) { + const box = document.createElement('div'); + box.className = 'box'; + + const article = document.createElement('article'); + article.className = 'media'; + + const mediaLeft = document.createElement('div'); + mediaLeft.className = 'media-left'; + + const img = document.createElement('img'); + img.className = 'mc-face-viewer-8x'; + mediaLeft.appendChild(img); + + const mediaContent = document.createElement('div'); + mediaContent.className = 'media-content'; + + const content = document.createElement('div'); + content.className = 'content'; + + const userParagraph = document.createElement('p'); + userParagraph.style.fontSize = '20px'; + userParagraph.textContent = lang.you_dont_have_any_friend_requests; + + content.appendChild(userParagraph); + mediaContent.appendChild(content); + + article.appendChild(mediaLeft); + article.appendChild(mediaContent); + + box.appendChild(article); + + modalBody.appendChild(box); + + img.style.backgroundImage = "url('https://minotar.net/skin/MHF_Steve.png')"; + } + + for (let solicitud of solicitudes.recibidas) { + try { + await axios.get(`http://api.battlylauncher.com/api/skin/${solicitud}.png`) + + const box1 = document.createElement('div'); + box1.className = 'box'; + + const article1 = document.createElement('article'); + article1.className = 'media'; + + const mediaLeft1 = document.createElement('div'); + mediaLeft1.className = 'media-left'; + + const img1 = document.createElement('img'); + img1.className = 'mc-face-viewer-8x'; + + mediaLeft1.appendChild(img1); + + const mediaContent1 = document.createElement('div'); + mediaContent1.className = 'media-content'; + + const content1 = document.createElement('div'); + content1.className = 'content'; + + const userParagraph1 = document.createElement('p'); + userParagraph1.style.fontSize = '20px'; + userParagraph1.textContent = solicitud; + + content1.appendChild(userParagraph1); + mediaContent1.appendChild(content1); + + const mediaRight1 = document.createElement('div'); + mediaRight1.className = 'media-right'; + mediaRight1.style.display = 'flex'; + mediaRight1.style.flexDirection = 'column'; + mediaRight1.style.alignItems = 'center'; + + const acceptButton1 = document.createElement('button'); + acceptButton1.className = 'button is-success is-square'; + acceptButton1.style.height = '30px'; + acceptButton1.style.width = '10px'; + + const acceptIcon1 = document.createElement('i'); + acceptIcon1.className = 'fa-solid fa-check'; + + acceptButton1.appendChild(acceptIcon1); + mediaRight1.appendChild(acceptButton1); + + const rejectButton1 = document.createElement('button'); + rejectButton1.className = 'button is-danger is-square'; + rejectButton1.style.height = '30px'; + rejectButton1.style.width = '10px'; + rejectButton1.style.marginTop = '5px'; + + const rejectIcon1 = document.createElement('i'); + rejectIcon1.className = 'fa-solid fa-xmark'; + + rejectButton1.appendChild(rejectIcon1); + mediaRight1.appendChild(rejectButton1); + + article1.appendChild(mediaLeft1); + article1.appendChild(mediaContent1); + article1.appendChild(mediaRight1); + + box1.appendChild(article1); + + modalBody.appendChild(box1); + img1.style.backgroundImage = "url('http://api.battlylauncher.com/api/skin/" + solicitud + ".png')"; + + + closeButton.addEventListener('click', () => { + modal.remove(); + }); + + acceptButton1.addEventListener('click', () => { + ipcRenderer.send('aceptar-solicitud', { + username: account.name, + solicitud: solicitud, + password: account.password + }); + + Toast.fire({ + icon: "success", + title: lang.request_accepted + }); + + modal.remove(); + }); + + rejectButton1.addEventListener('click', () => { + ipcRenderer.send('rechazar-solicitud', { + username: account.name, + solicitud: solicitud, + password: account.password + }); + + Toast.fire({ + icon: "success", + title: lang.request_rejected + }); + + modal.remove(); + }); + } catch (error) { + console.log(`❌ Error al obtener la skin de ${user}.`); + const box1 = document.createElement('div'); + box1.className = 'box'; + + const article1 = document.createElement('article'); + article1.className = 'media'; + + const mediaLeft1 = document.createElement('div'); + mediaLeft1.className = 'media-left'; + + const img1 = document.createElement('img'); + img1.className = 'mc-face-viewer-8x'; + + mediaLeft1.appendChild(img1); + + const mediaContent1 = document.createElement('div'); + mediaContent1.className = 'media-content'; + + const content1 = document.createElement('div'); + content1.className = 'content'; + + const userParagraph1 = document.createElement('p'); + userParagraph1.style.fontSize = '20px'; + userParagraph1.textContent = solicitud; + + content1.appendChild(userParagraph1); + mediaContent1.appendChild(content1); + + const mediaRight1 = document.createElement('div'); + mediaRight1.className = 'media-right'; + mediaRight1.style.display = 'flex'; + mediaRight1.style.flexDirection = 'column'; + mediaRight1.style.alignItems = 'center'; + + const acceptButton1 = document.createElement('button'); + acceptButton1.className = 'button is-success is-square'; + acceptButton1.style.height = '30px'; + acceptButton1.style.width = '10px'; + + const acceptIcon1 = document.createElement('i'); + acceptIcon1.className = 'fa-solid fa-check'; + + acceptButton1.appendChild(acceptIcon1); + mediaRight1.appendChild(acceptButton1); + + const rejectButton1 = document.createElement('button'); + rejectButton1.className = 'button is-danger is-square'; + rejectButton1.style.height = '30px'; + rejectButton1.style.width = '10px'; + rejectButton1.style.marginTop = '5px'; + + const rejectIcon1 = document.createElement('i'); + rejectIcon1.className = 'fa-solid fa-xmark'; + + rejectButton1.appendChild(rejectIcon1); + mediaRight1.appendChild(rejectButton1); + + article1.appendChild(mediaLeft1); + article1.appendChild(mediaContent1); + article1.appendChild(mediaRight1); + + box1.appendChild(article1); + + modalBody.appendChild(box1); + img1.style.backgroundImage = "url('https://minotar.net/skin/MHF_Steve.png')"; + + + closeButton.addEventListener('click', () => { + modal.remove(); + }); + + acceptButton1.addEventListener('click', () => { + ipcRenderer.send('aceptar-solicitud', { + username: account.name, + solicitud: solicitud, + password: account.password + }); + + Toast.fire({ + icon: "success", + title: lang.request_accepted + }); + + modal.remove(); + }); + + rejectButton1.addEventListener('click', () => { + ipcRenderer.send('rechazar-solicitud', { + username: account.name, + solicitud: solicitud, + password: account.password + }); + + Toast.fire({ + icon: "success", + title: lang.request_rejected + }); + + modal.remove(); + }); + } + } + + for (let solicitud of solicitudes.enviadas) { + try { + await axios.get(`http://api.battlylauncher.com/api/skin/${solicitud}.png`) + + // Crear el segundo cuadro de solicitud + const box2 = document.createElement('div'); + box2.className = 'box'; + + const article2 = document.createElement('article'); + article2.className = 'media'; + + const mediaLeft2 = document.createElement('div'); + mediaLeft2.className = 'media-left'; + + const img2 = document.createElement('img'); + img2.className = 'mc-face-viewer-8x'; + + mediaLeft2.appendChild(img2); + + const mediaContent2 = document.createElement('div'); + mediaContent2.className = 'media-content'; + + const content2 = document.createElement('div'); + content2.className = 'content'; + + const userParagraph2 = document.createElement('p'); + userParagraph2.style.fontSize = '20px'; + userParagraph2.textContent = solicitud; + + content2.appendChild(userParagraph2); + mediaContent2.appendChild(content2); + + const mediaRight2 = document.createElement('div'); + mediaRight2.className = 'media-right'; + mediaRight2.style.display = 'flex'; + mediaRight2.style.flexDirection = 'column'; + mediaRight2.style.alignItems = 'center'; + + const rejectButton2 = document.createElement('button'); + rejectButton2.className = 'button is-danger is-square'; + rejectButton2.style.height = '30px'; + rejectButton2.style.width = '10px'; + rejectButton2.style.marginTop = '5px'; + + const rejectIcon2 = document.createElement('i'); + rejectIcon2.className = 'fa-solid fa-ban'; + + rejectButton2.appendChild(rejectIcon2); + mediaRight2.appendChild(rejectButton2); + + article2.appendChild(mediaLeft2); + article2.appendChild(mediaContent2); + article2.appendChild(mediaRight2); + + box2.appendChild(article2); + + modalBody.appendChild(box2); + img2.style.backgroundImage = "url('http://api.battlylauncher.com/api/skin/" + solicitud + ".png')"; + } catch (error) { + console.log(`❌ Error al obtener la skin de ${user}.`); + // Crear el segundo cuadro de solicitud + const box2 = document.createElement('div'); + box2.className = 'box'; + + const article2 = document.createElement('article'); + article2.className = 'media'; + + const mediaLeft2 = document.createElement('div'); + mediaLeft2.className = 'media-left'; + + const img2 = document.createElement('img'); + img2.className = 'mc-face-viewer-8x'; + + mediaLeft2.appendChild(img2); + + const mediaContent2 = document.createElement('div'); + mediaContent2.className = 'media-content'; + + const content2 = document.createElement('div'); + content2.className = 'content'; + + const userParagraph2 = document.createElement('p'); + userParagraph2.style.fontSize = '20px'; + userParagraph2.textContent = solicitud; + + content2.appendChild(userParagraph2); + mediaContent2.appendChild(content2); + + const mediaRight2 = document.createElement('div'); + mediaRight2.className = 'media-right'; + mediaRight2.style.display = 'flex'; + mediaRight2.style.flexDirection = 'column'; + mediaRight2.style.alignItems = 'center'; + + const rejectButton2 = document.createElement('button'); + rejectButton2.className = 'button is-danger is-square'; + rejectButton2.style.height = '30px'; + rejectButton2.style.width = '10px'; + rejectButton2.style.marginTop = '5px'; + + const rejectIcon2 = document.createElement('i'); + rejectIcon2.className = 'fa-solid fa-ban'; + + rejectButton2.appendChild(rejectIcon2); + mediaRight2.appendChild(rejectButton2); + + article2.appendChild(mediaLeft2); + article2.appendChild(mediaContent2); + article2.appendChild(mediaRight2); + + box2.appendChild(article2); + + modalBody.appendChild(box2); + img2.style.backgroundImage = "url('https://minotar.net/skin/MHF_Steve.png')"; + } + } + }); + + + // Crear el pie del modal + const modalFooter = document.createElement('footer'); + modalFooter.className = 'modal-card-foot'; + + // Agregar elementos al modal + modalCard.appendChild(modalHeader); + modalCard.appendChild(modalBody); + modalCard.appendChild(modalFooter); + + modal.appendChild(modalBackground); + modal.appendChild(modalCard); + + + document.body.appendChild(modal); + }; + + // Añadir el manejador de eventos al botón + btnSolicitudes.addEventListener('click', handleSolicitudesClick); + } + + + async ObtenerAmigos() { + let btnAmigos = document.getElementById('friends-btn'); + let uuid = (await this.database.get("1234", "accounts-selected")).value; + let account = (await this.database.get(uuid.selected, "accounts")).value; + + let panelAmigos = document.getElementById('lista-de-amigos'); + + let amigosObtenidos = false; + + // Definir la función del evento fuera del addEventListener + btnAmigos.addEventListener('click', async (e) => { + panelAmigos.innerHTML = ''; + + document.querySelector(".preload-content").style.display = "block"; + const loadingText = document.getElementById("loading-text"); + loadingText.innerHTML = lang.loading_friends; + + ipcRenderer.send('obtener-amigos', { + username: account.name, + password: account.password + }); + + setTimeout(() => { + if (!amigosObtenidos) { + console.log('❌ Error al obtener la lista de amigos. Comprueba tu conexión a internet y vuelve a intentarlo más tarde.'); + const box = document.createElement('div'); + box.className = 'box'; + + const article = document.createElement('article'); + article.className = 'media'; + + const mediaLeft = document.createElement('div'); + mediaLeft.className = 'media-left'; + + const img = document.createElement('div'); + img.className = 'mc-face-viewer-8x'; + img.style.backgroundImage = "url('https://minotar.net/skin/MHF_Steve.png')"; + mediaLeft.appendChild(img); + + const mediaContent = document.createElement('div'); + mediaContent.className = 'media-content'; + + const content = document.createElement('div'); + content.className = 'content'; + + const userParagraph = document.createElement('p'); + userParagraph.style.fontSize = '20px'; + userParagraph.textContent = lang.error_loading_friends; + userParagraph.style.textAlign = 'center'; + + content.appendChild(userParagraph); + mediaContent.appendChild(content); + + article.appendChild(mediaContent); + + box.appendChild(article); + + panelAmigos.appendChild(box); + + document.querySelector(".preload-content").style.display = "none"; + } + }, 10000); + + }); + + let amigosOnline = []; + let amigosAusente = []; + let amigosOffline = []; + ipcRenderer.on('amigos', async (e, amigos) => { + + amigosObtenidos = true; + + if (amigos.length == 0) { + const box = document.createElement('div'); + box.className = 'box'; + + const article = document.createElement('article'); + article.className = 'media'; + + const mediaLeft = document.createElement('div'); + mediaLeft.className = 'media-left'; + + const img = document.createElement('div'); + img.className = 'mc-face-viewer-8x'; + img.style.backgroundImage = "url('https://minotar.net/skin/MHF_Steve.png')"; + mediaLeft.appendChild(img); + + const mediaContent = document.createElement('div'); + mediaContent.className = 'media-content'; + + const content = document.createElement('div'); + content.className = 'content'; + + const userParagraph = document.createElement('p'); + userParagraph.style.fontSize = '20px'; + userParagraph.textContent = 'No tienes amigos'; + + content.appendChild(userParagraph); + mediaContent.appendChild(content); + + article.appendChild(mediaLeft); + article.appendChild(mediaContent); + + box.appendChild(article); + + panelAmigos.appendChild(box); + + document.querySelector(".preload-content").style.display = "none"; + } + + //ordenar los amigos para mostrar los que están ausentes, online y offline + let amigosOrdenados = amigos.sort((a, b) => { + if (a.estado === "ausente" && b.estado === "online") { + return -1; + } else if (a.estado === "ausente" && b.estado === "offline") { + return -1; + } else if (a.estado === "online" && b.estado === "ausente") { + return 1; + } else if (a.estado === "online" && b.estado === "offline") { + return -1; + } else if (a.estado === "offline" && b.estado === "ausente") { + return 1; + } else if (a.estado === "offline" && b.estado === "online") { + return 1; + } else { + //ordenar alfabéticamente ignorando mayúsculas + let nameA = a.username.toUpperCase(); + let nameB = b.username.toUpperCase(); + if (nameA < nameB) { + return -1; + } + if (nameA > nameB) { + return 1; + } + return 0; + } + }); + + for (let amigo of amigosOrdenados) { + let username = amigo.username; + let status = amigo.estado; + let details = amigo.details ? amigo.details : 'Offline'; + + if (status === "online") { + try { + await axios.get(`http://api.battlylauncher.com/api/skin/${username}.png`) + + + const box = document.createElement('div'); + box.className = 'box friend-card'; + + const article = document.createElement('article'); + article.className = 'media'; + + const mediaLeft = document.createElement('div'); + mediaLeft.className = 'media-left'; + + const figure = document.createElement('figure'); + figure.className = 'image is-64x64'; + + const img = document.createElement('div'); + img.className = 'mc-face-viewer-8x'; + img.alt = 'Image'; + img.style.borderRadius = '5px'; + + const statusOverlay = document.createElement('div'); + statusOverlay.className = 'status-overlay'; + + const statusImg = document.createElement('img'); + statusImg.src = 'assets/images/icon.png'; + statusImg.alt = 'Status'; + statusImg.style.width = '25px'; + statusImg.style.borderRadius = '5px'; + + statusOverlay.appendChild(statusImg); + figure.appendChild(img); + figure.appendChild(statusOverlay); + mediaLeft.appendChild(figure); + + const mediaContent = document.createElement('div'); + mediaContent.className = 'media-content'; + + const content = document.createElement('div'); + content.className = 'content'; + + const strong = document.createElement('strong'); + strong.className = 'friend-username'; + strong.textContent = username; + + const span = document.createElement('span'); + span.style.marginLeft = '3px'; + + const statusImg2 = document.createElement('img'); + statusImg2.src = 'assets/images/status/online.png'; + statusImg2.alt = ''; + statusImg2.style.width = '15px'; + statusImg2.style.display = 'inline'; + + span.appendChild(statusImg2); + + const br = document.createElement('br'); + + const status = document.createElement('span'); + status.textContent = lang.in_the_main_menu; + + // Agregamos la etiqueta

    y colocamos strong, span, br y status dentro de ella + const paragraph = document.createElement('p'); + paragraph.appendChild(strong); + paragraph.appendChild(span); + paragraph.appendChild(br); + paragraph.appendChild(status); + + content.appendChild(paragraph); + mediaContent.appendChild(content); + + article.appendChild(mediaLeft); + article.appendChild(mediaContent); + + box.appendChild(article); + + panelAmigos.appendChild(box); + img.style.backgroundImage = `url('http://api.battlylauncher.com/api/skin/${username}.png')`; + + } catch (error) { + console.log(`❌ Error al obtener la skin de ${username}.`); + + const box = document.createElement('div'); + box.className = 'box friend-card'; + + const article = document.createElement('article'); + article.className = 'media'; + + const mediaLeft = document.createElement('div'); + mediaLeft.className = 'media-left'; + + const figure = document.createElement('figure'); + figure.className = 'image is-64x64'; + + const img = document.createElement('div'); + img.className = 'mc-face-viewer-8x'; + img.alt = 'Image'; + img.style.borderRadius = '5px'; + + const statusOverlay = document.createElement('div'); + statusOverlay.className = 'status-overlay'; + + const statusImg = document.createElement('img'); + statusImg.src = 'assets/images/icon.png'; + statusImg.alt = 'Status'; + statusImg.style.width = '25px'; + statusImg.style.borderRadius = '5px'; + + statusOverlay.appendChild(statusImg); + figure.appendChild(img); + figure.appendChild(statusOverlay); + mediaLeft.appendChild(figure); + + const mediaContent = document.createElement('div'); + mediaContent.className = 'media-content'; + + const content = document.createElement('div'); + content.className = 'content'; + + const strong = document.createElement('strong'); + strong.className = 'friend-username'; + strong.textContent = username; + + const span = document.createElement('span'); + span.style.marginLeft = '3px'; + + const statusImg2 = document.createElement('img'); + statusImg2.src = 'assets/images/status/online.png'; + statusImg2.alt = ''; + statusImg2.style.width = '15px'; + statusImg2.style.display = 'inline'; + + span.appendChild(statusImg2); + + const br = document.createElement('br'); + + const status = document.createElement('span'); + status.textContent = lang.in_the_main_menu; + + // Agregamos la etiqueta

    y colocamos strong, span, br y status dentro de ella + const paragraph = document.createElement('p'); + paragraph.appendChild(strong); + paragraph.appendChild(span); + paragraph.appendChild(br); + paragraph.appendChild(status); + + content.appendChild(paragraph); + mediaContent.appendChild(content); + + article.appendChild(mediaLeft); + article.appendChild(mediaContent); + + box.appendChild(article); + + panelAmigos.appendChild(box); + img.style.backgroundImage = `url('https://minotar.net/skin/MHF_Steve.png')`; + } + + } else if (status === "ausente") { + + let version; + let icon; + + if (details.includes("Forge")) { + version = "Forge"; + icon = "https://pbs.twimg.com/profile_images/778706890914095109/fhMDH9o6_400x400.jpg"; + } else if (details.includes("Fabric")) { + version = "Fabric"; + icon = "https://battlylauncher.com/assets/img/fabric.png"; + } else if (details.includes("Quilt")) { + version = "Quilt"; + icon = "https://battlylauncher.com/assets/img/quilt.png"; + } else if (details.includes("OptiFine")) { + version = "OptiFine"; + icon = "https://cdn.discordapp.com/attachments/933698201486237716/1170390085561237674/OptiFine_Logo.webp"; + } else if (details.includes("Vanilla")) { + version = "Vanilla"; + icon = "https://battlylauncher.com/assets/img/vanilla.png"; + } else if (details.includes("LabyMod")) { + version = "LabyMod"; + icon = "https://battlylauncher.com/assets/img/labymod.png"; + } else if (details.includes("CMPack")) { + version = "CMPack"; + icon = "https://battlylauncher.com/assets/img/cmpack.png"; + } else if (details.includes("Ares")) { + version = "Ares"; + icon = "https://battlylauncher.com/assets/img/ares.png"; + } else if (details.includes("BatMod")) { + version = "BatMod"; + icon = "https://battlylauncher.com/assets/img/batmod.png"; + } else if (details.includes("Battly")) { + version = "Battly"; + icon = "https://battlylauncher.com/assets/img/logo_500.png"; + } else { + version = "Desconocida"; + icon = "https://battlylauncher.com/assets/img/logo_500.png"; + } + + try { + await axios.get(`http://api.battlylauncher.com/api/skin/${username}.png`) + + const box = document.createElement('div'); + box.className = 'box friend-card'; + + const article = document.createElement('article'); + article.className = 'media'; + + const mediaLeft = document.createElement('div'); + mediaLeft.className = 'media-left'; + + const figure = document.createElement('figure'); + figure.className = 'image is-64x64'; + + const img = document.createElement('div'); + img.className = 'mc-face-viewer-8x'; + img.alt = 'Image'; + img.style.borderRadius = '5px'; + + const statusOverlay = document.createElement('div'); + statusOverlay.className = 'status-overlay'; + + const statusImg = document.createElement('img'); + statusImg.src = icon; + statusImg.alt = 'Status'; + statusImg.style.width = '25px'; + statusImg.style.borderRadius = '5px'; + + statusOverlay.appendChild(statusImg); + figure.appendChild(img); + figure.appendChild(statusOverlay); + mediaLeft.appendChild(figure); + + const mediaContent = document.createElement('div'); + mediaContent.className = 'media-content'; + + const content = document.createElement('div'); + content.className = 'content'; + + const strong = document.createElement('strong'); + strong.className = 'friend-username'; + strong.textContent = username; + + const span = document.createElement('span'); + span.style.marginLeft = '3px'; + + const statusImg2 = document.createElement('img'); + statusImg2.src = 'assets/images/status/idle.png'; + statusImg2.alt = ''; + statusImg2.style.width = '15px'; + statusImg2.style.display = 'inline'; + + span.appendChild(statusImg2); + + const br = document.createElement('br'); + + const status = document.createElement('span'); + status.textContent = details; + + const paragraph = document.createElement('p'); + paragraph.appendChild(strong); + paragraph.appendChild(span); + paragraph.appendChild(br); + paragraph.appendChild(status); + + content.appendChild(paragraph); + mediaContent.appendChild(content); + + article.appendChild(mediaLeft); + article.appendChild(mediaContent); + + box.appendChild(article); + + panelAmigos.appendChild(box); + img.style.backgroundImage = `url('http://api.battlylauncher.com/api/skin/${username}.png')`; + } catch (error) { + console.log(`❌ Error al obtener la skin de ${username}.`); + const box = document.createElement('div'); + box.className = 'box friend-card'; + + const article = document.createElement('article'); + article.className = 'media'; + + const mediaLeft = document.createElement('div'); + mediaLeft.className = 'media-left'; + + const figure = document.createElement('figure'); + figure.className = 'image is-64x64'; + + const img = document.createElement('div'); + img.className = 'mc-face-viewer-8x'; + img.alt = 'Image'; + img.style.borderRadius = '5px'; + + const statusOverlay = document.createElement('div'); + statusOverlay.className = 'status-overlay'; + + const statusImg = document.createElement('img'); + statusImg.src = icon; + statusImg.alt = 'Status'; + statusImg.style.width = '25px'; + statusImg.style.borderRadius = '5px'; + + statusOverlay.appendChild(statusImg); + figure.appendChild(img); + figure.appendChild(statusOverlay); + mediaLeft.appendChild(figure); + + const mediaContent = document.createElement('div'); + mediaContent.className = 'media-content'; + + const content = document.createElement('div'); + content.className = 'content'; + + const strong = document.createElement('strong'); + strong.className = 'friend-username'; + strong.textContent = username; + + const span = document.createElement('span'); + span.style.marginLeft = '3px'; + + const statusImg2 = document.createElement('img'); + statusImg2.src = 'assets/images/status/idle.png'; + statusImg2.alt = ''; + statusImg2.style.width = '15px'; + statusImg2.style.display = 'inline'; + + span.appendChild(statusImg2); + + const br = document.createElement('br'); + + const status = document.createElement('span'); + status.textContent = details; + + const paragraph = document.createElement('p'); + paragraph.appendChild(strong); + paragraph.appendChild(span); + paragraph.appendChild(br); + paragraph.appendChild(status); + + content.appendChild(paragraph); + mediaContent.appendChild(content); + + article.appendChild(mediaLeft); + article.appendChild(mediaContent); + + box.appendChild(article); + + panelAmigos.appendChild(box); + img.style.backgroundImage = `url('https://minotar.net/skin/MHF_Steve.png')`; + } + + } else { + try { + await axios.get(`http://api.battlylauncher.com/api/skin/${username}.png`) + + const box = document.createElement('div'); + box.className = 'box friend-card'; + + const article = document.createElement('article'); + article.className = 'media'; + + const mediaLeft = document.createElement('div'); + mediaLeft.className = 'media-left'; + + const figure = document.createElement('figure'); + figure.className = 'image is-64x64'; + + const img = document.createElement('div'); + img.className = 'mc-face-viewer-8x'; + img.alt = 'Image'; + img.style.borderRadius = '5px'; + + figure.appendChild(img); + mediaLeft.appendChild(figure); + + const mediaContent = document.createElement('div'); + mediaContent.className = 'media-content'; + + const content = document.createElement('div'); + content.className = 'content'; + + const strong = document.createElement('strong'); + strong.className = 'friend-username'; + strong.textContent = username; + + const span = document.createElement('span'); + span.style.marginLeft = '3px'; + + const statusImg = document.createElement('img'); + statusImg.src = 'assets/images/status/offline.png'; + statusImg.alt = ''; + statusImg.style.width = '15px'; + statusImg.style.display = 'inline'; + + span.appendChild(statusImg); + + const br = document.createElement('br'); + + const status = document.createElement('span'); + status.textContent = 'Offline'; + + const paragraph = document.createElement('p'); + paragraph.appendChild(strong); + paragraph.appendChild(span); + paragraph.appendChild(br); + paragraph.appendChild(status); + + content.appendChild(paragraph); + mediaContent.appendChild(content); + + article.appendChild(mediaLeft); + article.appendChild(mediaContent); + + box.appendChild(article); + + panelAmigos.appendChild(box); + img.style.backgroundImage = `url('http://api.battlylauncher.com/api/skin/${username}.png')`; + } + + catch (error) { + console.log(`❌ Error al obtener la skin de ${username}.`); + const box = document.createElement('div'); + box.className = 'box friend-card'; + + const article = document.createElement('article'); + article.className = 'media'; + + const mediaLeft = document.createElement('div'); + mediaLeft.className = 'media-left'; + + const figure = document.createElement('figure'); + figure.className = 'image is-64x64'; + + const img = document.createElement('div'); + img.className = 'mc-face-viewer-8x'; + img.alt = 'Image'; + img.style.borderRadius = '5px'; + + figure.appendChild(img); + mediaLeft.appendChild(figure); + + const mediaContent = document.createElement('div'); + mediaContent.className = 'media-content'; + + const content = document.createElement('div'); + content.className = 'content'; + + const strong = document.createElement('strong'); + strong.className = 'friend-username'; + strong.textContent = username; + + const span = document.createElement('span'); + span.style.marginLeft = '3px'; + + const statusImg = document.createElement('img'); + statusImg.src = 'assets/images/status/offline.png'; + statusImg.alt = ''; + statusImg.style.width = '15px'; + statusImg.style.display = 'inline'; + + span.appendChild(statusImg); + + const br = document.createElement('br'); + + const status = document.createElement('span'); + status.textContent = 'Offline'; + + const paragraph = document.createElement('p'); + paragraph.appendChild(strong); + paragraph.appendChild(span); + paragraph.appendChild(br); + paragraph.appendChild(status); + + content.appendChild(paragraph); + mediaContent.appendChild(content); + + article.appendChild(mediaLeft); + article.appendChild(mediaContent); + + box.appendChild(article); + + panelAmigos.appendChild(box); + img.style.backgroundImage = `url('https://minotar.net/skin/MHF_Steve.png')`; + } + } + + document.querySelector(".preload-content").style.display = "none"; + } + }); + } +} +export default Friends; \ No newline at end of file diff --git a/src/assets/js/panels/home.js b/src/assets/js/panels/home.js new file mode 100644 index 0000000..ba63beb --- /dev/null +++ b/src/assets/js/panels/home.js @@ -0,0 +1,7585 @@ +/** + * @author TECNO BROS + + */ +"use strict"; +import { + logger, + database, + changePanel +} from "../utils.js"; + +const { + Client, + Status +} = require("minecraft-launcher-core"); +const { + Launch, + Mojang +} = require("./assets/js/libs/mc/Index"); +const { + ipcRenderer, + ipcMain, + shell +} = require("electron"); + +const pkg = require("../package.json"); +const Swal = require("./assets/js/libs/sweetalert/sweetalert2.all.min"); + +const Toast = Swal.mixin({ + toast: true, + position: "top-end", + showConfirmButton: false, + timer: 5000, + timerProgressBar: true, + didOpen: (toast) => { + toast.addEventListener("mouseenter", Swal.stopTimer); + toast.addEventListener("mouseleave", Swal.resumeTimer); + }, +}); + + +function ShowPanelError(error) { + let audioError = new Audio("./assets/audios/error.mp3"); + audioError.play(); + + ipcRenderer.send("new-notification", { + title: "Error al abrir Minecraft", + body: "Consulta el error abriendo Battly.", + }); + // Crear el elemento div principal con la clase "modal is-active" + const modalDiv = document.createElement('div'); + modalDiv.className = 'modal is-active'; + modalDiv.style.zIndex = '4'; + + // Crear el elemento div con la clase "modal-background" y agregarlo al div principal + const modalBackgroundDiv = document.createElement('div'); + modalBackgroundDiv.className = 'modal-background'; + modalDiv.appendChild(modalBackgroundDiv); + + // Crear el elemento div con la clase "modal-card" y el estilo de fondo y agregarlo al div principal + const modalCardDiv = document.createElement('div'); + modalCardDiv.className = 'modal-card'; + modalCardDiv.style.backgroundColor = '#444444'; + modalDiv.appendChild(modalCardDiv); + + // Crear el elemento header con la clase "modal-card-head" y el estilo de fondo y agregarlo al div modal-card + const headerDiv = document.createElement('header'); + headerDiv.className = 'modal-card-head'; + headerDiv.style.backgroundColor = '#444444'; + modalCardDiv.appendChild(headerDiv); + + // Crear el elemento p con la clase "modal-card-title", el estilo de color y texto, y agregarlo al div header + const titleP = document.createElement('p'); + titleP.className = 'modal-card-title'; + titleP.style.color = '#fff'; + titleP.textContent = 'Error al abrir Minecraft'; + headerDiv.appendChild(titleP); + + // Crear el elemento section con la clase "modal-card-body" y el estilo de fondo y color, y agregarlo al div modal-card + const bodySection = document.createElement('section'); + bodySection.className = 'modal-card-body'; + bodySection.style.backgroundColor = '#444444'; + bodySection.style.color = '#fff'; + modalCardDiv.appendChild(bodySection); + + // Crear el elemento p con el mensaje de error y agregarlo al div section + const errorP = document.createElement('p'); + errorP.textContent = 'Esto es un mensaje de error al iniciar Minecraft. Esto no es por culpa de Battly, no reportar este problema.'; + bodySection.appendChild(errorP); + + // Crear el elemento div con la clase "card" y agregarlo al div section + const cardDiv = document.createElement('div'); + cardDiv.className = 'card'; + bodySection.appendChild(cardDiv); + + // Crear el elemento header con la clase "card-header" y agregarlo al div card + const cardHeaderDiv = document.createElement('header'); + cardHeaderDiv.className = 'card-header'; + cardDiv.appendChild(cardHeaderDiv); + + // Crear el elemento p con la clase "card-header-title" y agregarlo al div card-header + const cardTitleP = document.createElement('p'); + cardTitleP.className = 'card-header-title'; + cardTitleP.textContent = 'Error encontrado'; + cardHeaderDiv.appendChild(cardTitleP); + + // Crear el elemento div con la clase "card-content" y el id "content" y agregarlo al div card + const cardContentDiv = document.createElement('div'); + cardContentDiv.className = 'card-content'; + cardContentDiv.id = 'content'; + cardDiv.appendChild(cardContentDiv); + + // Crear el elemento textarea con las clases y atributos y agregarlo al div card-content + const textarea = document.createElement('textarea'); + textarea.className = 'textarea errores is-info is-family-code'; + textarea.disabled = true; + textarea.rows = '10'; + textarea.cols = '50'; + textarea.textContent = error; + cardContentDiv.appendChild(textarea); + + // Crear el elemento footer con la clase "modal-card-foot" y el estilo de fondo y agregarlo al div modal-card + const footerDiv = document.createElement('footer'); + footerDiv.className = 'modal-card-foot'; + footerDiv.style.backgroundColor = '#444444'; + modalCardDiv.appendChild(footerDiv); + + // Crear el elemento button con las clases y atributos y agregarlo al div modal-card-foot + const closeButton = document.createElement('button'); + closeButton.className = 'button is-danger'; + closeButton.textContent = 'Cerrar'; + closeButton.addEventListener('click', () => { + modalDiv.remove(); + }); + + //boton de guardar logs, mostrará un dialogo para guardar los logs en un archivo de texto, abrirá el explorador de archivos y se podrá guardar donde quiera + const saveLogsButton = document.createElement('button'); + saveLogsButton.className = 'button is-info'; + saveLogsButton.textContent = 'Guardar logs'; + saveLogsButton.addEventListener('click', () => { + let logs = document.querySelector('.errores').value; + let logsPath = path.join(__dirname, 'logs.txt'); + fs.writeFileSync(logsPath, logs); + shell.openPath(logsPath); + }); + + const discordBtn = document.createElement('button'); + discordBtn.className = 'button is-info'; + discordBtn.addEventListener('click', () => { + shell.openExternal('https://discord.gg/tecno-bros-885235460178342009'); + }); + discordBtn.innerHTML = ' Discord'; + + footerDiv.appendChild(closeButton); + footerDiv.appendChild(saveLogsButton); + footerDiv.appendChild(discordBtn); + // Agregar saltos de línea al final del código + modalDiv.appendChild(document.createElement('br')); + + // Agregar el div principal al cuerpo del documento + document.body.appendChild(modalDiv); +} + +import { + LoadAPI +} from "../utils/loadAPI.js"; + +const fetch = require("node-fetch"); +let offlineMode = false; +fetch("https://google.com") + .then(async () => { + offlineMode = false; + }) + .catch(async () => { + offlineMode = true; + }); + +const fs = require("fs"); +const path = require("path"); + +const dataDirectory = + process.env.APPDATA || + (process.platform == "darwin" ? + `${process.env.HOME}/Library/Application Support` : + process.env.HOME); + +let logFilePath = `${dataDirectory}/.battly/Registro.log`; +import { + consoleOutput +} from "../utils/logger.js"; +let consoleOutput_; + +import { Lang } from "../utils/lang.js"; +import * as NBT from "../../../../node_modules/nbtify/dist/index.js"; + +let lang; +let langs; +class Home { + static id = "home"; + async init(config, news) { + lang = await new Lang().GetLang(); + langs = lang; + this.WaitData(); + this.config = config; + this.news = await news; + this.offlineMode = offlineMode; + this.ShowNews(); + this.BattlyConfig = await new LoadAPI().GetConfig(); + this.Versions = await new LoadAPI().GetVersions(); + this.VersionsMojang = await new LoadAPI().GetVersionsMojang(); + this.database = await new database().init(); + this.initNews(); + this.initLaunch(); + this.initStatusServer(); + this.initBtn(); + this.CargarMods(); + this.IniciarEstadoDiscord(); + this.CargarVersiones(); + this.initConfig(); + this.InitTheme(); + this.GetLogsSocket(); + this.CambiarRutaJava(); + this.Instancias(); + this.GenerarLogsSocket(); + this.SetStatus(); + this.Solicitudes(); + this.Ads(); + } + + async Ads() { + let ads = document.getElementById("ads"); + ads.style.backgroundImage = `url(${this.BattlyConfig.ads})`; + } + + async Solicitudes() { + ipcRenderer.on("cargarSolicitudAmistad", async (event, args) => { + changePanel("friends"); + }); + + document.getElementById("friends-btn").addEventListener("click", () => { + changePanel("friends"); + }); + + document.getElementById("friends-volver-btn").addEventListener("click", () => { + document.querySelector(".preload-content").style.display = "none"; + changePanel("home"); + }); + } + + + async SetStatus() { + let selectedAccount = (await this.database.get("1234", "accounts-selected")).value; + let accounts = await this.database.getAll("accounts"); + + accounts.forEach((account) => { + if (account.value.uuid === selectedAccount.selected) { + this.UpdateStatus(account.value.name, "online", langs.in_the_menu); + } + }) + } + + async UpdateStatus(username, status, details) { + console.log(`🧩 ${username} > ${status} > ${details}`); + + let uuid = (await this.database.get("1234", "accounts-selected")).value; + let account = (await this.database.get(uuid.selected, "accounts")).value; + + if (account.type === "battly") { + if (!account.password || account.password === "" || account.password === undefined || account.password === null) { + Toast.fire({ + icon: 'error', + title: langs.password_not_set, + }); + + this.database.delete(uuid.selected, "accounts"); + return; + } else { + ipcRenderer.send('updateStatus', { + status: status, + details: details, + username: username, + password: account.password, + }) + } + } + } + + async Instancias() { + let instanciasBtn = document.getElementById("instancias-btn"); + + instanciasBtn.addEventListener("click", async () => { + // Crear el elemento modal + const modal = document.createElement('div'); + modal.classList.add('modal', 'is-active'); + modal.style.zIndex = '2'; + + // Crear el fondo del modal + const modalBackground = document.createElement('div'); + modalBackground.classList.add('modal-background'); + + // Crear el div del contenido del modal + const modalCard = document.createElement('div'); + modalCard.classList.add('modal-card'); + modalCard.style.backgroundColor = '#444444'; + + // Crear el encabezado del modal + const modalHeader = document.createElement('header'); + modalHeader.classList.add('modal-card-head'); + modalHeader.style.backgroundColor = '#444444'; + + const modalTitle = document.createElement('p'); + modalTitle.classList.add('modal-card-title'); + modalTitle.style.color = '#fff'; + modalTitle.innerHTML = ' ' + langs.instances; + + const closeBtn = document.createElement('button'); + closeBtn.classList.add('delete'); + closeBtn.setAttribute('aria-label', 'close'); + + modalHeader.appendChild(modalTitle); + modalHeader.appendChild(closeBtn); + + // Crear la sección del cuerpo del modal + const modalBody = document.createElement('section'); + modalBody.classList.add('modal-card-body'); + modalBody.style.backgroundColor = '#444444'; + modalBody.style.color = '#fff'; + + const bodyText = document.createElement('p'); + bodyText.innerHTML = langs.welcome_instances; + + const lineBreak = document.createElement('br'); + const lineBreak2 = document.createElement('br'); + + modalBody.appendChild(bodyText); + modalBody.appendChild(lineBreak); + + // Crear la primera tarjeta + + //obtener todas las carpetas que hay en la carpeta de instancias + let instancias; + if (!fs.existsSync(`${dataDirectory}/.battly/instances`)) { + fs.mkdirSync(`${dataDirectory}/.battly/instances`); + instancias = fs.readdirSync(`${dataDirectory}/.battly/instances`); + } else { + instancias = fs.readdirSync(`${dataDirectory}/.battly/instances`); + } + + //crear un array vacío + let instanciasArray = []; + //recorrer todas las carpetas + if (instancias.length > 0) { + for (let i = 0; i < instancias.length; i++) { + //obtener el archivo instance.json + try { + let instance = fs.readFileSync( + `${dataDirectory}/.battly/instances/${instancias[i]}/instance.json` + ); + //convertir el archivo a JSON + let instance_json = JSON.parse(instance); + instanciasArray.push(instance_json); + + // Crear el header de la primera tarjeta + + const card1 = document.createElement('div'); + card1.classList.add('card'); + card1.style.marginBottom = '-15px'; + + const cardHeader1 = document.createElement('header'); + cardHeader1.classList.add('card-header'); + cardHeader1.style.cursor = 'pointer'; + + const cardTitle1 = document.createElement('p'); + cardTitle1.classList.add('card-header-title'); + cardTitle1.textContent = instance_json.name; + + const cardIcon1 = document.createElement('button'); + cardIcon1.classList.add('card-header-icon'); + cardIcon1.setAttribute('aria-label', 'more options'); + + const icon1 = document.createElement('span'); + icon1.classList.add('icon'); + + const iconImage1 = document.createElement('i'); + iconImage1.classList.add('fas', 'fa-angle-down'); + + icon1.appendChild(iconImage1); + cardIcon1.appendChild(icon1); + + // Crear el contenido de la primera tarjeta + + const cardContent1 = document.createElement('div'); + cardContent1.classList.add('card-content'); + cardContent1.setAttribute('id', 'content'); + cardContent1.style.display = 'none'; + + const cardImage1 = document.createElement('figure'); + cardImage1.classList.add('image', 'is-32x32'); + + const img1 = document.createElement('img'); + img1.setAttribute('src', instance_json.image); + img1.style.borderRadius = '5px'; + + const cardDescription1 = document.createElement('div'); + cardDescription1.classList.add('content'); + cardDescription1.style.marginLeft = '10px'; + cardDescription1.textContent = instance_json.description; + //añadir font-family: 'Poppins';font-weight: 700; + cardDescription1.style.fontFamily = 'Poppins'; + cardDescription1.style.fontWeight = '700'; + + // Crear el footer de la primera tarjeta + + const cardFooter1 = document.createElement('footer'); + cardFooter1.classList.add('card-footer'); + cardFooter1.setAttribute('id', 'footer'); + cardFooter1.style.display = 'none'; + + const openButton1 = document.createElement('button'); + openButton1.classList.add('card-footer-item', 'button', 'is-info'); + openButton1.innerHTML = ' ' + langs.open_instance + ''; + + const editButton1 = document.createElement('button'); + editButton1.classList.add('card-footer-item', 'button', 'is-warning'); + editButton1.innerHTML = ' ' + langs.open_instance_folder + ''; + + const deleteButton1 = document.createElement('button'); + deleteButton1.classList.add('card-footer-item', 'button', 'is-danger'); + deleteButton1.innerHTML = ' ' + langs.delete_instance + ''; + + card1.appendChild(cardHeader1); + cardHeader1.appendChild(cardTitle1); + cardHeader1.appendChild(cardIcon1); + card1.appendChild(cardContent1); + cardContent1.appendChild(cardImage1); + cardImage1.appendChild(img1); + cardContent1.appendChild(cardDescription1); + card1.appendChild(cardFooter1); + cardFooter1.appendChild(openButton1); + cardFooter1.appendChild(editButton1); + cardFooter1.appendChild(deleteButton1); + cardFooter1.appendChild(lineBreak2); + modalBody.appendChild(card1); + + const lineBreak3 = document.createElement('br'); + modalBody.appendChild(lineBreak3); + + + cardHeader1.addEventListener('click', () => { + if (cardContent1.style.display === 'none') { + cardContent1.style.display = 'flex'; + cardFooter1.style.display = 'flex'; + iconImage1.classList.remove('fa-angle-down'); + iconImage1.classList.add('fa-angle-up'); + } else { + cardContent1.style.display = 'none'; + cardFooter1.style.display = 'none'; + iconImage1.classList.remove('fa-angle-up'); + iconImage1.classList.add('fa-angle-down'); + } + }); + + editButton1.addEventListener('click', () => { + let path = `${dataDirectory}/.battly/instances/${instancias[i]}` + shell.openPath(path.replace(/\//g, '\\')); + }); + + + deleteButton1.addEventListener('click', () => { + //eliminar el card, y eliminar la carpeta de la instancia + Swal.fire({ + title: langs.are_you_sure, + text: langs.are_you_sure_text, + showCancelButton: true, + confirmButtonColor: '#3e8ed0', + cancelButtonColor: '#d33', + confirmButtonText: langs.yes_delete, + cancelButtonText: langs.no_cancel, + }).then((result) => { + if (result.isConfirmed) { + card1.remove(); + lineBreak3.remove(); + fs.rmdirSync(`${dataDirectory}/.battly/instances/${instancias[i]}`, { recursive: true }); + Toast.fire({ + icon: 'success', + title: langs.instance_deleted_correctly, + }); + } + }); + }); + + + let loader; + if (instance_json.version.endsWith('-forge')) { + loader = 'forge'; + } else if (instance_json.version.endsWith('-fabric')) { + loader = 'fabric'; + } else if (instance_json.version.endsWith('-quilt')) { + loader = 'quilt'; + } + + let version; + + let loader_json = null; + if (instance_json.loader) loader_json = instance_json.loader; + + let loaderVersion = null; + if (loader_json) loaderVersion = loader_json.loaderVersion; + + if (instance_json.version.endsWith('-forge') || instance_json.version.endsWith('-fabric') || instance_json.version.endsWith('-quilt')) { + version = instance_json.version.replace('-forge', '').replace('-fabric', '').replace('-quilt', ''); + } else { + version = instance_json.version; + } + + if (!fs.existsSync(`${dataDirectory}/.battly/instances/${instancias[i]}/battly`)) { + fs.mkdirSync(`${dataDirectory}/.battly/instances/${instancias[i]}/battly`); + } + + if (!fs.existsSync(`${dataDirectory}/.battly/instances/${instancias[i]}/battly/mods-internos`)) { + fs.mkdirSync(`${dataDirectory}/.battly/instances/${instancias[i]}/battly/mods-internos`); + } + + if (!fs.existsSync(`${dataDirectory}/.battly/instances/${instancias[i]}/battly/launcher`)) { + fs.mkdirSync(`${dataDirectory}/.battly/instances/${instancias[i]}/battly/launcher`); + } + + if (!fs.existsSync(`${dataDirectory}/.battly/instances/${instancias[i]}/battly/launcher/config-launcher`)) { + fs.mkdirSync(`${dataDirectory}/.battly/instances/${instancias[i]}/battly/launcher/config-launcher`); + } + + if (!fs.existsSync(`${dataDirectory}/.battly/instances/${instancias[i]}/battly/launcher/forge`)) { + fs.mkdirSync(`${dataDirectory}/.battly/instances/${instancias[i]}/battly/launcher/forge`); + } + + if (!fs.existsSync(`${dataDirectory}/.battly/instances/${instancias[i]}/battly/launcher/mc-assets`)) { + fs.mkdirSync(`${dataDirectory}/.battly/instances/${instancias[i]}/battly/launcher/mc-assets`); + } + + let urlpkg = pkg.user ? `${pkg.url}/${pkg.user}` : pkg.url; + let uuid = (await this.database.get("1234", "accounts-selected")).value; + let account = (await this.database.get(uuid.selected, "accounts")).value; + let ram = (await this.database.get("1234", "ram")).value; + let Resolution = (await this.database.get("1234", "screen")).value; + let launcherSettings = (await this.database.get("1234", "launcher")).value; + + openButton1.addEventListener('click', () => { + let launch = new Launch(); + let opts = { + url: this.config.game_url === "" || this.config.game_url === undefined ? + `${urlpkg}/files` : + this.config.game_url, + authenticator: account, + detached: true, + timeout: 10000, + path: `${dataDirectory}/.battly/instances/${instancias[i]}`, + downloadFileMultiple: 20, + version: version, + loader: { + type: loader_json ? loader_json : loader, + build: loaderVersion ? loaderVersion : this.BattlyConfig.loader.build, + enable: true + }, + verify: false, + ignored: ["loader"], + java: false, + memory: { + min: `${ram.ramMin * 1024}M`, + max: `${ram.ramMax * 1024}M`, + }, + }; + launch.Launch(opts); + + // Crear el elemento modal + const preparingModal = document.createElement("div"); + preparingModal.className = "modal is-active"; + preparingModal.style.zIndex = "4"; + + // Modal background + const preparingModalBackground = document.createElement("div"); + preparingModalBackground.className = "modal-background"; + + // Modal card + const preparingModalCard = document.createElement("div"); + preparingModalCard.className = "modal-card"; + preparingModalCard.style.backgroundColor = "#444444"; + + // Modal card head + const preparingModalCardHead = document.createElement("header"); + preparingModalCardHead.className = "modal-card-head"; + preparingModalCardHead.style.backgroundColor = "#444444"; + + const preparingModalCardTitle = document.createElement("p"); + preparingModalCardTitle.className = "modal-card-title"; + preparingModalCardTitle.style.color = "#fff"; + + const preparingIcon = document.createElement("i"); + preparingIcon.className = "fa-solid fa-spinner fa-spin-pulse fa-sm"; + preparingIcon.style.color = "#fff"; + preparingIcon.style.marginRight = "5px"; + preparingIcon.style.verticalAlign = "middle"; + + const preparingText = document.createTextNode(langs.preparing_instance); + + + preparingModalCardTitle.appendChild(preparingText); + + preparingModalCardHead.appendChild(preparingModalCardTitle); + + // Modal card body + const preparingModalCardBody = document.createElement("section"); + preparingModalCardBody.className = "modal-card-body"; + preparingModalCardBody.style.backgroundColor = "#444444"; + preparingModalCardBody.style.color = "#fff"; + + const preparingMessage = document.createElement("p"); + let preparingMessageText = document.createTextNode(langs.preparing_instance); + preparingMessage.appendChild(preparingMessageText); + preparingMessage.appendChild(document.createElement("br")); + + const progress = document.createElement("progress"); + progress.className = "progress is-info"; + progress.setAttribute("max", "100"); + + preparingModalCardBody.appendChild(preparingMessage); + preparingModalCardBody.appendChild(progress); + + // Crear tarjeta 1 + const card1 = document.createElement("div"); + card1.className = "card"; + + const cardHeader1 = document.createElement("header"); + cardHeader1.className = "card-header"; + + const cardHeaderTitle1 = document.createElement("p"); + cardHeaderTitle1.className = "card-header-title"; + cardHeaderTitle1.appendChild(document.createTextNode(langs.downloading_version)); + + const cardHeaderIcon1 = document.createElement("button"); + cardHeaderIcon1.className = "card-header-icon"; + cardHeaderIcon1.setAttribute("aria-label", "more options"); + + const iconSpan1 = document.createElement("span"); + iconSpan1.className = "icon"; + + const icon1 = document.createElement("i"); + icon1.className = "fas fa-angle-down"; + icon1.setAttribute("aria-hidden", "true"); + + iconSpan1.appendChild(icon1); + cardHeaderIcon1.appendChild(iconSpan1); + + cardHeader1.appendChild(cardHeaderTitle1); + cardHeader1.appendChild(cardHeaderIcon1); + + const cardContent1 = document.createElement("div"); + cardContent1.className = "card-content"; + cardContent1.id = "content"; + cardContent1.style.display = "none"; + + const content1 = document.createElement("div"); + content1.className = "content"; + content1.appendChild(document.createTextNode(`🔄 ${langs.downloading_version}`)); + content1.style.fontFamily = "Poppins"; + content1.style.fontWeight = "700"; + + cardContent1.appendChild(content1); + + card1.appendChild(cardHeader1); + card1.appendChild(cardContent1); + + preparingModalCardBody.appendChild(card1); + preparingModalCardBody.appendChild(document.createElement("br")); + + // Crear tarjeta 2 + const card2 = document.createElement("div"); + card2.className = "card"; + + const cardHeader2 = document.createElement("header"); + cardHeader2.className = "card-header"; + + const cardHeaderTitle2 = document.createElement("p"); + cardHeaderTitle2.className = "card-header-title"; + cardHeaderTitle2.appendChild(document.createTextNode(langs.downloading_loader)); + + const cardHeaderIcon2 = document.createElement("button"); + cardHeaderIcon2.className = "card-header-icon"; + cardHeaderIcon2.setAttribute("aria-label", "more options"); + + const iconSpan2 = document.createElement("span"); + iconSpan2.className = "icon"; + + const icon2 = document.createElement("i"); + icon2.className = "fas fa-angle-down"; + icon2.setAttribute("aria-hidden", "true"); + + iconSpan2.appendChild(icon2); + cardHeaderIcon2.appendChild(iconSpan2); + + cardHeader2.appendChild(cardHeaderTitle2); + cardHeader2.appendChild(cardHeaderIcon2); + + const cardContent2 = document.createElement("div"); + cardContent2.className = "card-content"; + cardContent2.id = "content"; + cardContent2.style.display = "none"; + + const content2 = document.createElement("div"); + content2.className = "content"; + content2.appendChild(document.createTextNode(`🔄 ${langs.installing_loader}`)); + content2.style.fontFamily = "Poppins"; + content2.style.fontWeight = "700"; + + cardContent2.appendChild(content2); + + card2.appendChild(cardHeader2); + card2.appendChild(cardContent2); + + // Crear tarjeta 3 + const card3 = document.createElement("div"); + card3.className = "card"; + + const cardHeader3 = document.createElement("header"); + cardHeader3.className = "card-header"; + + const cardHeaderTitle3 = document.createElement("p"); + cardHeaderTitle3.className = "card-header-title"; + cardHeaderTitle3.appendChild(document.createTextNode(langs.downloading_java)); + + const cardHeaderIcon3 = document.createElement("button"); + cardHeaderIcon3.className = "card-header-icon"; + cardHeaderIcon3.setAttribute("aria-label", "more options"); + + const iconSpan3 = document.createElement("span"); + iconSpan3.className = "icon"; + + const icon3 = document.createElement("i"); + icon3.className = "fas fa-angle-down"; + icon3.setAttribute("aria-hidden", "true"); + + iconSpan3.appendChild(icon3); + cardHeaderIcon3.appendChild(iconSpan3); + + cardHeader3.appendChild(cardHeaderTitle3); + cardHeader3.appendChild(cardHeaderIcon3); + + const cardContent3 = document.createElement("div"); + cardContent3.className = "card-content"; + cardContent3.id = "content"; + cardContent3.style.display = "none"; + + const content3 = document.createElement("div"); + content3.className = "content"; + content3.appendChild(document.createTextNode(`🔄 ${langs.installing_java}`)); + content3.style.fontFamily = "Poppins"; + content3.style.fontWeight = "700"; + + cardContent3.appendChild(content3); + + card3.appendChild(cardHeader3); + card3.appendChild(cardContent3); + + + preparingModalCardBody.appendChild(card3); + preparingModalCardBody.appendChild(document.createElement("br")); + preparingModalCardBody.appendChild(card2); + + + // Modal card foot + const preparingModalCardFoot = document.createElement("footer"); + preparingModalCardFoot.className = "modal-card-foot"; + preparingModalCardFoot.style.backgroundColor = "#444444"; + + // Construir la estructura del modal + preparingModalCard.appendChild(preparingModalCardHead); + preparingModalCard.appendChild(preparingModalCardBody); + preparingModalCard.appendChild(preparingModalCardFoot); + + preparingModal.appendChild(preparingModalBackground); + preparingModal.appendChild(preparingModalCard); + + // Agregar el modal al contenedor en el DOM + document.body.appendChild(preparingModal); + modal.remove(); + + launch.on('extract', extract => { + new logger('Extract', '#00d1b2') + }); + + let assetsShown = false; + let javaShown = false; + let librariesShown = false; + + let content1Text; + content1Text = document.createTextNode(`🔄 ${langs.checking_assets}`); + let content3Text; + content3Text = document.createTextNode(`🔄 ${langs.checking_java}`); + let content2Text; + content2Text = document.createTextNode(`🔄 ${langs.checking_instance} ${loader_json ? loader_json : loader}...`); + + + launch.on('progress', (progress, size, element) => { + new logger('Progress', '#00d1b2') + //console.log(`Downloading ${element} ${Math.round((progress / size) * 100)}%`); + + + if (element === 'Assets') { + + + if (!assetsShown) { + //añadir un br + content1.appendChild(document.createElement('br')); + content1.appendChild(content1Text); + cardContent1.style.display = 'block'; + cardContent2.style.display = 'none'; + cardContent3.style.display = 'none'; + assetsShown = true; + } + + content1Text.textContent = `🔄 ${langs.downloading_assets}... (${Math.round((progress / size) * 100)}%)`; + + } else if (element === 'Java') { + + + if (!javaShown) { + content3.appendChild(document.createElement('br')); + content3.appendChild(content3Text); + cardContent1.style.display = 'none'; + cardContent2.style.display = 'none'; + cardContent3.style.display = 'block'; + javaShown = true; + } + + content3Text.textContent = `🔄 ${langs.downloading_java}... (${Math.round((progress / size) * 100)}%)`; + } else if (element === 'libraries') { + + + if (!librariesShown) { + content2.appendChild(document.createElement('br')); + content2.appendChild(content2Text); + cardContent1.style.display = 'none'; + cardContent2.style.display = 'block'; + cardContent3.style.display = 'none'; + librariesShown = true; + } + + content2Text.textContent = `🔄 ${langs.downloading} ${loader_json ? loader_json : loader}... (${Math.round((progress / size) * 100)}%)`; + } + }); + + + let assetsShownCheck = false; + let javaShownCheck = false; + let librariesShownCheck = false; + + launch.on('check', (progress, size, element) => { + new logger('Check', '#00d1b2') + + + if (element === 'assets') { + + + if (!assetsShownCheck) { + //añadir un br + content1.appendChild(document.createElement('br')); + content1.appendChild(content1Text); + cardContent1.style.display = 'block'; + cardContent2.style.display = 'none'; + cardContent3.style.display = 'none'; + assetsShownCheck = true; + } + + content1Text.textContent = `🔄 ${langs.checking_assets}... (${Math.round((progress / size) * 100)}%)`; + } else if (element === 'java') { + + if (!javaShownCheck) { + content3.appendChild(document.createElement('br')); + content3.appendChild(content3Text); + cardContent1.style.display = 'none'; + cardContent2.style.display = 'none'; + cardContent3.style.display = 'block'; + javaShownCheck = true; + } + + content3Text.textContent = `🔄 ${langs.checking_java}... (${Math.round((progress / size) * 100)}%)`; + } else if (element === 'libraries') { + + + if (!librariesShownCheck) { + content2.appendChild(document.createElement('br')); + content2.appendChild(content2Text); + cardContent1.style.display = 'none'; + cardContent2.style.display = 'block'; + cardContent3.style.display = 'none'; + librariesShownCheck = true; + } + + content2Text.textContent = `🔄 ${langs.checking_instance} ${loader_json ? loader_json : loader}... (${Math.round((progress / size) * 100)}%)`; + } + }); + + launch.on('speed', (speed) => { + preparingMessageText.textContent = `${langs.downloading_instance} (${(speed / 1067008).toFixed(2)} MB/s)`; + }) + + launch.on('patch', patch => { + new logger('Patch', '#00d1b2') + }); + + let inicio = false; + launch.on('data', (e) => { + new logger('Data', '#00d1b2') + if (!inicio) { + if (e.includes(`Setting user: ${account.name}`) || e.includes("Launching wrapped minecraft")) { + let typeOfVersion; + if (loader === "forge") { + typeOfVersion = "Forge"; + } else if (loader === "fabric") { + typeOfVersion = "Fabric"; + } else if (loader === "quilt") { + typeOfVersion = "Quilt"; + } else { + typeOfVersion = ""; + } + + ipcRenderer.send( + "new-status-discord-jugando", + `${langs.playing_in} ${version} ${typeOfVersion}` + ); + + this.UpdateStatus(account.name, 'ausente', `${langs.playing_in} ${version} ${typeOfVersion}`); + } + + ipcRenderer.send("new-notification", { + title: langs.minecraft_started_correctly, + body: langs.minecraft_started_correctly_body, + }); + + ipcRenderer.send("main-window-progress-reset"); + + preparingModal.remove(); + inicio = true; + + + if (launcherSettings.launcher.close === "close-launcher") ipcRenderer.send("main-window-hide"); + + let versiones = this.Versions; + + const skinsJarPath = `${dataDirectory}/.battly/instances/${instancias[i]}/mods/skins.jar`; + const skinsForgeJarPath = `${dataDirectory}/.battly/instances/${instancias[i]}/mods/skins-forge.jar`; + const skinsForgeNewJarPath = `${dataDirectory}/.battly/instances/${instancias[i]}/mods/skins-forge-new.jar`; + + let rutaPrincipalSkinsJar = `${dataDirectory}/.battly/instances/${instancias[i]}/battly/mods-internos/skins.jar`; + let rutaPrincipalSkinsForgeJar = `${dataDirectory}/.battly/instances/${instancias[i]}/battly/mods-internos/skins-forge.jar`; + let rutaPrincipalSkinsForgeNewJar = `${dataDirectory}/.battly/instances/${instancias[i]}/battly/mods-internos/skins-forge-new.jar`; + + let rutaModMultijugadorForge = `${dataDirectory}/.battly/instances/${instancias[i]}/battly/mods-internos/multijugador-forge.jar`; + let rutaModMultijugadorFabric = `${dataDirectory}/.battly/instances/${instancias[i]}/battly/mods-internos/multijugador-fabric.jar`; + + let rutaModMultijugadorForgeDeMods = `${dataDirectory}/.battly/instances/${instancias[i]}/mods/multijugador-forge.jar`; + let rutaModMultijugadorFabricDeMods = `${dataDirectory}/.battly/instances/${instancias[i]}/mods/multijugador-fabric.jar`; + + if (fs.existsSync(rutaModMultijugadorFabricDeMods)) { + fs.unlinkSync(rutaModMultijugadorFabricDeMods); + } + + if (fs.existsSync(rutaModMultijugadorForgeDeMods)) { + fs.unlinkSync(rutaModMultijugadorForgeDeMods); + } + + fs.unlinkSync(skinsForgeJarPath); + fs.unlinkSync(skinsForgeNewJarPath); + + const selectedVersion = version; + + + + let selectedVersionWithoutHyphen; + + if (selectedVersion.includes("-")) { + selectedVersionWithoutHyphen = selectedVersion.replace(/-[^.]+/, ""); + + } + + const versionInfo = versiones.versions.find( + (v) => v.id === selectedVersionWithoutHyphen + ); + + + if (versionInfo) { + function formatVersionNumber(version) { + const parsedVersion = parseFloat(version); + if (!isNaN(parsedVersion)) { + const formattedVersion = parsedVersion.toString(); + return formattedVersion; + } + return version; // Si no se puede analizar como número, devuelve la versión original + } + + // Ejemplo de uso: + const versionNumber = formatVersionNumber(versionInfo.version); + + let versionesCompatiblesConForgeNormal = [ + "1.16.5", + "1.16.4", + "1.16.3", + "1.16.2", + "1.16.1", + "1.16", + "1.15.2", + "1.15.1", + "1.15", + "1.14.4", + "1.14.3", + "1.14.2", + "1.14.1", + "1.14", + "1.13.2", + "1.13.1", + "1.13", + "1.12.2", + "1.12.1", + "1.12", + "1.11.2", + "1.11.1", + "1.11", + "1.10.2", + "1.10.1", + "1.10", + "1.9.4", + "1.9.3", + "1.9.2", + "1.9.1", + "1.9", + "1.8.9", + "1.8.8", + "1.8.7", + "1.8.6", + "1.8.5", + "1.8.4", + "1.8.3", + "1.8.2", + "1.8.1", + "1.8", + ]; + + + + const excludedVersions = [ + 1.16, 1.15, 1.14, 1.13, 1.12, 1.11, 1.1, 1.9, 1.8, 1.7, 1.6, + 1.5, 1.4, 1.3, + ]; + const includedVersionsForgeNew = [1.17, 1.18, 1.19, 1.2, 1.21]; + const versionesConMultijugadorDesactivado = ["1.16.4", "1.16.5"]; + + + + if ( + versionesConMultijugadorDesactivado.includes(version) && + loader === "forge" + ) { + fs.copyFileSync( + rutaModMultijugadorForge, + `${dataDirectory}/.battly/instances/${instancias[i]}/mods/multijugador-forge.jar` + ); + } else if ( + versionesConMultijugadorDesactivado.includes(version) && + loader === "fabric" + ) { + fs.copyFileSync( + rutaModMultijugadorFabric, + `${dataDirectory}/.battly/instances/${instancias[i]}/mods/multijugador-fabric.jar` + ); + } + + if ( + includedVersionsForgeNew.includes(parseFloat(version)) && + !excludedVersions.includes(parseFloat(version)) && + loader === "forge" + ) { + + + fs.copyFileSync( + rutaPrincipalSkinsForgeNewJar, + skinsForgeNewJarPath + ); + + // Eliminar skins.jar y skins-forge.jar + if (fs.existsSync(skinsJarPath)) { + fs.unlinkSync(skinsJarPath); + } + if (fs.existsSync(skinsForgeJarPath)) { + fs.unlinkSync(skinsForgeJarPath); + } + } else if ( + versionesCompatiblesConForgeNormal.includes(version) && + loader === "forge" + ) { + + + fs.copyFileSync(rutaPrincipalSkinsForgeJar, skinsForgeJarPath); + + // Eliminar skins.jar y skins-forge-new.jar + if (fs.existsSync(skinsJarPath)) { + fs.unlinkSync(skinsJarPath); + } + if (fs.existsSync(skinsForgeNewJarPath)) { + fs.unlinkSync(skinsForgeNewJarPath); + } + } else if (loader == "fabric" || loader == "quilt") { + + fs.copyFileSync(rutaPrincipalSkinsJar, skinsJarPath); + // Eliminar skins-forge.jar y skins-forge-new.jar + if (fs.existsSync(skinsForgeJarPath)) { + fs.unlinkSync(skinsForgeJarPath); + } + if (fs.existsSync(skinsForgeNewJarPath)) { + fs.unlinkSync(skinsForgeNewJarPath); + } + } + } else { + console.log("❌ La versión no está en la lista."); + } + + let archivoConfigSkins = `${dataDirectory}/.battly/instances/${instancias[i]}/CustomSkinLoader/CustomSkinLoader.json`; + let data = { + version: "14.15", + buildNumber: 8, + loadlist: [{ + name: "BattlyAPI", + type: "Legacy", + checkPNG: false, + skin: "http://api.battlylauncher.com/api/skin/{USERNAME}.png", + model: "auto", + cape: "http://api.battlylauncher.com/api/capa/{USERNAME}.png", + }, + { + name: "Mojang", + type: "MojangAPI", + apiRoot: "https://api.mojang.com/", + sessionRoot: "https://sessionserver.mojang.com/", + }, + { + name: "OptiFine", + type: "Legacy", + checkPNG: false, + model: "auto", + cape: "https://optifine.net/capes/{USERNAME}.png", + }, + { + name: "LabyMod", + type: "Legacy", + checkPNG: false, + model: "auto", + cape: "https://dl.labymod.net/capes/{STANDARD_UUID}", + }, + ], + enableDynamicSkull: true, + enableTransparentSkin: true, + forceIgnoreHttpsCertificate: true, + forceLoadAllTextures: true, + enableCape: true, + threadPoolSize: 8, + enableLogStdOut: false, + cacheExpiry: 30, + forceUpdateSkull: true, + enableLocalProfileCache: false, + enableCacheAutoClean: true, + forceDisableCache: true, + }; + + if (fs.existsSync(path.join(archivoConfigSkins))) { + fs.writeFileSync(archivoConfigSkins, JSON.stringify(data)); + } else { + fs.mkdirSync(`${dataDirectory}/.battly/instances/${instancias[i]}/CustomSkinLoader`, { recursive: true }); + fs.writeFileSync(archivoConfigSkins, JSON.stringify(data)); + } + + } + }) + + launch.on('close', code => { + + if (launcherSettings.launcher.close === "close-launcher") + ipcRenderer.send("main-window-show"); + + ipcRenderer.send('updateStatus', { + status: 'online', + details: langs.in_the_menu, + username: account.name, + }); + }); + + launch.on('error', err => { + new logger('[Error]', '#ff3860') + console.log(err); + }); + + + }); + } catch { + console.log("❌ No se ha podido leer el archivo instance.json"); + } + } + + } + + const card2 = document.createElement('div'); + card2.classList.add('card'); + card2.style.cursor = 'pointer'; + + const cardHeader2 = document.createElement('header'); + cardHeader2.classList.add('card-header'); + + const cardTitle2 = document.createElement('p'); + cardTitle2.classList.add('card-header-title'); + cardTitle2.textContent = langs.create_instance; + + const cardIcon2 = document.createElement('button'); + cardIcon2.classList.add('card-header-icon'); + cardIcon2.setAttribute('aria-label', 'more options'); + + const icon2 = document.createElement('span'); + icon2.classList.add('icon'); + + const iconImage2 = document.createElement('i'); + iconImage2.classList.add('fas', 'fa-plus'); + + icon2.appendChild(iconImage2); + cardIcon2.appendChild(icon2); + + // Agregar elementos al DOM + document.body.appendChild(modal); + modal.appendChild(modalBackground); + modal.appendChild(modalCard); + modalCard.appendChild(modalHeader); + modalCard.appendChild(modalBody); + modalBody.appendChild(lineBreak2); + modalBody.appendChild(card2); + card2.appendChild(cardHeader2); + cardHeader2.appendChild(cardTitle2); + cardHeader2.appendChild(cardIcon2); + + + closeBtn.addEventListener('click', () => { + modal.remove(); + }); + + + card2.addEventListener('click', () => { + // Crear el elemento modal + const modal = document.createElement("div"); + modal.className = "modal is-active"; + modal.style.zIndex = "3"; + + // Modal background + const modalBackground = document.createElement("div"); + modalBackground.className = "modal-background"; + + // Modal card + const modalCard = document.createElement("div"); + modalCard.className = "modal-card"; + modalCard.style.backgroundColor = "#444444"; + + // Modal card head + const modalCardHead = document.createElement("header"); + modalCardHead.className = "modal-card-head"; + modalCardHead.style.backgroundColor = "#444444"; + + const modalCardTitle = document.createElement("p"); + modalCardTitle.className = "modal-card-title"; + modalCardTitle.style.fontSize = "25px"; + modalCardTitle.style.fontFamily = "Poppins"; + modalCardTitle.style.color = "#fff"; + modalCardTitle.innerText = langs.create_instance; + + const closeButton = document.createElement("button"); + closeButton.className = "delete"; + closeButton.setAttribute("aria-label", "close"); + + modalCardHead.appendChild(modalCardTitle); + modalCardHead.appendChild(closeButton); + + // Modal card body + const modalCardBody = document.createElement("section"); + modalCardBody.className = "modal-card-body"; + modalCardBody.style.backgroundColor = "#444444"; + + const nameLabel = document.createElement("p"); + nameLabel.style.color = "#fff"; + nameLabel.innerText = langs.instance_name; + + const nameInput = document.createElement("input"); + nameInput.className = "input is-info"; + nameInput.type = "text"; + nameInput.style.fontFamily = "Poppins"; + nameInput.style.fontWeight = "500"; + nameInput.style.fontSize = "12px"; + nameInput.setAttribute("placeholder", langs.name); + + const descriptionLabel = document.createElement("p"); + descriptionLabel.style.color = "#fff"; + descriptionLabel.innerText = langs.instance_description; + + const descriptionTextarea = document.createElement("textarea"); + descriptionTextarea.className = "textarea is-info"; + descriptionTextarea.style.fontFamily = "Poppins"; + descriptionTextarea.style.height = "20px"; + descriptionTextarea.style.fontWeight = "500"; + descriptionTextarea.style.fontSize = "12px"; + descriptionTextarea.setAttribute("name", "about"); + descriptionTextarea.setAttribute("placeholder", langs.description); + + const imageLabel = document.createElement("p"); + imageLabel.style.color = "#fff"; + imageLabel.innerText = langs.instance_image; + + const imageContainer = document.createElement("div"); + imageContainer.style.display = "flex"; + + const imageFigure = document.createElement("figure"); + imageFigure.className = "image is-64x64"; + imageFigure.style.marginRight = "10px"; + + const image = document.createElement("img"); + image.src = "./assets/images/icons/minecraft.png"; + image.style.borderRadius = "5px"; + + const fileContainer = document.createElement("div"); + fileContainer.className = "file is-info is-boxed"; + fileContainer.style.height = "65px"; + + const fileLabel = document.createElement("label"); + fileLabel.className = "file-label"; + + const fileInput = document.createElement("input"); + fileInput.className = "file-input"; + fileInput.type = "file"; + fileInput.setAttribute("name", "resume"); + + const fileCta = document.createElement("span"); + fileCta.className = "file-cta"; + + const fileIcon = document.createElement("span"); + fileIcon.className = "file-icon"; + + const uploadIcon = document.createElement("i"); + uploadIcon.className = "fas fa-cloud-upload-alt"; + + const fileLabelText = document.createElement("span"); + fileLabelText.style.fontSize = "10px"; + fileLabelText.innerText = langs.select_a_file; + + fileIcon.appendChild(uploadIcon); + fileCta.appendChild(fileIcon); + fileCta.appendChild(fileLabelText); + fileLabel.appendChild(fileInput); + fileLabel.appendChild(fileCta); + fileContainer.appendChild(fileLabel); + + imageFigure.appendChild(image); + imageContainer.appendChild(imageFigure); + imageContainer.appendChild(fileContainer); + + const versionLabel = document.createElement("p"); + versionLabel.style.color = "#fff"; + versionLabel.innerText = langs.instance_version; + + const versionSelect = document.createElement("div"); + versionSelect.className = "select is-info"; + + const versionOptions = document.createElement("select"); + + versionSelect.appendChild(versionOptions); + + modalCardBody.appendChild(nameLabel); + modalCardBody.appendChild(nameInput); + modalCardBody.appendChild(document.createElement("br")); + modalCardBody.appendChild(document.createElement("br")); + modalCardBody.appendChild(descriptionLabel); + modalCardBody.appendChild(descriptionTextarea); + modalCardBody.appendChild(document.createElement("br")); + modalCardBody.appendChild(imageLabel); + modalCardBody.appendChild(imageContainer); + modalCardBody.appendChild(document.createElement("br")); + modalCardBody.appendChild(versionLabel); + modalCardBody.appendChild(versionSelect); + + // Modal card foot + const modalCardFoot = document.createElement("footer"); + modalCardFoot.className = "modal-card-foot"; + modalCardFoot.style.backgroundColor = "#444444"; + + const createButton = document.createElement("button"); + createButton.className = "button is-info is-responsive"; + createButton.style.fontSize = "12px"; + createButton.style.fontFamily = "Poppins"; + createButton.style.color = "#fff"; + createButton.innerText = langs.create_instance; + + modalCardFoot.appendChild(createButton); + + // Construir la estructura del modal + modalCard.appendChild(modalCardHead); + modalCard.appendChild(modalCardBody); + modalCard.appendChild(modalCardFoot); + + modal.appendChild(modalBackground); + modal.appendChild(modalCard); + + // Agregar el modal al contenedor en el DOM + document.body.appendChild(modal); + + + + let versiones = this.Versions; + for (let i = 0; i < versiones.versions.length; i++) { + if (versiones.versions[i].version.endsWith("-forge") || versiones.versions[i].version.endsWith("-fabric") || versiones.versions[i].version.endsWith("-quilt")) { + let version = versiones.versions[i]; + let option = document.createElement("option"); + option.value = version.version; + option.innerHTML = version.name; + versionOptions.appendChild(option); + } + } + + closeButton.addEventListener("click", () => { + modal.remove(); + }); + + + fileInput.addEventListener("change", () => { + let imagen = fileInput.files ? fileInput.files : null; + if (imagen.length > 0) { + let reader = new FileReader(); + reader.onload = function (e) { + image.src = e.target.result; + }; + reader.readAsDataURL(imagen[0]); + } + }); + + + createButton.addEventListener("click", () => { + let name = nameInput.value; + let description = descriptionTextarea.value; + let version = versionOptions.value; + + if (name && description && version) { + //crear un string random de 6 caracteres + let randomString = Math.random().toString(36).substring(2, 8); + //crear el archivo de la instancia + //comprobar si existe la carpeta de instancias + if (!fs.existsSync(`${dataDirectory}/.battly/instances`)) { + fs.mkdirSync(`${dataDirectory}/.battly/instances`); + } + + //comprobar si existe la carpeta de la instancia + if (!fs.existsSync(`${dataDirectory}/.battly/instances/${randomString}`)) { + fs.mkdirSync(`${dataDirectory}/.battly/instances/${randomString}`); + } else { + //generar otro string random + randomString = Math.random().toString(36).substring(2, 8); + //crear la carpeta de la instancia + fs.mkdirSync(`${dataDirectory}/.battly/instances/${randomString}`); + } + + + let imagen = fileInput.files ? fileInput.files : null; + if (imagen.length > 0) { + fs.copyFileSync( + imagen[0].path, + `${dataDirectory}/.battly/instances/${randomString}/icon.png` + ); + } else { + //descargar la imagen https://bulma.io/images/placeholders/128x128.png y moverla a la carpeta de la instancia + imagen = "/assets/images/icons/minecraft.png"; + //convertir a buffer + let buffer = fs.readFileSync(__dirname + imagen); + //escribir el archivo + fs.writeFileSync( + `${dataDirectory}/.battly/instances/${randomString}/icon.png`, + buffer + ); + } + + let instance = { + name: name, + description: description, + version: version, + image: `${dataDirectory}/.battly/instances/${randomString}/icon.png`, + id: randomString, + }; + + let instance_json = JSON.stringify(instance); + fs.writeFileSync( + path.join( + `${dataDirectory}/.battly/instances/${randomString}`, + "instance.json" + ), + instance_json + ); + + //eliminar el modal + modal.remove(); + + Toast.fire({ + icon: "success", + title: langs.instance_created_correctly, + }); + } else { + Toast.fire({ + icon: "error", + title: langs.fill_all_fields, + }); + } + }); + }); + }); + } + + + + async CambiarRutaJava() { + let inputRutaJava = document.getElementById("ruta-java-input"); + + let ruta_java = localStorage.getItem("java-path"); + + if (ruta_java) { + inputRutaJava.value = ruta_java; + } else { + //si es windows + if (process.platform === "win32") { + //hacer un scan en ``${dataDirectory}/.battly/runtime`` ver si están la carpeta jre-17.0.8-win32 o jre-17.0.1.12.1-win32 + if ( + fs.existsSync(`${dataDirectory}/.battly/runtime/jre-17.0.8-win32`) + ) { + //si existe, poner la ruta en el input + inputRutaJava.value = `${dataDirectory}/.battly/runtime/jre-17.0.8-win32/bin/java.exe`; + localStorage.setItem( + "java-path", + `${dataDirectory}/.battly/runtime/jre-17.0.8-win32/bin/java.exe` + ); + } else if ( + fs.existsSync(`${dataDirectory}/.battly/runtime/jre-17.0.1.12.1-win32`) + ) { + //si existe, poner la ruta en el input + inputRutaJava.value = `${dataDirectory}/.battly/runtime/jre-17.0.1.12.1-win32/bin/java.exe`; + localStorage.setItem( + "java-path", + `${dataDirectory}/.battly/runtime/jre-17.0.1.12.1-win32/bin/java.exe` + ); + } else if(fs.existsSync(`${dataDirectory}/.battly/runtime/jre-17.0.8-windows-x64`)) { + inputRutaJava.value = `${dataDirectory}/.battly/runtime/jre-17.0.8-windows-x64/bin/java.exe`; + localStorage.setItem( + "java-path", + `${dataDirectory}/.battly/runtime/jre-17.0.8-windows-x64/bin/java.exe` + ); + } else if(fs.existsSync(`${dataDirectory}/.battly/runtime/jre-17.0.1.12.1-windows-x64`)) { + inputRutaJava.value = `${dataDirectory}/.battly/runtime/jre-17.0.1.12.1-windows-x64/bin/java.exe`; + localStorage.setItem( + "java-path", + `${dataDirectory}/.battly/runtime/jre-17.0.1.12.1-windows-x64/bin/java.exe` + ); + } else { + inputRutaJava.value = "Java no encontrado. Haz click aquí para buscarlo."; + } + } else { + inputRutaJava.value = "Java no encontrado. Haz click aquí para buscarlo."; + } + } + } + + async GenerarLogsSocket() { + ipcRenderer.on("getLogsAnterior", async () => { + let generated = consoleOutput + "\n" + consoleOutput_; + await fs.writeFileSync(logFilePath, generated); + }) + } + + async GetLogsSocket() { + ipcRenderer.on("avisoObtenerLogs", async (event, args) => { + Swal.fire({ + title: langs.title_access_logs, + text: langs.text_access_logs, + html: `${langs.requester} ${args.user}
    ${langs.reason}: ${args.razon}

    ${langs.text_access_logs_two}`, + showCancelButton: true, + confirmButtonText: langs.allow, + cancelButtonText: langs.deny, + }).then(async (result) => { + if (result.isConfirmed) { + if (!fs.existsSync(logFilePath)) { + let generated = consoleOutput + "\n" + consoleOutput_; + await fs.writeFileSync(logFilePath, generated); + ipcRenderer.send("obtenerLogs"); + } else { + await fs.unlinkSync(logFilePath); + let generated = consoleOutput + "\n" + consoleOutput_; + await fs.writeFileSync(logFilePath, generated); + ipcRenderer.send("obtenerLogs"); + } + } else { + Toast.fire({ + icon: "error", + title: langs.access_logs_denied, + text: langs.access_logs_denied_text + }); + } + }); + }); + + ipcRenderer.on("enviarSocketID", async (event, args) => { + Swal.fire({ + title: langs.title_access_logs, + text: `${langs.your_unique_id_is} ${args.sessionID} ${langs.dont_share_it}`, + confirmButtonText: langs.copy, + }).then(async (result) => { + if (result.isConfirmed) { + navigator.clipboard.writeText(args.sessionID); + Toast.fire({ + icon: "success", + title: langs.id_copied_correctly + }); + } + }); + }); + } + + async WaitData() { + if (!fs.existsSync(`${dataDirectory}/.battly`)) { + fs.mkdirSync(`${dataDirectory}/.battly`); + } + + if (!fs.existsSync(`${dataDirectory}/.battly/instances`)) { + fs.mkdirSync(`${dataDirectory}/.battly/instances`); + } + + if (!fs.existsSync(`${dataDirectory}/.battly/battly`)) { + fs.mkdirSync(`${dataDirectory}/.battly/battly`); + } + + if (!fs.existsSync(`${dataDirectory}/.battly/battly/mods-internos`)) { + fs.mkdirSync(`${dataDirectory}/.battly/battly/mods-internos`); + } + + if (!fs.existsSync(`${dataDirectory}/.battly/battly/launcher`)) { + fs.mkdirSync(`${dataDirectory}/.battly/battly/launcher`); + } + + if (!fs.existsSync(`${dataDirectory}/.battly/battly/launcher/config-launcher`)) { + fs.mkdirSync(`${dataDirectory}/.battly/battly/launcher/config-launcher`); + } + + if (!fs.existsSync(`${dataDirectory}/.battly/battly/launcher/forge`)) { + fs.mkdirSync(`${dataDirectory}/.battly/battly/launcher/forge`); + } + + if (!fs.existsSync(`${dataDirectory}/.battly/battly/launcher/mc-assets`)) { + fs.mkdirSync(`${dataDirectory}/.battly/battly/launcher/mc-assets`); + } + } + + async ShowNews() { + let btnShowNews = document.getElementById("btnShowNews"); + btnShowNews.addEventListener("click", async () => { + changePanel("news"); + }); + let news_shown = localStorage.getItem("news_shown_v1.7"); + if ( + !news_shown || + news_shown == "false" || + news_shown == null || + news_shown == undefined + ) { + setTimeout(function () { + changePanel("news"); + }, 3000); + } + } + + async InitTheme() { + const btnDownload1 = document.getElementById("music-btn"); + btnDownload1.addEventListener("click", () => { + changePanel("music"); + }); + + let color = localStorage.getItem("theme-color"); + if (!color) color = "#3e8ed0"; + let color_bottom_bar = localStorage.getItem("theme-color-bottom-bar"); + let opacity = localStorage.getItem("theme-opacity-bottom-bar"); + let background_img = localStorage.getItem("background-img"); + + let buttons = document.querySelectorAll(".button"); + let btns = document.querySelectorAll(".btn"); + let tab_btns = document.querySelectorAll(".tab-btn"); + let inputs = document.querySelectorAll(".input"); + let select = document.querySelectorAll(".select"); + let select_options = document.querySelectorAll(".select-version"); + let select_selected = document.querySelectorAll(".select-selected"); + let select_selected_span = document.querySelectorAll( + ".select-selected span" + ); + let bottom_bar = document.querySelector(".bottom_bar"); + let bottom_bar_settings = document.querySelector(".bottom_bar_settings"); + let bottom_bar_mods = document.querySelector(".bottom_bar_mods"); + + if (color_bottom_bar) { } else { + color_bottom_bar.value = "#1f1f1f"; + localStorage.setItem("theme-color-bottom-bar", "#1f1f1f"); + } + + bottom_bar.style.backgroundColor = color_bottom_bar; + bottom_bar_settings.style.backgroundColor = color_bottom_bar; + bottom_bar_mods.style.backgroundColor = color_bottom_bar; + + buttons.forEach((button) => { + button.style.backgroundColor = color; + }); + + if (opacity) { + bottom_bar.style.opacity = opacity; + bottom_bar_settings.style.opacity = opacity; + bottom_bar_mods.style.opacity = opacity; + } else { + bottom_bar.style.opacity = "1"; + bottom_bar_settings.style.opacity = "1"; + bottom_bar_mods.style.opacity = "1"; + } + + document.querySelector(".save-tabs-btn").style.backgroundColor = color; + + btns.forEach((btn) => { + btn.style.backgroundColor = color; + }); + + tab_btns.forEach((tab_btn) => { + tab_btn.style.backgroundColor = color; + }); + + inputs.forEach((input) => { + input.style.backgroundColor = color; + }); + + select.forEach((select) => { + select.style.backgroundColor = color; + }); + + select_options.forEach((select_option) => { + select_option.style.backgroundColor = color; + }); + + select_selected.forEach((select_selected) => { + select_selected.style.backgroundColor = color; + }); + + select_selected_span.forEach((select_selected_span) => { + select_selected_span.style.backgroundColor = color; + }); + + if (background_img) { + document.body.style.backgroundImage = `url(${background_img})`; + } else { } + } + + async IniciarEstadoDiscord() { + ipcRenderer.send("new-status-discord"); + } + + async CargarVersiones() { + let versiones = document.getElementById("listaDeVersiones"); + let btnReloadVersions = document.getElementById("reiniciar-versiones"); + btnReloadVersions.addEventListener("click", () => { + versiones.innerHTML = ""; + this.CargarVersiones(); + + Toast.fire({ + icon: "success", + title: langs.version_list_updated, + }); + }); + try { + let versiones_nuevas = fs.readdirSync( + dataDirectory + "/.battly/versions" + ); + + let versions_vanilla = []; + + for (let i = 0; i < versiones_nuevas.length; i++) { + let data_versions_mojang = this.VersionsMojang; + + for (let i = 0; i < data_versions_mojang.versions.length; i++) { + let version = data_versions_mojang.versions[i].id; + versions_vanilla.push(version); + } + + + + + let version = versiones_nuevas[i]; + + if (!versions_vanilla.includes(version)) { + let option = document.createElement("option"); + //si contiene OptiFine- eliminar todo lo que vaya después de OptiFine pero incluir la palabra OptiFine + if (version.includes("OptiFine_")) { + // Usa una expresión regular para eliminar todo después de "OptiFine" y agrega "OptiFine" + let version_optifine = version.replace(/OptiFine.*$/, "OptiFine"); + option.value = version + `-extra`; + option.innerHTML = version_optifine; + versiones.appendChild(option); + } else { + option.value = version + `-extra`; + option.innerHTML = version; + versiones.appendChild(option); + } + } else { + let option = document.createElement("option"); + option.value = version + ``; + option.innerHTML = version + ""; + versiones.appendChild(option); + } + } + } catch { } + } + + async CargarMods() { + let BotonUnirseServidorDiscord = document.getElementById( + "BotonUnirseServidorDiscord" + ); + BotonUnirseServidorDiscord.addEventListener("click", function () { + window.open("https://discord.gg/tecno-bros-885235460178342009", "_blank"); + }); + } + + async initConfig() { + let config = this.BattlyConfig; + let config_json = JSON.stringify(config); + fs.mkdirSync( + `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }`, { + recursive: true, + } + ); + fs.mkdirSync( + `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/versions`, { + recursive: true, + } + ); + + let versionsConfig = this.Versions; + let config_json_versions = JSON.stringify(versionsConfig); + fs.mkdirSync( + `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }`, { + recursive: true, + } + ); + + document.getElementById("instancias-btn").innerHTML = ` ${langs.instances}`; + document.getElementById("download-btn").innerHTML = ` ${langs.download}`; + document.getElementById("play-btn").innerHTML = `${langs.play} `; + document.getElementById("news-battly").innerHTML = `${langs.news_battly}`; + document.getElementById("status-battly").innerHTML = `${langs.status_battly}`; + document.getElementById("playing-now-text").innerHTML = `${langs.playing_now_text}`; + document.getElementById("playing-now-body").innerHTML = `${langs.playing_now_body}`; + document.getElementById("ads-text").innerHTML = `${langs.ads_text}`; + + /* settings */ + document.getElementById("accounts-btn").innerHTML = `${langs.accounts_btn}`; + document.getElementById("java-btn").innerHTML = `${langs.java_btn}`; + document.getElementById("ram-btn").innerHTML = `${langs.ram_btn}`; + document.getElementById("launcher-btn").innerHTML = `${langs.launcher_btn}`; + document.getElementById("theme-btn").innerHTML = `${langs.theme_btn}`; + document.getElementById("background-btn").innerHTML = `${langs.background_btn}`; + document.getElementById("save-btn").innerHTML = `${langs.save_btn}`; + document.getElementById("account-information").innerHTML = `${langs.account_information}`; + document.getElementById("mc-id-text").innerHTML = `${langs.mc_id_text}`; + document.getElementById("mostrarskin-userinfo-btn").innerHTML = `${langs.showskin_userinfo_btn}`; + document.getElementById("eliminarcuenta-userinfo-btn").innerHTML = `${langs.deleteaccount_userinfo_btn}`; + document.getElementById("establecer-skin").innerHTML = `${langs.set_skin}`; + document.getElementById("cerrar-userinfo-btn").innerHTML = `${langs.close}`; + document.getElementById("my-accounts").innerHTML = `${langs.my_accounts}`; + document.getElementById("add-account-text").innerHTML = `${langs.add_account_text}`; + document.getElementById("java-settings").innerHTML = `${langs.java_settings}`; + document.getElementById("java-text-info").innerHTML = `${langs.java_text_info}`; + document.getElementById("java-text-info2").innerHTML = `${langs.java_text_info2}`; + document.getElementById("ram-settings").innerHTML = `${langs.ram_settings}`; + document.getElementById("ram-text-info").innerHTML = `${langs.ram_text_info}`; + document.getElementById("of-ram").innerHTML = `${langs.of_ram}`; + document.getElementById("of-ram-disponible").innerHTML = `${langs.of_ram_disponible}`; + document.getElementById("you-have-a-total").innerHTML = `${langs.you_have_a_total}`; + document.getElementById("ram-text-info").innerHTML = `${langs.ram_text_info}`; + document.getElementById("battly-settings").innerHTML = `${langs.battly_settings}`; + document.getElementById("battly-settings-information").innerHTML = `${langs.battly_settings_information}`; + document.getElementById("minimalize-battly").innerHTML = `${langs.minimalize_battly}`; + document.getElementById("keep-battly-opened").innerHTML = `${langs.keep_battly_opened}`; + document.getElementById("obtener-socketid").innerHTML = `${langs.get_socketid}`; + document.getElementById("battly-theme").innerHTML = `${langs.battly_theme}`; + document.getElementById("welcome").innerHTML = `${langs.welcome}`; + document.getElementById("battly-theme-text").innerHTML = `${langs.battly_theme_text}`; + document.getElementById("change-theme-text").innerHTML = `${langs.change_theme_text}`; + document.getElementById("buttons-color").innerHTML = `${langs.buttons_color}`; + document.getElementById("bottom-bar-text").innerHTML = `${langs.bottom_bar_text}`; + document.getElementById("bottom-bar-opacity").innerHTML = `${langs.bottom_bar_opacity}`; + document.getElementById("starting-music").innerHTML = `${langs.starting_music}`; + document.getElementById("resize-image-text").innerHTML = `${langs.resize_image_text}`; + document.getElementById("establecer-fondo").innerHTML = `${langs.set_background_text}`; + document.getElementById("cerrar-preview-btn").innerHTML = `${langs.cancel}`; + document.getElementById("customize-background").innerHTML = `${langs.customize_background}`; + document.getElementById("resize-background").innerHTML = `${langs.resize_background}`; + document.getElementById("background-image-text").innerHTML = `${langs.background_image_text}`; + document.getElementById("restablecer-fondo").innerHTML = `${langs.reset_background}`; + document.getElementById("select-a-background").innerHTML = `${langs.select_a_background}`; + document.getElementById("button_instalar_modpack").innerHTML = `${langs.install_modpack}`; + document.getElementById("volver").innerHTML = `${langs.return}`; + document.getElementById("input_buscar_mods").placeholder = `${langs.search_mods}`; + document.getElementById("add-friends").innerHTML = `${langs.add_friend}`; + document.getElementById("solicitudes").innerHTML = `${langs.show_requests}`; + document.getElementById("friends-volver-btn").innerHTML = `${langs.return}`; + document.getElementById("welcome_battly_social").innerHTML = `${langs.welcome_battly_social}`; + document.getElementById("friends_list_text").innerHTML = `${langs.friends_list_text}`; + document.getElementById("start_minecraft_text").innerHTML = `${langs.start_minecraft_text}`; + document.getElementById("textInfo").innerHTML = `${langs.select_the_version_that_you_want}`; + document.getElementById("select_a_version").innerHTML = `${langs.select_a_version}`; + document.getElementById("show-playlists").innerHTML = `${langs.playlists}`; + document.getElementById("return-btn").innerHTML = `${langs.return}`; + document.getElementById("playing-now").innerHTML = `${langs.playing_now}`; + document.getElementById("nombre-de-cancion").placeholder = `${langs.song_name}`; + document.getElementById("reproducir-btn").innerHTML = `${langs.search_song}`; + document.getElementById("save-playlist").innerHTML = `${langs.save_playlist}`; + document.getElementById("cancel-btn-login").innerHTML = `${langs.cancel}`; + //document.getElementById("cancel_login_two").innerHTML = `${langs.cancel}`; + document.getElementById("lost_your_account").innerHTML = `${langs.lost_your_account}`; + document.getElementById("recover_it_here").innerHTML = `${langs.recover_it_here}`; + document.getElementById("username_text").placeholder = `${langs.username}`; + document.getElementById("password_text").placeholder = `${langs.password}`; + document.getElementById("register_open_btn").innerHTML = `${langs.register_open_btn}`; + document.getElementById("login-text").innerHTML = `${langs.login}`; + document.getElementById("you-dont-have-account").innerHTML = `${langs.you_dont_have_account}`; + document.getElementById("login-btn").innerHTML = `${langs.login}`; + + + } + + async initNews() { + let news = document.querySelector(".news-list"); + if (this.news) { + if (!this.news.length) { + let blockNews = document.createElement("div"); + blockNews.classList.add("news-block", "opacity-1"); + blockNews.innerHTML = ` +

    +
    +
    No hay noticias disponibles actualmente.
    +
    +
    +
    +
    +

    Puedes seguir todas las noticias relacionadas con el servidor aquí.

    +
    +
    `; + news.appendChild(blockNews); + } else { + for (let News of this.news) { + let date = await this.getdate(News.publish_date); + let blockNews = document.createElement("div"); + blockNews.classList.add("news-block"); + blockNews.innerHTML = ` +
    +
    +
    ${News.title}
    +
    +
    +
    ${date.day}
    +
    ${date.month}
    +
    +
    +
    +
    +

    ${News.content.replace(/\n/g, "
    ")}

    +

    ${News.author + }

    +
    +
    `; + news.appendChild(blockNews); + } + } + } else { + let blockNews = document.createElement("div"); + blockNews.classList.add("news-block", "opacity-1"); + blockNews.innerHTML = ` +
    +
    +
    Error.
    +
    +
    +
    +
    +

    No se puede contactar con el servidor de noticias.
    Por favor, compruebe su configuración.

    +
    +
    `; + // news.appendChild(blockNews); + } + } + + async initLaunch() { + //crear el archivo launcher_profiles.json en la ruta de main del launcher + let launcherProfiles; + let accounts = await this.database.getAll("accounts"); + let accountsSelected = await this.database.get("1234", "accounts-selected"); + + let profiles = {}; + let profiles_ = []; + for (let account of accounts) { + profiles_.push(account); + } + + for (let i = 0; i < profiles_.length; i++) { + let profileName = profiles_[i].value.name; + profiles[profiles_[i].value.uuid] = { + created: Date.now(), + icon: "Grass", + lastUsed: "1970-01-02T00:00:00.000Z", + lastVersionId: "latest-release", + name: "", + type: "latest-release", + }; + } + + launcherProfiles = { + profiles: profiles, + settings: { + crashAssistance: true, + enableAdvanced: false, + enableAnalytics: true, + enableHistorical: false, + enableReleases: true, + enableSnapshots: false, + keepLauncherOpen: false, + profileSorting: "ByLastPlayed", + showGameLog: false, + showMenu: false, + soundOn: false, + }, + version: 3, + }; + + let launcherProfilesJson = JSON.stringify(launcherProfiles); + fs.mkdirSync( + `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }`, { + recursive: true, + } + ); + fs.writeFileSync( + path.join( + `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }`, + "launcher_profiles.json" + ), + launcherProfilesJson + ); + + let data = this.BattlyConfig; + let new_version = data.new_version; + let new_version_message = data.new_version_message; + let new_version_news = data.new_version_news; + let new_version_html = data.new_version_html; + + if (new_version == true) { + const Swal_ = require("./assets/js/libs/sweetalert/sweetalert2.all.min"); + + Swal_.fire({ + title: new_version_message, + html: new_version_html, + confirmButtonText: langs.accept, + }); + } + + let mcModPack; + + document.getElementById("play-btn").addEventListener("click", async () => { + let modalStartVersions = document.getElementById("modalStartVersion"); + modalStartVersions.classList.add("is-active"); + }); + + document + .getElementById("closeStartVersion") + .addEventListener("click", async () => { + let modalStartVersions = document.getElementById("modalStartVersion"); + modalStartVersions.classList.remove("is-active"); + }); + + document + .getElementById("cancelStartVersion") + .addEventListener("click", async () => { + let modalStartVersions = document.getElementById("modalStartVersion"); + modalStartVersions.classList.remove("is-active"); + }); + + let data_versions = this.Versions; + let data_versions_mojang = this.VersionsMojang; + + document + .getElementById("listaDeVersiones") + .addEventListener("change", async () => { + let version_selected = + document.getElementById("listaDeVersiones").value; + let versiones = data_versions.versions; + + //comprobar si la versión es compatible con forge, fabric o quilt, obteniendo las versiones, ejemplo: + /* {"versions":[{"version":"1.20.1","name":"1.20.1"},{"version":"1.20.1-forge","name":"1.20.1 - Forge"},{"version":"1.20.1-fabric","name":"1.20.1 - Fabric"},{"version":"1.20.1-quilt","name":"1.20.1 - Quilt"} ]} */ + let radioVanilla = document.getElementById("radioVanilla"); + let radioForge = document.getElementById("radioForge"); + let radioFabric = document.getElementById("radioFabric"); + let radioQuilt = document.getElementById("radioQuilt"); + + let versions_vanilla = []; + let versiones_compatible_forge = []; + let versiones_compatible_fabric = []; + let versiones_compatible_quilt = []; + + for (let i = 0; i < versiones.length; i++) { + let version = versiones[i].version; + if (version.endsWith("-forge")) { + versiones_compatible_forge.push(versiones[i].realVersion); + } else if (version.endsWith("-fabric")) { + versiones_compatible_fabric.push(versiones[i].realVersion); + } else if (version.endsWith("-quilt")) { + versiones_compatible_quilt.push(versiones[i].realVersion); + } + } + + for (let i = 0; i < data_versions_mojang.versions.length; i++) { + let version = data_versions_mojang.versions[i].id; + versions_vanilla.push(version); + } + + if ( + versiones_compatible_forge.includes(version_selected) && + versiones_compatible_fabric.includes(version_selected) && + versiones_compatible_quilt.includes(version_selected) + ) { + document.getElementById("tipo-de-versiones").style.display = ""; + radioVanilla.style.display = ""; + radioForge.style.display = ""; + radioFabric.style.display = ""; + radioQuilt.style.display = ""; + let footermodaliniciarversion = document.getElementById( + "footermodaliniciarversion" + ); + footermodaliniciarversion.style.display = "none"; + } else if ( + versiones_compatible_forge.includes(version_selected) && + versiones_compatible_fabric.includes(version_selected) + ) { + document.getElementById("tipo-de-versiones").style.display = ""; + radioVanilla.style.display = ""; + radioForge.style.display = ""; + radioFabric.style.display = ""; + radioQuilt.style.display = "none"; + let footermodaliniciarversion = document.getElementById( + "footermodaliniciarversion" + ); + footermodaliniciarversion.style.display = "none"; + } else if ( + versiones_compatible_forge.includes(version_selected) && + versiones_compatible_quilt.includes(version_selected) + ) { + document.getElementById("tipo-de-versiones").style.display = ""; + radioVanilla.style.display = ""; + radioForge.style.display = ""; + radioFabric.style.display = "none"; + radioQuilt.style.display = ""; + let footermodaliniciarversion = document.getElementById( + "footermodaliniciarversion" + ); + footermodaliniciarversion.style.display = "none"; + } else if ( + versiones_compatible_fabric.includes(version_selected) && + versiones_compatible_quilt.includes(version_selected) + ) { + document.getElementById("tipo-de-versiones").style.display = ""; + radioVanilla.style.display = ""; + radioForge.style.display = "none"; + radioFabric.style.display = ""; + radioQuilt.style.display = ""; + let footermodaliniciarversion = document.getElementById( + "footermodaliniciarversion" + ); + footermodaliniciarversion.style.display = "none"; + } else if (versiones_compatible_forge.includes(version_selected)) { + document.getElementById("tipo-de-versiones").style.display = ""; + radioVanilla.style.display = ""; + radioForge.style.display = ""; + radioFabric.style.display = "none"; + radioQuilt.style.display = "none"; + let footermodaliniciarversion = document.getElementById( + "footermodaliniciarversion" + ); + footermodaliniciarversion.style.display = "none"; + } else if (versiones_compatible_fabric.includes(version_selected)) { + document.getElementById("tipo-de-versiones").style.display = ""; + radioVanilla.style.display = ""; + radioForge.style.display = "none"; + radioFabric.style.display = ""; + radioQuilt.style.display = "none"; + let footermodaliniciarversion = document.getElementById( + "footermodaliniciarversion" + ); + footermodaliniciarversion.style.display = "none"; + } else if (versiones_compatible_quilt.includes(version_selected)) { + document.getElementById("tipo-de-versiones").style.display = ""; + radioVanilla.style.display = ""; + radioForge.style.display = "none"; + radioFabric.style.display = "none"; + radioQuilt.style.display = ""; + let footermodaliniciarversion = document.getElementById( + "footermodaliniciarversion" + ); + footermodaliniciarversion.style.display = "none"; + } else if (versions_vanilla.includes(version_selected)) { + document.getElementById("tipo-de-versiones").style.display = ""; + radioVanilla.style.display = ""; + radioForge.style.display = "none"; + radioFabric.style.display = "none"; + radioQuilt.style.display = "none"; + let footermodaliniciarversion = document.getElementById( + "footermodaliniciarversion" + ); + footermodaliniciarversion.style.display = "none"; + } else if (version_selected === "dx") { + document.getElementById("tipo-de-versiones").display = "none"; + radioVanilla.style.display = "none"; + radioForge.style.display = "none"; + radioFabric.style.display = "none"; + radioQuilt.style.display = "none"; + let footermodaliniciarversion = document.getElementById( + "footermodaliniciarversion" + ); + footermodaliniciarversion.style.display = "none"; + } else { + document.getElementById("tipo-de-versiones").display = "none"; + radioVanilla.style.display = "none"; + radioForge.style.display = "none"; + radioFabric.style.display = "none"; + radioQuilt.style.display = "none"; + let footermodaliniciarversion = document.getElementById( + "footermodaliniciarversion" + ); + footermodaliniciarversion.style.display = ""; + } + }); + + //radio con name loader + let radio = document.getElementsByName("loader"); + radio.forEach((element) => { + element.addEventListener("click", async () => { + let footermodaliniciarversion = document.getElementById( + "footermodaliniciarversion" + ); + footermodaliniciarversion.style.display = ""; + }); + }); + + document + .getElementById("startStartVersion") + .addEventListener("click", async () => { + let version = document.getElementById("listaDeVersiones").value; + let versionType; + let progressBar1 = document.getElementById("progressBar1_"); + let modalDiv1 = document.getElementById("modalStartVersion"); + + let urlpkg = pkg.user ? `${pkg.url}/${pkg.user}` : pkg.url; + let uuid = (await this.database.get("1234", "accounts-selected")).value; + let account = (await this.database.get(uuid.selected, "accounts")).value; + let ram = (await this.database.get("1234", "ram")).value; + let Resolution = (await this.database.get("1234", "screen")).value; + let launcherSettings = (await this.database.get("1234", "launcher")).value; + + let isForgeCheckBox = false; + let isFabricCheckBox = false; + let isQuiltCheckBox = false; + + let settings_btn = document.getElementById("settings-btn"); + let select_versions = document.getElementById("select-version"); + let mods_btn = document.getElementById("boton_abrir_mods"); + let discord_btn = document.getElementById("BotonUnirseServidorDiscord"); + + let footermodaliniciarversion = document.getElementById( + "footermodaliniciarversion" + ); + footermodaliniciarversion.style.display = "none"; + + let textInfo = document.getElementById("textInfo"); + textInfo.innerHTML = langs.starting_version_can_take; + + let radio = document.getElementsByName("loader"); + + radio.forEach((element) => { + if (element.checked) { + if (version.endsWith("-extra")) { + versionType = "extra"; + } else { + versionType = element.value; + } + } + }); + + if (versionType === "vanilla") { + version = version; + } else if (versionType === "fabric") { + version += `-fabric`; + } else if (versionType === "forge") { + version += `-forge`; + } else if (versionType === "quilt") { + version += `-quilt`; + } else { + } + + let version_real; + if (version.endsWith("-forge")) { + version_real = version.replace("-forge", ""); + } else if (version.endsWith("-fabric")) { + version_real = version.replace("-fabric", ""); + } else if (version.endsWith("-quilt")) { + version_real = version.replace("-quilt", ""); + } else if (version.endsWith("-extra")) { + version_real = version.replace("-extra", ""); + } else { + version_real = version; + } + + if (version.endsWith("-forge")) { + version = version.replace("-forge", ""); + isForgeCheckBox = true; + isFabricCheckBox = false; + isQuiltCheckBox = false; + } else if (version.endsWith("-fabric")) { + version = version.replace("-fabric", ""); + isFabricCheckBox = true; + isForgeCheckBox = false; + isQuiltCheckBox = false; + } else if (version.endsWith("-quilt")) { + version = version.replace("-quilt", ""); + isQuiltCheckBox = true; + isForgeCheckBox = false; + isFabricCheckBox = false; + } + + let type; + if (isForgeCheckBox == true) { + type = "forge"; + mcModPack = "forge"; + } else if (isFabricCheckBox == true) { + type = "fabric"; + mcModPack = "fabric"; + } else if (isQuiltCheckBox == true) { + type = "quilt"; + mcModPack = "quilt"; + } + + //hacer un json.parse del archivo de versiones y obtener el dato "assets" + + //comprobar si existe el archivo de versiones + + // Si la versión acaba con -extra hacer let assets = JSON.parse(fs.readFileSync(`${dataDirectory}/.battly/versions/${version_real}/${version_real}.json`)).assets; + // si no, ignorar + let assets; + let versionData; + if (version_real === "1.8") { + assets = "1.8"; + versionData = { + number: assets, + custom: version_real, + type: "release", + }; + } else if ( + version.endsWith("-extra") && + !version.includes("OptiFine") && + !version_real.includes("LabyMod") + ) { + assets = JSON.parse( + fs.readFileSync( + `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/versions/${version_real}/${version_real}.json` + ) + ).assets; + versionData = { + number: assets, + custom: version_real, + type: "release", + }; + } else if (version.includes("OptiFine") && version.endsWith("-extra")) { + assets = JSON.parse( + fs.readFileSync( + `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/versions/${version_real}/${version_real}.json` + ) + ).inheritsFrom; + versionData = { + number: assets, + custom: version_real, + type: "release", + }; + } else if (version.includes("LabyMod") && version.endsWith("-extra")) { + assets = JSON.parse( + fs.readFileSync( + `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/versions/${version_real}/${version_real}.json` + ) + )._minecraftVersion; + versionData = { + number: version_real, + type: "release", + }; + } else if ( + version_real.endsWith("-forge") || + version_real.endsWith("-fabric") || + version_real.endsWith("-quilt") + ) { + versionData = version; + } else { + versionData = version_real; + } + + let playBtn = document.getElementById("download-btn"); + let info = document.getElementById("textInfoStatus"); + let logTextArea1 = document.getElementById("logTextArea1_"); + + if (Resolution.screen.width == "") { + screen = false; + } else { + screen = { + width: Resolution.screen.width, + height: Resolution.screen.height, + }; + } + + let opts; + + let javapath = localStorage.getItem("java-path"); + if (!javapath || javapath == null || javapath == undefined) { + opts = { + url: this.config.game_url === "" || this.config.game_url === undefined ? + `${urlpkg}/files` : + this.config.game_url, + authorization: account, + authenticator: account, + detached: false, + timeout: 10000, + root: `${dataDirectory}/.battly`, + path: `${dataDirectory}/.battly`, + overrides: { + detached: false, + screen: screen, + }, + downloadFileMultiple: 20, + //javaPath: "C:\\Users\\ilyas\\Desktop\\RND Projects\\Java\\bin\\java.exe", + version: versionData, + loader: { + type: type, + build: this.BattlyConfig.loader.build, + enable: isForgeCheckBox ? + true : + isFabricCheckBox ? + true : + isQuiltCheckBox ? + true : + false, + }, + verify: false, + ignored: ["loader"], + java: false, + memory: { + min: `${ram.ramMin * 1024}M`, + max: `${ram.ramMax * 1024}M`, + }, + }; + } else { + if (version.endsWith("-extra")) { + opts = { + url: this.config.game_url === "" || this.config.game_url === undefined ? + `${urlpkg}/files` : + this.config.game_url, + authorization: account, + authenticator: account, + detached: false, + timeout: 10000, + root: `${dataDirectory}/.battly`, + path: `${dataDirectory}/.battly`, + overrides: { + detached: false, + screen: screen, + }, + downloadFileMultiple: 20, + javaPath: javapath, + version: versionData, + loader: { + type: type, + build: this.BattlyConfig.loader.build, + enable: isForgeCheckBox ? + true : + isFabricCheckBox ? + true : + isQuiltCheckBox ? + true : + false, + }, + verify: false, + ignored: ["loader"], + java: false, + memory: { + min: `${ram.ramMin * 1024}M`, + max: `${ram.ramMax * 1024}M`, + }, + }; + } else { + opts = { + url: this.config.game_url === "" || this.config.game_url === undefined ? + `${urlpkg}/files` : + this.config.game_url, + authorization: account, + authenticator: account, + detached: false, + timeout: 10000, + root: `${dataDirectory}/.battly`, + path: `${dataDirectory}/.battly`, + overrides: { + detached: false, + screen: screen, + }, + downloadFileMultiple: 20, + //javaPath: "C:\\Users\\ilyas\\Desktop\\RND Projects\\Java\\bin\\java.exe", + version: versionData, + loader: { + type: type, + build: this.BattlyConfig.loader.build, + enable: isForgeCheckBox ? + true : + isFabricCheckBox ? + true : + isQuiltCheckBox ? + true : + false, + }, + verify: false, + ignored: ["loader"], + java: false, + memory: { + min: `${ram.ramMin * 1024}M`, + max: `${ram.ramMax * 1024}M`, + }, + }; + } + } + + const launch = new Client(); + const launch_core = new Launch(); + + try { + if (version === "1.8") { + await launch.launch(opts); + document.getElementById("carga-de-versiones").style.display = ""; + } else if ( + version_real.endsWith("-forge") || + version_real.endsWith("-fabric") || + version_real.endsWith("-quilt") + ) { + await launch_core.Launch(opts); + document.getElementById("carga-de-versiones").style.display = ""; + } else if (version.endsWith("-extra")) { + launch.launch(opts); + document.getElementById("carga-de-versiones").style.display = ""; + } else { + await launch_core.Launch(opts); + document.getElementById("carga-de-versiones").style.display = ""; + } + } catch (error) { + setTimeout(() => { + playBtn.style.display = ""; + info.style.display = "none"; + progressBar1.style.display = "none"; + }, 3000); + console.log(error); + } + + launch.on("extract", (extract) => { + consoleOutput_ += `[EXTRACT] ${extract}\n`; + let seMostroInstalando = false; + if (seMostroInstalando) { } else { + seMostroInstalando = true; + } + }); + + launch.on("debug", (e) => { + consoleOutput_ += `[DEBUG] ${JSON.stringify(e, null, 2)}\n`; + if (e.includes("Failed to start due to TypeError")) return ShowPanelError(`${langs.error_detected_one} \nError:\n${e}`); + + if (e.includes("Downloaded and extracted natives")) { + + progressBar1.style.display = ""; + progressBar1.max = 100; + progressBar1.value = 0; + + info.innerHTML = langs.downloading_files; + } + + if (e.includes("Attempting to download Minecraft version jar")) { + info.innerHTML = langs.downloading_version; + } + + if (e.includes("Attempting to download assets")) { + info.innerHTML = langs.downloading_assets; + } + + if (e.includes("Downloaded Minecraft version jar")) { + info.innerHTML = langs.downloading_libraries; + } + + if (e.includes("Downloaded and extracted natives")) { + info.innerHTML = langs.downloading_natives; + } + + if (e.includes("Failed to start the minecraft server")) return ShowPanelError(`${langs.error_detected_one} \nError:\n${e}`); + if (e.includes('Exception in thread "main" ')) return ShowPanelError(`${langs.error_detected_two} \nError:\n${e}`); + + if (e.includes("There is insufficient memory for the Java Runtime Environment to continue.")) return ShowPanelError(`${langs.error_detected_three} \nError:\n${e}`); + if (e.includes("Could not reserve enough space for object heap")) return ShowPanelError(`${langs.error_detected_three} \nError:\n${e}`); + + if (e.includes("Forge patcher exited with code 1")) { + ShowPanelError(`${langs.error_detected_four} \nError:\n${e}`); + progressBar1.style.display = "none"; + info.style.display = "none"; + playBtn.style.display = ""; + } + + if (e.includes("Unable to launch")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if (e.includes("Minecraft Crash Report") && !e.includes("THIS IS NOT A ERROR")) return ShowPanelError(`${langs.error_detected_one} \nError:\n${e}`); + + if (e.includes("java.lang.ClassCastException")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if (e.includes("Minecraft has crashed!")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + }); + launch.on("data", (e) => { + consoleOutput_ += `[DEBUG] ${JSON.stringify(e, null, 2)}\n`; + if (e.includes("Failed to start du { + ipcRenderer.send("main-window-progress-reset"); + /* + let hours = Math.floor(time / 3600); + let minutes = Math.floor((time - hours * 3600) / 60); + let seconds = Math.floor(time - hours * 3600 - minutes * 60); + console.log(`${hours}h ${minutes}m ${seconds}s`);*/ + }); + + let timeoutId; + + launch.on("speed", (speed) => { + /* + let velocidad = speed / 1067008; + + if (velocidad > 0) { + clearTimeout(timeoutId); // cancela el mensaje de alerta si la velocidad no es cero + } else { + timeoutId = setTimeout(() => { + progressBar1.style.display = "none" + progressBar1.max = 100; + progressBar1.value = 0; + playBtn.style.display = "" + info.style.display = "none" + clearTimeout(timeoutId); + const swal = require('sweetalert'); + crasheo = true; + + Toast.fire({ + title: "Error", + text: "Error al descargar esta versión. Reinicia el launcher o inténtalo de nuevo más tarde. [ERROR: 2]", + icon: "error", + button: "Aceptar", + }).then((value) => { + if(value) { + ipcRenderer.send('restartLauncher') + } + }); + + }, 10000); + }*/ + }); + + launch.on("patch", (patch) => { + consoleOutput_ += `[INSTALANDO LOADER] ${patch}\n`; + let seMostroInstalando = false; + if (seMostroInstalando) { } else { + logTextArea1.innerHTML = `${langs.installing_loader}...`; + seMostroInstalando = true; + } + + info.innerHTML = `${langs.installing_loader}...`; + }); + + let inicio = false; + let iniciando = false; + launch.on("data", async (e) => { + new logger("Minecraft", "#36b030"); + consoleOutput_ += `[MC] ${e}\n`; + if (launcherSettings.launcher.close === "close-launcher") + ipcRenderer.send("main-window-hide"); + + if (e.includes("Launching with arguments")) + info.innerHTML = `${langs.starting_minecraft}...`;; + + if (e.includes("Failed to start the minecraft server")) return ShowPanelError(`${langs.error_detected_one} \nError:\n${e}`); + if (e.includes('Exception in thread "main" ')) return ShowPanelError(`${langs.error_detected_two} \nError:\n${e}`); + + if (e.includes("There is insufficient memory for the Java Runtime Environment to continue.")) return ShowPanelError(`${langs.error_detected_three} \nError:\n${e}`); + if (e.includes("Could not reserve enough space for object heap")) return ShowPanelError(`${langs.error_detected_three} \nError:\n${e}`); + + if (e.includes("Forge patcher exited with code 1")) { + ShowPanelError(`${langs.error_detected_four} \nError:\n${e}`); + progressBar1.style.display = "none"; + info.style.display = "none"; + playBtn.style.display = ""; + } + + if (e.includes("Unable to launch")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if (e.includes("Minecraft Crash Report") && !e.includes("THIS IS NOT A ERROR")) return ShowPanelError(`${langs.error_detected_one} \nError:\n${e}`); + + if (e.includes("java.lang.ClassCastException")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if (e.includes("Minecraft has crashed!")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if ( + e.includes(`Setting user: ${account.name}`) || + e.includes("Launching wrapped minecraft") + ) { + if (inicio == false) { + let typeOfVersion; + if (version_real.endsWith("-forge")) { + typeOfVersion = "Forge"; + } else if (version_real.endsWith("-fabric")) { + typeOfVersion = "Fabric"; + } else if (version_real.endsWith("-quilt")) { + typeOfVersion = "Quilt"; + } else { + typeOfVersion = ""; + } + + + if (version_real.includes("OptiFine")) { + let version_optifine = version_real.substring(0, 6); + version_optifine = version_optifine.replace("-", ""); + + ipcRenderer.send( + "new-status-discord-jugando", + `${langs.playing_in} OptiFine ${version_optifine}` + ); + + this.UpdateStatus(account.name, 'ausente', `${langs.playing_in} OptiFine ${version_optifine}`); + } else if (version_real.includes("LabyMod")) { + ipcRenderer.send( + "new-status-discord-jugando", + `${langs.playing_in} LabyMod` + ); + + this.UpdateStatus(account.name, 'ausente', `${langs.playing_in} LabyMod`); + } else if (version_real.includes("cmpack")) { + ipcRenderer.send( + "new-status-discord-jugando", + `${langs.playing_in} CMPack` + ); + + this.UpdateStatus(account.name, 'ausente', `${langs.playing_in} CMPack`); + } else { + ipcRenderer.send( + "new-status-discord-jugando", + `${langs.playing_in} ${version_real + .replace("-forge", "") + .replace("-fabric", "") + .replace("-quilt", "")} ${typeOfVersion}` + ); + + this.UpdateStatus(account.name, 'ausente', `${langs.playing_in} ${version_real + .replace("-forge", "") + .replace("-fabric", "") + .replace("-quilt", "")} ${typeOfVersion}`); + } + + modalDiv1.classList.remove("is-active"); + inicio = true; + info.innerHTML = `${langs.minecraft_started_correctly}.`; + logTextArea1.innerHTML = ``; + textInfo.innerHTML = `Selecciona la versión que quieres abrir`; + ipcRenderer.send("new-notification", { + title: langs.minecraft_started_correctly, + body: langs.minecraft_started_correctly_body, + }); + + ipcRenderer.send("main-window-progress-reset"); + } + } + + if (e.includes("Connecting to")) { + let msj = e.split("Connecting to ")[1].split("...")[0]; + info.innerHTML = `Conectando a ${msj}`; + } + }); + + launch.on("close", (code) => { + consoleOutput_ += `---------- [MC] Código de salida: ${code}\n ----------`; + if (launcherSettings.launcher.close === "close-launcher") + ipcRenderer.send("main-window-show"); + + ipcRenderer.send('updateStatus', { + status: 'online', + details: langs.in_the_menu, + username: account.name, + }) + info.style.display = "none"; + playBtn.style.display = ""; + info.innerHTML = `Verificando archivos...`; + footermodaliniciarversion.style.display = ""; + textInfo.innerHTML = "Selecciona la versión que quieres abrir"; + new logger("Launcher", "#3e8ed0"); + console.log("🔧 Minecraft cerrado"); + document.getElementById("carga-de-versiones").style.display = "none"; + + progressBar1.style.display = "none"; + + + //convertir todos los strings a null + version = null; + versionType = null; + versionData = null; + version_real = null; + assets = null; + type = null; + isForgeCheckBox = false; + isFabricCheckBox = false; + isQuiltCheckBox = false; + document.getElementById("radioVanilla").removeAttribute("checked"); + document.getElementById("radioForge").removeAttribute("checked"); + document.getElementById("radioFabric").removeAttribute("checked"); + document.getElementById("radioQuilt").removeAttribute("checked"); + + + + ipcRenderer.send("delete-and-new-status-discord"); + }); + + launch.on("error", (err) => { + consoleOutput_ += `[ERROR] ${JSON.stringify(err, null, 2)}\n`; + + progressBar1.style.display = "none"; + info.style.display = "none"; + playBtn.style.display = ""; + + return Toast.fire({ + title: "Error", + text: "Error al iniciar Minecraft. Error desconocido. Vuelve a iniciar Minecraft. [ERROR: 7] \nError: " + + err.error, + icon: "error", + button: "Aceptar", + }); + }); + + let seMostroExtrayendo_core = false; + let seMostroInstalando_core = false; + + launch_core.on("extract", (extract) => { + consoleOutput_ += `[EXTRACT] ${extract}\n`; + if (seMostroExtrayendo_core) { } else { + logTextArea1.innerHTML = `${langs.extracting_loader}.`; + seMostroExtrayendo_core = true; + } + }); + + launch_core.on("debug", (e) => { + consoleOutput_ += `[MC] ${JSON.stringify(e, null, 2)}\n`; + if (e.includes("Failed to start due to TypeError")) { + Toast.fire({ + icon: "error", + title: "Error al iniciar Minecraft", + }); + progressBar1.style.display = "none"; + progressBar1.max = 100; + progressBar1.value = 0; + playBtn.style.display = ""; + info.style.display = "none"; + crasheo = true; + } + + if (e.includes("Downloaded and extracted natives")) { + progressBar1.style.display = ""; + progressBar1.max = 100; + progressBar1.value = 0; + + info.innerHTML = langs.downloading_files; + } + + if (e.includes("Attempting to download Minecraft version jar")) { + info.innerHTML = langs.downloading_version; + } + + if (e.includes("Attempting to download assets")) { + info.innerHTML = langs.downloading_assets + } + + if (e.includes("Downloaded Minecraft version jar")) { + info.innerHTML = langs.downloading_libraries; + } + + if (e.includes("Downloaded and extracted natives")) { + info.innerHTML = langs.downloading_natives; + } + + if (e.includes("Failed to start the minecraft server")) return ShowPanelError(`${langs.error_detected_one} \nError:\n${e}`); + if (e.includes('Exception in thread "main" ')) return ShowPanelError(`${langs.error_detected_two} \nError:\n${e}`); + + if (e.includes("There is insufficient memory for the Java Runtime Environment to continue.")) return ShowPanelError(`${langs.error_detected_three} \nError:\n${e}`); + if (e.includes("Could not reserve enough space for object heap")) return ShowPanelError(`${langs.error_detected_three} \nError:\n${e}`); + + if (e.includes("Forge patcher exited with code 1")) { + ShowPanelError(`${langs.error_detected_four} \nError:\n${e}`); + progressBar1.style.display = "none"; + info.style.display = "none"; + playBtn.style.display = ""; + } + + if (e.includes("Unable to launch")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if (e.includes("Minecraft Crash Report") && !e.includes("THIS IS NOT A ERROR")) return ShowPanelError(`${langs.error_detected_one} \nError:\n${e}`); + + if (e.includes("java.lang.ClassCastException")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if (e.includes("Minecraft has crashed!")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + }); + launch_core.on("data", async (e) => { + new logger("Minecraft", "#36b030"); + consoleOutput_ += `[MC] ${e}\n`; + if (launcherSettings.launcher.close === "close-launcher") + ipcRenderer.send("main-window-hide"); + progressBar1.style.display = "none"; + + if (e.includes("Launching with arguments")) + info.innerHTML = `${langs.starting_minecraft}...`;; + + if (iniciando == false) { + + iniciando = true; + + /* editar archivo servers.dat */ + let serversDat = `${dataDirectory}/.battly/servers.dat`; + + if (fs.existsSync(serversDat)) { + try { + const serversDatFile = fs.readFileSync(serversDat); + const serversDatData = await NBT.read(serversDatFile); + + + let servers = this.BattlyConfig.promoted_servers; + + + let serversArray = []; + + for (let i = 0; i < servers.length; i++) { + const newServer = { + name: servers[i].name, + ip: servers[i].ip, + icon: servers[i].icon, + }; + + // Verificar si la IP ya existe en el archivo servers.dat + const ipExists = serversDatData.data.servers.some(server => server.ip === newServer.ip); + + if (!ipExists) { + serversArray.push(newServer); + } + } + + + + // Añadir los nuevos servidores al array existente en serversDatData.data.servers + serversDatData.data.servers = serversArray.concat(serversDatData.data.servers); + const editedServersDat = await NBT.write(serversDatData); + fs.writeFileSync(serversDat, editedServersDat); + } catch (error) { + console.error("Error al procesar el archivo NBT:", error); + } + } else { + try { + let servers = this.BattlyConfig.promoted_servers; + + + let serversArray = []; + + for (let i = 0; i < servers.length; i++) { + const newServer = { + name: servers[i].name, + ip: servers[i].ip, + icon: servers[i].icon, + }; + serversArray.push(newServer); + } + + + + // Crear un nuevo archivo servers.dat con los servidores nuevos + const newData = { servers: serversArray }; + const editedServersDat = await NBT.write(newData); + fs.writeFileSync(serversDat, editedServersDat); + } catch (error) { + console.error("Error al crear el nuevo archivo NBT:", error); + } + } + + + //añadir + + let versiones = this.Versions; + + const skinsJarPath = `${dataDirectory}/.battly/mods/skins.jar`; + const skinsForgeJarPath = `${dataDirectory}/.battly/mods/skins-forge.jar`; + const skinsForgeNewJarPath = `${dataDirectory}/.battly/mods/skins-forge-new.jar`; + + let rutaPrincipalSkinsJar = `${dataDirectory}/.battly/battly/mods-internos/skins.jar`; + let rutaPrincipalSkinsForgeJar = `${dataDirectory}/.battly/battly/mods-internos/skins-forge.jar`; + let rutaPrincipalSkinsForgeNewJar = `${dataDirectory}/.battly/battly/mods-internos/skins-forge-new.jar`; + + let rutaModMultijugadorForge = `${dataDirectory}/.battly/battly/mods-internos/multijugador-forge.jar`; + let rutaModMultijugadorFabric = `${dataDirectory}/.battly/battly/mods-internos/multijugador-fabric.jar`; + + let rutaModMultijugadorForgeDeMods = `${dataDirectory}/.battly/mods/multijugador-forge.jar`; + let rutaModMultijugadorFabricDeMods = `${dataDirectory}/.battly/mods/multijugador-fabric.jar`; + + if (fs.existsSync(rutaModMultijugadorFabricDeMods)) { + fs.unlinkSync(rutaModMultijugadorFabricDeMods); + } + + if (fs.existsSync(rutaModMultijugadorForgeDeMods)) { + fs.unlinkSync(rutaModMultijugadorForgeDeMods); + } + + fs.unlinkSync(skinsForgeJarPath); + fs.unlinkSync(skinsForgeNewJarPath); + + const selectedVersion = version; + + + let selectedVersionWithoutHyphen; + + if (selectedVersion.includes("-")) { + selectedVersionWithoutHyphen = selectedVersion.replace(/-[^.]+/, ""); + } + + const versionInfo = versiones.versions.find( + (v) => v.id === selectedVersionWithoutHyphen + ); + + + + if (versionInfo) { + function formatVersionNumber(version) { + const parsedVersion = parseFloat(version); + if (!isNaN(parsedVersion)) { + const formattedVersion = parsedVersion.toString(); + return formattedVersion; + } + return version; // Si no se puede analizar como número, devuelve la versión original + } + + // Ejemplo de uso: + const versionNumber = formatVersionNumber(versionInfo.version); + + let versionesCompatiblesConForgeNormal = [ + "1.16.5", + "1.16.4", + "1.16.3", + "1.16.2", + "1.16.1", + "1.16", + "1.15.2", + "1.15.1", + "1.15", + "1.14.4", + "1.14.3", + "1.14.2", + "1.14.1", + "1.14", + "1.13.2", + "1.13.1", + "1.13", + "1.12.2", + "1.12.1", + "1.12", + "1.11.2", + "1.11.1", + "1.11", + "1.10.2", + "1.10.1", + "1.10", + "1.9.4", + "1.9.3", + "1.9.2", + "1.9.1", + "1.9", + "1.8.9", + "1.8.8", + "1.8.7", + "1.8.6", + "1.8.5", + "1.8.4", + "1.8.3", + "1.8.2", + "1.8.1", + "1.8", + ]; + + + + const excludedVersions = [ + 1.16, 1.15, 1.14, 1.13, 1.12, 1.11, 1.1, 1.9, 1.8, 1.7, 1.6, + 1.5, 1.4, 1.3, + ]; + const includedVersionsForgeNew = [1.17, 1.18, 1.19, 1.2, 1.21]; + const versionesConMultijugadorDesactivado = ["1.16.4", "1.16.5"]; + + + + if ( + versionesConMultijugadorDesactivado.includes(version) && + versionType === "forge" + ) { + fs.copyFileSync( + rutaModMultijugadorForge, + `${dataDirectory}/.battly/mods/multijugador-forge.jar` + ); + } else if ( + versionesConMultijugadorDesactivado.includes(version) && + versionType === "fabric" + ) { + fs.copyFileSync( + rutaModMultijugadorFabric, + `${dataDirectory}/.battly/mods/multijugador-fabric.jar` + ); + } + + if ( + includedVersionsForgeNew.includes(parseFloat(version_real)) && + !excludedVersions.includes(parseFloat(version_real)) && + versionType == "forge" + ) { + + + fs.copyFileSync( + rutaPrincipalSkinsForgeNewJar, + skinsForgeNewJarPath + ); + + // Eliminar skins.jar y skins-forge.jar + if (fs.existsSync(skinsJarPath)) { + fs.unlinkSync(skinsJarPath); + } + if (fs.existsSync(skinsForgeJarPath)) { + fs.unlinkSync(skinsForgeJarPath); + } + } else if ( + versionesCompatiblesConForgeNormal.includes(version_real) && + versionType == "forge" + ) { + + + fs.copyFileSync(rutaPrincipalSkinsForgeJar, skinsForgeJarPath); + + // Eliminar skins.jar y skins-forge-new.jar + if (fs.existsSync(skinsJarPath)) { + fs.unlinkSync(skinsJarPath); + } + if (fs.existsSync(skinsForgeNewJarPath)) { + fs.unlinkSync(skinsForgeNewJarPath); + } + } else if (versionType == "fabric" || versionType == "quilt") { + + + fs.copyFileSync(rutaPrincipalSkinsJar, skinsJarPath); + // Eliminar skins-forge.jar y skins-forge-new.jar + if (fs.existsSync(skinsForgeJarPath)) { + fs.unlinkSync(skinsForgeJarPath); + } + if (fs.existsSync(skinsForgeNewJarPath)) { + fs.unlinkSync(skinsForgeNewJarPath); + } + } + } + + let archivoConfigSkins = `${dataDirectory}/.battly/CustomSkinLoader/CustomSkinLoader.json`; + let data = { + version: "14.15", + buildNumber: 8, + loadlist: [{ + name: "BattlyAPI", + type: "Legacy", + checkPNG: false, + skin: "http://api.battlylauncher.com/api/skin/{USERNAME}.png", + model: "auto", + cape: "http://api.battlylauncher.com/api/capa/{USERNAME}.png", + }, + { + name: "Mojang", + type: "MojangAPI", + apiRoot: "https://api.mojang.com/", + sessionRoot: "https://sessionserver.mojang.com/", + }, + { + name: "OptiFine", + type: "Legacy", + checkPNG: false, + model: "auto", + cape: "https://optifine.net/capes/{USERNAME}.png", + }, + { + name: "LabyMod", + type: "Legacy", + checkPNG: false, + model: "auto", + cape: "https://dl.labymod.net/capes/{STANDARD_UUID}", + }, + ], + enableDynamicSkull: true, + enableTransparentSkin: true, + forceIgnoreHttpsCertificate: true, + forceLoadAllTextures: true, + enableCape: true, + threadPoolSize: 8, + enableLogStdOut: false, + cacheExpiry: 30, + forceUpdateSkull: true, + enableLocalProfileCache: false, + enableCacheAutoClean: true, + forceDisableCache: true, + }; + + if (fs.existsSync(path.join(archivoConfigSkins))) { + fs.writeFileSync(archivoConfigSkins, JSON.stringify(data)); + } else { + fs.mkdirSync( + `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/CustomSkinLoader` + ); + fs.writeFileSync(archivoConfigSkins, JSON.stringify(data)); + } + } + + if (e.includes("Failed to start the minecraft server")) return ShowPanelError(`${langs.error_detected_one} \nError:\n${e}`); + if (e.includes('Exception in thread "main" ')) return ShowPanelError(`${langs.error_detected_two} \nError:\n${e}`); + + if (e.includes("There is insufficient memory for the Java Runtime Environment to continue.")) return ShowPanelError(`${langs.error_detected_three} \nError:\n${e}`); + if (e.includes("Could not reserve enough space for object heap")) return ShowPanelError(`${langs.error_detected_three} \nError:\n${e}`); + + if (e.includes("Forge patcher exited with code 1")) { + ShowPanelError(`${langs.error_detected_four} \nError:\n${e}`); + progressBar1.style.display = "none"; + info.style.display = "none"; + playBtn.style.display = ""; + } + + if (e.includes("Unable to launch")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if (e.includes("Minecraft Crash Report") && !e.includes("THIS IS NOT A ERROR")) return ShowPanelError(`${langs.error_detected_one} \nError:\n${e}`); + + if (e.includes("java.lang.ClassCastException")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if (e.includes("Minecraft has crashed!")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if ( + e.includes(`Setting user: ${account.name}`) || + e.includes("Launching wrapped minecraft") + ) { + if (inicio == false) { + let typeOfVersion; + if (version_real.endsWith("-forge")) { + typeOfVersion = "Forge"; + } else if (version_real.endsWith("-fabric")) { + typeOfVersion = "Fabric"; + } else if (version_real.endsWith("-quilt")) { + typeOfVersion = "Quilt"; + } else { + typeOfVersion = ""; + } + + if (version_real.includes("OptiFine")) { + let version_optifine = version_real.substring(0, 6); + version_optifine = version_optifine.replace("-", ""); + + ipcRenderer.send( + "new-status-discord-jugando", + `${langs.playing_in} OptiFine ${version_optifine}` + ); + + this.UpdateStatus(account.name, 'ausente', `${langs.playing_in} OptiFine ${version_optifine}`); + } else if (version_real.includes("LabyMod")) { + ipcRenderer.send( + "new-status-discord-jugando", + `${langs.playing_in} LabyMod` + ); + + this.UpdateStatus(account.name, 'ausente', `${langs.playing_in} LabyMod`); + } else if (version_real.includes("cmpack")) { + ipcRenderer.send( + "new-status-discord-jugando", + `${langs.playing_in} CMPack` + ); + + this.UpdateStatus(account.name, 'ausente', `${langs.playing_in} CMPack`); + } else { + ipcRenderer.send( + "new-status-discord-jugando", + `${langs.playing_in} ${version_real + .replace("-forge", "") + .replace("-fabric", "") + .replace("-quilt", "")} ${typeOfVersion}` + ); + + this.UpdateStatus(account.name, 'ausente', `${langs.playing_in} ${version_real + .replace("-forge", "") + .replace("-fabric", "") + .replace("-quilt", "")} ${typeOfVersion}`); + } + + modalDiv1.classList.remove("is-active"); + inicio = true; + info.innerHTML = `${langs.minecraft_started_correctly}.`; + logTextArea1.innerHTML = ``; + textInfo.innerHTML = `Selecciona la versión que quieres abrir`; + ipcRenderer.send("new-notification", { + title: langs.minecraft_started_correctly, + body: langs.minecraft_started_correctly_body, + }); + + ipcRenderer.send("main-window-progress-reset"); + } + } + + if (e.includes("Connecting to")) { + let msj = e.split("Connecting to ")[1].split("...")[0]; + info.innerHTML = `Conectando a ${msj}`; + } + }); + + launch_core.on("progress", (progress, size) => { + consoleOutput_ += `[DESCARGANDO] ${progress} / ${size}\n`; + if (seMostroInstalando_core) { } else { + seMostroInstalando_core = true; + } + let progreso = ((progress / size) * 100).toFixed(0); + //si el progreso es más de 100, ponerlo a 100 + if (progreso > 100) { + progreso = 100; + } + progressBar1.style.display = "block"; + info.innerHTML = `Descargando... ${progreso}%`; + ipcRenderer.send("main-window-progress", { + progress, + size + }); + progressBar1.value = progress; + progressBar1.max = size; + }); + launch_core.on("check", (progress, size) => { + consoleOutput_ += `[INSTALANDO MC] ${progress} / ${size}\n`; + let seMostroInstalando = false; + if (seMostroInstalando) { } else { + logTextArea1.innerHTML = `${langs.extracting_loader}.`; + seMostroInstalando = true; + } + progressBar1.style.display = ""; + let size_actual = 100; + let progress_actual = ((progress / size) * 100).toFixed(0); + ipcRenderer.send("main-window-progress", { + progress_actual, + size_actual, + }); + info.innerHTML = `Extrayendo ModPack... ${progress_actual}%`; + progressBar1.value = progress; + progressBar1.max = size; + }); + + launch_core.on("estimated", (time) => { + ipcRenderer.send("main-window-progress-reset"); + /* + let hours = Math.floor(time / 3600); + let minutes = Math.floor((time - hours * 3600) / 60); + let seconds = Math.floor(time - hours * 3600 - minutes * 60); + console.log(`${hours}h ${minutes}m ${seconds}s`);*/ + }); + + launch_core.on("speed", (speed) => { + /* + let velocidad = speed / 1067008; + + if (velocidad > 0) { + clearTimeout(timeoutId); // cancela el mensaje de alerta si la velocidad no es cero + } else { + timeoutId = setTimeout(() => { + progressBar1.style.display = "none" + progressBar1.max = 100; + progressBar1.value = 0; + playBtn.style.display = "" + info.style.display = "none" + clearTimeout(timeoutId); + const swal = require('sweetalert'); + crasheo = true; + + Toast.fire({ + title: "Error", + text: "Error al descargar esta versión. Reinicia el launcher o inténtalo de nuevo más tarde. [ERROR: 2]", + icon: "error", + button: "Aceptar", + }).then((value) => { + if(value) { + ipcRenderer.send('restartLauncher') + } + }); + + }, 10000); + }*/ + }); + + let seMostroInstalando = false; + launch_core.on("patch", (patch) => { + consoleOutput_ += `[INSTALANDO LOADER] ${patch}\n`; + if (seMostroInstalando) { } else { + logTextArea1.innerHTML = `${langs.extracting_loader}.`; + seMostroInstalando = true; + } + }); + + launch_core.on("data", async (e) => { + new logger("Minecraft", "#36b030"); + consoleOutput_ += `[MC] ${e}\n`; + if (launcherSettings.launcher.close === "close-launcher") + ipcRenderer.send("main-window-hide"); + progressBar1.style.display = "none"; + + if (e.includes("Launching with arguments")) + info.innerHTML = `${langs.starting_minecraft}...`;; + + if (iniciando == false) { + + iniciando = true; + + let serversDat = `${dataDirectory}/.battly/servers.dat`; + + if (fs.existsSync(serversDat)) { + try { + const serversDatFile = fs.readFileSync(serversDat); + const serversDatData = await NBT.read(serversDatFile); + + + let servers = this.BattlyConfig.promoted_servers; + + + let serversArray = []; + + for (let i = 0; i < servers.length; i++) { + const newServer = { + name: servers[i].name, + ip: servers[i].ip, + icon: servers[i].icon, + }; + + // Verificar si la IP ya existe en el archivo servers.dat + const ipExists = serversDatData.data.servers.some(server => server.ip === newServer.ip); + + if (!ipExists) { + serversArray.push(newServer); + } + } + + + + // Añadir los nuevos servidores al array existente en serversDatData.data.servers + serversDatData.data.servers = serversArray.concat(serversDatData.data.servers); + const editedServersDat = await NBT.write(serversDatData); + fs.writeFileSync(serversDat, editedServersDat); + } catch (error) { + console.error("Error al procesar el archivo NBT:", error); + } + } else { + try { + let servers = this.BattlyConfig.promoted_servers; + + + let serversArray = []; + + for (let i = 0; i < servers.length; i++) { + const newServer = { + name: servers[i].name, + ip: servers[i].ip, + icon: servers[i].icon, + }; + serversArray.push(newServer); + } + + + + // Crear un nuevo archivo servers.dat con los servidores nuevos + const newData = { servers: serversArray }; + const editedServersDat = await NBT.write(newData); + fs.writeFileSync(serversDat, editedServersDat); + } catch (error) { + console.error("Error al crear el nuevo archivo NBT:", error); + } + } + + let versiones = this.Versions; + + const skinsJarPath = `${dataDirectory}/.battly/mods/skins.jar`; + const skinsForgeJarPath = `${dataDirectory}/.battly/mods/skins-forge.jar`; + const skinsForgeNewJarPath = `${dataDirectory}/.battly/mods/skins-forge-new.jar`; + + let rutaPrincipalSkinsJar = `${dataDirectory}/.battly/battly/mods-internos/skins.jar`; + let rutaPrincipalSkinsForgeJar = `${dataDirectory}/.battly/battly/mods-internos/skins-forge.jar`; + let rutaPrincipalSkinsForgeNewJar = `${dataDirectory}/.battly/battly/mods-internos/skins-forge-new.jar`; + + let rutaModMultijugadorForge = `${dataDirectory}/.battly/battly/mods-internos/multijugador-forge.jar`; + let rutaModMultijugadorFabric = `${dataDirectory}/.battly/battly/mods-internos/multijugador-fabric.jar`; + + let rutaModMultijugadorForgeDeMods = `${dataDirectory}/.battly/mods/multijugador-forge.jar`; + let rutaModMultijugadorFabricDeMods = `${dataDirectory}/.battly/mods/multijugador-fabric.jar`; + + if (fs.existsSync(rutaModMultijugadorFabricDeMods)) { + fs.unlinkSync(rutaModMultijugadorFabricDeMods); + } + + if (fs.existsSync(rutaModMultijugadorForgeDeMods)) { + fs.unlinkSync(rutaModMultijugadorForgeDeMods); + } + + fs.unlinkSync(skinsJarPath); + fs.unlinkSync(skinsForgeJarPath); + fs.unlinkSync(skinsForgeNewJarPath); + + const selectedVersion = version; + + let selectedVersionWithoutHyphen; + if (selectedVersion.includes("-")) { + selectedVersionWithoutHyphen = selectedVersion.replace(/-[^.]+/, ""); + } + + const versionInfo = versiones.versions.find( + (v) => v.id === selectedVersionWithoutHyphen + ); + + if (versionInfo) { + function formatVersionNumber(version) { + const parsedVersion = parseFloat(version); + if (!isNaN(parsedVersion)) { + const formattedVersion = parsedVersion.toString(); + return formattedVersion; + } + return version; // Si no se puede analizar como número, devuelve la versión original + } + + // Ejemplo de uso: + const versionNumber = formatVersionNumber(versionInfo.version); + + let versionesCompatiblesConForgeNormal = [ + "1.16.5", + "1.16.4", + "1.16.3", + "1.16.2", + "1.16.1", + "1.16", + "1.15.2", + "1.15.1", + "1.15", + "1.14.4", + "1.14.3", + "1.14.2", + "1.14.1", + "1.14", + "1.13.2", + "1.13.1", + "1.13", + "1.12.2", + "1.12.1", + "1.12", + "1.11.2", + "1.11.1", + "1.11", + "1.10.2", + "1.10.1", + "1.10", + "1.9.4", + "1.9.3", + "1.9.2", + "1.9.1", + "1.9", + "1.8.9", + "1.8.8", + "1.8.7", + "1.8.6", + "1.8.5", + "1.8.4", + "1.8.3", + "1.8.2", + "1.8.1", + "1.8", + ]; + + + + const excludedVersions = [ + 1.16, 1.15, 1.14, 1.13, 1.12, 1.11, 1.1, 1.9, 1.8, 1.7, 1.6, + 1.5, 1.4, 1.3, + ]; + const includedVersionsForgeNew = [1.17, 1.18, 1.19, 1.2, 1.21]; + + const versionesConMultijugadorDesactivado = ["1.16.4", "1.16.5"]; + + + + if ( + versionesConMultijugadorDesactivado.includes(version) && + versionType === "forge" + ) { + fs.copyFileSync( + rutaModMultijugadorForge, + `${dataDirectory}/.battly/mods/multijugador-forge.jar` + ); + } else if ( + versionesConMultijugadorDesactivado.includes(version) && + versionType === "fabric" + ) { + fs.copyFileSync( + rutaModMultijugadorFabric, + `${dataDirectory}/.battly/mods/multijugador-fabric.jar` + ); + } + + if ( + includedVersionsForgeNew.includes(parseFloat(version_real)) && + !excludedVersions.includes(parseFloat(version_real)) && + versionType == "forge" + ) { + + + fs.copyFileSync( + rutaPrincipalSkinsForgeNewJar, + skinsForgeNewJarPath + ); + + // Eliminar skins.jar y skins-forge.jar + if (fs.existsSync(skinsJarPath)) { + fs.unlinkSync(skinsJarPath); + } + if (fs.existsSync(skinsForgeJarPath)) { + fs.unlinkSync(skinsForgeJarPath); + } + } else if ( + versionesCompatiblesConForgeNormal.includes(version_real) && + versionType == "forge" + ) { + + + fs.copyFileSync(rutaPrincipalSkinsForgeJar, skinsForgeJarPath); + + // Eliminar skins.jar y skins-forge-new.jar + if (fs.existsSync(skinsJarPath)) { + fs.unlinkSync(skinsJarPath); + } + if (fs.existsSync(skinsForgeNewJarPath)) { + fs.unlinkSync(skinsForgeNewJarPath); + } + } else if (versionType == "fabric" || versionType == "quilt") { + + + fs.copyFileSync(rutaPrincipalSkinsJar, skinsJarPath); + // Eliminar skins-forge.jar y skins-forge-new.jar + if (fs.existsSync(skinsForgeJarPath)) { + fs.unlinkSync(skinsForgeJarPath); + } + if (fs.existsSync(skinsForgeNewJarPath)) { + fs.unlinkSync(skinsForgeNewJarPath); + } + } + } + + let archivoConfigSkins = `${dataDirectory}/.battly/CustomSkinLoader/CustomSkinLoader.json`; + let data = { + version: "14.15", + buildNumber: 8, + loadlist: [{ + name: "BattlyAPI", + type: "Legacy", + checkPNG: false, + skin: "http://api.battlylauncher.com/api/skin/{USERNAME}.png", + model: "auto", + cape: "http://api.battlylauncher.com/api/capa/{USERNAME}.png", + }, + { + name: "Mojang", + type: "MojangAPI", + apiRoot: "https://api.mojang.com/", + sessionRoot: "https://sessionserver.mojang.com/", + }, + { + name: "OptiFine", + type: "Legacy", + checkPNG: false, + model: "auto", + cape: "https://optifine.net/capes/{USERNAME}.png", + }, + { + name: "LabyMod", + type: "Legacy", + checkPNG: false, + model: "auto", + cape: "https://dl.labymod.net/capes/{STANDARD_UUID}", + }, + ], + enableDynamicSkull: true, + enableTransparentSkin: true, + forceIgnoreHttpsCertificate: true, + forceLoadAllTextures: true, + enableCape: true, + threadPoolSize: 8, + enableLogStdOut: false, + cacheExpiry: 30, + forceUpdateSkull: true, + enableLocalProfileCache: false, + enableCacheAutoClean: true, + forceDisableCache: true, + }; + + if (fs.existsSync(path.join(archivoConfigSkins))) { + fs.writeFileSync(archivoConfigSkins, JSON.stringify(data)); + } else { + fs.mkdirSync( + `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/CustomSkinLoader` + ); + fs.writeFileSync(archivoConfigSkins, JSON.stringify(data)); + } + } + + if (e.includes("Failed to start the minecraft server")) return ShowPanelError(`${langs.error_detected_one} \nError:\n${e}`); + if (e.includes('Exception in thread "main" ')) return ShowPanelError(`${langs.error_detected_two} \nError:\n${e}`); + + if (e.includes("There is insufficient memory for the Java Runtime Environment to continue.")) return ShowPanelError(`${langs.error_detected_three} \nError:\n${e}`); + if (e.includes("Could not reserve enough space for object heap")) return ShowPanelError(`${langs.error_detected_three} \nError:\n${e}`); + + if (e.includes("Forge patcher exited with code 1")) { + ShowPanelError(`${langs.error_detected_four} \nError:\n${e}`); + progressBar1.style.display = "none"; + info.style.display = "none"; + playBtn.style.display = ""; + } + + if (e.includes("Unable to launch")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if (e.includes("Minecraft Crash Report") && !e.includes("THIS IS NOT A ERROR")) return ShowPanelError(`${langs.error_detected_one} \nError:\n${e}`); + + if (e.includes("java.lang.ClassCastException")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if (e.includes("Minecraft has crashed!")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if ( + e.includes(`Setting user: ${account.name}`) || + e.includes("Launching wrapped minecraft") + ) { + if (inicio == false) { + let typeOfVersion; + if (version_real.endsWith("-forge")) { + typeOfVersion = "Forge"; + } else if (version_real.endsWith("-fabric")) { + typeOfVersion = "Fabric"; + } else if (version_real.endsWith("-quilt")) { + typeOfVersion = "Quilt"; + } else { + typeOfVersion = ""; + } + ipcRenderer.send( + "new-status-discord-jugando", + `${langs.playing_in} ${version_real + .replace("-forge", "") + .replace("-fabric", "") + .replace("-quilt", "")} ${typeOfVersion}` + ); + + this.UpdateStatus(account.name, 'ausente', `${langs.playing_in} ${version_real.replace("-forge", "").replace("-fabric", "").replace("-quilt", "")} ${typeOfVersion}`); + modalDiv1.classList.remove("is-active"); + inicio = true; + info.innerHTML = `${langs.minecraft_started_correctly}.`; + logTextArea1.innerHTML = ``; + textInfo.innerHTML = `Selecciona la versión que quieres abrir`; + ipcRenderer.send("new-notification", { + title: langs.minecraft_started_correctly, + body: langs.minecraft_started_correctly_body, + }); + + ipcRenderer.send("main-window-progress-reset"); + } + } + }); + + launch_core.on("close", (code) => { + consoleOutput_ += `---------- [MC] Código de salida: ${code}\n ----------`; + modalDiv1.classList.remove("is-active"); + if (launcherSettings.launcher.close === "close-launcher") + ipcRenderer.send("main-window-show"); + + ipcRenderer.send('updateStatus', { + status: 'online', + details: langs.in_the_menu, + username: account.name, + }) + progressBar1.style.display = "none"; + info.style.display = "none"; + playBtn.style.display = ""; + info.innerHTML = `Verificando archivos...`; + footermodaliniciarversion.style.display = ""; + textInfo.innerHTML = "Selecciona la versión que quieres abrir"; + new logger("Launcher", "#3e8ed0"); + console.log("🔧 Minecraft cerrado"); + + progressBar1.style.display = "none"; + + version = null; + versionType = null; + versionData = null; + version_real = null; + assets = null; + type = null; + isForgeCheckBox = false; + isFabricCheckBox = false; + isQuiltCheckBox = false; + document.getElementById("radioVanilla").removeAttribute("checked"); + document.getElementById("radioForge").removeAttribute("checked"); + document.getElementById("radioFabric").removeAttribute("checked"); + document.getElementById("radioQuilt").removeAttribute("checked"); + + + + + ipcRenderer.send("delete-and-new-status-discord"); + }); + + launch_core.on("error", (err) => { + consoleOutput_ += `[ERROR] ${JSON.stringify(err, null, 2)}\n`; + }); + }); + + document + .getElementById("download-btn") + .addEventListener("click", async () => { + let versionMojangData = this.VersionsMojang; + versionMojangData = versionMojangData.versions; + + let snapshots = []; + let releases = []; + let betas = []; + let alphas = []; + + for (let i = 0; i < versionMojangData.length; i++) { + if (versionMojangData[i].type == "release") { + releases.push(versionMojangData[i]); + } else if (versionMojangData[i].type == "snapshot") { + snapshots.push(versionMojangData[i]); + } + } + + let versionBattlyData = this.Versions; + versionBattlyData = versionBattlyData.versions; + + let forgeVersions = []; + let fabricVersions = []; + let quiltVersions = []; + let optifineVersions = []; + + for (let i = 0; i < versionBattlyData.length; i++) { + if (versionBattlyData[i].version.endsWith("-forge")) { + forgeVersions.push(versionBattlyData[i]); + } else if (versionBattlyData[i].version.endsWith("-fabric")) { + fabricVersions.push(versionBattlyData[i]); + } else if (versionBattlyData[i].version.endsWith("-quilt")) { + quiltVersions.push(versionBattlyData[i]); + } else if (versionBattlyData[i].version.endsWith("-optifine")) { + optifineVersions.push(versionBattlyData[i]); + } + } + + //betas + for (let i = 0; i < versionMojangData.length; i++) { + if (versionMojangData[i].type == "old_beta") { + betas.push(versionMojangData[i]); + } + } + + //alphas + for (let i = 0; i < versionMojangData.length; i++) { + if (versionMojangData[i].type == "old_alpha") { + alphas.push(versionMojangData[i]); + } + } + + // Crear el div modal principal + let modalDiv = document.createElement("div"); + modalDiv.classList.add("modal"); + modalDiv.classList.add("is-active"); + + // Crear el fondo del modal + let modalBackground = document.createElement("div"); + modalBackground.classList.add("modal-background"); + + // Crear el div del contenido del modal + let modalCard = document.createElement("div"); + modalCard.classList.add("modal-card"); + + // Crear el encabezado del modal + let modalHeader = document.createElement("header"); + modalHeader.classList.add("modal-card-head"); + + let modalTitle = document.createElement("p"); + modalTitle.classList.add("modal-card-title"); + modalTitle.innerText = langs.download_version; + + let modalCloseButton = document.createElement("button"); + modalCloseButton.classList.add("delete"); + modalCloseButton.setAttribute("aria-label", "close"); + + modalHeader.appendChild(modalTitle); + modalHeader.appendChild(modalCloseButton); + + // Crear la sección del cuerpo del modal + let modalSection = document.createElement("section"); + modalSection.classList.add("modal-card-body"); + + let cardDiv = document.createElement("div"); + cardDiv.classList.add("card"); + let cardContentDiv = document.createElement("div"); + cardContentDiv.classList.add("card-content"); + + let mediaDiv = document.createElement("div"); + mediaDiv.classList.add("media"); + + let mediaLeftDiv = document.createElement("div"); + mediaLeftDiv.classList.add("media-left"); + + let imageFigure = document.createElement("figure"); + imageFigure.classList.add("image"); + imageFigure.classList.add("is-48x48"); + + let image = document.createElement("img"); + image.src = + "./assets/images/icons/minecraft.png"; + image.alt = "Placeholder image"; + image.id = "versionImg"; + + imageFigure.appendChild(image); + mediaLeftDiv.appendChild(imageFigure); + mediaDiv.appendChild(mediaLeftDiv); + + let mediaContentDiv = document.createElement("div"); + mediaContentDiv.classList.add("media-content"); + + let title = document.createElement("p"); + title.classList.add("title"); + title.classList.add("is-4"); + title.id = "titleVersions"; + title.innerText = "Java"; + + let subtitle = document.createElement("p"); + subtitle.classList.add("subtitle"); + subtitle.classList.add("is-6"); + subtitle.id = "subtitleVersions"; + subtitle.innerHTML = ' 1.20.1'; + + mediaContentDiv.appendChild(title); + mediaContentDiv.appendChild(subtitle); + mediaDiv.appendChild(mediaContentDiv); + + cardContentDiv.appendChild(mediaDiv); + + let contentDiv = document.createElement("div"); + contentDiv.classList.add("content"); + const hr = document.createElement("hr"); + const span = document.createElement("span"); + span.style.fontSize = "20px"; + span.innerText = langs.type_of_version; + contentDiv.appendChild(hr); + contentDiv.appendChild(span); + const br = document.createElement("br"); + contentDiv.appendChild(br); + contentDiv.innerHTML += ` + + + + + + + +
    +
    +
    +
    + +
    + + +
    + + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + + +
    + +
    + +
    + +
    + +
    + +
    + +
    +
    + +
    + +
    + + +`; + + cardContentDiv.appendChild(contentDiv); + cardDiv.appendChild(cardContentDiv); + + let cardFooterDiv = document.createElement("div"); + cardFooterDiv.classList.add("card-footer"); + + let cardFooterItemDiv = document.createElement("div"); + cardFooterItemDiv.classList.add("card-footer-item"); + + let footerText = document.createElement("p"); + footerText.style.fontSize = "10px"; + footerText.innerHTML = langs.mojang_copyright; + + cardFooterItemDiv.appendChild(footerText); + cardFooterDiv.appendChild(cardFooterItemDiv); + cardDiv.appendChild(cardFooterDiv); + + modalSection.appendChild(cardDiv); + + // Crear el pie del modal + let modalFooter = document.createElement("footer"); + modalFooter.classList.add("modal-card-foot"); + + let downloadButton = document.createElement("button"); + downloadButton.classList.add("button"); + downloadButton.classList.add("is-info"); + downloadButton.innerText = langs.download_version; + + let deleteButton = document.createElement("button"); + deleteButton.classList.add("button"); + deleteButton.classList.add("is-danger"); + deleteButton.innerText = langs.delete_version; + + modalFooter.appendChild(downloadButton); + modalFooter.appendChild(deleteButton); + + // Agregar elementos al modal + modalCard.appendChild(modalHeader); + modalCard.appendChild(modalSection); + modalCard.appendChild(modalFooter); + + modalDiv.appendChild(modalBackground); + modalDiv.appendChild(modalCard); + + document.body.appendChild(modalDiv); + // Agregar el modal al cuerpo del documento + modalCloseButton.addEventListener("click", function () { + //eliminar el modal + modalDiv.remove(); + }); + + const normal = document.getElementById("normal"); + const normalVersionType = document.getElementById("selectNormal"); + const snapshot = document.getElementById("snapshot"); + const beta = document.getElementById("beta"); + const snapshotVersionType = document.getElementById("selectSnapshot"); + const betaVersionType = document.getElementById("selectBeta"); + const alpha = document.getElementById("alpha"); + const alphaVersionType = document.getElementById("selectAlpha"); + const selectAlpha = document.getElementById("selectAlpha"); + const selectForgeBuild = document.getElementById("selectForgeBuild"); + + let radioNormal = document.getElementById("opcionNormal"); + let radioSnapshot = document.getElementById("opcionSnapshot"); + + let tipoDeVersiones = document.getElementById("tipoDeVersiones"); + + normal.style.display = "none"; + snapshot.style.display = "none"; + beta.style.display = "none"; + alpha.style.display = "none"; + + const radio = document.getElementsByName("opcion"); + + radio.forEach((element) => { + element.addEventListener("click", () => { + if (element.value == "normal") { + normal.style.display = ""; + snapshot.style.display = "none"; + beta.style.display = "none"; + alpha.style.display = "none"; + } else if (element.value == "snapshot") { + normal.style.display = "none"; + snapshot.style.display = ""; + beta.style.display = "none"; + alpha.style.display = "none"; + } else if (element.value == "beta") { + normal.style.display = "none"; + snapshot.style.display = "none"; + beta.style.display = ""; + alpha.style.display = "none"; + } else if (element.value == "alpha") { + normal.style.display = "none"; + snapshot.style.display = "none"; + beta.style.display = "none"; + alpha.style.display = ""; + } + }); + }); + + //si vanilla está seleccionado, style.display = "" en todos los radio de tipo de versión + //en cambio, si está seleccionado otra versión que nosea vanilla, style.display = "none" en todos los radio de tipo de versión + + const radio2 = document.getElementsByName("option"); + const fabric = document.getElementById("versionesFabric"); + const fabricVersionType = document.getElementById("selectFabric"); + const forge = document.getElementById("versionesForge"); + const forgeVersionType = document.getElementById("selectForge"); + const quilt = document.getElementById("versionesQuilt"); + const quiltVersionType = document.getElementById("selectQuilt"); + const optifine = document.getElementById("versionesOptiFine"); + const optifineVersionType = document.getElementById("selectOptiFine"); + const clientes = document.getElementById("versionesClientes"); + const clientesVersionType = document.getElementById("selectClientes"); + + let titleVersions = document.getElementById("titleVersions"); + let subtitleVersions = document.getElementById("subtitleVersions"); + let versionImg = document.getElementById("versionImg"); + + deleteButton.style.display = "none"; + + tipoDeVersiones.style.display = "none"; + fabric.style.display = "none"; + forge.style.display = "none"; + quilt.style.display = "none"; + optifine.style.display = "none"; + clientes.style.display = "none"; + + for (let i = 0; i < versionBattlyData.length; i++) { + if (versionBattlyData[i].type === "client") { + clientesVersionType.innerHTML += ``; + } + } + + radio2.forEach((element) => { + element.addEventListener("click", () => { + if (element.value == "vanilla") { + versionImg.src = + "./assets/images/icons/minecraft.png"; + tipoDeVersiones.style.display = ""; + radioNormal.style.display = ""; + radioSnapshot.style.display = ""; + fabric.style.display = "none"; + forge.style.display = "none"; + quilt.style.display = "none"; + optifine.style.display = "none"; + clientes.style.display = "none"; + titleVersions.innerHTML = "Java"; + subtitleVersions.innerHTML = + ' ' + normalVersionType.value; + } else if (element.value == "fabric") { + versionImg.src = + "./assets/images/icons/fabric.png"; + tipoDeVersiones.style.display = "none"; + fabric.style.display = ""; + forge.style.display = "none"; + quilt.style.display = "none"; + optifine.style.display = "none"; + clientes.style.display = "none"; + titleVersions.innerHTML = "Fabric"; + subtitleVersions.innerHTML = + ' ' + + fabricVersionType.value.replace("-fabric", ""); + } else if (element.value == "forge") { + versionImg.src = + "./assets/images/icons/forge.png" + tipoDeVersiones.style.display = "none"; + fabric.style.display = "none"; + forge.style.display = ""; + quilt.style.display = "none"; + optifine.style.display = "none"; + clientes.style.display = "none"; + titleVersions.innerHTML = "Forge"; + subtitleVersions.innerHTML = + ' ' + + forgeVersionType.value.replace("-forge", ""); + } else if (element.value == "quilt") { + versionImg.src = + "./assets/images/icons/quilt.png"; + tipoDeVersiones.style.display = "none"; + fabric.style.display = "none"; + forge.style.display = "none"; + quilt.style.display = ""; + optifine.style.display = "none"; + clientes.style.display = "none"; + titleVersions.innerHTML = "Quilt"; + subtitleVersions.innerHTML = + ' ' + + quiltVersionType.value.replace("-quilt", ""); + } else if (element.value == "optifine") { + versionImg.src = + "./assets/images/icons/optifine.png"; + tipoDeVersiones.style.display = "none"; + fabric.style.display = "none"; + forge.style.display = "none"; + quilt.style.display = "none"; + optifine.style.display = ""; + clientes.style.display = "none"; + titleVersions.innerHTML = "OptiFine"; + subtitleVersions.innerHTML = + ' ' + + optifineVersionType.value.replace("-optifine", ""); + } else if (element.value == "clientes") { + versionImg.src = + "./assets/images/icons/clients.png"; + tipoDeVersiones.style.display = "none"; + fabric.style.display = "none"; + forge.style.display = "none"; + quilt.style.display = "none"; + optifine.style.display = "none"; + clientes.style.display = ""; + titleVersions.innerHTML = "Clientes"; + subtitleVersions.innerHTML = + ' ' + + clientesVersionType.name; + } + }); + }); + + normalVersionType.addEventListener("change", () => { + subtitleVersions.innerHTML = + ' ' + normalVersionType.value; + if ( + fs.existsSync( + `${dataDirectory}/.battly/versions/${normalVersionType.value}` + ) + ) { + deleteButton.style.display = ""; + } else { + deleteButton.style.display = "none"; + } + }); + + snapshotVersionType.addEventListener("change", () => { + subtitleVersions.innerHTML = + ' ' + snapshotVersionType.value; + if ( + fs.existsSync( + `${dataDirectory}/.battly/versions/${snapshotVersionType.value}` + ) + ) { + deleteButton.style.display = ""; + } else { + deleteButton.style.display = "none"; + } + }); + + betaVersionType.addEventListener("change", () => { + subtitleVersions.innerHTML = + ' ' + betaVersionType.value; + if ( + fs.existsSync( + `${dataDirectory}/.battly/versions/${betaVersionType.value}` + ) + ) { + deleteButton.style.display = ""; + } else { + deleteButton.style.display = "none"; + } + }); + + alphaVersionType.addEventListener("change", () => { + subtitleVersions.innerHTML = + ' ' + alphaVersionType.value; + if ( + fs.existsSync( + `${dataDirectory}/.battly/versions/${alphaVersionType.value}` + ) + ) { + deleteButton.style.display = ""; + } else { + deleteButton.style.display = "none"; + } + }); + + fabricVersionType.addEventListener("change", () => { + subtitleVersions.innerHTML = + ' ' + + fabricVersionType.value.replace("-fabric", ""); + }); + + forgeVersionType.addEventListener("change", async () => { + subtitleVersions.innerHTML = + ' ' + + forgeVersionType.value.replace("-forge", ""); + + const axios = require("axios"); + await axios.get("https://files.minecraftforge.net/net/minecraftforge/forge/maven-metadata.json").then((response) => { + let data = response.data; + + // Agregar las opciones de "latest" y "recommended" + let latestOption = document.createElement("option"); + latestOption.value = "latest"; + latestOption.innerHTML = langs.latest; + selectForgeBuild.appendChild(latestOption); + + let recommendedOption = document.createElement("option"); + recommendedOption.value = "recommended"; + recommendedOption.innerHTML = langs.recommended; + selectForgeBuild.appendChild(recommendedOption); + + for (let version in data) { + if (version === forgeVersionType.value.replace("-forge", "")) { + let build = data[version]; + // Limpiar el select antes de agregar nuevas opciones + selectForgeBuild.innerHTML = ""; + + // Agregar las opciones de "latest" y "recommended" nuevamente + selectForgeBuild.appendChild(latestOption.cloneNode(true)); + selectForgeBuild.appendChild(recommendedOption.cloneNode(true)); + + // Agregar las otras versiones + for (let j = 0; j < build.length; j++) { + let option = document.createElement("option"); + option.value = build[j]; + option.innerHTML = build[j]; + selectForgeBuild.appendChild(option); + } + } + } + }); + + + }); + + quiltVersionType.addEventListener("change", () => { + subtitleVersions.innerHTML = + ' ' + + quiltVersionType.value.replace("-quilt", ""); + }); + + optifineVersionType.addEventListener("change", () => { + subtitleVersions.innerHTML = + ' ' + + optifineVersionType.value.replace("-optifine", ""); + }); + + clientesVersionType.addEventListener("change", () => { + let selectedIndex = clientesVersionType.selectedIndex; + subtitleVersions.innerHTML = ' ' + clientesVersionType.options[selectedIndex].text; + + // Obtener el valor del atributo "img" + let imgUrl = clientesVersionType.options[selectedIndex].getAttribute("img"); + + // Usar imgUrl según tus necesidades + versionImg.src = imgUrl; + }); + + + let selectNormal = document.getElementById("selectNormal"); + let selectSnapshot = document.getElementById("selectSnapshot"); + let selectBeta = document.getElementById("selectBeta"); + + for (let i = 0; i < releases.length; i++) { + let option = document.createElement("option"); + option.value = releases[i].id; + option.innerHTML = releases[i].id; + selectNormal.appendChild(option); + } + + for (let i = 0; i < snapshots.length; i++) { + let option = document.createElement("option"); + option.value = snapshots[i].id; + option.innerHTML = snapshots[i].id; + selectSnapshot.appendChild(option); + } + + for (let i = 0; i < betas.length; i++) { + let option = document.createElement("option"); + option.value = betas[i].id; + option.innerHTML = betas[i].id; + selectBeta.appendChild(option); + } + + for (let i = 0; i < alphas.length; i++) { + let option = document.createElement("option"); + option.value = alphas[i].id; + option.innerHTML = alphas[i].id; + selectAlpha.appendChild(option); + } + + let selectFabric = document.getElementById("selectFabric"); + let selectForge = document.getElementById("selectForge"); + let selectQuilt = document.getElementById("selectQuilt"); + let selectOptiFine = document.getElementById("selectOptiFine"); + + for (let i = 0; i < fabricVersions.length; i++) { + let option = document.createElement("option"); + option.value = fabricVersions[i].version; + option.innerHTML = fabricVersions[i].version.replace("-fabric", ""); + selectFabric.appendChild(option); + } + + for (let i = 0; i < forgeVersions.length; i++) { + let option = document.createElement("option"); + option.value = forgeVersions[i].version; + option.innerHTML = forgeVersions[i].version.replace("-forge", ""); + selectForge.appendChild(option); + } + + for (let i = 0; i < quiltVersions.length; i++) { + let option = document.createElement("option"); + option.value = quiltVersions[i].version; + option.innerHTML = quiltVersions[i].version.replace("-quilt", ""); + selectQuilt.appendChild(option); + } + + for (let i = 0; i < optifineVersions.length; i++) { + let option = document.createElement("option"); + option.value = optifineVersions[i].version; + option.innerHTML = optifineVersions[i].version.replace("-optifine", ""); + selectOptiFine.appendChild(option); + } + + deleteButton.addEventListener("click", () => { + Swal.fire({ + title: langs.are_you_sure, + text: langs.delete_version_text, + showCancelButton: true, + confirmButtonColor: "#00d1b2", + cancelButtonColor: "#ff3860", + confirmButtonText: langs.yes_delete, + cancelButtonText: langs.no_cancel, + }).then((result) => { + if (result.isConfirmed) { + fs.rmdirSync( + `${dataDirectory}/.battly/versions/${normalVersionType.value}`, { + recursive: true + } + ); + deleteButton.style.display = "none"; + Toast.fire({ + icon: "success", + title: langs.version_deleted_correctly, + }); + } + }); + }); + + let version; + let versionType; + + //comprobar el radio seleccionado, vanilla, fabric, forge o quilt + //si es vanilla, comprobar si el radio de tipo de versión es normal o snapshot + //si es normal, comprobar el valor del select de normal + //si es snapshot, comprobar el valor del select de snapshot + //si es fabric, comprobar el valor del select de fabric + //si es forge, comprobar el valor del select de forge + //si es quilt, comprobar el valor del select de quilt + + + + downloadButton.addEventListener("click", async () => { + + //comprobar si hay alguna opción seleccionada + if (document.querySelector('input[name="option"]:checked') == null) return Toast.fire({ + icon: "error", + title: langs.you_need_select_version, + }); + + //obtener el valor de option y ver si el value de checked es vanilla + if (document.querySelector('input[name="option"]:checked').value == "vanilla" && document.querySelector('input[name="opcion"]:checked') == null) return Toast.fire({ + icon: "error", + title: langs.you_need_select_version, + }); + + let urlpkg = pkg.user ? `${pkg.url}/${pkg.user}` : pkg.url; + let uuid = (await this.database.get("1234", "accounts-selected")) + .value; + let account = (await this.database.get(uuid.selected, "accounts")) + .value; + let ram = (await this.database.get("1234", "ram")).value; + let Resolution = (await this.database.get("1234", "screen")).value; + let launcherSettings = (await this.database.get("1234", "launcher")) + .value; + ipcRenderer.send("main-window-progress-loading"); + let radio = document.getElementsByName("option"); + let radio2 = document.getElementsByName("opcion"); + + radio.forEach((element) => { + if (element.checked) { + version = element.value; + } + }); + + radio2.forEach((element) => { + if (element.checked) { + versionType = element.value; + } + }); + + let tipo_del_loader = version; + + if (version == "vanilla") { + if (versionType == "normal") { + version = selectNormal.value; + } else if (versionType == "snapshot") { + version = selectSnapshot.value; + } else if (versionType == "beta") { + version = selectBeta.value; + } else if (versionType == "alpha") { + version = selectAlpha.value; + } + } else if (version == "fabric") { + version = selectFabric.value; + versionType = "fabric"; + } else if (version == "forge") { + version = selectForge.value; + versionType = "forge"; + } else if (version == "quilt") { + version = selectQuilt.value; + versionType = "quilt"; + } else if (version == "optifine") { + await LaunchOptiFineVersion(account, ram, Resolution, launcherSettings); + return; + } else if (version == "clientes") { + await LaunchClientVersion(account, ram, Resolution, launcherSettings); + return; + } + + + + async function LaunchClientVersion(account, ram, Resolution, launcherSettings) { + + const https = require("https"); + + let client = clientesVersionType.value; + + modalDiv.remove(); + + // Crear el div modal principal + let modalDiv1 = document.createElement("div"); + modalDiv1.classList.add("modal"); + modalDiv1.classList.add("is-active"); + + // Crear el fondo del modal + let modalBackground1 = document.createElement("div"); + modalBackground1.classList.add("modal-background"); + + // Crear el div del contenido del modal + let modalCard1 = document.createElement("div"); + modalCard1.classList.add("modal-card"); + + // Crear el encabezado del modal + let modalHeader1 = document.createElement("header"); + modalHeader1.classList.add("modal-card-head"); + + let modalTitle1 = document.createElement("p"); + modalTitle1.classList.add("modal-card-title"); + modalTitle1.innerText = `${langs.downloading_client}...`; + + modalHeader1.appendChild(modalTitle1); + + // Crear la sección del cuerpo del modal + let modalSection1 = document.createElement("section"); + modalSection1.classList.add("modal-card-body"); + + let cardDiv1 = document.createElement("div"); + cardDiv1.classList.add("card"); + let cardContentDiv1 = document.createElement("div"); + cardContentDiv1.classList.add("card-content"); + + let contentDiv1 = document.createElement("div"); + contentDiv1.classList.add("content"); + + let progressText1 = document.createElement("span"); + progressText1.style.fontSize = "15px"; + progressText1.innerText = langs.starting_download_client_can_take; + + const progressBar1 = document.createElement("progress"); + progressBar1.className = "progress is-info"; + progressBar1.setAttribute("max", "100"); + progressBar1.style.borderRadius = "5px"; + + let logText1 = document.createElement("span"); + logText1.style.fontSize = "15px"; + logText1.innerText = langs.log; + + let logTextArea1 = document.createElement("textarea"); + logTextArea1.classList.add("textarea"); + logTextArea1.classList.add("is-link"); + logTextArea1.placeholder = langs.battly_log + logTextArea1.disabled = true; + logTextArea1.style.overflow = "hidden"; + + contentDiv1.appendChild(progressText1); + contentDiv1.appendChild(document.createElement("br")); + contentDiv1.appendChild(progressBar1); + contentDiv1.appendChild(document.createElement("br")); + contentDiv1.appendChild(logText1); + contentDiv1.appendChild(logTextArea1); + cardContentDiv1.appendChild(contentDiv1); + + let cardFooterDiv1 = document.createElement("div"); + cardFooterDiv1.classList.add("card-footer"); + + let cardFooterItemDiv1 = document.createElement("div"); + cardFooterItemDiv1.classList.add("card-footer-item"); + + let footerText1 = document.createElement("p"); + footerText1.style.fontSize = "10px"; + footerText1.innerHTML = langs.mojang_copyright; + + cardFooterItemDiv1.appendChild(footerText1); + cardFooterDiv1.appendChild(cardFooterItemDiv1); + cardContentDiv1.appendChild(contentDiv1); + cardDiv1.appendChild(cardContentDiv1); + + modalSection1.appendChild(cardDiv1); + + /*
    + +
    +*/ + + // Crear el pie del modal + let modalFooter1 = document.createElement("footer"); + modalFooter1.classList.add("modal-card-foot"); + + let guardarLogsInicio = document.createElement("button"); + guardarLogsInicio.classList.add("button"); + guardarLogsInicio.classList.add("is-info"); + guardarLogsInicio.id = "guardar-logs-inicio"; + guardarLogsInicio.innerText = langs.save_logs; + + modalFooter1.appendChild(guardarLogsInicio); + + // Agregar elementos al modal + modalCard1.appendChild(modalHeader1); + modalCard1.appendChild(modalSection1); + modalCard1.appendChild(modalFooter1); + + modalDiv1.appendChild(modalBackground1); + modalDiv1.appendChild(modalCard1); + + // Agregar el modal al cuerpo del documento + document.body.appendChild(modalDiv1); + + ipcRenderer.send("main-window-progress-loading"); + + + const clientURL = clientesVersionType.options[clientesVersionType.selectedIndex].getAttribute("download"); + const folderName = clientesVersionType.options[clientesVersionType.selectedIndex].getAttribute("folderName"); + + async function downloadFiles() { + try { + // Crear carpeta + await fs.mkdirSync(`${dataDirectory}/.battly/temp`, { + recursive: true + }); + + // Descargar archivo JAR + const zipPath = `${dataDirectory}/.battly/temp/${client}.zip`; + const zipFile = await fs.createWriteStream(zipPath); + const response = await downloadFile(clientURL, zipFile); + } catch (error) { + console.error('Error:', error); + } + } + + async function downloadFile(url, file) { + return new Promise((resolve, reject) => { + https.get(url, (response) => { + let totalLength = response.headers['content-length']; + let actual = 0; + let progress = 0; + + if (response.statusCode === 200) { + logTextArea1.value += `🔄 ${langs.downloading} ${folderName}...\n`; + updateTextareaScroll(); + response.pipe(file); + + response.on('data', (chunk) => { + actual += chunk.length; + progress = parseInt(((actual / totalLength) * 100).toFixed(0)); + + // Asegúrate de que progressBar1 es el elemento correcto para la barra de progreso + progressBar1.value = progress; + }); + + file.on('finish', () => { + file.close(); + logTextArea1.value += `✅ ${folderName} ${langs.downloaded_successfully}.\n`; + updateTextareaScroll(); + resolve(response); + }); + } else { + logTextArea1.value += `❌ ${langs.error_downloading} ${url}. ${langs.status}: ${response.statusCode}\n`; + reject(`Error al descargar ${url}. Estado: ${response.statusCode}`); + } + }).on('error', (error) => { + logTextArea1.value += `❌ ${langs.error_http}: ${error.message}\n`; + reject(`Error en la solicitud HTTP: ${error.message}`); + }); + }); + } + + const ADM = require("adm-zip"); + + async function ExtractFiles() { + const zipFilePath = `${dataDirectory}/.battly/temp/${client}.zip`; + const extractPath = `${dataDirectory}/.battly`; + + const zip = new ADM(zipFilePath); + + // Obtener la lista de entradas en el zip + const entries = zip.getEntries(); + + // Establecer el máximo de la barra de progreso al número total de archivos + progressBar1.max = entries.length; + + // Extraer cada archivo por separado + for (let index = 0; index < entries.length; index++) { + const entry = entries[index]; + + let progress = parseInt(((index + 1) / entries.length) * 100).toFixed(0); + // Mostrar progreso + logTextArea1.value += `🔄 ${langs.extracting} ${entry.name} - ${langs.progress}: ${progress}%\n`; + + progressBar1.value = index + 1; + + zip.extractEntryTo(entry, extractPath, true, true); + + updateTextareaScroll(); + } + + logTextArea1.value += `✅ ${langs.files_extracted_successfully}\n`; + updateTextareaScroll(); + progressBar1.max = 100; + } + + async function DeleteTempFiles() { + logTextArea1.value += `🔄 ${langs.deleting_temp_files}...\n`; + updateTextareaScroll(); + + await fs.rmdirSync(`${dataDirectory}/.battly/temp`, { + recursive: true + }); + logTextArea1.value += `✅ ${langs.temp_files_deleted_successfully}\n`; + updateTextareaScroll(); + } + + + function updateTextareaScroll() { + logTextArea1.scrollTop = logTextArea1.scrollHeight; // Hacer que el scrollTop sea igual a la altura del contenido + } + + async function CheckAndDownloadJava() { + if (!fs.existsSync(`${dataDirectory}/.battly/versions/1.20.1`)) { + modalDiv1.remove(); + + let Toast_ = Swal.mixin({ + toast: true, + position: "top-end", + showConfirmButton: false, + timer: 10000, + timerProgressBar: true, + didOpen: (toast) => { + toast.addEventListener("mouseenter", Swal.stopTimer); + toast.addEventListener("mouseleave", Swal.resumeTimer); + }, + }); + Toast_.fire({ + icon: "error", + title: langs.error_downloading_version, + text: langs.version_java_error + }); + return; + } + } + + const launch = new Client(); + + // Descargar los archivos y esperar + try { + progressText1.innerHTML = `🔄 ${langs.downloading_files}...`; + logText1.innerHTML = `🔄 ${langs.downloading_files}...`; + updateTextareaScroll(); + await CheckAndDownloadJava(); + await downloadFiles(); + await ExtractFiles(); + await DeleteTempFiles(); + + let realVersion = await fs.readFileSync(`${dataDirectory}/.battly/versions/${folderName}/${folderName}.json`, "utf-8"); + realVersion = JSON.parse(realVersion).assets; + + logText1.innerHTML = `🔄 ${langs.installing_minecraft_files}...`; + logTextArea1.innerHTML += `✅ ${langs.client_files_downloaded_successfully}.\n🔄 ${langs.installing_minecraft_files}...\n`; + updateTextareaScroll(); + progressBar1.value = 100; + // Realizar el lanzamiento después de descargar los archivos + let javapath = localStorage.getItem("java-path"); + if (!javapath || javapath == null || javapath == undefined) { + launch.launch({ + authorization: account, + detached: false, + timeout: 10000, + root: `${dataDirectory}/.battly`, + path: `${dataDirectory}/.battly`, + overrides: { + detached: false, + screen: screen, + }, + downloadFileMultiple: 20, + version: { + custom: folderName, + number: realVersion, + type: "release" + + }, + verify: false, + ignored: ["loader"], + memory: { + min: `${ram.ramMin * 1024}M`, + max: `${ram.ramMax * 1024}M`, + }, + }); + } else { + launch.launch({ + authorization: account, + detached: false, + timeout: 10000, + root: `${dataDirectory}/.battly`, + path: `${dataDirectory}/.battly`, + overrides: { + detached: false, + screen: screen, + }, + downloadFileMultiple: 20, + version: { + custom: folderName, + number: realVersion, + type: "release" + + }, + java: true, + javaPath: javapath, + verify: false, + ignored: ["loader"], + memory: { + min: `${ram.ramMin * 1024}M`, + max: `${ram.ramMax * 1024}M`, + }, + }); + } + + launch.on('debug', (e) => { + if (e.includes("Attempting to download assets")) { + progressText1.innerHTML = `🔄 ${langs.downloading_assets}...`; + logText1.innerHTML = `🔄 ${langs.downloading_assets}...`; + progressBar1.value = 0; + } + + if (e.includes("Failed to start the minecraft server")) return ShowPanelError(`${langs.error_detected_one} \nError:\n${e}`); + if (e.includes('Exception in thread "main" ')) return ShowPanelError(`${langs.error_detected_two} \nError:\n${e}`); + + if (e.includes("There is insufficient memory for the Java Runtime Environment to continue.")) return ShowPanelError(`${langs.error_detected_three} \nError:\n${e}`); + if (e.includes("Could not reserve enough space for object heap")) return ShowPanelError(`${langs.error_detected_three} \nError:\n${e}`); + + if (e.includes("Forge patcher exited with code 1")) { + ShowPanelError(`${langs.error_detected_four} \nError:\n${e}`); + progressBar1.style.display = "none"; + info.style.display = "none"; + playBtn.style.display = ""; + } + + if (e.includes("Unable to launch")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if (e.includes("Minecraft Crash Report") && !e.includes("THIS IS NOT A ERROR")) return ShowPanelError(`${langs.error_detected_one} \nError:\n${e}`); + + if (e.includes("java.lang.ClassCastException")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if (e.includes("Minecraft has crashed!")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + }); + + let inicio = false; + launch.on('data', (e) => { + //si sale que está iniciando, eliminar el modaldiv1 + if (!inicio) { + new logger("Minecraft", "#36b030"); + if (e.includes("Setting user") || e.includes("Launching wrapped minecraft")) { + modalDiv1.remove(); + ipcRenderer.send("new-notification", { + title: langs.minecraft_started_correctly, + body: langs.minecraft_started_correctly_body, + }); + + + if (launcherSettings.launcher.close === "close-launcher") + ipcRenderer.send("main-window-hide") + + ipcRenderer.send("main-window-progress-reset"); + + inicio = true; + } + } + + if (e.includes("Failed to start the minecraft server")) return ShowPanelError(`${langs.error_detected_one} \nError:\n${e}`); + if (e.includes('Exception in thread "main" ')) return ShowPanelError(`${langs.error_detected_two} \nError:\n${e}`); + + if (e.includes("There is insufficient memory for the Java Runtime Environment to continue.")) return ShowPanelError(`${langs.error_detected_three} \nError:\n${e}`); + if (e.includes("Could not reserve enough space for object heap")) return ShowPanelError(`${langs.error_detected_three} \nError:\n${e}`); + + if (e.includes("Forge patcher exited with code 1")) { + ShowPanelError(`${langs.error_detected_four} \nError:\n${e}`); + progressBar1.style.display = "none"; + info.style.display = "none"; + playBtn.style.display = ""; + } + + if (e.includes("Unable to launch")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if (e.includes("Minecraft Crash Report") && !e.includes("THIS IS NOT A ERROR")) return ShowPanelError(`${langs.error_detected_one} \nError:\n${e}`); + + if (e.includes("java.lang.ClassCastException")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if (e.includes("Minecraft has crashed!")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + }); + + let progressShown = false; + launch.on('progress', (e) => { + if (!progressShown) { + logTextArea1.value += `🔄 Descargando archivos de Minecraft...`; + progressShown = true; + } + let progress = (e.task / e.total * 100).toFixed(2); + progressText1.innerHTML = "🔄 Descargando archivos... " + progress + "%"; + progressBar1.value = progress + }); + + launch.on('close', (e) => { + //eliminar el modaldiv1 + modalDiv1.remove(); + + if (launcherSettings.launcher.close === "close-launcher") + ipcRenderer.send("main-window-show"); + + ipcRenderer.send('updateStatus', { + status: 'online', + details: langs.in_the_menu, + username: account.name, + }) + }); + + //download status + launch.on('download-status', (e) => { + if (e.type == "task") { + if (e.task == "Downloading") { + progressText1.innerHTML = "🔄 Descargando archivos... " + e.progress + "%"; + progressBar1.value = e.progress; + } + } + }); + } catch (error) { + console.error('Error durante la descarga:'); + console.error(error); + } + } + + + async function LaunchOptiFineVersion(account, ram, Resolution, launcherSettings) { + + const https = require("https"); + const fs = require("fs"); + const util = require('util'); + const mkdir = util.promisify(fs.mkdir); + + let version = selectOptiFine.value; + version = version.replace("-optifine", ""); + + // Obtén el valor de fileName desde los datos de la versión + let fileName = ""; + let realVersion = ""; + for (let i = 0; i < optifineVersions.length; i++) { + if (optifineVersions[i].realVersion == version) { + fileName = optifineVersions[i].fileName; + realVersion = optifineVersions[i].realVersion; + } + } + + modalDiv.remove(); + + // Crear el div modal principal + let modalDiv1 = document.createElement("div"); + modalDiv1.classList.add("modal"); + modalDiv1.classList.add("is-active"); + + // Crear el fondo del modal + let modalBackground1 = document.createElement("div"); + modalBackground1.classList.add("modal-background"); + + // Crear el div del contenido del modal + let modalCard1 = document.createElement("div"); + modalCard1.classList.add("modal-card"); + + // Crear el encabezado del modal + let modalHeader1 = document.createElement("header"); + modalHeader1.classList.add("modal-card-head"); + + let modalTitle1 = document.createElement("p"); + modalTitle1.classList.add("modal-card-title"); + modalTitle1.innerText = `${langs.downloading_version}...`; + + modalHeader1.appendChild(modalTitle1); + + // Crear la sección del cuerpo del modal + let modalSection1 = document.createElement("section"); + modalSection1.classList.add("modal-card-body"); + + let cardDiv1 = document.createElement("div"); + cardDiv1.classList.add("card"); + let cardContentDiv1 = document.createElement("div"); + cardContentDiv1.classList.add("card-content"); + + let contentDiv1 = document.createElement("div"); + contentDiv1.classList.add("content"); + + let progressText1 = document.createElement("span"); + progressText1.style.fontSize = "15px"; + progressText1.innerText = langs.starting_download_can_take; + + const progressBar1 = document.createElement("progress"); + progressBar1.className = "progress is-info"; + progressBar1.setAttribute("max", "100"); + progressBar1.style.borderRadius = "5px"; + + let logText1 = document.createElement("span"); + logText1.style.fontSize = "15px"; + logText1.innerText = langs.log; + + let logTextArea1 = document.createElement("textarea"); + logTextArea1.classList.add("textarea"); + logTextArea1.classList.add("is-link"); + logTextArea1.placeholder = langs.battly_log; + logTextArea1.disabled = true; + logTextArea1.style.overflow = "hidden"; + + contentDiv1.appendChild(progressText1); + contentDiv1.appendChild(document.createElement("br")); + contentDiv1.appendChild(progressBar1); + contentDiv1.appendChild(document.createElement("br")); + contentDiv1.appendChild(logText1); + contentDiv1.appendChild(logTextArea1); + cardContentDiv1.appendChild(contentDiv1); + + let cardFooterDiv1 = document.createElement("div"); + cardFooterDiv1.classList.add("card-footer"); + + let cardFooterItemDiv1 = document.createElement("div"); + cardFooterItemDiv1.classList.add("card-footer-item"); + + let footerText1 = document.createElement("p"); + footerText1.style.fontSize = "10px"; + footerText1.innerHTML = langs.mojang_copyright; + + cardFooterItemDiv1.appendChild(footerText1); + cardFooterDiv1.appendChild(cardFooterItemDiv1); + cardContentDiv1.appendChild(contentDiv1); + cardDiv1.appendChild(cardContentDiv1); + + modalSection1.appendChild(cardDiv1); + + /*
    + +
    +*/ + + // Crear el pie del modal + let modalFooter1 = document.createElement("footer"); + modalFooter1.classList.add("modal-card-foot"); + + let guardarLogsInicio = document.createElement("button"); + guardarLogsInicio.classList.add("button"); + guardarLogsInicio.classList.add("is-info"); + guardarLogsInicio.id = "guardar-logs-inicio"; + guardarLogsInicio.innerText = langs.save_logs; + + modalFooter1.appendChild(guardarLogsInicio); + + // Agregar elementos al modal + modalCard1.appendChild(modalHeader1); + modalCard1.appendChild(modalSection1); + modalCard1.appendChild(modalFooter1); + + modalDiv1.appendChild(modalBackground1); + modalDiv1.appendChild(modalCard1); + + // Agregar el modal al cuerpo del documento + document.body.appendChild(modalDiv1); + + ipcRenderer.send("main-window-progress-loading"); + + const jarURL = `https://raw.githubusercontent.com/1ly4s0/battlylauncher-optifine/main/${fileName}/${fileName}.jar`; + const jsonURL = `https://raw.githubusercontent.com/1ly4s0/battlylauncher-optifine/main/${fileName}/${fileName}.json`; + + async function downloadFiles() { + try { + // Crear carpeta + await mkdir(`${dataDirectory}/.battly/versions/${fileName}`, { + recursive: true + }); + + // Descargar archivo JAR + const jarPath = `${dataDirectory}/.battly/versions/${fileName}/${fileName}.jar`; + const jarFile = fs.createWriteStream(jarPath); + const response = await downloadFile(jarURL, jarFile); + + // Descargar archivo JSON + const jsonPath = `${dataDirectory}/.battly/versions/${fileName}/${fileName}.json`; + const jsonFile = fs.createWriteStream(jsonPath); + const jsonResponse = await downloadFile(jsonURL, jsonFile); + } catch (error) { + console.error('Error:', error); + } + } + + function downloadFile(url, file) { + return new Promise((resolve, reject) => { + https.get(url, (response) => { + if (response.statusCode === 200) { + response.pipe(file); + file.on('finish', () => { + file.close(); + resolve(response); + }); + } else { + logTextArea1.value += `❌ Error al descargar ${url}. Estado: ${response.statusCode}\n`; + reject(`Error al descargar ${url}. Estado: ${response.statusCode}`); + } + }).on('error', (error) => { + logTextArea1.value += `❌ Error en la solicitud HTTP: ${error.message}\n`; + reject(`Error en la solicitud HTTP: ${error.message}`); + }); + }); + } + + function updateTextareaScroll() { + logTextArea1.scrollTop = logTextArea1.scrollHeight; // Hacer que el scrollTop sea igual a la altura del contenido + } + + async function CreateLibrariesDirectory() { + if (!fs.existsSync(`${dataDirectory}/.battly/libraries`)) { + logTextArea1.value += "🔄 Creando carpeta libraries...\n"; + updateTextareaScroll(); + fs.mkdirSync(`${dataDirectory}/.battly/libraries`, { + recursive: true + }); + logTextArea1.value += "✅ Carpeta libraries creada.\n"; + progressBar1.value = 10; + updateTextareaScroll(); + } else { + logTextArea1.value += "⏩ La carpeta libraries ya existe. Saltando...\n"; + progressBar1.value = 10; + updateTextareaScroll(); + } + + if (!fs.existsSync(`${dataDirectory}/.battly/libraries/optifine`)) { + logTextArea1.value += "🔄 Creando carpeta optifine...\n"; + updateTextareaScroll(); + fs.mkdirSync(`${dataDirectory}/.battly/libraries/optifine`, { + recursive: true + }); + logTextArea1.value += "✅ Carpeta optifine creada.\n"; + progressBar1.value = 20; + updateTextareaScroll(); + } else { + logTextArea1.value += "⏩ La carpeta optifine ya existe. Saltando...\n"; + progressBar1.value = 20; + updateTextareaScroll(); + } + + if (!fs.existsSync(`${dataDirectory}/.battly/libraries/optifine/OptiFine`)) { + logTextArea1.value += "🔄 Creando carpeta OptiFine...\n"; + updateTextareaScroll(); + fs.mkdirSync(`${dataDirectory}/.battly/libraries/optifine/OptiFine`, { + recursive: true + }); + logTextArea1.value += "✅ Carpeta OptiFine creada.\n"; + progressBar1.value = 30; + updateTextareaScroll(); + } else { + logTextArea1.value += "⏩ La carpeta OptiFine ya existe. Saltando...\n"; + progressBar1.value = 30; + updateTextareaScroll(); + } + + if (!fs.existsSync(`${dataDirectory}/.battly/libraries/optifine/launchwrapper-of`)) { + logTextArea1.value += "🔄 Creando carpeta launchwrapper-of...\n"; + updateTextareaScroll(); + fs.mkdirSync(`${dataDirectory}/.battly/libraries/optifine/launchwrapper-of`, { + recursive: true + }); + logTextArea1.value += "✅ Carpeta launchwrapper-of creada.\n"; + progressBar1.value = 40; + updateTextareaScroll(); + } else { + logTextArea1.value += "⏩ La carpeta launchwrapper-of ya existe. Saltando...\n"; + progressBar1.value = 40; + updateTextareaScroll(); + } + + if (!fs.existsSync(`${dataDirectory}/.battly/libraries/optifine/launchwrapper-of/2.1`)) { + logTextArea1.value += "🔄 Creando carpeta 2.1...\n"; + updateTextareaScroll(); + fs.mkdirSync(`${dataDirectory}/.battly/libraries/optifine/launchwrapper-of/2.1`, { + recursive: true + }); + logTextArea1.value += "✅ Carpeta 2.1 creada.\n"; + progressBar1.value = 50; + updateTextareaScroll(); + } else { + logTextArea1.value += "⏩ La carpeta 2.1 ya existe. Saltando...\n"; + progressBar1.value = 50; + updateTextareaScroll(); + } + + if (!fs.existsSync(`${dataDirectory}/.battly/libraries/optifine/launchwrapper-of/2.2`)) { + logTextArea1.value += "🔄 Creando carpeta 2.2...\n"; + updateTextareaScroll(); + fs.mkdirSync(`${dataDirectory}/.battly/libraries/optifine/launchwrapper-of/2.2`, { + recursive: true + }); + logTextArea1.value += "✅ Carpeta 2.2 creada.\n"; + progressBar1.value = 60; + updateTextareaScroll(); + } else { + logTextArea1.value += "⏩ La carpeta 2.2 ya existe. Saltando...\n"; + progressBar1.value = 60; + updateTextareaScroll(); + } + + if (!fs.existsSync(`${dataDirectory}/.battly/libraries/optifine/launchwrapper-of/2.3`)) { + logTextArea1.value += "🔄 Creando carpeta 2.3...\n"; + updateTextareaScroll(); + fs.mkdirSync(`${dataDirectory}/.battly/libraries/optifine/launchwrapper-of/2.3`, { + recursive: true + }); + logTextArea1.value += "✅ Carpeta 2.3 creada.\n"; + progressBar1.value = 70; + updateTextareaScroll(); + } else { + logTextArea1.value += "⏩ La carpeta 2.3 ya existe. Saltando...\n"; + progressBar1.value = 70; + updateTextareaScroll(); + } + + if (!fs.existsSync(`${dataDirectory}/.battly/libraries/optifine/OptiFine/${fileName.replace("-OptiFine", "")}`)) { + logTextArea1.value += "🔄 Creando carpeta " + fileName.replace("-OptiFine", "") + "...\n"; + updateTextareaScroll(); + fs.mkdirSync(`${dataDirectory}/.battly/libraries/optifine/OptiFine/${fileName.replace("-OptiFine", "")}`, { + recursive: true + }); + logTextArea1.value += "✅ Carpeta " + fileName.replace("-OptiFine", "") + " creada.\n"; + progressBar1.value = 80; + updateTextareaScroll(); + } else { + logTextArea1.value += "⏩ La carpeta " + fileName.replace("-OptiFine", "") + " ya existe. Saltando...\n"; + progressBar1.value = 80; + updateTextareaScroll(); + } + + const libraryJARURL = `https://raw.githubusercontent.com/1ly4s0/battlylauncher-optifine/main/libraries/optifine/OptiFine/${fileName.replace("-OptiFine", "")}/OptiFine-${fileName.replace("-OptiFine", "")}.jar`; + + logTextArea1.value += "🔄 Descargando archivo JAR de OptiFine...\n"; + updateTextareaScroll(); + const libraryJARFile = fs.createWriteStream(`${dataDirectory}/.battly/libraries/optifine/OptiFine/${fileName.replace("-OptiFine", "")}/OptiFine-${fileName.replace("-OptiFine", "")}.jar`); + const libraryJARResponse = await downloadFile(libraryJARURL, libraryJARFile); + logTextArea1.value += `✅ Archivo JAR de OptiFine descargado: ${libraryJARResponse.statusCode}\n`; + updateTextareaScroll(); + + /* ahora descargar launchwrapper-of-2.1.jar, launchwrapper-of-2.2.jar y launchwrapper-of-2.3.jar y ponerlos en sus respectivas carpetas */ + + const wrapperJARURL21 = `https://raw.githubusercontent.com/1ly4s0/battlylauncher-optifine/main/libraries/optifine/launchwrapper-of/2.1/launchwrapper-of-2.1.jar`; + const wrapperJARURL22 = `https://raw.githubusercontent.com/1ly4s0/battlylauncher-optifine/main/libraries/optifine/launchwrapper-of/2.2/launchwrapper-of-2.2.jar`; + const wrapperJARURL23 = `https://raw.githubusercontent.com/1ly4s0/battlylauncher-optifine/main/libraries/optifine/launchwrapper-of/2.3/launchwrapper-of-2.3.jar`; + + const wrapperJAR21File = fs.createWriteStream(`${dataDirectory}/.battly/libraries/optifine/launchwrapper-of/2.1/launchwrapper-of-2.1.jar`); + logTextArea1.value += "🔄 Descargando archivo launchwrapper 2.1...\n"; + updateTextareaScroll(); + + const wrapperJAR22File = fs.createWriteStream(`${dataDirectory}/.battly/libraries/optifine/launchwrapper-of/2.2/launchwrapper-of-2.2.jar`); + logTextArea1.value += "🔄 Descargando archivo launchwrapper 2.2...\n"; + updateTextareaScroll(); + + const wrapperJAR23File = fs.createWriteStream(`${dataDirectory}/.battly/libraries/optifine/launchwrapper-of/2.3/launchwrapper-of-2.3.jar`); + logTextArea1.value += "🔄 Descargando archivo launchwrapper 2.3...\n"; + updateTextareaScroll(); + + const wrapperJAR21Response = await downloadFile(wrapperJARURL21, wrapperJAR21File); + logTextArea1.value += `✅ Archivo JAR de launchwrapper-of-2.1 descargado: ${wrapperJAR21Response.statusCode}\n`; + progressBar1.value = 85; + updateTextareaScroll(); + + const wrapperJAR22Response = await downloadFile(wrapperJARURL22, wrapperJAR22File); + logTextArea1.value += `✅ Archivo JAR de launchwrapper-of-2.2 descargado: ${wrapperJAR22Response.statusCode}\n`; + progressBar1.value = 90; + updateTextareaScroll(); + + const wrapperJAR23Response = await downloadFile(wrapperJARURL23, wrapperJAR23File); + logTextArea1.value += `✅ Archivo JAR de launchwrapper-of-2.3 descargado: ${wrapperJAR23Response.statusCode}\n`; + progressBar1.value = 95; + updateTextareaScroll(); + } + + async function CheckAndDownloadJava() { + if (!fs.existsSync(`${dataDirectory}/.battly/versions/1.20.1`)) { + modalDiv1.remove(); + + let Toast_ = Swal.mixin({ + toast: true, + position: "top-end", + showConfirmButton: false, + timer: 10000, + timerProgressBar: true, + didOpen: (toast) => { + toast.addEventListener("mouseenter", Swal.stopTimer); + toast.addEventListener("mouseleave", Swal.resumeTimer); + }, + }); + Toast_.fire({ + icon: "error", + title: "Error al descargar la versión.", + text: "No tienes la versión requerida de Java, para descargarla, descarga la 1.20.1 de vanilla y luego vuelve a intentarlo." + }); + return; + } + } + + const launch = new Client(); + + // Descargar los archivos y esperar + try { + progressText1.innerHTML = "🔄 Descargando archivos..."; + logText1.innerHTML = "🔄 Descargando archivos..."; + await CheckAndDownloadJava(); + await downloadFiles(); + await CreateLibrariesDirectory(); + + progressText1.innerHTML = "✅ Descargando archivos... Completado."; + logText1.innerHTML = "🔄 Abriendo OptiFine..."; + logTextArea1.innerHTML += `✅ Descarga de archivos completada. Instalando dependencias...`; + progressBar1.value = 100; + + // Realizar el lanzamiento después de descargar los archivos + let javapath = localStorage.getItem("java-path"); + if (!javapath || javapath == null || javapath == undefined) { + launch.launch({ + authorization: account, + detached: false, + timeout: 10000, + root: `${dataDirectory}/.battly`, + path: `${dataDirectory}/.battly`, + overrides: { + detached: false, + screen: screen, + }, + downloadFileMultiple: 20, + version: { + custom: fileName, + number: realVersion, + type: "release" + + }, + verify: false, + ignored: ["loader"], + memory: { + min: `${ram.ramMin * 1024}M`, + max: `${ram.ramMax * 1024}M`, + }, + }); + } else { + launch.launch({ + authorization: account, + detached: false, + timeout: 10000, + root: `${dataDirectory}/.battly`, + path: `${dataDirectory}/.battly`, + overrides: { + detached: false, + screen: screen, + }, + downloadFileMultiple: 20, + version: { + custom: fileName, + number: realVersion, + type: "release" + + }, + java: true, + javaPath: javapath, + verify: false, + ignored: ["loader"], + memory: { + min: `${ram.ramMin * 1024}M`, + max: `${ram.ramMax * 1024}M`, + }, + }); + } + + launch.on('debug', (e) => { + if (e.includes("Attempting to download assets")) { + progressText1.innerHTML = "🔄 Descargando archivos..."; + logText1.innerHTML = "🔄 Descargando archivos..."; + progressBar1.value = 0; + } + + if (e.includes("Failed to start the minecraft server")) return ShowPanelError(`${langs.error_detected_one} \nError:\n${e}`); + if (e.includes('Exception in thread "main" ')) return ShowPanelError(`${langs.error_detected_two} \nError:\n${e}`); + + if (e.includes("There is insufficient memory for the Java Runtime Environment to continue.")) return ShowPanelError(`${langs.error_detected_three} \nError:\n${e}`); + if (e.includes("Could not reserve enough space for object heap")) return ShowPanelError(`${langs.error_detected_three} \nError:\n${e}`); + + if (e.includes("Forge patcher exited with code 1")) { + ShowPanelError(`${langs.error_detected_four} \nError:\n${e}`); + progressBar1.style.display = "none"; + info.style.display = "none"; + playBtn.style.display = ""; + } + + if (e.includes("Unable to launch")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if (e.includes("Minecraft Crash Report") && !e.includes("THIS IS NOT A ERROR")) return ShowPanelError(`${langs.error_detected_one} \nError:\n${e}`); + + if (e.includes("java.lang.ClassCastException")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if (e.includes("Minecraft has crashed!")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + }); + + let inicio = false; + launch.on('data', (e) => { + //si sale que está iniciando, eliminar el modaldiv1 + if (!inicio) { + new logger("Minecraft", "#36b030"); + if (e.includes("Setting user") || e.includes("Launching wrapped minecraft")) { + modalDiv1.remove(); + ipcRenderer.send("new-notification", { + title: langs.minecraft_started_correctly, + body: langs.minecraft_started_correctly_body, + }); + + + if (launcherSettings.launcher.close === "close-launcher") + ipcRenderer.send("main-window-hide") + + ipcRenderer.send("main-window-progress-reset"); + + inicio = true; + } + } + + if (e.includes("Failed to start the minecraft server")) return ShowPanelError(`${langs.error_detected_one} \nError:\n${e}`); + if (e.includes('Exception in thread "main" ')) return ShowPanelError(`${langs.error_detected_two} \nError:\n${e}`); + + if (e.includes("There is insufficient memory for the Java Runtime Environment to continue.")) return ShowPanelError(`${langs.error_detected_three} \nError:\n${e}`); + if (e.includes("Could not reserve enough space for object heap")) return ShowPanelError(`${langs.error_detected_three} \nError:\n${e}`); + + if (e.includes("Forge patcher exited with code 1")) { + ShowPanelError(`${langs.error_detected_four} \nError:\n${e}`); + progressBar1.style.display = "none"; + info.style.display = "none"; + playBtn.style.display = ""; + } + + if (e.includes("Unable to launch")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if (e.includes("Minecraft Crash Report") && !e.includes("THIS IS NOT A ERROR")) return ShowPanelError(`${langs.error_detected_one} \nError:\n${e}`); + + if (e.includes("java.lang.ClassCastException")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if (e.includes("Minecraft has crashed!")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + }); + + let progressShown = false; + launch.on('progress', (e) => { + if (!progressShown) { + logTextArea1.value += `🔄 Descargando archivos de Minecraft...`; + progressShown = true; + } + + let progress = (e.task / e.total * 100).toFixed(2); + progressText1.innerHTML = "🔄 Descargando archivos... " + progress + "%"; + progressBar1.value = progress + }); + + launch.on('close', (e) => { + //eliminar el modaldiv1 + modalDiv1.remove(); + + if (launcherSettings.launcher.close === "close-launcher") + ipcRenderer.send("main-window-show"); + + ipcRenderer.send('updateStatus', { + status: 'online', + details: langs.in_the_menu, + username: account.name, + }) + }); + + //download status + launch.on('download-status', (e) => { + if (e.type == "task") { + if (e.task == "Downloading") { + progressText1.innerHTML = "🔄 Descargando archivos... " + e.progress + "%"; + progressBar1.value = e.progress; + } + } + }); + } catch (error) { + console.error('Error durante la descarga:'); + console.error(error); + } + } + + + modalDiv.remove(); + + // Crear el div modal principal + let modalDiv1 = document.createElement("div"); + modalDiv1.classList.add("modal"); + modalDiv1.classList.add("is-active"); + + // Crear el fondo del modal + let modalBackground1 = document.createElement("div"); + modalBackground1.classList.add("modal-background"); + + // Crear el div del contenido del modal + let modalCard1 = document.createElement("div"); + modalCard1.classList.add("modal-card"); + + // Crear el encabezado del modal + let modalHeader1 = document.createElement("header"); + modalHeader1.classList.add("modal-card-head"); + + let modalTitle1 = document.createElement("p"); + modalTitle1.classList.add("modal-card-title"); + modalTitle1.innerText = `${langs.downloading_version}...`; + + modalHeader1.appendChild(modalTitle1); + + // Crear la sección del cuerpo del modal + let modalSection1 = document.createElement("section"); + modalSection1.classList.add("modal-card-body"); + + let cardDiv1 = document.createElement("div"); + cardDiv1.classList.add("card"); + let cardContentDiv1 = document.createElement("div"); + cardContentDiv1.classList.add("card-content"); + + let contentDiv1 = document.createElement("div"); + contentDiv1.classList.add("content"); + + let progressText1 = document.createElement("span"); + progressText1.style.fontSize = "15px"; + progressText1.innerText = langs.starting_download_can_take; + + const progressBar1 = document.createElement("progress"); + progressBar1.className = "progress is-info"; + progressBar1.setAttribute("max", "100"); + progressBar1.style.borderRadius = "5px"; + + let logText1 = document.createElement("span"); + logText1.style.fontSize = "15px"; + logText1.innerText = langs.log; + + let logTextArea1 = document.createElement("textarea"); + logTextArea1.classList.add("textarea"); + logTextArea1.classList.add("is-link"); + logTextArea1.placeholder = langs.battly_log; + logTextArea1.disabled = true; + logTextArea1.style.overflow = "hidden"; + + contentDiv1.appendChild(progressText1); + contentDiv1.appendChild(document.createElement("br")); + contentDiv1.appendChild(progressBar1); + contentDiv1.appendChild(document.createElement("br")); + contentDiv1.appendChild(logText1); + contentDiv1.appendChild(logTextArea1); + cardContentDiv1.appendChild(contentDiv1); + + let cardFooterDiv1 = document.createElement("div"); + cardFooterDiv1.classList.add("card-footer"); + + let cardFooterItemDiv1 = document.createElement("div"); + cardFooterItemDiv1.classList.add("card-footer-item"); + + let footerText1 = document.createElement("p"); + footerText1.style.fontSize = "10px"; + footerText1.innerHTML = langs.mojang_copyright; + + cardFooterItemDiv1.appendChild(footerText1); + cardFooterDiv1.appendChild(cardFooterItemDiv1); + cardContentDiv1.appendChild(contentDiv1); + cardDiv1.appendChild(cardContentDiv1); + + modalSection1.appendChild(cardDiv1); + + /*
    + +
    +*/ + + // Crear el pie del modal + let modalFooter1 = document.createElement("footer"); + modalFooter1.classList.add("modal-card-foot"); + + let guardarLogsInicio = document.createElement("button"); + guardarLogsInicio.classList.add("button"); + guardarLogsInicio.classList.add("is-info"); + guardarLogsInicio.id = "guardar-logs-inicio"; + guardarLogsInicio.innerText = langs.save_logs; + + modalFooter1.appendChild(guardarLogsInicio); + + // Agregar elementos al modal + modalCard1.appendChild(modalHeader1); + modalCard1.appendChild(modalSection1); + modalCard1.appendChild(modalFooter1); + + modalDiv1.appendChild(modalBackground1); + modalDiv1.appendChild(modalCard1); + + // Agregar el modal al cuerpo del documento + document.body.appendChild(modalDiv1); + + function updateTextareaScroll() { + logTextArea1.scrollTop = logTextArea1.scrollHeight; // Hacer que el scrollTop sea igual a la altura del contenido + } + + guardarLogsInicio.addEventListener("click", () => { + this.Registros(); + }); + + let isForgeCheckBox = false; + let isFabricCheckBox = false; + let isQuiltCheckBox = false; + + let settings_btn = document.getElementById("settings-btn"); + let select_versions = document.getElementById("select-version"); + let mods_btn = document.getElementById("boton_abrir_mods"); + let discord_btn = document.getElementById( + "BotonUnirseServidorDiscord" + ); + + let version_real = version + .replace("-extra", "") + .replace("-forge", "") + .replace("-fabric", "") + .replace("-quilt", ""); + + if (versionType === "forge") { + version = version.replace("-forge", ""); + isForgeCheckBox = true; + isFabricCheckBox = false; + isQuiltCheckBox = false; + } else if (versionType === "fabric") { + version = version.replace("-fabric", ""); + isFabricCheckBox = true; + isForgeCheckBox = false; + isQuiltCheckBox = false; + } else if (versionType === "quilt") { + version = version.replace("-quilt", ""); + isQuiltCheckBox = true; + isForgeCheckBox = false; + isFabricCheckBox = false; + } + + let type; + if (isForgeCheckBox == true) { + type = "forge"; + mcModPack = "forge"; + } else if (isFabricCheckBox == true) { + type = "fabric"; + mcModPack = "fabric"; + } else if (isQuiltCheckBox == true) { + type = "quilt"; + mcModPack = "quilt"; + } else { + type = "vanilla"; + mcModPack = "vanilla"; + } + + //hacer un json.parse del archivo de versiones y obtener el dato "assets" + + //comprobar si existe el archivo de versiones + + // Si la versión acaba con -extra hacer let assets = JSON.parse(fs.readFileSync(`${dataDirectory}/.battly/versions/${version_real}/${version_real}.json`)).assets; + // si no, ignorar + let assets; + let versionData; + if (version_real === "1.8") { + assets = "1.8"; + versionData = { + number: assets, + custom: version_real, + type: "release", + }; + } else if ( + version.endsWith("-extra") && + !version.includes("OptiFine") && + !version.includes("LabyMod") + ) { + assets = JSON.parse( + fs.readFileSync( + `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/versions/${version_real}/${version_real}.json` + ) + ).assets; + + versionData = { + number: assets, + custom: version_real, + type: "release", + }; + } else if ( + version.includes("OptiFine") && + version.endsWith("-extra") + ) { + assets = JSON.parse( + fs.readFileSync( + `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/versions/${version_real}/${version_real}.json` + ) + ).inheritsFrom; + + versionData = { + number: assets, + custom: version_real, + type: "release", + }; + } else if ( + version.includes("LabyMod") && + version.endsWith("-extra") + ) { + assets = JSON.parse( + fs.readFileSync( + `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/versions/${version_real}/${version_real}.json` + ) + )._minecraftVersion; + + versionData = { + number: version_real, + type: "release", + }; + } else { + versionData = version_real; + } + + let playBtn = document.getElementById("download-btn"); + let info = progressText1; + + if (Resolution.screen.width == "") { + screen = false; + } else { + screen = { + width: Resolution.screen.width, + height: Resolution.screen.height, + }; + } + + + let opts; + if (isForgeCheckBox == true) { + opts = { + url: this.config.game_url === "" || this.config.game_url === undefined ? + `${urlpkg}/files` : + this.config.game_url, + authorization: account, + authenticator: account, + detached: false, + timeout: 10000, + root: `${dataDirectory}/.battly`, + path: `${dataDirectory}/.battly`, + overrides: { + detached: false, + screen: screen, + }, + downloadFileMultiple: 20, + //javaPath: "C:\\Users\\ilyas\\Desktop\\RND Projects\\Java\\bin\\java.exe", + version: versionData, + loader: { + type: type, + build: selectForgeBuild.value, + enable: isForgeCheckBox ? + true : + isFabricCheckBox ? + true : + isQuiltCheckBox ? + true : + false, + }, + verify: false, + ignored: ["loader", ...this.config.ignored], + java: false, + memory: { + min: `${ram.ramMin * 1024}M`, + max: `${ram.ramMax * 1024}M`, + }, + }; + } else { + opts = { + url: this.config.game_url === "" || this.config.game_url === undefined ? + `${urlpkg}/files` : + this.config.game_url, + authorization: account, + authenticator: account, + detached: false, + timeout: 10000, + root: `${dataDirectory}/.battly`, + path: `${dataDirectory}/.battly`, + overrides: { + detached: false, + screen: screen, + }, + downloadFileMultiple: 20, + //javaPath: "C:\\Users\\ilyas\\Desktop\\RND Projects\\Java\\bin\\java.exe", + version: versionData, + loader: { + type: type, + build: this.BattlyConfig.loader.build, + enable: isForgeCheckBox ? + true : + isFabricCheckBox ? + true : + isQuiltCheckBox ? + true : + false, + }, + verify: false, + ignored: ["loader", ...this.config.ignored], + java: false, + memory: { + min: `${ram.ramMin * 1024}M`, + max: `${ram.ramMax * 1024}M`, + }, + }; + } + + const launch = new Client(); + const launch_core = new Launch(); + + try { + /* + Si la versión acaba con -forge o -fabric, iniciar launch_core.launch(opts); + Si no, iniciar launch.launch(opts); + */ + if (version === "1.8") { + await launch.launch(opts); + document.getElementById("carga-de-versiones").style.display = ""; + } else if ( + version.endsWith("-forge") || + version.endsWith("-fabric") || + version.endsWith("-quilt") + ) { + await launch_core.Launch(opts); + document.getElementById("carga-de-versiones").style.display = ""; + } else if (version.endsWith("-extra")) { + launch.launch(opts); + document.getElementById("carga-de-versiones").style.display = ""; + } else { + await launch_core.Launch(opts); + document.getElementById("carga-de-versiones").style.display = ""; + } + } catch (error) { + setTimeout(() => { + playBtn.style.display = ""; + info.style.display = "none"; + progressBar1.style.display = "none"; + }, 3000); + console.log(error); + } + + launch.on("extract", (extract) => { + consoleOutput_ += `[EXTRACT] ${extract}\n`; + let seMostroInstalando = false; + if (seMostroInstalando) { } else { + logTextArea1.innerHTML = `${langs.extracting_loader}.`; + updateTextareaScroll(); + seMostroInstalando = true; + } + }); + + launch.on("debug", (e) => { + consoleOutput_ += `[ERROR] ${JSON.stringify(e, null, 2)}\n`; + if (e.includes("Failed to start due to TypeError")) { + Toast.fire({ + icon: "error", + title: "Error al iniciar Minecraft", + }); + progressBar1.style.display = "none"; + progressBar1.max = 100; + progressBar1.value = 0; + playBtn.style.display = ""; + info.style.display = "none"; + crasheo = true; + } + + if (e.includes("Downloaded and extracted natives")) { + + progressBar1.style.display = ""; + progressBar1.max = 100; + progressBar1.value = 0; + + info.innerHTML = langs.downloading_files; + } + + if (e.includes("Attempting to download Minecraft version jar")) { + info.innerHTML = langs.downloading_version; + } + + if (e.includes("Attempting to download assets")) { + info.innerHTML = langs.downloading_assets; + } + + if (e.includes("Downloaded Minecraft version jar")) { + info.innerHTML = langs.downloading_libraries; + } + + if (e.includes("Downloaded and extracted natives")) { + info.innerHTML = langs.downloading_natives; + } + + if (e.includes("Failed to start the minecraft server")) return ShowPanelError(`${langs.error_detected_one} \nError:\n${e}`); + if (e.includes('Exception in thread "main" ')) return ShowPanelError(`${langs.error_detected_two} \nError:\n${e}`); + + if (e.includes("There is insufficient memory for the Java Runtime Environment to continue.")) return ShowPanelError(`${langs.error_detected_three} \nError:\n${e}`); + if (e.includes("Could not reserve enough space for object heap")) return ShowPanelError(`${langs.error_detected_three} \nError:\n${e}`); + + if (e.includes("Forge patcher exited with code 1")) { + ShowPanelError(`${langs.error_detected_four} \nError:\n${e}`); + progressBar1.style.display = "none"; + info.style.display = "none"; + playBtn.style.display = ""; + } + + if (e.includes("Unable to launch")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if (e.includes("Minecraft Crash Report") && !e.includes("THIS IS NOT A ERROR")) return ShowPanelError(`${langs.error_detected_one} \nError:\n${e}`); + + if (e.includes("java.lang.ClassCastException")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if (e.includes("Minecraft has crashed!")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + }); + + launch.on("progress", function (e) { + + let total = e.total; + let current = e.task; + + let progress = ((current / total) * 100).toFixed(0); + let total_ = 100; + + ipcRenderer.send("main-window-progress_", { + total_, + progress, + }); + + progressBar1.style.display = ""; + progressBar1.max = total; + progressBar1.value = current; + }); + + let crasheo = false; + + launch.on("estimated", (time) => { + ipcRenderer.send("main-window-progress-reset"); + /* + let hours = Math.floor(time / 3600); + let minutes = Math.floor((time - hours * 3600) / 60); + let seconds = Math.floor(time - hours * 3600 - minutes * 60); + console.log(`${hours}h ${minutes}m ${seconds}s`);*/ + }); + + let timeoutId; + + launch.on("speed", (speed) => { + /* + let velocidad = speed / 1067008; + + if (velocidad > 0) { + clearTimeout(timeoutId); // cancela el mensaje de alerta si la velocidad no es cero + } else { + timeoutId = setTimeout(() => { + progressBar1.style.display = "none" + progressBar1.max = 100; + progressBar1.value = 0; + playBtn.style.display = "" + info.style.display = "none" + clearTimeout(timeoutId); + const swal = require('sweetalert'); + crasheo = true; + + Toast.fire({ + title: "Error", + text: "Error al descargar esta versión. Reinicia el launcher o inténtalo de nuevo más tarde. [ERROR: 2]", + icon: "error", + button: "Aceptar", + }).then((value) => { + if(value) { + ipcRenderer.send('restartLauncher') + } + }); + + }, 10000); + }*/ + }); + + launch.on("patch", (patch) => { + consoleOutput_ += `[INSTALANDO LOADER] ${patch}\n`; + let seMostroInstalando = false; + if (seMostroInstalando) { } else { + logTextArea1.innerHTML = `${langs.installing_loader}...\n`; + seMostroInstalando = true; + } + + info.innerHTML = `${langs.installing_loader}...`; + }); + + let inicio = false; + let iniciando = false; + launch.on("data", async (e) => { + new logger("Minecraft", "#36b030"); + consoleOutput_ += `[MC] ${e}\n`; + if (launcherSettings.launcher.close === "close-launcher") + ipcRenderer.send("main-window-hide"); + + if (e.includes("Launching with arguments")) + info.innerHTML = `${langs.starting_minecraft}...`;; + + if (iniciando == false) { + + Toast.fire({ + icon: "info", + title: `${langs.starting_minecraft}...`, + }); + iniciando = true; + } + + let serversDat = `${dataDirectory}/.battly/servers.dat`; + + if (fs.existsSync(serversDat)) { + try { + const serversDatFile = fs.readFileSync(serversDat); + const serversDatData = await NBT.read(serversDatFile); + + + let servers = this.BattlyConfig.promoted_servers; + + + let serversArray = []; + + for (let i = 0; i < servers.length; i++) { + const newServer = { + name: servers[i].name, + ip: servers[i].ip, + icon: servers[i].icon, + }; + + // Verificar si la IP ya existe en el archivo servers.dat + const ipExists = serversDatData.data.servers.some(server => server.ip === newServer.ip); + + if (!ipExists) { + serversArray.push(newServer); + } + } + + + + // Añadir los nuevos servidores al array existente en serversDatData.data.servers + serversDatData.data.servers = serversArray.concat(serversDatData.data.servers); + const editedServersDat = await NBT.write(serversDatData); + fs.writeFileSync(serversDat, editedServersDat); + } catch (error) { + console.error("Error al procesar el archivo NBT:", error); + } + } else { + try { + let servers = this.BattlyConfig.promoted_servers; + + + let serversArray = []; + + for (let i = 0; i < servers.length; i++) { + const newServer = { + name: servers[i].name, + ip: servers[i].ip, + icon: servers[i].icon, + }; + serversArray.push(newServer); + } + + + + // Crear un nuevo archivo servers.dat con los servidores nuevos + const newData = { servers: serversArray }; + const editedServersDat = await NBT.write(newData); + fs.writeFileSync(serversDat, editedServersDat); + } catch (error) { + console.error("Error al crear el nuevo archivo NBT:", error); + } + } + + if (e.includes("Failed to start the minecraft server")) return ShowPanelError(`${langs.error_detected_one} \nError:\n${e}`); + if (e.includes('Exception in thread "main" ')) return ShowPanelError(`${langs.error_detected_two} \nError:\n${e}`); + + if (e.includes("There is insufficient memory for the Java Runtime Environment to continue.")) return ShowPanelError(`${langs.error_detected_three} \nError:\n${e}`); + if (e.includes("Could not reserve enough space for object heap")) return ShowPanelError(`${langs.error_detected_three} \nError:\n${e}`); + + if (e.includes("Forge patcher exited with code 1")) { + ShowPanelError(`${langs.error_detected_four} \nError:\n${e}`); + progressBar1.style.display = "none"; + info.style.display = "none"; + playBtn.style.display = ""; + } + + if (e.includes("Unable to launch")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if (e.includes("Minecraft Crash Report") && !e.includes("THIS IS NOT A ERROR")) return ShowPanelError(`${langs.error_detected_one} \nError:\n${e}`); + + if (e.includes("java.lang.ClassCastException")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if (e.includes("Minecraft has crashed!")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if ( + e.includes(`Setting user: ${account.name}`) || + e.includes("Launching wrapped minecraft") + ) { + if (inicio == false) { + let typeOfVersion; + if (version.endsWith("-forge")) { + typeOfVersion = "Forge"; + } else if (version_real.endsWith("-fabric")) { + typeOfVersion = "Fabric"; + } else if (version_real.endsWith("-quilt")) { + typeOfVersion = "Quilt"; + } else { + typeOfVersion = ""; + } + ipcRenderer.send( + "new-status-discord-jugando", + `${langs.playing_in} ${version + .replace("-forge", "") + .replace("-fabric", "") + .replace("-quilt", "")} ${typeOfVersion}` + ); + + this.UpdateStatus(account.name, 'ausente', `${langs.playing_in} ${version_real.replace("-forge", "").replace("-fabric", "").replace("-quilt", "")} ${typeOfVersion}`); + + modalDiv1.remove(); + inicio = true; + info.innerHTML = `${langs.minecraft_started_correctly}.`; + ipcRenderer.send("new-notification", { + title: langs.minecraft_started_correctly, + body: langs.minecraft_started_correctly_body, + }); + + ipcRenderer.send("main-window-progress-reset"); + } + } + + if (e.includes("Connecting to")) { + let msj = e.split("Connecting to ")[1].split("...")[0]; + info.innerHTML = `Conectando a ${msj}`; + } + }); + + launch.on("close", (code) => { + consoleOutput_ += `---------- [MC] Código de salida: ${code}\n ----------`; + if (launcherSettings.launcher.close === "close-launcher") + ipcRenderer.send("main-window-show"); + + ipcRenderer.send('updateStatus', { + status: 'online', + details: langs.in_the_menu, + username: account.name, + }) + info.style.display = "none"; + playBtn.style.display = ""; + info.innerHTML = `Verificando archivos...`; + new logger("Launcher", "#3e8ed0"); + progressBar1.style.display = "none"; + console.log("🔧 Minecraft cerrado"); + + ipcRenderer.send("delete-and-new-status-discord"); + + version = null; + versionType = null; + versionData = null; + version_real = null; + assets = null; + type = null; + isForgeCheckBox = false; + isFabricCheckBox = false; + isQuiltCheckBox = false; + document.getElementById("radioVanilla").removeAttribute("checked"); + document.getElementById("radioForge").removeAttribute("checked"); + document.getElementById("radioFabric").removeAttribute("checked"); + document.getElementById("radioQuilt").removeAttribute("checked"); + + + + }); + + let seMostroExtrayendo_core = false; + let seMostroInstalando_core = false; + + launch_core.on("extract", (extract) => { + consoleOutput_ += `[EXTRACT] ${extract}\n`; + if (seMostroExtrayendo_core) { } else { + logTextArea1.innerHTML = `${langs.extracting_loader}.`; + updateTextareaScroll(); + seMostroExtrayendo_core = true; + } + }); + + launch_core.on("debug", (e) => { + consoleOutput_ += `[MC] ${JSON.stringify(e, null, 2)}\n`; + if (e.includes("Failed to start due to TypeError")) { + progressBar1.style.display = "none"; + progressBar1.max = 100; + progressBar1.value = 0; + playBtn.style.display = ""; + info.style.display = "none"; + crasheo = true; + } + + if (e.includes("Downloaded and extracted natives")) { + progressBar1.style.display = ""; + progressBar1.max = 100; + progressBar1.value = 0; + + info.innerHTML = langs.downloading_files; + } + + if (e.includes("Attempting to download Minecraft version jar")) { + info.innerHTML = langs.downloading_version; + } + + if (e.includes("Attempting to download assets")) { + info.innerHTML = langs.downloading_assets; + } + + if (e.includes("Downloaded Minecraft version jar")) { + info.innerHTML = langs.downloading_libraries; + } + + if (e.includes("Downloaded and extracted natives")) { + info.innerHTML = langs.downloading_natives; + } + + if (e.includes("Failed to start the minecraft server")) return ShowPanelError(`${langs.error_detected_one} \nError:\n${e}`); + if (e.includes('Exception in thread "main" ')) return ShowPanelError(`${langs.error_detected_two} \nError:\n${e}`); + + if (e.includes("There is insufficient memory for the Java Runtime Environment to continue.")) return ShowPanelError(`${langs.error_detected_three} \nError:\n${e}`); + if (e.includes("Could not reserve enough space for object heap")) return ShowPanelError(`${langs.error_detected_three} \nError:\n${e}`); + + if (e.includes("Forge patcher exited with code 1")) { + ShowPanelError(`${langs.error_detected_four} \nError:\n${e}`); + progressBar1.style.display = "none"; + info.style.display = "none"; + playBtn.style.display = ""; + } + + if (e.includes("Unable to launch")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if (e.includes("Minecraft Crash Report") && !e.includes("THIS IS NOT A ERROR")) return ShowPanelError(`${langs.error_detected_one} \nError:\n${e}`); + + if (e.includes("java.lang.ClassCastException")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if (e.includes("Minecraft has crashed!")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + }); + launch_core.on("data", async (e) => { + new logger("Minecraft", "#36b030"); + consoleOutput_ += `[MC] ${e}\n`; + if (launcherSettings.launcher.close === "close-launcher") + ipcRenderer.send("main-window-hide"); + progressBar1.style.display = "none"; + + if (e.includes("Launching with arguments")) + info.innerHTML = `${langs.starting_minecraft}...`;; + + if (iniciando == false) { + + iniciando = true; + + let serversDat = `${dataDirectory}/.battly/servers.dat`; + + if (fs.existsSync(serversDat)) { + try { + const serversDatFile = fs.readFileSync(serversDat); + const serversDatData = await NBT.read(serversDatFile); + + + let servers = this.BattlyConfig.promoted_servers; + + + let serversArray = []; + + for (let i = 0; i < servers.length; i++) { + const newServer = { + name: servers[i].name, + ip: servers[i].ip, + icon: servers[i].icon, + }; + + // Verificar si la IP ya existe en el archivo servers.dat + const ipExists = serversDatData.data.servers.some(server => server.ip === newServer.ip); + + if (!ipExists) { + serversArray.push(newServer); + } + } + + + + // Añadir los nuevos servidores al array existente en serversDatData.data.servers + serversDatData.data.servers = serversArray.concat(serversDatData.data.servers); + const editedServersDat = await NBT.write(serversDatData); + fs.writeFileSync(serversDat, editedServersDat); + } catch (error) { + console.error("Error al procesar el archivo NBT:", error); + } + } else { + try { + let servers = this.BattlyConfig.promoted_servers; + + + let serversArray = []; + + for (let i = 0; i < servers.length; i++) { + const newServer = { + name: servers[i].name, + ip: servers[i].ip, + icon: servers[i].icon, + }; + serversArray.push(newServer); + } + + + + // Crear un nuevo archivo servers.dat con los servidores nuevos + const newData = { servers: serversArray }; + const editedServersDat = await NBT.write(newData); + fs.writeFileSync(serversDat, editedServersDat); + } catch (error) { + console.error("Error al crear el nuevo archivo NBT:", error); + } + } + + let versiones = this.Versions; + + const skinsJarPath = `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/mods/skins.jar`; + const skinsForgeJarPath = `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/mods/skins-forge.jar`; + const skinsForgeNewJarPath = `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/mods/skins-forge-new.jar`; + + let rutaPrincipalSkinsJar = `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/battly/mods-internos/skins.jar`; + let rutaPrincipalSkinsForgeJar = `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/battly/mods-internos/skins-forge.jar`; + let rutaPrincipalSkinsForgeNewJar = `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/battly/mods-internos/skins-forge-new.jar`; + + let rutaModMultijugadorForge = `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/battly/mods-internos/multijugador-forge.jar`; + let rutaModMultijugadorFabric = `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/battly/mods-internos/multijugador-fabric.jar`; + + let rutaModMultijugadorForgeDeMods = `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/mods/multijugador-forge.jar`; + let rutaModMultijugadorFabricDeMods = `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/mods/multijugador-fabric.jar`; + + if (fs.existsSync(rutaModMultijugadorFabricDeMods)) { + fs.unlinkSync(rutaModMultijugadorFabricDeMods); + } + + if (fs.existsSync(rutaModMultijugadorForgeDeMods)) { + fs.unlinkSync(rutaModMultijugadorForgeDeMods); + } + + fs.unlinkSync(skinsJarPath); + fs.unlinkSync(skinsForgeJarPath); + fs.unlinkSync(skinsForgeNewJarPath); + + const selectedVersion = version; + + let selectedVersionWithoutHyphen; + if (selectedVersion.includes("-")) { + selectedVersionWithoutHyphen = selectedVersion.replace(/-[^.]+/, ""); + + } + + const versionInfo = versiones.versions.find( + (v) => v.id === selectedVersionWithoutHyphen + ); + + + + if (versionInfo) { + function formatVersionNumber(version) { + const parsedVersion = parseFloat(version); + if (!isNaN(parsedVersion)) { + const formattedVersion = parsedVersion.toString(); + return formattedVersion; + } + return version; // Si no se puede analizar como número, devuelve la versión original + } + + // Ejemplo de uso: + const versionNumber = formatVersionNumber(versionInfo.version); + + let versionesCompatiblesConForgeNormal = [ + "1.16.5", + "1.16.4", + "1.16.3", + "1.16.2", + "1.16.1", + "1.16", + "1.15.2", + "1.15.1", + "1.15", + "1.14.4", + "1.14.3", + "1.14.2", + "1.14.1", + "1.14", + "1.13.2", + "1.13.1", + "1.13", + "1.12.2", + "1.12.1", + "1.12", + "1.11.2", + "1.11.1", + "1.11", + "1.10.2", + "1.10.1", + "1.10", + "1.9.4", + "1.9.3", + "1.9.2", + "1.9.1", + "1.9", + "1.8.9", + "1.8.8", + "1.8.7", + "1.8.6", + "1.8.5", + "1.8.4", + "1.8.3", + "1.8.2", + "1.8.1", + "1.8", + ]; + + + + const excludedVersions = [ + 1.16, 1.15, 1.14, 1.13, 1.12, 1.11, 1.1, 1.9, 1.8, 1.7, 1.6, + 1.5, 1.4, 1.3, + ]; + const includedVersionsForgeNew = [1.17, 1.18, 1.19, 1.2, 1.21]; + const versionesConMultijugadorDesactivado = [ + "1.16.4", + "1.16.5", + ]; + + + + if ( + versionesConMultijugadorDesactivado.includes(version) && + versionType === "forge" + ) { + fs.copyFileSync( + rutaModMultijugadorForge, + `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/mods/multijugador-forge.jar` + ); + } else if ( + versionesConMultijugadorDesactivado.includes(version) && + versionType === "fabric" + ) { + fs.copyFileSync( + rutaModMultijugadorFabric, + `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/mods/multijugador-fabric.jar` + ); + } + + if ( + includedVersionsForgeNew.includes( + parseFloat(version_real) + ) && + !excludedVersions.includes(parseFloat(version_real)) && + versionType == "forge" + ) { + + + fs.copyFileSync( + rutaPrincipalSkinsForgeNewJar, + skinsForgeNewJarPath + ); + + // Eliminar skins.jar y skins-forge.jar + if (fs.existsSync(skinsJarPath)) { + fs.unlinkSync(skinsJarPath); + } + if (fs.existsSync(skinsForgeJarPath)) { + fs.unlinkSync(skinsForgeJarPath); + } + } else if ( + versionesCompatiblesConForgeNormal.includes(version_real) && + versionType == "forge" + ) { + + + fs.copyFileSync( + rutaPrincipalSkinsForgeJar, + skinsForgeJarPath + ); + + // Eliminar skins.jar y skins-forge-new.jar + if (fs.existsSync(skinsJarPath)) { + fs.unlinkSync(skinsJarPath); + } + if (fs.existsSync(skinsForgeNewJarPath)) { + fs.unlinkSync(skinsForgeNewJarPath); + } + } else if (versionType == "fabric" || versionType == "quilt") { + + + fs.copyFileSync(rutaPrincipalSkinsJar, skinsJarPath); + // Eliminar skins-forge.jar y skins-forge-new.jar + if (fs.existsSync(skinsForgeJarPath)) { + fs.unlinkSync(skinsForgeJarPath); + } + if (fs.existsSync(skinsForgeNewJarPath)) { + fs.unlinkSync(skinsForgeNewJarPath); + } + } + } + + let archivoConfigSkins = `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/CustomSkinLoader/CustomSkinLoader.json`; + let data = { + version: "14.15", + buildNumber: 8, + loadlist: [{ + name: "BattlyAPI", + type: "Legacy", + checkPNG: false, + skin: "http://api.battlylauncher.com/api/skin/{USERNAME}.png", + model: "auto", + cape: "http://api.battlylauncher.com/api/capa/{USERNAME}.png", + }, + { + name: "Mojang", + type: "MojangAPI", + apiRoot: "https://api.mojang.com/", + sessionRoot: "https://sessionserver.mojang.com/", + }, + { + name: "OptiFine", + type: "Legacy", + checkPNG: false, + model: "auto", + cape: "https://optifine.net/capes/{USERNAME}.png", + }, + { + name: "LabyMod", + type: "Legacy", + checkPNG: false, + model: "auto", + cape: "https://dl.labymod.net/capes/{STANDARD_UUID}", + }, + ], + enableDynamicSkull: true, + enableTransparentSkin: true, + forceIgnoreHttpsCertificate: true, + forceLoadAllTextures: true, + enableCape: true, + threadPoolSize: 8, + enableLogStdOut: false, + cacheExpiry: 30, + forceUpdateSkull: true, + enableLocalProfileCache: false, + enableCacheAutoClean: true, + forceDisableCache: true, + }; + + if (fs.existsSync(path.join(archivoConfigSkins))) { + fs.writeFileSync(archivoConfigSkins, JSON.stringify(data)); + } else { + fs.mkdirSync( + `${dataDirectory}/.battly/CustomSkinLoader` + ); + fs.writeFileSync(archivoConfigSkins, JSON.stringify(data)); + } + } + + if (e.includes("Failed to start the minecraft server")) return ShowPanelError(`${langs.error_detected_one} \nError:\n${e}`); + if (e.includes('Exception in thread "main" ')) return ShowPanelError(`${langs.error_detected_two} \nError:\n${e}`); + + if (e.includes("There is insufficient memory for the Java Runtime Environment to continue.")) return ShowPanelError(`${langs.error_detected_three} \nError:\n${e}`); + if (e.includes("Could not reserve enough space for object heap")) return ShowPanelError(`${langs.error_detected_three} \nError:\n${e}`); + + if (e.includes("Forge patcher exited with code 1")) { + ShowPanelError(`${langs.error_detected_four} \nError:\n${e}`); + progressBar1.style.display = "none"; + info.style.display = "none"; + playBtn.style.display = ""; + } + + if (e.includes("Unable to launch")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if (e.includes("Minecraft Crash Report") && !e.includes("THIS IS NOT A ERROR")) return ShowPanelError(`${langs.error_detected_one} \nError:\n${e}`); + + if (e.includes("java.lang.ClassCastException")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if (e.includes("Minecraft has crashed!")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if ( + e.includes(`Setting user: ${account.name}`) || + e.includes("Launching wrapped minecraft") + ) { + if (inicio == false) { + let typeOfVersion; + if (version_real.endsWith("-forge")) { + typeOfVersion = "Forge"; + } else if (version_real.endsWith("-fabric")) { + typeOfVersion = "Fabric"; + } else if (version_real.endsWith("-quilt")) { + typeOfVersion = "Quilt"; + } else { + typeOfVersion = ""; + } + ipcRenderer.send( + "new-status-discord-jugando", + `${langs.playing_in} ${version_real + .replace("-forge", "") + .replace("-fabric", "") + .replace("-quilt", "")} ${typeOfVersion}` + ); + + + + this.UpdateStatus(account.name, 'ausente', `${langs.playing_in} ${version_real.replace("-forge", "").replace("-fabric", "").replace("-quilt", "")} ${typeOfVersion}`); + + modalDiv1.remove(); + inicio = true; + info.innerHTML = `${langs.minecraft_started_correctly}.`; + ipcRenderer.send("new-notification", { + title: langs.minecraft_started_correctly, + body: langs.minecraft_started_correctly_body, + }); + + ipcRenderer.send("main-window-progress-reset"); + } + } + }); + + + let lastProgreso = -1; + + launch_core.on("progress", (progress, size) => { + let progreso = ((progress / size) * 100).toFixed(0); + if (progreso > 100) { + progreso = 100; + } + + if (progreso != lastProgreso) { + logTextArea1.innerHTML += `\n${langs.downloading_version}... ${progreso}%`; + lastProgreso = progreso; + } else { + } + + consoleOutput_ += `[DESCARGANDO] ${progress} / ${size}\n`; + updateTextareaScroll(); + ipcRenderer.send("main-window-progress", { + progress, + size + }); + if (!isNaN(progress)) { + // Solo asignar progressBar1.value si progress es un número + progressBar1.value = progress; + } + + if (!isNaN(size)) { + // Solo asignar progressBar1.max si size es un número + progressBar1.max = size; + } + + }); + launch_core.on("check", (progress, size) => { + + let progreso = ((progress / size) * 100).toFixed(0); + if (progreso > 100) { + progreso = 100; + } + + if (progreso != lastProgreso) { + logTextArea1.innerHTML += `\n${langs.downloading}... ${progreso}%`; + lastProgreso = progreso; + updateTextareaScroll(); + + } else { + } + + consoleOutput_ += `[INSTALANDO MC] ${progress} / ${size}\n`; + let seMostroInstalando = false; + if (seMostroInstalando) { } else { + seMostroInstalando = true; + } + progressBar1.style.display = ""; + let size_actual = 100; + let progress_actual = ((progress / size) * 100).toFixed(0); + ipcRenderer.send("main-window-progress", { + progress_actual, + size_actual, + }); + progressBar1.value = progress; + progressBar1.max = size; + }); + + let estimatedTime = `- ${langs.calculating_time}...`; + + launch_core.on("estimated", (time) => { + ipcRenderer.send("main-window-progress-reset"); + + if (isNaN(time) || !isFinite(time)) { + estimatedTime = `- ${langs.estimated_time_not_available}`; + } else { + let hours = Math.floor(time / 3600); + let minutes = Math.floor((time - hours * 3600) / 60); + let seconds = Math.floor(time - hours * 3600 - minutes * 60); + + if (hours > 0) { + estimatedTime = hours > 1 ? `- ${langs.remaining} ${hours}h` : `- ${langs.remaining_two} ${hours}h`; + } else if (minutes > 0) { + estimatedTime = minutes > 1 ? `- ${langs.remaining} ${minutes}m` : `- ${langs.remaining_two} ${minutes}m`; + } else { + estimatedTime = seconds > 1 ? `- ${langs.remaining} ${seconds}s` : `- ${langs.remaining_two} ${seconds}s`; + } + } + + }); + + + launch_core.on("speed", (speed) => { + + let velocidad = speed / 1067008; + + + info.innerHTML = `${langs.downloading}... (${(velocidad).toFixed(2)} MB/s) - ${estimatedTime}`; + /* + + if (velocidad > 0) { + clearTimeout(timeoutId); // cancela el mensaje de alerta si la velocidad no es cero + } else { + timeoutId = setTimeout(() => { + progressBar1.style.display = "none" + progressBar1.max = 100; + progressBar1.value = 0; + playBtn.style.display = "" + info.style.display = "none" + clearTimeout(timeoutId); + const swal = require('sweetalert'); + crasheo = true; + + Toast.fire({ + title: "Error", + text: "Error al descargar esta versión. Reinicia el launcher o inténtalo de nuevo más tarde. [ERROR: 2]", + icon: "error", + button: "Aceptar", + }).then((value) => { + if(value) { + ipcRenderer.send('restartLauncher') + } + }); + + }, 10000); + }*/ + }); + + launch_core.on("patch", (patch) => { + + logTextArea1.innerHTML += `\n${langs.extracting_loader}... [${patch}]`; + updateTextareaScroll(); + consoleOutput_ += `[INSTAL. LOADER] ${patch}\n`; + }); + + launch_core.on("data", async (e) => { + new logger("Minecraft", "#36b030"); + consoleOutput_ += `[MC] ${e}\n`; + if (launcherSettings.launcher.close === "close-launcher") + ipcRenderer.send("main-window-hide"); + progressBar1.style.display = "none"; + + if (e.includes("Launching with arguments")) + info.innerHTML = `${langs.starting_minecraft}...`;; + + if (iniciando == false) { + + Toast.fire({ + icon: "info", + title: `${langs.starting_minecraft}...`, + }); + iniciando = true; + + let serversDat = `${dataDirectory}/.battly/servers.dat`; + + if (fs.existsSync(serversDat)) { + try { + const serversDatFile = fs.readFileSync(serversDat); + const serversDatData = await NBT.read(serversDatFile); + + + let servers = this.BattlyConfig.promoted_servers; + + + let serversArray = []; + + for (let i = 0; i < servers.length; i++) { + const newServer = { + name: servers[i].name, + ip: servers[i].ip, + icon: servers[i].icon, + }; + + // Verificar si la IP ya existe en el archivo servers.dat + const ipExists = serversDatData.data.servers.some(server => server.ip === newServer.ip); + + if (!ipExists) { + serversArray.push(newServer); + } + } + + + + // Añadir los nuevos servidores al array existente en serversDatData.data.servers + serversDatData.data.servers = serversArray.concat(serversDatData.data.servers); + const editedServersDat = await NBT.write(serversDatData); + fs.writeFileSync(serversDat, editedServersDat); + } catch (error) { + console.error("Error al procesar el archivo NBT:", error); + } + } else { + try { + let servers = this.BattlyConfig.promoted_servers; + + + let serversArray = []; + + for (let i = 0; i < servers.length; i++) { + const newServer = { + name: servers[i].name, + ip: servers[i].ip, + icon: servers[i].icon, + }; + serversArray.push(newServer); + } + + + + // Crear un nuevo archivo servers.dat con los servidores nuevos + const newData = { servers: serversArray }; + const editedServersDat = await NBT.write(newData); + fs.writeFileSync(serversDat, editedServersDat); + } catch (error) { + console.error("Error al crear el nuevo archivo NBT:", error); + } + } + + let versiones = this.Versions; + + const skinsJarPath = `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/mods/skins.jar`; + const skinsForgeJarPath = `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/mods/skins-forge.jar`; + const skinsForgeNewJarPath = `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/mods/skins-forge-new.jar`; + + let rutaPrincipalSkinsJar = `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/battly/mods-internos/skins.jar`; + let rutaPrincipalSkinsForgeJar = `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/battly/mods-internos/skins-forge.jar`; + let rutaPrincipalSkinsForgeNewJar = `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/battly/mods-internos/skins-forge-new.jar`; + + let rutaModMultijugadorForge = `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/battly/mods-internos/multijugador-forge.jar`; + let rutaModMultijugadorFabric = `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/battly/mods-internos/multijugador-fabric.jar`; + + let rutaModMultijugadorForgeDeMods = `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/mods/multijugador-forge.jar`; + let rutaModMultijugadorFabricDeMods = `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/mods/multijugador-fabric.jar`; + + if (fs.existsSync(rutaModMultijugadorFabricDeMods)) { + fs.unlinkSync(rutaModMultijugadorFabricDeMods); + } + + if (fs.existsSync(rutaModMultijugadorForgeDeMods)) { + fs.unlinkSync(rutaModMultijugadorForgeDeMods); + } + + fs.unlinkSync(skinsJarPath); + fs.unlinkSync(skinsForgeJarPath); + fs.unlinkSync(skinsForgeNewJarPath); + + const selectedVersion = version; + + let selectedVersionWithoutHyphen; + if (selectedVersion.includes("-")) { + selectedVersionWithoutHyphen = selectedVersion.replace(/-[^.]+/, ""); + + } + + const versionInfo = versiones.versions.find( + (v) => v.id === selectedVersionWithoutHyphen + ); + + if (versionInfo) { + function formatVersionNumber(version) { + const parsedVersion = parseFloat(version); + if (!isNaN(parsedVersion)) { + const formattedVersion = parsedVersion.toString(); + return formattedVersion; + } + return version; // Si no se puede analizar como número, devuelve la versión original + } + + // Ejemplo de uso: + const versionNumber = formatVersionNumber(versionInfo.version); + + + + let versionesCompatiblesConForgeNormal = [ + "1.16.5", + "1.16.4", + "1.16.3", + "1.16.2", + "1.16.1", + "1.16", + "1.15.2", + "1.15.1", + "1.15", + "1.14.4", + "1.14.3", + "1.14.2", + "1.14.1", + "1.14", + "1.13.2", + "1.13.1", + "1.13", + "1.12.2", + "1.12.1", + "1.12", + "1.11.2", + "1.11.1", + "1.11", + "1.10.2", + "1.10.1", + "1.10", + "1.9.4", + "1.9.3", + "1.9.2", + "1.9.1", + "1.9", + "1.8.9", + "1.8.8", + "1.8.7", + "1.8.6", + "1.8.5", + "1.8.4", + "1.8.3", + "1.8.2", + "1.8.1", + "1.8", + ]; + + + + const excludedVersions = [ + 1.16, 1.15, 1.14, 1.13, 1.12, 1.11, 1.1, 1.9, 1.8, 1.7, 1.6, + 1.5, 1.4, 1.3, + ]; + const includedVersionsForgeNew = [1.17, 1.18, 1.19, 1.2, 1.21]; + const versionesConMultijugadorDesactivado = [ + "1.16.4", + "1.16.5", + ]; + + + + if ( + versionesConMultijugadorDesactivado.includes(version) && + versionType === "forge" + ) { + fs.copyFileSync( + rutaModMultijugadorForge, + `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/mods/multijugador-forge.jar` + ); + } else if ( + versionesConMultijugadorDesactivado.includes(version) && + versionType === "fabric" + ) { + fs.copyFileSync( + rutaModMultijugadorFabric, + `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/mods/multijugador-fabric.jar` + ); + } + + if ( + includedVersionsForgeNew.includes( + parseFloat(version_real) + ) && + !excludedVersions.includes(parseFloat(version_real)) && + versionType == "forge" + ) { + + + fs.copyFileSync( + rutaPrincipalSkinsForgeNewJar, + skinsForgeNewJarPath + ); + + // Eliminar skins.jar y skins-forge.jar + if (fs.existsSync(skinsJarPath)) { + fs.unlinkSync(skinsJarPath); + } + if (fs.existsSync(skinsForgeJarPath)) { + fs.unlinkSync(skinsForgeJarPath); + } + } else if ( + versionesCompatiblesConForgeNormal.includes(version_real) && + versionType == "forge" + ) { + + + fs.copyFileSync( + rutaPrincipalSkinsForgeJar, + skinsForgeJarPath + ); + + // Eliminar skins.jar y skins-forge-new.jar + if (fs.existsSync(skinsJarPath)) { + fs.unlinkSync(skinsJarPath); + } + if (fs.existsSync(skinsForgeNewJarPath)) { + fs.unlinkSync(skinsForgeNewJarPath); + } + } else if (versionType == "fabric" || versionType == "quilt") { + + + fs.copyFileSync(rutaPrincipalSkinsJar, skinsJarPath); + // Eliminar skins-forge.jar y skins-forge-new.jar + if (fs.existsSync(skinsForgeJarPath)) { + fs.unlinkSync(skinsForgeJarPath); + } + if (fs.existsSync(skinsForgeNewJarPath)) { + fs.unlinkSync(skinsForgeNewJarPath); + } + } + } + + let archivoConfigSkins = `${dataDirectory}/${process.platform == "darwin" + ? this.config.dataDirectory + : `.${this.config.dataDirectory}` + }/CustomSkinLoader/CustomSkinLoader.json`; + let data = { + version: "14.15", + buildNumber: 8, + loadlist: [{ + name: "BattlyAPI", + type: "Legacy", + checkPNG: false, + skin: "http://api.battlylauncher.com/api/skin/{USERNAME}.png", + model: "auto", + cape: "http://api.battlylauncher.com/api/capa/{USERNAME}.png", + }, + { + name: "Mojang", + type: "MojangAPI", + apiRoot: "https://api.mojang.com/", + sessionRoot: "https://sessionserver.mojang.com/", + }, + { + name: "OptiFine", + type: "Legacy", + checkPNG: false, + model: "auto", + cape: "https://optifine.net/capes/{USERNAME}.png", + }, + { + name: "LabyMod", + type: "Legacy", + checkPNG: false, + model: "auto", + cape: "https://dl.labymod.net/capes/{STANDARD_UUID}", + }, + ], + enableDynamicSkull: true, + enableTransparentSkin: true, + forceIgnoreHttpsCertificate: true, + forceLoadAllTextures: true, + enableCape: true, + threadPoolSize: 8, + enableLogStdOut: false, + cacheExpiry: 30, + forceUpdateSkull: true, + enableLocalProfileCache: false, + enableCacheAutoClean: true, + forceDisableCache: true, + }; + + if (fs.existsSync(path.join(archivoConfigSkins))) { + fs.writeFileSync(archivoConfigSkins, JSON.stringify(data)); + } else { + fs.mkdirSync( + `${dataDirectory}/.battly/CustomSkinLoader` + ); + fs.writeFileSync(archivoConfigSkins, JSON.stringify(data)); + } + } + + if (e.includes("Failed to start the minecraft server")) return ShowPanelError(`${langs.error_detected_one} \nError:\n${e}`); + if (e.includes('Exception in thread "main" ')) return ShowPanelError(`${langs.error_detected_two} \nError:\n${e}`); + + if (e.includes("There is insufficient memory for the Java Runtime Environment to continue.")) return ShowPanelError(`${langs.error_detected_three} \nError:\n${e}`); + if (e.includes("Could not reserve enough space for object heap")) return ShowPanelError(`${langs.error_detected_three} \nError:\n${e}`); + + if (e.includes("Forge patcher exited with code 1")) { + ShowPanelError(`${langs.error_detected_four} \nError:\n${e}`); + progressBar1.style.display = "none"; + info.style.display = "none"; + playBtn.style.display = ""; + } + + if (e.includes("Unable to launch")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if (e.includes("Minecraft Crash Report") && !e.includes("THIS IS NOT A ERROR")) return ShowPanelError(`${langs.error_detected_one} \nError:\n${e}`); + + if (e.includes("java.lang.ClassCastException")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if (e.includes("Minecraft has crashed!")) return ShowPanelError(`${langs.error_detected_five} \nError:\n${e}`); + + if ( + e.includes(`Setting user: ${account.name}`) || + e.includes("Launching wrapped minecraft") + ) { + if (inicio == false) { + let typeOfVersion; + if (version.endsWith("-forge")) { + typeOfVersion = "Forge"; + } else if (version.endsWith("-fabric")) { + typeOfVersion = "Fabric"; + } else if (version.endsWith("-quilt")) { + typeOfVersion = "Quilt"; + } else { + typeOfVersion = ""; + } + ipcRenderer.send( + "new-status-discord-jugando", + `${langs.playing_in} ${version + .replace("-forge", "") + .replace("-fabric", "") + .replace("-quilt", "")} ${typeOfVersion}` + ); + + + + this.UpdateStatus(account.name, 'ausente', `${langs.playing_in} ${version_real.replace("-forge", "").replace("-fabric", "").replace("-quilt", "")} ${typeOfVersion}`); + modalDiv1.remove(); + inicio = true; + info.innerHTML = `${langs.minecraft_started_correctly}.`; + ipcRenderer.send("new-notification", { + title: langs.minecraft_started_correctly, + body: langs.minecraft_started_correctly_body, + }); + + ipcRenderer.send("main-window-progress-reset"); + } + } + + if (e.includes("Connecting to")) { + let msj = e.split("Connecting to ")[1].split("...")[0]; + info.innerHTML = `Conectando a ${msj}`; + } + }); + + launch_core.on("close", (code) => { + consoleOutput_ += `---------- [MC] Código de salida: ${code}\n ----------`; + modalDiv1.remove(); + if (launcherSettings.launcher.close === "close-launcher") + ipcRenderer.send("main-window-show"); + + ipcRenderer.send('updateStatus', { + status: 'online', + details: langs.in_the_menu, + username: account.name, + }) + progressBar1.style.display = "none"; + info.style.display = "none"; + playBtn.style.display = ""; + info.innerHTML = `Verificando archivos...`; + new logger("Launcher", "#3e8ed0"); + console.log("🔧 Minecraft cerrado"); + + progressBar1.style.display = "none"; + ipcRenderer.send("delete-and-new-status-discord"); + + version = null; + versionType = null; + versionData = null; + version_real = null; + assets = null; + type = null; + isForgeCheckBox = false; + isFabricCheckBox = false; + isQuiltCheckBox = false; + document.getElementById("radioVanilla").removeAttribute("checked"); + document.getElementById("radioForge").removeAttribute("checked"); + document.getElementById("radioFabric").removeAttribute("checked"); + document.getElementById("radioQuilt").removeAttribute("checked"); + + }); + + launch_core.on("error", (err) => { + consoleOutput_ += `[ERROR] ${JSON.stringify(err, null, 2)}\n`; + }); + }); + }); + } + + async initStatusServer() { + let APIServerData = document.getElementById("Battly_API_Desc"); + let WEBServerData = document.getElementById("Battly_WEB_Desc"); + let APIServerStatus = document.getElementById("Battly_API_Estado"); + let WEBServerStatus = document.getElementById("Battly_WEB_Estado"); + let miembrosEnLinea = document.getElementById("Miembros_Online"); + + let APIServer = "https://api.battlylauncher.com"; + let WEBServer = "https://battlylauncher.com"; + let APIMembers = `${APIServer}/battlylauncher/usuarios_online`; + + const https = require("https"); + const httpsAgent = new https.Agent({ + rejectUnauthorized: false, + }); + + const axios = require("axios"); + await axios + .get(APIServer, { + httpsAgent, + }) + .then((res) => { + if (res.status === 200) { + APIServerData.innerHTML = `${langs.operative}`; + APIServerStatus.className = "online"; + } else { + APIServerData.innerHTML = `${langs.no_connected}`; + APIServerStatus.className = "online off"; + } + }) + .catch((err) => { + APIServerData.innerHTML = `${langs.no_connected}`; + APIServerStatus.className = "online off"; + }); + + await axios + .get(WEBServer, { + httpsAgent, + }) + .then((res) => { + if (res.status === 200) { + WEBServerData.innerHTML = `${langs.operative}`; + WEBServerStatus.className = "online"; + } else { + WEBServerData.innerHTML = `${langs.no_connected}`; + WEBServerStatus.className = "online off"; + } + }) + .catch((err) => { + WEBServerData.innerHTML = `${langs.no_connected}`; + WEBServerStatus.className = "online off"; + }); + + await axios + .get(APIMembers, { + httpsAgent, + }) + .then((res) => { + if (res.status === 200) { + miembrosEnLinea.innerHTML = `${res.data.usuarios} ${langs.users_online}` + } + }) + .catch((err) => { + miembrosEnLinea.innerHTML = "0"; + }); + } + + initBtn() { + document.getElementById("settings-btn").addEventListener("click", () => { + changePanel("settings"); + }); + } + + async getdate(e) { + let date = new Date(e); + let year = date.getFullYear(); + let month = date.getMonth() + 1; + let day = date.getDate(); + let allMonth = [ + langs.january, + langs.february, + langs.march, + langs.april, + langs.may, + langs.june, + langs.july, + langs.august, + langs.september, + langs.october, + langs.november, + langs.december, + ]; + return { + year: year, + month: allMonth[month - 1], + day: day, + }; + } +} +export default Home; \ No newline at end of file diff --git a/src/assets/js/panels/login.js b/src/assets/js/panels/login.js new file mode 100644 index 0000000..a749798 --- /dev/null +++ b/src/assets/js/panels/login.js @@ -0,0 +1,383 @@ +/** + * @author TECNO BROS + + */ + +'use strict'; + +import { database, changePanel, addAccount, accountSelect } from '../utils.js'; +const { ipcRenderer } = require('electron'); +import { Lang } from "../utils/lang.js"; + +let lang; + +class Login { + static id = "login"; + async init(config) { + this.config = config + this.database = await new database().init(); + lang = await new Lang().GetLang(); + this.getOffline() + this.getOnline() + this.OpenWeb() + } + + async OpenWeb() { + let register_open_btn = document.getElementById("register_open_btn") + register_open_btn.addEventListener("click", () => { + window.open("https://battlylauncher.com/register", "_blank") + }); + } + + getOnline() { + console.log(`🔃 Iniciando panel de Microsoft...`) + this.loginMicrosoft(); + document.querySelector('.cancel-login').addEventListener("click", () => { + document.querySelector(".cancel-login").style.display = "none"; + changePanel("settings"); + }) + } + + getOffline() { + console.log(`🔃 Iniciando panel de offline...`) + this.loginOffline(); + document.querySelector('.cancel-login').addEventListener("click", () => { + document.querySelector(".cancel-login").style.display = "none"; + changePanel("settings"); + }) + } + + loginMicrosoft() { + let microsoftBtn = document.getElementById("microsoft-button") + let mojangBtn = document.querySelector('.mojang') + let cancelBtn = document.querySelector('.cancel-login') + + microsoftBtn.addEventListener("click", () => { + document.querySelector(".preload-content").style.display = ""; + document.getElementById("loading-text").innerHTML = lang.a_microsoft_panel_opened; + microsoftBtn.disabled = true; + mojangBtn.disabled = true; + cancelBtn.disabled = true; + ipcRenderer.invoke('Microsoft-window', this.config.client_id).then(account_connect => { + document.querySelector(".preload-content").style.display = ""; + document.getElementById("loading-text").innerHTML = lang.logging_in; + + if (!account_connect) { + document.getElementById("loading-text").innerHTML = lang.error_logging_in; + setTimeout(() => { + document.querySelector(".preload-content").style.display = "none"; + changePanel("settings"); + }, 3000); + console.log("❌ Error al iniciar sesión con Microsoft"); + microsoftBtn.disabled = false; + mojangBtn.disabled = false; + cancelBtn.disabled = false; + return; + } + + let account = { + type: "microsoft", + access_token: account_connect.access_token, + client_token: account_connect.client_token, + uuid: account_connect.uuid, + name: account_connect.name, + refresh_token: account_connect.refresh_token, + user_properties: account_connect.user_properties, + meta: account_connect.meta + } + + let profile = { + uuid: account_connect.uuid, + skins: account_connect.profile.skins || [], + capes: account_connect.profile.capes || [] + } + + this.database.add(account, 'accounts') + this.database.add(profile, 'profile') + this.database.update({ uuid: "1234", selected: account.uuid }, 'accounts-selected'); + + addAccount(account) + accountSelect(account.uuid) + let news_shown = localStorage.getItem("news_shown_v1.7"); + if (!news_shown || news_shown == "false" || news_shown == null || news_shown == undefined) { + document.querySelector(".preload-content").style.display = "none"; + changePanel("news"); + } else { + document.querySelector(".preload-content").style.display = "none"; + changePanel("home") + } + + microsoftBtn.disabled = false; + mojangBtn.disabled = false; + cancelBtn.disabled = false; + cancelBtn.style.display = "none"; + }).catch(err => { + console.log(err) + microsoftBtn.disabled = false; + mojangBtn.disabled = false; + cancelBtn.disabled = false; + + document.getElementById("loading-text").innerHTML = lang.error_logging_in; + setTimeout(() => { + document.querySelector(".preload-content").style.display = "none"; + changePanel("settings"); + }, 3000); + + }); + }) + } + + + + async loginOffline() { + let mailInput = document.getElementById("username_text") + let passwordInput = document.getElementById("password_text") + let cancelMojangBtn = document.getElementById("cancelar-btn-login") + let infoLoginPanel = document.getElementById("info-login-panel") + let infoLogin = document.getElementById("info-login") + let loginBtn = document.getElementById("login-btn") + + cancelMojangBtn.addEventListener("click", () => { + mailInput.value = ""; + passwordInput.value = ""; + infoLogin.innerHTML = " "; + infoLoginPanel.classList.remove("is-active"); + changePanel("settings"); + }) + + + loginBtn.addEventListener("click", async () => { + cancelMojangBtn.disabled = false; + loginBtn.disabled = true; + mailInput.disabled = true; + passwordInput.disabled = true; + infoLoginPanel.classList.add("is-active"); + infoLogin.innerHTML = lang.logging_in; + + + if (mailInput.value == "") { + infoLogin.innerHTML = lang.set_your_username; + setTimeout(() => { + infoLoginPanel.classList.remove("is-active"); + }, 3000); + cancelMojangBtn.disabled = false; + loginBtn.disabled = false; + mailInput.disabled = false; + passwordInput.disabled = false; + return + } + + if (mailInput.value.length < 3) { + infoLogin.innerHTML = lang.threecharacters_username; + setTimeout(() => { + infoLoginPanel.classList.remove("is-active"); + }, 3000); + cancelMojangBtn.disabled = false; + loginBtn.disabled = false; + mailInput.disabled = false; + passwordInput.disabled = false; + return + }; + + if (passwordInput.value == "") { + infoLogin.innerHTML = lang.set_your_password; + setTimeout(() => { + infoLoginPanel.classList.remove("is-active"); + }, 3000); + cancelMojangBtn.disabled = false; + loginBtn.disabled = false; + mailInput.disabled = false; + passwordInput.disabled = false; + return + } + + if (passwordInput.value.length < 3) { + infoLogin.innerHTML = lang.threecharacters_password; + setTimeout(() => { + infoLoginPanel.classList.remove("is-active"); + }, 3000); + cancelMojangBtn.disabled = false; + loginBtn.disabled = false; + mailInput.disabled = false; + passwordInput.disabled = false; + return + }; + + const crypto = require('crypto'); + async function uuid(username) { + let md5Bytes = crypto.createHash('md5').update(username).digest(); + md5Bytes[6] &= 0x0f; + md5Bytes[6] |= 0x30; + md5Bytes[8] &= 0x3f; + md5Bytes[8] |= 0x80; + return md5Bytes.toString('hex'); + } + + + let account; + let uuid_; + + await uuid(mailInput.value).then(uuid => { + uuid_ = uuid; + }); + + let accounts; + var request = indexedDB.open("database", 1); + + request.onerror = function (event) { + console.log("❌ Error al abrir la base de datos"); + }; + + request.onsuccess = function (event) { + // Obtener la base de datos + var db = event.target.result; + + // Iniciar una transacción + var transaction = db.transaction("accounts", "readonly"); + + // Obtener el almacén de objetos desde la transacción + var objectStore = transaction.objectStore("accounts"); + + // Hacer una solicitud para obtener todos los registros + var getAllRequest = objectStore.getAll(); + + // Manejar el evento de éxito de la solicitud + getAllRequest.onsuccess = function (event) { + // Obtener los datos del resultado de la solicitud + accounts = event.target.result; + console.log("✅ Base de datos abierta correctamente"); + console.log(accounts); + }; + + // Manejar el evento de éxito de la transacción + transaction.oncomplete = function (event) { + // Cerrar la base de datos después de completar la transacción + db.close(); + }; + }; + + //comprobar si el usuario existe + try { + let account = accounts.find(account => account.value.uuid == uuid_); + if (account) { + infoLogin.innerHTML = lang.account_already_exists; + setTimeout(() => { + infoLoginPanel.classList.remove("is-active"); + }, 3000); + cancelMojangBtn.disabled = false; + loginBtn.disabled = false; + mailInput.disabled = false; + passwordInput.disabled = false; + return + } + } catch (error) { + console.log("No hay cuentas") + console.log(error) + } + + + const axios = require("axios"); + + let data = await axios.post("https://battlylauncher.com/api/battly/launcher/login", { + Headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify({ + "username": mailInput.value ? mailInput.value : "1", + "password": passwordInput.value ? passwordInput.value : "1" + }) + }).catch(err => { + console.log(err) + cancelMojangBtn.disabled = false; + loginBtn.disabled = false; + mailInput.disabled = false; + passwordInput.disabled = false; + mailInput.value = ""; + passwordInput.value = ""; + infoLogin.innerHTML = lang.username_or_password_incorrect; + setTimeout(() => { + infoLoginPanel.classList.remove("is-active"); + }, 3000); + return + }) + + if(data.data.status == "error") { + infoLogin.innerHTML = data.data.error + cancelMojangBtn.disabled = false; + loginBtn.disabled = false; + mailInput.disabled = false; + passwordInput.disabled = false; + infoLogin.innerHTML = data.data.message; + setTimeout(() => { + infoLoginPanel.classList.remove("is-active"); + }, 3000); + return + } + + if (data.data.status == "success") { + + + + + account = { + type: "battly", + access_token: "1234", + client_token: "1234", + uuid: uuid_, + name: mailInput.value, + password: passwordInput.value, + user_properties: '{}', + meta: { + type: "cracked", + offline: true + } + } + + await this.database.add(account, 'accounts') + await this.database.update({ uuid: "1234", selected: account.uuid }, 'accounts-selected'); + + infoLoginPanel.classList.remove("is-active"); + + await addAccount(account) + await accountSelect(account.uuid) + let news_shown = localStorage.getItem("news_shown_v1.7"); + if (!news_shown || news_shown == "false" || news_shown == null || news_shown == undefined) { + document.querySelector(".preload-content").style.display = "none"; + changePanel("news"); + } else { + document.querySelector(".preload-content").style.display = "none"; + changePanel("home") + } + + + cancelMojangBtn.disabled = false; + cancelMojangBtn.click(); + mailInput.value = ""; + passwordInput.value = ""; + loginBtn.disabled = false; + mailInput.disabled = false; + passwordInput.disabled = false; + loginBtn.style.display = "block"; + infoLogin.innerHTML = " "; + + let welcome = document.querySelector('.news-list'); + let blockWelcome = document.createElement('div'); + blockWelcome.classList.add('news-block', 'opacity-1'); + blockWelcome.innerHTML = ` +
    +
    +
    ${lang.welcome_again_to_battly}, ${account.name}
    +
    +
    +
    +
    +

    ${lang.we_hope_you_enjoy}

    +
    +
    `; + welcome.prepend(blockWelcome); + } + }) + } +} + +export default Login; \ No newline at end of file diff --git a/src/assets/js/panels/mods.js b/src/assets/js/panels/mods.js new file mode 100644 index 0000000..e19b56d --- /dev/null +++ b/src/assets/js/panels/mods.js @@ -0,0 +1,1172 @@ +'use strict'; + +import { + database, + changePanel, + addAccount, + accountSelect +} from '../utils.js'; +const { + ipcRenderer +} = require('electron'); +const axios = require('axios'); +const dataDirectory = process.env.APPDATA || (process.platform == 'darwin' ? `${process.env.HOME}/Library/Application Support` : process.env.HOME) +const fs = require('fs'); + +const Swal = require('./assets/js/libs/sweetalert/sweetalert2.all.min'); + +const Toast = Swal.mixin({ + toast: true, + position: 'top-end', + showConfirmButton: false, + timer: 3000, + timerProgressBar: true, + didOpen: (toast) => { + toast.addEventListener('mouseenter', Swal.stopTimer) + toast.addEventListener('mouseleave', Swal.resumeTimer) + } +}) +let lang; +import { Lang } from "../utils/lang.js"; + +class Mods { + static id = "mods"; + + + async init(config) { + this.config = config + this.database = await new database().init(); + lang = await new Lang().GetLang(); + this.Inicio(); + this.BuscarMods(); + this.CheckIfIsTheLatestScroll(); + this.InsalarModPack(); + } + + + async InsalarModPack() { + let btnInstalarModPack = document.getElementById("button_instalar_modpack"); + + btnInstalarModPack.addEventListener("click", async () => { + // Crear el elemento div con la clase "modal is-active" + const modalDiv = document.createElement("div"); + modalDiv.className = "modal is-active"; + modalDiv.style.zIndex = "9999"; + + // Crear el elemento div con la clase "modal-background" y añadirlo como hijo de modalDiv + const modalBackgroundDiv = document.createElement("div"); + modalBackgroundDiv.className = "modal-background"; + modalDiv.appendChild(modalBackgroundDiv); + + // Crear el elemento div con la clase "modal-card" y añadirlo como hijo de modalDiv + const modalCardDiv = document.createElement("div"); + modalCardDiv.className = "modal-card"; + modalDiv.appendChild(modalCardDiv); + + // Crear el elemento header con la clase "modal-card-head" y añadirlo como hijo de modalCardDiv + const headerDiv = document.createElement("header"); + headerDiv.className = "modal-card-head"; + modalCardDiv.appendChild(headerDiv); + + // Crear el elemento p con la clase "modal-card-title" y añadirlo como hijo de headerDiv + const titleP = document.createElement("p"); + titleP.className = "modal-card-title"; + titleP.textContent = lang.install_modpack_text; + headerDiv.appendChild(titleP); + + // Crear el botón para cerrar el modal y añadirlo como hijo de headerDiv + const closeButton = document.createElement("button"); + closeButton.className = "delete"; + closeButton.setAttribute("aria-label", "close"); + headerDiv.appendChild(closeButton); + + // Crear el elemento section con la clase "modal-card-body" y añadirlo como hijo de modalCardDiv + const bodySection = document.createElement("section"); + bodySection.className = "modal-card-body"; + modalCardDiv.appendChild(bodySection); + + // Crear el elemento p con el texto y añadirlo como hijo de bodySection + const textP = document.createElement("p"); + textP.textContent = lang.compatible_with_curseforge_or_modrinth + bodySection.appendChild(textP); + + // Crear el elemento div con las clases "file is-small is-boxed has-name" y estilos, y añadirlo como hijo de bodySection + const fileDiv = document.createElement("div"); + fileDiv.className = "file is-small is-boxed has-name"; + fileDiv.style.alignItems = "center"; + bodySection.appendChild(fileDiv); + + // Crear el elemento label con la clase "file-label" y añadirlo como hijo de fileDiv + const fileLabel = document.createElement("label"); + fileLabel.className = "file-label"; + fileDiv.appendChild(fileLabel); + + // Crear el elemento input con la clase "file-input" y atributo tipo "file" y añadirlo como hijo de fileLabel + const fileInput = document.createElement("input"); + fileInput.className = "file-input"; + fileInput.setAttribute("type", "file"); + fileInput.setAttribute("name", "resume"); + fileInput.setAttribute("accept", ".zip, .mrpack"); // Establece las extensiones permitidas + fileLabel.appendChild(fileInput); + + // Crear el elemento span con la clase "file-cta" y añadirlo como hijo de fileLabel + const fileCtaSpan = document.createElement("span"); + fileCtaSpan.className = "file-cta"; + fileLabel.appendChild(fileCtaSpan); + + // Crear el elemento span con la clase "file-icon" y añadirlo como hijo de fileCtaSpan + const fileIconSpan = document.createElement("span"); + fileIconSpan.className = "file-icon"; + fileCtaSpan.appendChild(fileIconSpan); + + // Crear el icono dentro de fileIconSpan + const fileIcon = document.createElement("i"); + fileIcon.className = "fas fa-upload"; + fileIconSpan.appendChild(fileIcon); + + // Crear el elemento span con la clase "file-label" y añadirlo como hijo de fileCtaSpan + const fileLabelSpan = document.createElement("span"); + fileLabelSpan.className = "file-label"; + fileLabelSpan.textContent = lang.select_a_file; + fileCtaSpan.appendChild(fileLabelSpan); + + // Crear el elemento span con la clase "file-name" y estilos, y añadirlo como hijo de fileLabel + const fileNameSpan = document.createElement("span"); + fileNameSpan.className = "file-name"; + fileNameSpan.style.textAlign = "center"; + fileNameSpan.textContent = "ZIP/MRPACK"; + fileLabel.appendChild(fileNameSpan); + + // Crear el elemento footer con la clase "modal-card-foot" y añadirlo como hijo de modalCardDiv + const footerDiv = document.createElement("footer"); + footerDiv.className = "modal-card-foot"; + modalCardDiv.appendChild(footerDiv); + + // Crear el botón "Instalar" y añadirlo como hijo de footerDiv + const installButton = document.createElement("button"); + installButton.className = "button is-info"; + installButton.textContent = lang.install; + footerDiv.appendChild(installButton); + + // Crear el botón "Cancelar" y añadirlo como hijo de footerDiv + const cancelButton = document.createElement("button"); + cancelButton.className = "button"; + cancelButton.textContent = lang.cancel; + footerDiv.appendChild(cancelButton); + + // Agregar modalDiv al documento como último hijo del body + document.body.appendChild(modalDiv); + + + closeButton.addEventListener("click", () => { + modalDiv.remove(); + }); + + cancelButton.addEventListener("click", () => { + modalDiv.remove(); + }); + + fileInput.addEventListener("change", () => { + const file = fileInput.files[0]; + if (file) { + fileNameSpan.textContent = file.name; + } + }); + + installButton.addEventListener("click", async () => { + + + + if (fileInput.files.length == 0) { + Toast.fire({ + icon: 'error', + title: lang.you_didnt_selected_any_file + }) + } else { + + footerDiv.remove(); + + + const file = fileInput.files[0]; + + /* eliminar el bodySection */ + bodySection.remove(); + + /* crear el nuevo bodySection */ + const bodySection2 = document.createElement("section"); + bodySection2.className = "modal-card-body"; + modalCardDiv.appendChild(bodySection2); + + /* añadir esto: + +

    Instalando ModPack... Puede tardar...

    + + */ + + const textP2 = document.createElement("p"); + textP2.innerHTML = lang.installing_modpack_can_take; + bodySection2.appendChild(textP2); + + const progress = document.createElement("progress"); + progress.className = "progress is-info"; + progress.value = "0"; + progress.max = "100"; + bodySection2.appendChild(progress); + + /* eliminar el footerDiv */ + footerDiv.remove(); + + /* crear el nuevo footerDiv */ + const footerDiv2 = document.createElement("footer"); + footerDiv2.className = "modal-card-foot"; + modalCardDiv.appendChild(footerDiv2); + + + const fs = require('fs-extra'); + const fetch = require('node-fetch'); + const path = require('path'); + + // Reemplaza con la ruta real de tu archivo manifest.json + const apiKey = '$2a$10$S7nVFhQKpxteK4Fwf9yoxejmI.NjJiE53Qh4IeaDbIu/./oTM/MKa'; // Reemplaza con tu clave API de CurseForge + + + + + async function descargarModModrinth(archivo, randomString) { + + let name = archivo.name; + let description = archivo.summary ? archivo.summary : lang.no_description; + let version = archivo.dependencies.minecraft; + let loader; + let loaderVersion; + let loader_ = archivo.dependencies["fabric-loader"]; + let loader_forge = archivo.dependencies["forge"]; + + if (loader_) { + loader = "fabric"; + loaderVersion = loader_; + } else if (loader_forge) { + loader = "forge"; + loader_ = archivo.dependencies["forge"]; + loaderVersion = loader_; + } else { + loader = "quilt"; + loader_ = archivo.dependencies["quilt-loader"]; + loaderVersion = loader_; + } + + + + if (name && description && version && loader && loaderVersion) { + //crear un string random de 6 caracteres + + //crear el archivo de la instancia + //comprobar si existe la carpeta de instancias + + + + + //descargar la imagen https://bulma.io/images/placeholders/128x128.png y moverla a la carpeta de la instancia + fetch("https://battlylauncher.com/assets/img/mc-icon.png") + .then((res) => res.buffer()) + .then((buffer) => { + fs.writeFileSync( + `${dataDirectory}/.battly/instances/${randomString}/icon.png`, + buffer + ); + }); + + + let instance = { + name: name, + description: description, + version: version, + image: `${dataDirectory}/.battly/instances/${randomString}/icon.png`, + id: randomString, + loader: loader, + loaderVersion: loaderVersion, + }; + + let instance_json = JSON.stringify(instance); + fs.writeFileSync( + path.join( + `${dataDirectory}/.battly/instances/${randomString}`, + "instance.json" + ), + instance_json + ); + + + let files = []; + let totalFiles = archivo.files.length; + let totalFilesDownloaded = 0; + + let percent = 0; + progress.max = totalFiles; + + + for (let i = 0; i < archivo.files.length; i++) { + const file = archivo.files[i]; + let path = file.path; + let fileSize = file.fileSize; + let downloads = file.downloads; + + //crear las carpetas necesarias + let carpetas = path.split("/"); + let carpetas2 = carpetas.slice(0, carpetas.length - 1); + let carpetas3 = carpetas2.join("/"); + let carpetas4 = `${dataDirectory}/.battly/instances/${randomString}/${carpetas3}`; + if (!fs.existsSync(carpetas4)) { + fs.mkdirSync(carpetas4, { + recursive: true, + }); + } + + for (let fileDownload of downloads) { + await fetch(fileDownload).then((res) => { + const dest = fs.createWriteStream(`${dataDirectory}/.battly/instances/${randomString}/${path}`); + res.body.pipe(dest); + totalFilesDownloaded++; + progress.value = totalFilesDownloaded; + + textP2.innerHTML = `${lang.installing_modpack_can_take}

    ${lang.installing_file} ${path} (${totalFilesDownloaded} / ${totalFiles})`; + if (totalFilesDownloaded == totalFiles) { + modalDiv.remove(); + + ipcRenderer.send("new-notification", { + title: lang.modpack_installed, + body: `ModPack ${name} ${lang.modpack_installed_correctly}.` + }); + } + }); + } + } + } + + } + + async function descargarMod(projectID, fileID, destino, manifestPath) { + const url = `https://api.curseforge.com/v1/mods/${projectID}/files/${fileID}/download-url`; + const modData = `https://api.curseforge.com/v1/mods/${projectID}` + const axios = require('axios'); + const responseDatos = await axios.get(modData, { + headers: { + 'x-api-key': apiKey, + }, + }); + + try { + const response = await fetch(url, { + headers: { + 'X-Api-Key': apiKey, + }, + }); + + if (response.ok) { + const { + data + } = await response.json(); + const response2 = await fetch(data); + + if (response2.ok) { + const archivoDescargado = await response2.buffer(); + // Guarda el archivo en la carpeta 'destino' + await fs.writeFile(path.join(destino, `${responseDatos.data.data.name.replace(/[\/\\:*?"<>|]/g, "_")}.jar`), archivoDescargado); + } else { } + } else { } + } catch (error) { + console.error(`Error al descargar el mod ${projectID}-${fileID}:`); + console.error(error); + } + } + + let destinationFile = file.path; + + const AdmZip = require('adm-zip'); + + const tipoArchivo = file.name.split('.').pop(); + + //ruta del archivo + + let json; + + if (tipoArchivo === 'zip') { + let randomString = Math.random().toString(36).substring(2, 8); + if (!fs.existsSync(`${dataDirectory}/.battly/instances`)) { + fs.mkdirSync(`${dataDirectory}/.battly/instances`); + } + + //comprobar si existe la carpeta de la instancia + if (!fs.existsSync(`${dataDirectory}/.battly/instances/${randomString}`)) { + fs.mkdirSync(`${dataDirectory}/.battly/instances/${randomString}`); + } else { + //generar otro string random + randomString = Math.random().toString(36).substring(2, 8); + //crear la carpeta de la instancia + fs.mkdirSync(`${dataDirectory}/.battly/instances/${randomString}`); + } + const destinationFolder = `${dataDirectory}/.battly/instances/${randomString}`; + + + + + if (!fs.existsSync(destinationFolder)) { + fs.mkdirSync(destinationFolder); + } + + if (!fs.existsSync(dataDirectory + '/.battly/temp')) { + fs.mkdirSync(dataDirectory + '/.battly/temp'); + } + + if (!fs.existsSync(destinationFolder + '/mods')) { + fs.mkdirSync(destinationFolder + '/mods'); + } + + const destinoMods = destinationFolder + '/mods'; + + const zip = new AdmZip(destinationFile); + zip.extractAllTo(destinationFolder, true); + json = await fs.readFile(path.join(destinationFolder, 'manifest.json'), 'utf8'); + + setTimeout(async () => { + + + const manifestPath = `${destinationFolder}/manifest.json`; + async function leerManifest() { + try { + const manifestData = await fs.readFile(manifestPath, 'utf8'); + const manifest = JSON.parse(manifestData); + return manifest; + } catch (error) { + throw error; + } + } + + const manifest = await leerManifest(path.join(destinationFolder, 'manifest.json')); + + let total = manifest.files.length; + let restante = total; + let totalFilesDownloaded = 0; + + let name = manifest.name; + let description = manifest.author ? manifest.author : "Sin descripción"; + let version = manifest.minecraft.version; + let loader; + let loaderVersion; + let loader_ = manifest.minecraft.modLoaders[0].id; + + if (loader_.startsWith("fabric")) { + loader = "fabric"; + loaderVersion = loader_.replace("fabric-", ""); + } else if (loader_.startsWith("forge")) { + loader = "forge"; + loaderVersion = loader_.replace("forge-", ""); + } else { + loader = "quilt"; + loaderVersion = loader_.replace("quilt-", ""); + } + + + + if (name && description && version && loader && loaderVersion) { + + + + //descargar la imagen https://bulma.io/images/placeholders/128x128.png y moverla a la carpeta de la instancia + fetch("https://battlylauncher.com/assets/img/mc-icon.png") + .then((res) => res.buffer()) + .then((buffer) => { + fs.writeFileSync( + `${dataDirectory}/.battly/instances/${randomString}/icon.png`, + buffer + ); + }); + + + let instance = { + name: name, + description: description, + version: version, + image: `${dataDirectory}/.battly/instances/${randomString}/icon.png`, + id: randomString, + loader: loader, + loaderVersion: loaderVersion, + }; + + let instance_json = JSON.stringify(instance); + fs.writeFileSync( + path.join( + `${dataDirectory}/.battly/instances/${randomString}`, + "instance.json" + ), + instance_json + ); + + await fs.copy(path.join(destinationFolder, 'overrides'), destinationFolder); + + //eliminar la carpeta overrides + await fs.remove(path.join(destinationFolder, 'overrides')); + + + for (const mod of manifest.files) { + await descargarMod(mod.projectID, mod.fileID, destinoMods, manifestPath); + const modData = `https://api.curseforge.com/v1/mods/${mod.projectID}` + const axios = require('axios'); + const responseDatos = await axios.get(modData, { + headers: { + 'x-api-key': apiKey, + }, + }); + + restante--; + progress.max = total; + progress.value = total - restante; + totalFilesDownloaded++; + textP2.innerHTML = `${lang.installing_modpack_can_take}

    ${lang.installing_mod} ${responseDatos.data.data.name} (${totalFilesDownloaded} / ${total})`; + + if (restante === 0) { + modalDiv.remove(); + + ipcRenderer.send("new-notification", { + title: lang.modpack_installed, + body: `ModPack ${name} ${lang.modpack_installed_correctly}.` + }); + } + + } + } + }, 1000); + } else if (tipoArchivo === 'mrpack') { + let randomString = Math.random().toString(36).substring(2, 8); + if (!fs.existsSync(`${dataDirectory}/.battly/instances`)) { + fs.mkdirSync(`${dataDirectory}/.battly/instances`); + } + + //comprobar si existe la carpeta de la instancia + if (!fs.existsSync(`${dataDirectory}/.battly/instances/${randomString}`)) { + fs.mkdirSync(`${dataDirectory}/.battly/instances/${randomString}`); + } else { + //generar otro string random + randomString = Math.random().toString(36).substring(2, 8); + //crear la carpeta de la instancia + fs.mkdirSync(`${dataDirectory}/.battly/instances/${randomString}`); + } + const destinationFolder = `${dataDirectory}/.battly/instances/${randomString}`; + + fs.mkdirSync(`${dataDirectory}/.battly/instances/${randomString}`, { + recursive: true + }); + + if (!fs.existsSync(destinationFolder)) { + fs.mkdirSync(destinationFolder); + } + + const zip = new AdmZip(destinationFile); + await zip.extractAllTo(destinationFolder, true); + json = await fs.readFile(path.join(destinationFolder, 'modrinth.index.json'), 'utf8'); + + //mover lo que hay en la carpeta overrides a la carpeta battly + await fs.copy(path.join(destinationFolder, 'overrides'), destinationFolder); + + //eliminar la carpeta overrides + await fs.remove(path.join(destinationFolder, 'overrides')); + + await descargarModModrinth(JSON.parse(json), randomString); + + } else { + Toast.fire({ + icon: 'error', + title: lang.the_file_is_not_compatible + }) + } + + + } + }); + + }); + } + + async CheckIfIsTheLatestScroll() { + const modsContainer = document.getElementById('mods_container'); + + let options = { + root: modsContainer, + rootMargin: '0px', + threshold: 1.0 + }; + + //comprobar si ha scrolleado hasta el final con un observer + let observer = new IntersectionObserver((entries, observer) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + this.CargarMods(); + } + }); + }, options); + + observer.observe(modsContainer); + + } + + async Inicio() { + let btnOpenMods = document.getElementById("boton_abrir_mods"); + btnOpenMods.addEventListener("click", () => { + this.CargarMods(); + }); + let boton_mods = document.getElementById("boton_abrir_mods"); + boton_mods.addEventListener("click", () => { + changePanel("mods"); + }); + + let boton_volver = document.getElementById("volver"); + boton_volver.addEventListener("click", () => { + changePanel("home"); + document.querySelector(".preload-content").style.display = "none"; + }); + + let mods_container = document.getElementById("mods_container"); + /* comprobar si se ha deslizado el scroll hasta el final */ + mods_container.addEventListener("scroll", () => { + if (mods_container.scrollTop + mods_container.clientHeight >= mods_container.scrollHeight) { + this.CargarMods(); + } + }); + + //comprobar si existe el directorio de mods + if (!fs.existsSync(`${dataDirectory}/.battly/mods`)) { + fs.mkdirSync(`${dataDirectory}/.battly/mods`); + } + } + + async BuscarMods() { + let input_buscar_mods = document.getElementById("input_buscar_mods"); + let boton_buscar_mods = document.getElementById("boton_buscar_mods"); + + //al hacer click en enter que ejecute la función this.CargarMods(input_buscar_mods.value); + input_buscar_mods.addEventListener("keyup", (event) => { + if (event.keyCode === 13) { + event.preventDefault(); + if (input_buscar_mods.value == "") { + this.CargarMods(); + } else { + this.BuscarModsPorNombre(input_buscar_mods.value); + } + } + }); + } + + async BuscarModsPorNombre(nombre) { + document.querySelector(".preload-content").style.display = "block"; + const loadingText = document.getElementById("loading-text"); + loadingText.innerText = lang.searching_mods; + + mods_container.innerHTML = ""; + await axios.get(`https://api.modrinth.com/v2/search?limit=100&query=${nombre}&facets=[["project_type:mod"]]`).then(async (response) => { + let mods = response.data.hits; + let mods_container = document.getElementById("mods_container"); + + let totalMods = mods.length; + let totalModsCargados = 0; + + for (let i = 0; i < mods.length; i++) { + totalModsCargados++; + if (totalModsCargados == totalMods) { + document.querySelector(".preload-content").style.display = "none"; + } + let mod = mods[i]; + + let mod_data = await this.ObtenerMod(mod.project_id); + + let mod_card = document.createElement("div"); + mod_card.classList.add("feature-card2-feature-card"); + + let mod_download = document.createElement("a"); + mod_download.classList.add("feature-card2-download"); + + let mod_download_icon = document.createElement("img"); + mod_download_icon.classList.add("feature-card2-download-icon"); + mod_download_icon.src = "assets/images/descargar.png"; + + let mod_icon = document.createElement("img"); + mod_icon.classList.add("feature-card2-icon"); + mod_icon.src = mod.icon_url ? mod.icon_url : "assets/images/pregunta.png"; + + let mod_container = document.createElement("div"); + mod_container.classList.add("feature-card2-container"); + + let mod_name = document.createElement("h2"); + mod_name.classList.add("feature-card2-text"); + mod_name.innerText = mod.title; + + let mod_description = document.createElement("span"); + if (mod.description.length > 100) { + mod_description.innerText = mod.description.slice(0, 100) + "..."; + } else { + mod_description.innerText = mod.description; + } + mod_description.style.color = "#fff"; + + mod_container.appendChild(mod_name); + mod_container.appendChild(mod_description); + + mod_download.appendChild(mod_download_icon); + + mod_card.appendChild(mod_download); + mod_card.appendChild(mod_icon); + mod_card.appendChild(mod_container); + + mods_container.appendChild(mod_card); + + mod_download.addEventListener("click", () => { + this.ShowPanelInfo(mod.project_id); + }); + } + }).catch((error) => { + console.log(error); + }); + } + + async DescargarMod(downloadLink, mod, nombre, fileName) { + + const mod_data = await this.ObtenerMod(mod); + + const fetch = require('node-fetch'); + + Toast.fire({ + icon: 'info', + title: `${lang.downloading_mod}...` + }) + + let error_downloading_mod = lang.error_downloading_mod; + let mod_downloaded_successfully = lang.mod_downloaded_successfully; + + let file = fs.createWriteStream(`${dataDirectory}/.battly/mods/${fileName}`); + let request = await fetch(downloadLink); + await new Promise((resolve, reject) => { + request.body.pipe(file); + request.body.on("error", (err) => { + Toast.fire({ + icon: 'error', + title: `${error_downloading_mod} ${nombre}.`, + text: err + }) + reject(err); + }); + file.on("finish", function () { + resolve(); + Toast.fire({ + icon: 'success', + title: `${nombre} ${mod_downloaded_successfully}.` + }) + }); + }); + + + + if (mod_data[0].dependencies.length > 0) { + this.DescargarDependencias(mod, mod_data[0].dependencies[0].version_number); + } + } + + async ObtenerMod(id) { + const mod_data = await axios.get(`https://api.modrinth.com/v2/project/${id}/version`).then((response) => { + return response.data; + }).catch((error) => { + console.log(error); + }); + return mod_data; + } + + async ObtenerModData(id) { + const mod_data = await axios.get(`https://api.modrinth.com/v2/project/${id}`).then((response) => { + return response.data; + }).catch((error) => { + console.log(error); + }); + return mod_data; + } + + async DescargarDependencias(mod, version) { + console.log(version); + const mod_data = await this.ObtenerMod(mod); + console.log(mod_data[0].dependencies) + + if (mod_data[0].dependencies.length > 0) { + for (let i = 0; i < mod_data[0].dependencies.length; i++) { + if (mod_data[0].dependencies[i].version_number == version) { + const dependency = mod_data[0].dependencies[i].project_id; + const dependency_data = await this.ObtenerMod(dependency); + if (dependency_data[0].files.length > 0) { + const downloadLink = dependency_data[0].files[0].url; + const response = await fetch(downloadLink); + const fileBuffer = await response.arrayBuffer(); + const fs = require('fs'); + fs.writeFile(`${dataDirectory}/.battly/mods/${dependency_data[0].files[0].filename}`, Buffer.from(fileBuffer), (err) => { + if (err) { + Toast.fire({ + icon: 'error', + title: `${lang.error_downloading_dependency}: ${dependency_data[0].name}`, + text: err.message + }); + } else { + Toast.fire({ + icon: 'success', + title: `${lang.dependency}: ${dependency_data[0].name} ${lang.downloaded_successfully_two}.` + }); + } + }); + } + } + } + } + } + + async ShowPanelInfo(id) { + document.querySelector(".preload-content").style.display = "block"; + const loadingText = document.getElementById("loading-text"); + loadingText.innerText = lang.loading_mod_information; + const mod_data = await this.ObtenerModData(id); + const mod_data_downloads = await this.ObtenerMod(id); + + + let loaders = mod_data.loaders; + let loadersText = ""; + for (let i = 0; i < loaders.length; i++) { + /* jungar todo y mostrar algo como Forge - Fabric - Rift , que el último no tenga el - */ + if (i == 0) { + loadersText += loaders[i].charAt(0).toUpperCase() + loaders[i].slice(1); + } else if (i == loaders.length - 1) { + loadersText += " - " + loaders[i].charAt(0).toUpperCase() + loaders[i].slice(1); + } + } + + let versiones_soportadas = mod_data.game_versions; + let versiones_soportadas_text = ""; + + for (let i = 0; i < versiones_soportadas.length; i++) { + /* Solo poner la primera y la última versión, ejemplo: si las soportadas son ["1.16.5", "1.17.1", "1.17.2"] solo poner 1.16.5 - 1.17.2 */ + if (i == 0) { + versiones_soportadas_text += versiones_soportadas[i]; + } else if (i == versiones_soportadas.length - 1) { + versiones_soportadas_text += " - " + versiones_soportadas[i]; + } + } + + let loadersInfo = ` ${loadersText} (${versiones_soportadas_text})`; + + let mod_body = document.getElementById("battly_mods"); + + + // Crear elementos + let modalDiv = document.createElement("div"); + modalDiv.classList.add("modal"); + //añadir el z-index para que se vea por encima de todo + + let modalBackgroundDiv = document.createElement("div"); + modalBackgroundDiv.classList.add("modal-background"); + + let modalCardDiv = document.createElement("div"); + modalCardDiv.classList.add("modal-card"); + + let modalHeader = document.createElement("header"); + modalHeader.classList.add("modal-card-head"); + + let modalTitle = document.createElement("p"); + modalTitle.classList.add("modal-card-title"); + modalTitle.innerText = lang.mod_information; + + let modalCloseButton = document.createElement("button"); + modalCloseButton.classList.add("delete"); + modalCloseButton.setAttribute("aria-label", "close"); + + let modalSection = document.createElement("section"); + modalSection.classList.add("modal-card-body"); + modalSection.style.scrollbarColor = "#d3d3d3 #d3d3d3"; + modalSection.style.scrollbarWidth = "thin"; + + // Crear contenido de la tarjeta + let cardDiv = document.createElement("div"); + cardDiv.classList.add("card"); + + let cardContentDiv = document.createElement("div"); + cardContentDiv.classList.add("card-content"); + + // Crear contenido de media + let mediaDiv = document.createElement("div"); + mediaDiv.classList.add("media"); + + let mediaLeftDiv = document.createElement("div"); + mediaLeftDiv.classList.add("media-left"); + + let mediaImage = document.createElement("figure"); + mediaImage.classList.add("image"); + mediaImage.classList.add("is-48x48"); + + let mediaImageSrc = document.createElement("img"); + mediaImageSrc.src = mod_data.icon_url ? mod_data.icon_url : "assets/images/pregunta.png"; + mediaImageSrc.alt = "Image"; + + let mediaContentDiv = document.createElement("div"); + mediaContentDiv.classList.add("media-content"); + + let mediaTitle = document.createElement("p"); + mediaTitle.classList.add("title"); + mediaTitle.classList.add("is-4"); + mediaTitle.innerText = mod_data.title; + + let mediaSubtitle = document.createElement("p"); + mediaSubtitle.classList.add("subtitle"); + mediaSubtitle.classList.add("is-6"); + mediaSubtitle.innerHTML = loadersInfo; + + // ... + + // Crear contenido de contenido + let contentDiv = document.createElement("div"); + contentDiv.classList.add("content"); + + let contentText = document.createElement("p"); + contentText.innerHTML = ` + ${mod_data.description} +
    +
    + ${lang.mod_stats} +
    + ${lang.downloads}: ${mod_data.downloads} +
    + ${lang.followers}: ${mod_data.followers} +
    +
    + ${mod_data.body.replace(/\*\*(.*?)\*\*/g, '$1').replace(/!\[(.*?)\]\((.*?)\)/g, '$1').replace(/### (.*?)\n/g, '

    $1

    \n').replace(/## (.*?)\n/g, '

    $1

    \n').replace(/# (.*?)\n/g, '

    $1

    \n').replace(/\[(.*?)\]\((.*?)\)/g, '$1').replace(/- (.*)\n/g, '
  • $1
  • \n').replace(/\n---\n/g, '\n
    \n').replace(//g, '').replace(/__(.*?)__/g, '$1').replace(/_(.*?)_/g, '$1').replace(/\*(.*?)\*/g, '$1')} +
    +
    + + `; + + // ... + + // Crear footer + let footerDiv = document.createElement("footer"); + footerDiv.classList.add("modal-card-foot"); + + let selectDiv = document.createElement("div"); + selectDiv.classList.add("select"); + selectDiv.classList.add("is-link"); + selectDiv.style.marginRight = "10px"; + selectDiv.style.width = "auto"; + + let selectElement = document.createElement("select"); + selectElement.style.width = "auto"; + selectElement.style.height = "40px"; + selectElement.style.transform = "translate(0px, -5px)"; + for (let version of mod_data_downloads) { + let versionName = version.version_number; + let versionID = version.id; + let supportedVersions = version.game_versions; + let supportedVersionsText = ""; + for (let i = 0; i < supportedVersions.length; i++) { + //poner todas las versiones separadas por - y la última no tenga el - + if (i == 0) { + supportedVersionsText += supportedVersions[i]; + } else if (i == supportedVersions.length - 1) { + supportedVersionsText += " - " + supportedVersions[i]; + } + } + let optionElement = document.createElement("option"); + optionElement.value = versionID; + optionElement.innerText = `${supportedVersionsText} (${versionName})` + selectElement.appendChild(optionElement); + } + + let downloadButton = document.createElement("button"); + downloadButton.classList.add("button"); + downloadButton.classList.add("is-info"); + downloadButton.innerText = lang.download_mod; + + let deleteButton = document.createElement("button"); + deleteButton.classList.add("button"); + deleteButton.innerText = lang.delete_mod; + if (fs.existsSync(`${dataDirectory}/.battly/mods/${mod_data_downloads[0].files[0].filename}`)) { + deleteButton.classList.add("is-danger"); + deleteButton.classList.add("is-active"); + + } else { + deleteButton.classList.add("is-hidden"); + } + + let cardFooterDiv = document.createElement("div"); + cardFooterDiv.classList.add("card-footer"); + + let cardFooterItem = document.createElement("div"); + cardFooterItem.classList.add("card-footer-item"); + + let cardFooterText = document.createElement("p"); + cardFooterText.style.fontSize = "10px"; + cardFooterText.innerHTML = lang.all_this_information_copyright_modrinth; + + // Agregar elementos al DOM + mediaImage.appendChild(mediaImageSrc); + mediaLeftDiv.appendChild(mediaImage); + mediaDiv.appendChild(mediaLeftDiv); + + mediaContentDiv.appendChild(mediaTitle); + mediaContentDiv.appendChild(mediaSubtitle); + + contentDiv.appendChild(contentText); + + selectDiv.appendChild(selectElement); + + footerDiv.appendChild(selectDiv); + footerDiv.appendChild(downloadButton); + footerDiv.appendChild(deleteButton); + + cardFooterItem.appendChild(cardFooterText); + + cardFooterDiv.appendChild(cardFooterItem); + + mediaDiv.appendChild(mediaLeftDiv); + mediaDiv.appendChild(mediaContentDiv); + + cardContentDiv.appendChild(mediaDiv); + cardContentDiv.appendChild(contentDiv); + cardContentDiv.appendChild(cardFooterDiv); + + cardDiv.appendChild(cardContentDiv); + + modalHeader.appendChild(modalTitle); + modalHeader.appendChild(modalCloseButton); + + modalSection.appendChild(cardDiv); + + modalCardDiv.appendChild(modalHeader); + modalCardDiv.appendChild(modalSection); + modalCardDiv.appendChild(footerDiv); + + modalDiv.appendChild(modalBackgroundDiv); + modalDiv.appendChild(modalCardDiv); + + mod_body.appendChild(modalDiv); + + modalDiv.classList.add("is-active"); + + document.querySelector(".preload-content").style.display = "none"; + + + + + downloadButton.addEventListener("click", () => { + this.DescargarMod(mod_data_downloads[selectElement.selectedIndex].files[0].url, mod_data.id, mod_data.title, mod_data_downloads[selectElement.selectedIndex].files[0].filename); + }); + + deleteButton.addEventListener("click", () => { + /* eliminar el archivo */ + fs.unlink(`${dataDirectory}/.battly/mods/${mod_data_downloads[0].files[0].filename}`, (err) => { + if (err) { + console.error(err) + return + } + }); + + /* eliminar las dependencias */ + if (mod_data_downloads[0].dependencies.length > 0) { + for (let i = 0; i < mod_data_downloads[0].dependencies.length; i++) { + const dependency = mod_data_downloads[0].dependencies[i].project_id; + const dependency_data = this.ObtenerMod(dependency); + if (dependency_data[0].files.length > 0) { + fs.unlink(`${dataDirectory}/.battly/mods/${dependency_data[0].files[0].filename}`, (err) => { + if (err) { + console.error(err) + return + } + }); + } + } + } + + Toast.fire({ + icon: 'success', + title: `${mod_data.title} ${lang.deleted_successfully}.` + }) + + }); + + modalCloseButton.addEventListener("click", () => { + modalDiv.classList.remove("is-active"); + modalDiv.remove(); + }); + } + + + async CargarMods() { + document.querySelector(".preload-content").style.display = "block"; + const loadingText = document.getElementById("loading-text"); + loadingText.innerText = lang.searching_mods; + await axios.get("https://api.modrinth.com/v2/search?limit=100&index=relevance").then(async (response) => { + let mods = response.data.hits; + let mods_container = document.getElementById("mods_container"); + mods_container.innerHTML = ""; + + + let totalMods = mods.length; + let totalModsCargados = 0; + + for (let i = 0; i < mods.length; i++) { + totalModsCargados++; + if (totalModsCargados == totalMods) { + document.querySelector(".preload-content").style.display = "none"; + } + let mod = mods[i]; + + let mod_card = document.createElement("div"); + mod_card.classList.add("feature-card2-feature-card"); + + let mod_download = document.createElement("a"); + mod_download.classList.add("feature-card2-download"); + + let mod_download_icon = document.createElement("img"); + mod_download_icon.classList.add("feature-card2-download-icon"); + mod_download_icon.src = "assets/images/descargar.png"; + + let mod_icon = document.createElement("img"); + mod_icon.classList.add("feature-card2-icon"); + mod_icon.src = mod.icon_url ? mod.icon_url : "assets/images/pregunta.png"; + + let mod_container = document.createElement("div"); + mod_container.classList.add("feature-card2-container"); + + let mod_name = document.createElement("h2"); + mod_name.classList.add("feature-card2-text"); + mod_name.innerText = mod.title; + + let mod_description = document.createElement("span"); + if (mod.description.length > 100) { + mod_description.innerText = mod.description.slice(0, 100) + "..."; + } else { + mod_description.innerText = mod.description; + } + mod_description.style.color = "#fff"; + + mod_container.appendChild(mod_name); + mod_container.appendChild(mod_description); + + mod_download.appendChild(mod_download_icon); + + mod_card.appendChild(mod_download); + mod_card.appendChild(mod_icon); + mod_card.appendChild(mod_container); + + mods_container.appendChild(mod_card); + + mod_download.addEventListener("click", () => { + this.ShowPanelInfo(mod.project_id); + }); + } + + }).catch((error) => { + console.log(error); + }); + } +} + +export default Mods; \ No newline at end of file diff --git a/src/assets/js/panels/music-small.js b/src/assets/js/panels/music-small.js new file mode 100644 index 0000000..28d4751 --- /dev/null +++ b/src/assets/js/panels/music-small.js @@ -0,0 +1,24 @@ +/** + * @author TECNO BROS + + */ + +'use strict'; + +const { ipcRenderer } = require('electron'); +class MusicSmall { + static id = "music-small"; + async init() { + this.ShowMusicInfo(); + } + + + async ShowMusicInfo() { + ipcRenderer.on('get-song-test', (song) => { + document.getElementById("musicSmallName").innerText = musicList_[indexNumb - 1].name; + document.getElementById("musicSmallDesc").innerText = musicList_[indexNumb - 1].author; + document.getElementById("musicSmallImg").src = musicList_[indexNumb - 1].img; + }); + } +} +export default MusicSmall; \ No newline at end of file diff --git a/src/assets/js/panels/music.js b/src/assets/js/panels/music.js new file mode 100644 index 0000000..6881294 --- /dev/null +++ b/src/assets/js/panels/music.js @@ -0,0 +1,968 @@ + +'use strict'; + +const { ipcMain, ipcRenderer } = require('electron'); +import { database, changePanel, addAccount, accountSelect } from '../utils.js'; + +const Swal = require('./assets/js/libs/sweetalert/sweetalert2.all.min'); +const usetube = require('./assets/js/libs/youtube/usetube'); + +const ytdl = require('ytdl-core'); + +const dataDirectory = `${process.env.APPDATA || (process.platform == 'darwin' ? `${process.env.HOME}/Library/Application Support` : process.env.HOME)}/.battly` +const fs = require('fs'); + +const Toast = Swal.mixin({ + toast: true, + position: 'top-end', + showConfirmButton: false, + timer: 5000, + timerProgressBar: false, + didOpen: (toast) => { + toast.addEventListener('mouseenter', Swal.stopTimer) + toast.addEventListener('mouseleave', Swal.resumeTimer) + }, +}); + +let musicList_ = []; +import { Lang } from "../utils/lang.js"; +let lang; + +class Music { + static id = "music"; + async init(config) { + this.config = config + this.database = await new database().init(); + this.lang = await new Lang().GetLang(); + lang = this.lang; + this.load(); + this.PlayLists(); + } + + async PlayLists() { + if (!fs.existsSync(`${dataDirectory}`)) { + fs.mkdirSync(`${dataDirectory}`); + } + + if (!fs.existsSync(`${dataDirectory}/battly`)) { + fs.mkdirSync(`${dataDirectory}/battly`); + } + + if (!fs.existsSync(`${dataDirectory}/battly/launcher`)) { + fs.mkdirSync(`${dataDirectory}/battly/launcher`); + } + + if (!fs.existsSync(`${dataDirectory}/battly/launcher/music`)) { + fs.mkdirSync(`${dataDirectory}/battly/launcher/music`); + } + + if (!fs.existsSync(`${dataDirectory}/battly/launcher/music/playlists.json`)) { + fs.writeFileSync(`${dataDirectory}/battly/launcher/music/playlists.json`, JSON.stringify([])); + } + + document.getElementById("save-playlist").addEventListener("click", async () => { + let playlistsFile = await fs.readFileSync(`${dataDirectory}/battly/launcher/music/playlists.json`, 'utf8'); + let playlists = JSON.parse(playlistsFile); + + if (musicList_.length === 0) return Toast.fire({ + icon: 'error', + title: lang.you_dont_have_songs_in_your_playlist + }); + + // Crear el elemento div principal con la clase "modal is-active" y estilo z-index + const modalDiv = document.createElement('div'); + modalDiv.className = 'modal is-active'; + modalDiv.style.zIndex = '4'; + + // Crear el elemento div con la clase "modal-background" y agregarlo al div principal + const modalBackgroundDiv = document.createElement('div'); + modalBackgroundDiv.className = 'modal-background'; + modalDiv.appendChild(modalBackgroundDiv); + + // Crear el elemento div con la clase "modal-card" y estilo de fondo y agregarlo al div principal + const modalCardDiv = document.createElement('div'); + modalCardDiv.className = 'modal-card'; + modalCardDiv.style.backgroundColor = '#444444'; + modalDiv.appendChild(modalCardDiv); + + // Crear el elemento header con la clase "modal-card-head" y estilo de fondo y agregarlo al div modal-card + const headerDiv = document.createElement('header'); + headerDiv.className = 'modal-card-head'; + headerDiv.style.backgroundColor = '#444444'; + modalCardDiv.appendChild(headerDiv); + + let modalCloseButton = document.createElement("button"); + modalCloseButton.classList.add("delete"); + modalCloseButton.setAttribute("aria-label", "close"); + + // Crear el elemento p con la clase "modal-card-title", estilo de color y texto, y agregarlo al div header + const titleP = document.createElement('p'); + titleP.className = 'modal-card-title'; + titleP.style.color = '#fff'; + titleP.textContent = lang.save_playlist_text; + headerDiv.appendChild(titleP); + headerDiv.appendChild(modalCloseButton); + + // Crear el elemento section con la clase "modal-card-body" y estilos de fondo y color, y agregarlo al div modal-card + const bodySection = document.createElement('section'); + bodySection.className = 'modal-card-body'; + bodySection.style.backgroundColor = '#444444'; + bodySection.style.color = '#fff'; + modalCardDiv.appendChild(bodySection); + + // Crear el elemento p con el título de la playlist y agregarlo al div section + const playlistTitleP = document.createElement('p'); + playlistTitleP.textContent = lang.playlist_name; + bodySection.appendChild(playlistTitleP); + + // Crear el elemento input con la clase "input is-info" y agregarlo al div section + const inputText = document.createElement('input'); + inputText.type = 'text'; + inputText.className = 'input is-info'; + bodySection.appendChild(inputText); + + // Crear el elemento footer con la clase "modal-card-foot" y estilo de fondo y agregarlo al div modal-card + const footerDiv = document.createElement('footer'); + footerDiv.className = 'modal-card-foot'; + footerDiv.style.backgroundColor = '#444444'; + modalCardDiv.appendChild(footerDiv); + + // Crear el elemento button con la clase "button is-info" y texto "Guardar", y agregarlo al div footer + const saveButton = document.createElement('button'); + saveButton.className = 'button is-info'; + saveButton.textContent = lang.save; + footerDiv.appendChild(saveButton); + + saveButton.addEventListener('click', () => { + const playlistName = inputText.value; + + if (playlistName.length < 0) return Toast.fire({ + icon: 'error', + title: lang.you_need_to_set_a_playlist_name + }); + + for (let playlist in playlists) { + if (playlist.name === playlistName) return Toast.fire({ + icon: 'error', + title: lang.already_have_a_playlist_with_this_name + }); + } + + let newPlaylist = { + name: playlistName, + songs: musicList_, + } + + playlists.push(newPlaylist); + + fs.writeFileSync(`${dataDirectory}/battly/launcher/music/playlists.json`, JSON.stringify(playlists)); + + modalDiv.remove(); + + Toast.fire({ + icon: 'success', + title: lang.playlist_saved_correctly + }); + }); + + modalCloseButton.addEventListener('click', () => { + modalDiv.remove(); + }); + + // Crear el elemento button con la clase "button is-danger" y texto "Cancelar", y agregarlo al div footer + const cancelButton = document.createElement('button'); + cancelButton.className = 'button is-danger'; + cancelButton.textContent = lang.cancel; + footerDiv.appendChild(cancelButton); + + cancelButton.addEventListener('click', () => { + modalDiv.remove(); + }); + + // Agregar el div principal al cuerpo del documento + document.body.appendChild(modalDiv); + }); + } + + async load() { + + document.getElementById("show-playlists").addEventListener("click", async () => { + let playlistsFile = await fs.readFileSync(`${dataDirectory}/battly/launcher/music/playlists.json`, 'utf8'); + let playlists = JSON.parse(playlistsFile); + // Crear el elemento div principal con la clase "modal is-active" y estilo z-index + const modalDiv = document.createElement('div'); + modalDiv.className = 'modal is-active'; + modalDiv.style.zIndex = '4'; + + // Crear el elemento div con la clase "modal-background" y agregarlo al div principal + const modalBackgroundDiv = document.createElement('div'); + modalBackgroundDiv.className = 'modal-background'; + modalDiv.appendChild(modalBackgroundDiv); + + // Crear el elemento div con la clase "modal-card" y estilo de fondo y agregarlo al div principal + const modalCardDiv = document.createElement('div'); + modalCardDiv.className = 'modal-card'; + modalCardDiv.style.backgroundColor = '#444444'; + modalDiv.appendChild(modalCardDiv); + + // Crear el elemento header con la clase "modal-card-head" y estilo de fondo y agregarlo al div modal-card + const headerDiv = document.createElement('header'); + headerDiv.className = 'modal-card-head'; + headerDiv.style.backgroundColor = '#444444'; + modalCardDiv.appendChild(headerDiv); + + let modalCloseButton = document.createElement("button"); + modalCloseButton.classList.add("delete"); + modalCloseButton.setAttribute("aria-label", "close"); + + modalCloseButton.addEventListener('click', () => { + modalDiv.remove(); + }); + + // Crear el elemento p con la clase "modal-card-title", estilo de color y texto, y agregarlo al div header + const titleP = document.createElement('p'); + titleP.className = 'modal-card-title'; + titleP.style.color = '#fff'; + titleP.textContent = lang.saved_playlists; + headerDiv.appendChild(titleP); + headerDiv.appendChild(modalCloseButton); + + // Crear el elemento section con la clase "modal-card-body" y estilos de fondo y color, y agregarlo al div modal-card + const bodySection = document.createElement('section'); + bodySection.className = 'modal-card-body'; + bodySection.style.backgroundColor = '#444444'; + bodySection.style.color = '#fff'; + modalCardDiv.appendChild(bodySection); + + // Crear el elemento p con el mensaje de bienvenida y agregarlo al div section + const welcomeP = document.createElement('p'); + welcomeP.innerHTML = lang.welcome_to_the_new_playlists_system; + bodySection.appendChild(welcomeP); + + for (let playlist of playlists) { + const cardDiv = document.createElement('div'); + cardDiv.className = 'card'; + bodySection.appendChild(cardDiv); + + // Crear el elemento header con la clase "card-header is-flex" y agregarlo al div card + const cardHeaderDiv = document.createElement('header'); + cardHeaderDiv.className = 'card-header is-flex'; + cardDiv.appendChild(cardHeaderDiv); + + // Crear el elemento p con la clase "card-header-title" y texto "Playlist 1", y agregarlo al div card-header + const cardTitleP = document.createElement('p'); + cardTitleP.className = 'card-header-title'; + cardTitleP.textContent = playlist.name; + cardHeaderDiv.appendChild(cardTitleP); + + // Crear el elemento div con la clase "buttons" y estilo de margen derecho, y agregarlo al div card-header + const buttonsDiv = document.createElement('div'); + buttonsDiv.className = 'buttons'; + buttonsDiv.style.marginRight = '5px'; + cardHeaderDiv.appendChild(buttonsDiv); + + // Crear el elemento button con la clase "button is-info" y estilo de margen derecho, y agregarlo al div buttons + const playButton = document.createElement('button'); + playButton.className = 'button is-info'; + playButton.style.marginRight = '0px'; + buttonsDiv.appendChild(playButton); + + playButton.addEventListener('click', async () => { + musicList_ = playlist.songs; + let newMusicList = []; + + // Crear el elemento modal + const modal = document.createElement("div"); + modal.classList.add("modal", "is-active"); + modal.style.zIndex = "4"; + + // Crear el fondo del modal + const modalBackground = document.createElement("div"); + modalBackground.classList.add("modal-background"); + + // Crear la tarjeta del modal + const modalCard = document.createElement("div"); + modalCard.classList.add("modal-card"); + modalCard.style.backgroundColor = "#444444"; + modalCard.style.borderRadius = "5px"; + + // Crear el cuerpo de la tarjeta del modal + const modalCardBody = document.createElement("section"); + modalCardBody.classList.add("modal-card-body"); + modalCardBody.style.backgroundColor = "#444444"; + modalCardBody.style.textAlign = "center"; + + // Crear la imagen + const image = document.createElement("img"); + image.src = "./assets/images/icons/loading.gif"; + image.style.width = "70px"; + image.style.height = "70px"; + image.style.margin = "0 auto"; + image.alt = ""; + + // Crear el párrafo + const paragraph = document.createElement("p"); + paragraph.style.color = "#fff"; + paragraph.style.fontSize = "20px"; + paragraph.innerText = lang.getting_songs; + + // Agregar la imagen y el párrafo al cuerpo de la tarjeta del modal + modalCardBody.appendChild(image); + modalCardBody.appendChild(paragraph); + + // Agregar el cuerpo de la tarjeta al modal + modalCard.appendChild(modalCardBody); + + // Agregar el fondo del modal y la tarjeta del modal al modal + modal.appendChild(modalBackground); + modal.appendChild(modalCard); + + // Agregar el modal al documento body + document.body.appendChild(modal); + + modalDiv.remove(); + + for (let song of playlist.songs) { + paragraph.innerText = `${lang.getting} ${song.name} (${newMusicList.length}/${playlist.songs.length})`; + await ytdl.getInfo(song.url, { quality: 'highestaudio' }) + .then(info => { + const audioFormat = info.formats.find(format => format.mimeType.includes('audio/mp4')); + + if (!audioFormat) { + console.error("No se encontró un formato de audio adecuado"); + return; + } + + const audioUrl = audioFormat.url; + + newMusicList.push({ + url: song.url, + name: song.name, + author: song.author, + img: song.img, + audio: audioUrl, + duration: song.duration + }); + + + + const resultsDiv = document.getElementById("playlist"); + let i = 1; + + if (newMusicList.length === playlist.songs.length) { + clicked(1); + musicList_ = newMusicList; + + document.getElementById("playlist").innerHTML = ""; + + // Mapear el array original para mantener el orden + const orderedMusicList = playlist.songs.map((song, index) => { + const music = musicList_.find(item => item.name === song.name); + return { ...music, index }; // Añadir el índice al objeto si es necesario + }); + + for (let music of orderedMusicList) { + paragraph.innerText = `${lang.loading} ${music.name} (${i}/${orderedMusicList.length})`; + i++; + + const cardDiv = document.createElement("div"); + cardDiv.classList.add("card"); + cardDiv.classList.add("cards"); + cardDiv.setAttribute("data-id", i + 1); + + const img = document.createElement("img"); + img.src = music.img; + img.alt = lang.thumbnail; + img.classList.add("thumbnail"); + cardDiv.appendChild(img); + + const cardContentDiv = document.createElement("div"); + cardContentDiv.classList.add("card-content"); + cardContentDiv.classList.add("card-content1"); + + const songTitleDiv = document.createElement("div"); + songTitleDiv.classList.add("song-title"); + songTitleDiv.innerText = music.name; + cardContentDiv.appendChild(songTitleDiv); + + const artistDiv = document.createElement("div"); + artistDiv.classList.add("artist"); + artistDiv.innerText = music.author; + cardContentDiv.appendChild(artistDiv); + + const button = document.createElement("button"); + button.classList.add("delete-button"); + button.classList.add("button"); + button.classList.add("is-danger"); + button.innerText = lang.delete; + + button.addEventListener("click", async () => { + button.disabled = true; + button.classList.add("is-loading"); + const index = orderedMusicList.indexOf(music); + if (index > -1) { + orderedMusicList.splice(index, 1); + } + cardDiv.remove(); + button.disabled = false; + button.classList.remove("is-loading"); + button.classList.remove("is-info"); + button.classList.add("is-success"); + + setTimeout(() => { + button.classList.remove("is-success"); + button.classList.add("is-danger"); + }, 2000); + }); + + cardContentDiv.appendChild(button); + cardDiv.appendChild(cardContentDiv); + + resultsDiv.appendChild(cardDiv); + } + } + }); + } + + paragraph.innerHTML = `${lang.songs_loaded_playing} ${newMusicList[0].name}`; + setTimeout(() => { + modal.remove(); + }, 5000); + }); + + // Crear el elemento span con el ícono de reproducción y agregarlo al botón playButton + const playIconSpan = document.createElement('span'); + playIconSpan.innerHTML = ''; + playButton.appendChild(playIconSpan); + + // Crear el elemento button con la clase "button is-danger", y agregarlo al div buttons + const deleteButton = document.createElement('button'); + deleteButton.className = 'button is-danger'; + buttonsDiv.appendChild(deleteButton); + + deleteButton.addEventListener('click', () => { + const index = playlists.indexOf(playlist); + if (index > -1) { + playlists.splice(index, 1); + } + fs.writeFileSync(`${dataDirectory}/battly/launcher/music/playlists.json`, JSON.stringify(playlists)); + cardDiv.remove(); + Toast.fire({ + icon: 'success', + title: lang.playlist_deleted_correctly + }); + }); + + // Crear el elemento span con el ícono de eliminación y agregarlo al botón deleteButton + const deleteIconSpan = document.createElement('span'); + deleteIconSpan.innerHTML = ''; + deleteButton.appendChild(deleteIconSpan); + + //crear un separador de 5px + const separator = document.createElement('div'); + separator.style.height = '5px'; + bodySection.appendChild(separator); + } + document.body.appendChild(modalDiv); + }); + + let sortable = new Sortable(document.getElementById('playlist'), { + animation: 250, // Duración de la animación en milisegundos + ghostClass: 'seleccionado', // Clase de estilo para el elemento seleccionado + chosenClass: 'seleccionado', // Clase de estilo para el elemento elegido + }); + + const playlistAudio = document.getElementById("main-audio"); + + + + + + document.getElementById("return-btn").addEventListener("click", () => { + changePanel("home"); + }); + + const wrapper = document.getElementById("card-wrapper"), + musicImg = wrapper.querySelector(".img-area img"), + musicName = document.querySelector(".song-details .artist"), + playPauseBtn = wrapper.querySelector(".play-pause"), + prevBtn = wrapper.querySelector("#prev"), + nextBtn = wrapper.querySelector("#next"), + mainAudio = wrapper.querySelector("#main-audio"), + progressArea = wrapper.querySelector(".progress-area"), + progressBar = progressArea.querySelector(".progress-bar"); + + + + + + + function playAudioFromVideoId(videoId) { + ytdl.getInfo(videoId, { quality: 'highestaudio' }) + .then(info => { + const audioFormat = info.formats.find(format => format.mimeType.includes('audio/mp4')); + + if (!audioFormat) { + console.error("No se encontró un formato de audio adecuado"); + return; + } + + const audioUrl = audioFormat.url; + + /* formato: { name: "Nice piano and ukulele", author: "Royalty", img: "https://www.bensound.com/bensound-img/buddy.jpg", audio: "https://www.bensound.com/bensound-music/bensound-buddy.mp3", duration: "2:02" }, + */ + + //convertir a minutos:segundos + const duration = info.videoDetails.lengthSeconds; + const minutes = Math.floor(duration / 60); + const seconds = duration % 60; + const durationString = minutes + ":" + seconds; + + musicList_.push({ + url: videoId, + name: info.videoDetails.title, + author: info.videoDetails.author.name, + img: info.videoDetails.thumbnails[0].url, + audio: audioUrl, + duration: durationString + }); + + addMusicToPlaylist(musicList_.length); + }) + .catch(error => { + console.error("Error al obtener información del video:"); + console.error(error); + }); + } + + async function searchAndShowResults(songName) { + let btnSearch = document.getElementById("reproducir-btn"); + btnSearch.disabled = true; + btnSearch.classList.add("is-loading"); + let results = await usetube.searchVideo(songName) + results = results.videos; + + if (results.length > 0) { + + + const resultsDiv = document.getElementById("playlist"); + resultsDiv.innerHTML = ""; + + for (let i = 0; i < results.length; i++) { + const result = results[i]; + const videoId = result.id; + const title = result.title; + const author = result.artist; + const thumbnail = `https://img.youtube.com/vi/${videoId}/mqdefault.jpg`; + + /* crear esto: +
    + + Miniatura +
    +
    Nombre de la Canción 1
    +
    Nombre del Artista
    + +
    +
    + */ + + const cardDiv = document.createElement("div"); + cardDiv.classList.add("card"); + cardDiv.classList.add("cards"); + cardDiv.setAttribute("data-id", i + 1); + + const img = document.createElement("img"); + img.src = thumbnail; + img.alt = lang.thumbnail; + img.classList.add("thumbnail"); + cardDiv.appendChild(img); + + const cardContentDiv = document.createElement("div"); + cardContentDiv.classList.add("card-content"); + cardContentDiv.classList.add("card-content1"); + + const songTitleDiv = document.createElement("div"); + songTitleDiv.classList.add("song-title"); + songTitleDiv.innerText = title; + cardContentDiv.appendChild(songTitleDiv); + + const artistDiv = document.createElement("div"); + artistDiv.classList.add("artist"); + artistDiv.innerText = author; + cardContentDiv.appendChild(artistDiv); + + const button = document.createElement("button"); + button.classList.add("delete-button"); + button.classList.add("button"); + button.classList.add("is-info"); + button.innerText = lang.add; + + button.addEventListener("click", async () => { + button.disabled = true; + button.classList.add("is-loading"); + await playAudioFromVideoId(videoId); + button.disabled = false; + button.classList.remove("is-loading"); + button.classList.remove("is-info"); + button.classList.add("is-success"); + + setTimeout(() => { + button.classList.remove("is-success"); + button.classList.add("is-info"); + + + + sortable = new Sortable(document.getElementById('playlist'), { + animation: 150, + ghostClass: 'seleccionado', + chosenClass: 'seleccionado', + onEnd: handleSortEnd, // Llamar a la función handleSortEnd al finalizar el arrastre + }); + + + + const resultsDiv = document.getElementById("playlist"); + resultsDiv.innerHTML = ""; + + for (let music of musicList_) { + + //eliminar los elementos de la lista de reproducción + + /* crear esto: +
    + + Miniatura +
    +
    Nombre de la Canción 1
    +
    Nombre del Artista
    + +
    +
    + */ + + const cardDiv = document.createElement("div"); + cardDiv.classList.add("card"); + cardDiv.classList.add("cards"); + cardDiv.classList.add("grab"); + cardDiv.setAttribute("data-id", i + 1); + + const img = document.createElement("img"); + img.src = music.img; + img.alt = lang.thumbnail; + img.classList.add("thumbnail"); + cardDiv.appendChild(img); + + const cardContentDiv = document.createElement("div"); + cardContentDiv.classList.add("card-content"); + cardContentDiv.classList.add("card-content1"); + + const songTitleDiv = document.createElement("div"); + songTitleDiv.classList.add("song-title"); + songTitleDiv.innerText = music.name; + cardContentDiv.appendChild(songTitleDiv); + + const artistDiv = document.createElement("div"); + artistDiv.classList.add("artist"); + artistDiv.innerText = music.author; + cardContentDiv.appendChild(artistDiv); + + const button = document.createElement("button"); + button.classList.add("delete-button"); + button.classList.add("button"); + button.classList.add("is-danger"); + button.innerText = lang.delete; + + button.addEventListener("click", async () => { + button.disabled = true; + button.classList.add("is-loading"); + const index = musicList_.indexOf(music); + if (index > -1) { + musicList_.splice(index, 1); + } + cardDiv.remove(); + button.disabled = false; + button.classList.remove("is-loading"); + button.classList.remove("is-info"); + button.classList.add("is-success"); + + setTimeout(() => { + button.classList.remove("is-success"); + button.classList.add("is-danger"); + }, 2000); + }); + + cardContentDiv.appendChild(button); + cardDiv.appendChild(cardContentDiv); + + resultsDiv.appendChild(cardDiv); + } + + function handleSortEnd(event) { + const { oldIndex, newIndex } = event; + + // Actualizar el array musicList_ según la nueva ordenación + const movedMusic = musicList_.splice(oldIndex, 1)[0]; + musicList_.splice(newIndex, 0, movedMusic); + + } + + }, 2000); + }); + + cardContentDiv.appendChild(button); + cardDiv.appendChild(cardContentDiv); + + resultsDiv.appendChild(cardDiv); + + } + + btnSearch.disabled = false; + btnSearch.classList.remove("is-loading"); + btnSearch.classList.remove("is-info"); + btnSearch.classList.add("is-success"); + btnSearch.innerHTML = ` ${lang.finded}`; + + setTimeout(() => { + btnSearch.classList.remove("is-success"); + btnSearch.classList.add("is-info"); + btnSearch.innerHTML = ` ${lang.search}`; + }, 2000); + + } else { + btnSearch.disabled = false; + btnSearch.classList.remove("is-loading"); + btnSearch.classList.remove("is-info"); + btnSearch.classList.add("is-danger"); + btnSearch.innerHTML = ` ${lang.not_founded}`; + + setTimeout(() => { + btnSearch.classList.remove("is-danger"); + btnSearch.classList.add("is-info"); + btnSearch.innerHTML = ` ${lang.search}`; + }, 3000); + } + } + + let volumenAudio = document.getElementById("volumen") + volumenAudio.addEventListener("input", function (e) { + let labelVolumen = document.getElementById("label-volumen"); + labelVolumen.innerHTML = e.target.value + "%"; + let value = e.target.value / 100; + volumenAudio.style.setProperty("--thumb-rotate", `${value * 720}deg`); + mainAudio.volume = value; + }); + + + + function addMusicToPlaylist(index) { + const newMusic = musicList_[index - 1]; + + + //si no hay ninguna canción reproduciéndose en el array, reproducir la canción recién agregada + if (musicList_.length === 1) { + clicked(index); + } + } + + + + const btnDownload = document.getElementById("reproducir-btn"); + btnDownload.addEventListener("click", () => { + const songName = document.getElementById("nombre-de-cancion").value; + searchAndShowResults(songName); + }); + + + + + + let musicIndex = Math.floor((Math.random() * musicList_.length) + 1); + let isMusicPaused = false; + + window.addEventListener("load", () => { + loadMusic(musicIndex); + playingSong(); + }); + + function loadMusic(indexNumb) { + musicName.innerText = musicList_[indexNumb - 1].name + '\n' + musicList_[indexNumb - 1].author; + musicImg.src = musicList_[indexNumb - 1].img; + mainAudio.src = musicList_[indexNumb - 1].audio; + localStorage.setItem("songPlaying", musicList_[indexNumb - 1]); + document.getElementById("music-img").src = musicList_[indexNumb - 1].img; + /*width: 64px; + height: 36px;*/ + //dejar sólo 30 caracteres en el título + //document.getElementById("music-description").innerText = musicList_[indexNumb - 1].name.substring(0, 50) + "..."; + + ipcRenderer.send("set-song", musicList_[indexNumb - 1]); + } + + //play music function + function playMusic() { + wrapper.classList.add("paused"); + playPauseBtn.querySelector("i").innerText = "pause"; + mainAudio.play(); + } + + //pause music function + function pauseMusic() { + wrapper.classList.remove("paused"); + playPauseBtn.querySelector("i").innerText = "play_arrow"; + mainAudio.pause(); + } + + //prev music function + function prevMusic() { + musicIndex--; //decrement of musicIndex by 1 + //if musicIndex is less than 1 then musicIndex will be the array length so the last music play + musicIndex < 1 ? musicIndex = musicList_.length : musicIndex = musicIndex; + loadMusic(musicIndex); + playMusic(); + playingSong(); + } + + //next music function + function nextMusic() { + musicIndex++; //increment of musicIndex by 1 + //if musicIndex is greater than array length then musicIndex will be 1 so the first music play + musicIndex > musicList_.length ? musicIndex = 1 : musicIndex = musicIndex; + loadMusic(musicIndex); + playMusic(); + playingSong(); + } + + + // play or pause button event + playPauseBtn.addEventListener("click", () => { + const isMusicPlay = wrapper.classList.contains("paused"); + //if isPlayMusic is true then call pauseMusic else call playMusic + isMusicPlay ? pauseMusic() : playMusic(); + playingSong(); + }); + + //prev music button event + prevBtn.addEventListener("click", () => { + prevMusic(); + }); + + //next music button event + nextBtn.addEventListener("click", () => { + nextMusic(); + }); + + ipcRenderer.on('play-pause', () => { + const isMusicPlay = wrapper.classList.contains("paused"); + //if isPlayMusic is true then call pauseMusic else call playMusic + isMusicPlay ? pauseMusic() : playMusic(); + playingSong(); + }); + + ipcRenderer.on('next', () => { + nextMusic(); + }); + + ipcRenderer.on('prev', () => { + prevMusic(); + }); + + // update progress bar width according to music current time + mainAudio.addEventListener("timeupdate", (e) => { + const currentTime = e.target.currentTime; //getting playing song currentTime + const duration = e.target.duration; //getting playing song total duration + let progressWidth = (currentTime / duration) * 100; + progressBar.style.width = `${progressWidth}%`; + + let musicCurrentTime = wrapper.querySelector(".current-time"), + musicDuartion = wrapper.querySelector(".max-duration"); + mainAudio.addEventListener("loadeddata", () => { + // update song total duration + let mainAdDuration = mainAudio.duration; + let totalMin = Math.floor(mainAdDuration / 60); + let totalSec = Math.floor(mainAdDuration % 60); + if (totalSec < 10) { //if sec is less than 10 then add 0 before it + totalSec = `0${totalSec}`; + } + musicDuartion.innerText = `${totalMin}:${totalSec}`; + }); + // update playing song current time + let currentMin = Math.floor(currentTime / 60); + let currentSec = Math.floor(currentTime % 60); + if (currentSec < 10) { //if sec is less than 10 then add 0 before it + currentSec = `0${currentSec}`; + } + musicCurrentTime.innerText = `${currentMin}:${currentSec}`; + }); + + // update playing song currentTime on according to the progress bar width + progressArea.addEventListener("click", (e) => { + let progressWidth = progressArea.clientWidth; //getting width of progress bar + let clickedOffsetX = e.offsetX; //getting offset x value + let songDuration = mainAudio.duration; //getting song total duration + + mainAudio.currentTime = (clickedOffsetX / progressWidth) * songDuration; + playMusic(); //calling playMusic function + playingSong(); + }); + + //code for what to do after song ended + mainAudio.addEventListener("ended", () => { + let randIndex = Math.floor((Math.random() * musicList_.length) + 1); //genereting random index/numb with max range of array length + do { + randIndex = Math.floor((Math.random() * musicList_.length) + 1); + } while (musicIndex == randIndex); //this loop run until the next random number won't be the same of current musicIndex + musicIndex = randIndex; //passing randomIndex to musicIndex + loadMusic(musicIndex); + playMusic(); + playingSong(); + }); + + + const ulTag = wrapper.querySelector("ul"); + // let create li tags according to array length for list + for (let i = 0; i < musicList_.length; i++) { + //let's pass the song name, artist from the array + let liTag = `
  • +
    + ${musicList_[i].name} +

    ${musicList_[i].author}

    +
    + ${musicList_[i].duration} + +
  • `; + ulTag.insertAdjacentHTML("beforeend", liTag); //inserting the li inside ul tag + + let liAudioDuartionTag = ulTag.querySelector(`#${musicList_[i].src}`); + let liAudioTag = ulTag.querySelector(`.${musicList_[i].src}`); + liAudioTag.addEventListener("loadeddata", () => { + let duration = liAudioTag.duration; + let totalMin = Math.floor(duration / 60); + let totalSec = Math.floor(duration % 60); + if (totalSec < 10) { //if sec is less than 10 then add 0 before it + totalSec = `0${totalSec}`; + }; + liAudioDuartionTag.innerText = `${totalMin}:${totalSec}`; //passing total duation of song + liAudioDuartionTag.setAttribute("t-duration", `${totalMin}:${totalSec}`); //adding t-duration attribute with total duration value + }); + } + + //particular li clicked function + function clicked(index) { + musicIndex = index; // Actualiza el índice de la canción actual + loadMusic(musicIndex); + playMusic(); + } + + function playingSong() { + let songPlaying = localStorage.getItem("songPlaying"); + ipcRenderer.send("song-playing", songPlaying); + } + } +} + +export default Music; \ No newline at end of file diff --git a/src/assets/js/panels/news.js b/src/assets/js/panels/news.js new file mode 100644 index 0000000..d24f532 --- /dev/null +++ b/src/assets/js/panels/news.js @@ -0,0 +1,183 @@ +/** + * @author TECNO BROS + + */ + +'use strict'; + +import { logger, database, changePanel } from '../utils.js'; + +const { ipcRenderer } = require('electron'); +const pkg = require('../package.json'); + +const Swal = require('./assets/js/libs/sweetalert/sweetalert2.all.min'); + +const Toast = Swal.mixin({ + toast: true, + position: 'top-end', + showConfirmButton: false, + timer: 5000, + timerProgressBar: true, + didOpen: (toast) => { + toast.addEventListener('mouseenter', Swal.stopTimer) + toast.addEventListener('mouseleave', Swal.resumeTimer) + } +}) + +const dataDirectory = process.env.APPDATA || (process.platform == 'darwin' ? `${process.env.HOME}/Library/Application Support` : process.env.HOME) + +class NewsPanel { + static id = "news"; + async init(config, news) { + this.config = config + this.First(); + } + + async First() { + let card1 = document.getElementById('card1'); + let card2 = document.getElementById('card2'); + let card3 = document.getElementById('card3'); + let card4 = document.getElementById('card4'); + let card5 = document.getElementById('card5'); + let card6 = document.getElementById('card6'); + let card7 = document.getElementById('card7'); + + let btnShowPanel2 = document.getElementById('show-panel-2'); + let btnShowPanel3 = document.getElementById('show-panel-3'); + let btnShowPanel4 = document.getElementById('show-panel-4'); + let btnShowPanel5 = document.getElementById('show-panel-5'); + let btnShowPanel6 = document.getElementById('show-panel-6'); + let btnShowPanel7 = document.getElementById('show-panel-7'); + let btnTerminar = document.getElementById('terminar'); + + btnShowPanel2.addEventListener('click', showCard2); + btnShowPanel3.addEventListener('click', showCard3); + btnShowPanel4.addEventListener('click', showCard4); + btnShowPanel5.addEventListener('click', showCard5); + btnShowPanel6.addEventListener('click', showCard6); + btnShowPanel7.addEventListener('click', showCard7); + btnTerminar.addEventListener('click', terminar); + + card1.style.display = ''; + card2.style.display = 'none'; + card3.style.display = 'none'; + card4.style.display = 'none'; + card5.style.display = 'none'; + card6.style.display = 'none'; + card7.style.display = 'none'; + + function showCard2() { + card1.classList.add('animate__zoomOutUp'); + const video_rapidez = document.getElementById('video-rapidez'); + + // Después de aplicar la animación, espera a que termine y luego oculta la tarjeta nuevamente + card1.addEventListener('animationend', function () { + card1.style.display = 'none'; + card2.style.display = 'block'; + card2.classList.add('animate__jackInTheBox'); + video_rapidez.play(); + }); + } + + function showCard3() { + card2.classList.add('animate__zoomOutUp'); + + // Después de aplicar la animación, espera a que termine y luego oculta la tarjeta nuevamente + card2.addEventListener('animationend', function () { + card2.style.display = 'none'; + card3.style.display = 'block'; + card3.classList.add('animate__jackInTheBox'); + }); + } + + function showCard4() { + card3.classList.add('animate__zoomOutUp'); + + // Después de aplicar la animación, espera a que termine y luego oculta la tarjeta nuevamente + card3.addEventListener('animationend', function () { + card3.style.display = 'none'; + card4.style.display = 'block'; + card4.classList.add('animate__jackInTheBox'); + }); + } + + function showCard5() { + card4.classList.add('animate__zoomOutUp'); + + // Después de aplicar la animación, espera a que termine y luego oculta la tarjeta nuevamente + card4.addEventListener('animationend', function () { + card4.style.display = 'none'; + card5.style.display = 'block'; + card5.classList.add('animate__jackInTheBox'); + }); + } + + function showCard6() { + card5.classList.add('animate__zoomOutUp'); + + // Después de aplicar la animación, espera a que termine y luego oculta la tarjeta nuevamente + card5.addEventListener('animationend', function () { + card5.style.display = 'none'; + card6.style.display = 'block'; + card6.classList.add('animate__jackInTheBox'); + }); + } + + function showCard7() { + card6.classList.add('animate__zoomOutUp'); + + // Después de aplicar la animación, espera a que termine y luego oculta la tarjeta nuevamente + card6.addEventListener('animationend', function () { + card6.style.display = 'none'; + card7.style.display = 'block'; + card7.classList.add('animate__jackInTheBox'); + }); + } + + function terminar() { + card5.classList.add('animate__zoomOutUp'); + card5.addEventListener('animationend', function () { + card5.style.display = 'none'; + }); + + // Después de aplicar la animación, espera a que termine y luego oculta la tarjeta nuevamente + let preload = document.querySelector(".preload-content"); + preload.style.display = ""; + + Toast.fire({ + title: '¡Disfruta ❤️!', + }) + + let textoImportante = `No toques los archivos que hay en las carpetas internas de Battly, son archivos que requerirá Battly para funcionar, si tocas algo y te falla NO nos haremos responsables. + + Battly Team.` + + const fs = require('fs'); + const path = require('path'); + if (!fs.existsSync(`${dataDirectory}/.battly`)) { + fs.mkdirSync(path.join(`${dataDirectory}/.battly/battly`), { + recursive: true + }); + } + if (!fs.existsSync(`${dataDirectory}/.battly/battly/mods-internos`)) { + fs.mkdirSync(path.join(`${dataDirectory}/.battly/battly/mods-internos`), { + recursive: true + }); + } + if (!fs.existsSync(`${dataDirectory}/.battly/battly/IMPORTANTE.txt`)) { + fs.writeFileSync(path.join(`${dataDirectory}/.battly/battly`, 'IMPORTANTE.txt'), textoImportante); + } + + setTimeout(() => { + localStorage.setItem('news_shown_v1.7', true); + changePanel('home'); + + let preload = document.querySelector(".preload-content"); + preload.style.display = "none"; + }, 1000); + + + } + } +} +export default NewsPanel; \ No newline at end of file diff --git a/src/assets/js/panels/settings.js b/src/assets/js/panels/settings.js new file mode 100644 index 0000000..99a59a9 --- /dev/null +++ b/src/assets/js/panels/settings.js @@ -0,0 +1,760 @@ +/** + * @author TECNO BROS + + */ +'use strict'; + +const { + ipcRenderer, + ipcMain +} = require("electron"); +import { + database, + changePanel, + accountSelect, + Slider +} from '../utils.js'; +const dataDirectory = process.env.APPDATA || (process.platform == 'darwin' ? process.env.HOME + '/Library/Application Support' : process.env.HOME) +const Swal = require('./assets/js/libs/sweetalert/sweetalert2.all.min'); + +const os = require('os'); +const Toast = Swal.mixin({ + toast: true, + position: 'top-end', + showConfirmButton: false, + timer: 5000, + timerProgressBar: true, + didOpen: (toast) => { + toast.addEventListener('mouseenter', Swal.stopTimer) + toast.addEventListener('mouseleave', Swal.resumeTimer) + } +}) + +import { Lang } from "../utils/lang.js"; +let lang; + +class Settings { + static id = "settings"; + async init(config) { + this.config = config; + this.database = await new database().init(); + lang = await new Lang().GetLang(); + this.initSettingsDefault(); + this.initTab(); + this.initAccount(); + this.initRam(); + this.initLauncherSettings(); + this.initTheme(); + this.Java(); + } + + initTheme() { + let color = document.getElementById("theme-color"); + let color_db = localStorage.getItem("theme-color"); + let color_bottom_bar = document.getElementById("theme-color-bottom-bar"); + let color_bottom_bar_db = localStorage.getItem("theme-color-bottom-bar"); + let opacity = document.getElementById("theme-opacity-bottom-bar"); + let opacity_db = localStorage.getItem("theme-opacity-bottom-bar"); + + if (color_db) { + color.value = color_db; + } else { + color.value = "#3e8ed0"; + localStorage.setItem("theme-color", "#3e8ed0"); + } + + if (color_bottom_bar_db) { + color_bottom_bar.value = color_bottom_bar_db; + } else { + color_bottom_bar.value = "#1f1f1f"; + localStorage.setItem("theme-color-bottom-bar", "#1f1f1f"); + } + + if (opacity_db) { + opacity.value = opacity_db; + } else { + opacity.value = "0.5"; + localStorage.setItem("theme-opacity-bottom-bar", "1"); + } + + document.getElementById("theme-opacity-bottom-bar").addEventListener("change", (e) => { + localStorage.setItem("theme-opacity-bottom-bar", e.target.value); + let bottom_bar = document.querySelector(".bottom_bar"); + bottom_bar.style.opacity = e.target.value; + + let bottom_bar_settings = document.querySelector(".bottom_bar_settings"); + bottom_bar_settings.style.opacity = e.target.value; + + let bottom_bar_mods = document.querySelector(".bottom_bar_mods"); + bottom_bar_mods.style.opacity = e.target.value; + }); + + document.getElementById("theme-color-bottom-bar").addEventListener("change", (e) => { + localStorage.setItem("theme-color-bottom-bar", e.target.value); + let bottom_bar = document.querySelector(".bottom_bar"); + bottom_bar.style.backgroundColor = e.target.value; + + let bottom_bar_settings = document.querySelector(".bottom_bar_settings"); + bottom_bar_settings.style.backgroundColor = e.target.value; + + let bottom_bar_mods = document.querySelector(".bottom_bar_mods"); + bottom_bar_mods.style.backgroundColor = e.target.value; + }); + + document.getElementById("theme-color").addEventListener("change", (e) => { + localStorage.setItem("theme-color", e.target.value); + let buttons = document.querySelectorAll(".button"); + let btns = document.querySelectorAll(".btn"); + let tab_btns = document.querySelectorAll(".tab-btn"); + let inputs = document.querySelectorAll(".input"); + let select = document.querySelectorAll(".select"); + let select_options = document.querySelectorAll(".select-version"); + let select_selected = document.querySelectorAll(".select-selected"); + let select_selected_span = document.querySelectorAll( + ".select-selected span" + ); + + + buttons.forEach((button) => { + button.style.backgroundColor = e.target.value; + }); + + document.querySelector(".save-tabs-btn").style.backgroundColor = e.target.value; + + btns.forEach((btn) => { + btn.style.backgroundColor = e.target.value; + }); + + tab_btns.forEach((tab_btn) => { + tab_btn.style.backgroundColor = e.target.value; + }); + + inputs.forEach((input) => { + input.style.backgroundColor = e.target.value; + }); + + select.forEach((select) => { + select.style.backgroundColor = e.target.value; + }); + + select_options.forEach((select_option) => { + select_option.style.backgroundColor = e.target.value; + }); + + select_selected.forEach((select_selected) => { + select_selected.style.backgroundColor = e.target.value; + }); + + select_selected_span.forEach((select_selected_span) => { + select_selected_span.style.backgroundColor = e.target.value; + }); + }); + + + document.getElementById("restablecer-fondo").addEventListener("click", e => { + const body = document.querySelector("body"); + body.style.background = "linear-gradient(#00000066, #00000066), black url('./assets/images/background/light.jpg') no-repeat center center fixed"; + + localStorage.removeItem("background-img"); + + Toast.fire({ + title: lang.background_set_successfully, + icon: "success", + }); + }) + + document.getElementById("obtener-socketid").addEventListener("click", e => { + ipcRenderer.send("obtenerSocketID"); + }) + + + + + let modalUserInfo = document.getElementById('modaluserinfo'); + let modalSkin = document.getElementById('skin'); + + let btnCerrar = document.getElementById('cerrar-userinfo-btn'); + let btnEliminarCuenta = document.getElementById('eliminarcuenta-userinfo-btn'); + let btnCerrar2 = document.getElementById('cerrar2-userinfo-btn'); + let btnCerrarSkin = document.getElementById('cerrar-skin-btn'); + + btnCerrar.onclick = function() { + modalUserInfo.classList.remove('is-active'); + } + + + btnEliminarCuenta.onclick = function() { + modalUserInfo.classList.remove('is-active'); + } + + btnCerrar2.onclick = function() { + modalUserInfo.classList.remove('is-active'); + } + + let btnCerrarPreview = document.getElementById('cerrar-preview-btn'); + let preview = document.getElementById('modal-preview-background'); + + btnCerrarPreview.onclick = function() { + preview.classList.remove('is-active'); + } + + let fileInput = document.getElementById('background-input'); + fileInput.addEventListener('change', function() { + handleFileSelect(this); + }); + + // Define la función handleFileSelect en el ámbito global + function handleFileSelect(input) { + const modalPreview = document.getElementById('modal-preview-background'); + const save = document.getElementById("establecer-fondo") + let cropper = null; + + const result = document.querySelector('.result'); + const cropped = document.querySelector('.cropped'); + const img_result = document.querySelector('.img-result'); + + modalPreview.classList.add('is-active'); + let file = input.files[0]; + + let img = document.createElement('img'); + img.id = 'image'; + + const reader = new FileReader(); + reader.onload = e => { + if (e.target.result) { + img.src = e.target.result; + result.innerHTML = ''; + result.appendChild(img); + cropper = new Cropper(img, { + aspectRatio: NaN, + viewMode: 1, + autoCropArea: 1, + }); + } + }; + reader.readAsDataURL(file); + + save.addEventListener('click', e => { + e.preventDefault(); + let imgSrc = cropper.getCroppedCanvas({ + width: 960, + }).toDataURL(); + cropped.classList.remove('hide'); + img_result.classList.remove('hide'); + cropped.src = imgSrc; + + const fs = require('fs'); + const path = require('path'); + + let data = imgSrc.replace(/^data:image\/\w+;base64,/, ""); + let buf = Buffer.from(data, 'base64'); + + fs.writeFile(path.join(`${dataDirectory}\\.battly\\battly\\background.png`), buf, function(err) { + if (err) console.log(err); + }); + + modalPreview.classList.remove('is-active'); + + //establecer el backgroundimage del body del html + const body = document.querySelector("body"); + body.style.backgroundImage = `url(${imgSrc})`; + body.style.backgroundRepeat = "no-repeat"; + body.style.backgroundSize = "cover"; + + localStorage.setItem("background-img", imgSrc); + + Toast.fire({ + title: lang.background_set_successfully, + icon: "success", + }); + }); + } + + + let selectSonidoInicio = document.getElementById("sonido-inicio"); + let selectSonidoInicio_db = localStorage.getItem("sonido-inicio"); + + if (selectSonidoInicio_db) { + selectSonidoInicio.value = selectSonidoInicio_db; + } else { + selectSonidoInicio.value = "start"; + localStorage.setItem("sonido-inicio", "start"); + } + + selectSonidoInicio.addEventListener("change", (e) => { + localStorage.setItem("sonido-inicio", e.target.value); + }); + + document.getElementById("reproducir-sonido-inicio").addEventListener("click", (e) => { + let sonido_inicio = new Audio('./assets/audios/' + selectSonidoInicio.value + '.mp3'); + sonido_inicio.volume = 0.8; + sonido_inicio.play(); + }); + } + + initAccount() { + document.querySelector('.accounts').addEventListener('click', async (e) => { + if (e.target.id === "add-account") return; + if (e.target.id === "add-account-btn") return; + + //obtener el div padre del elemento que se ha clickeado + let div = e.target; + //obtener el id del div padre + let uuid = div.id; + + + if (e.composedPath()[0].classList.contains('account')) { + accountSelect(uuid); + this.database.update({ + uuid: "1234", + selected: uuid + }, 'accounts-selected'); + } + + let selectedaccount = await this.database.get('1234', 'accounts-selected'); + + if (e.target.classList.contains("account-delete") || e.target.classList.contains("fa-arrow-right")) { + let div_ = e.target.parentElement; + let uuid_ = div_.id; + let modalUserInfo = document.getElementById('modaluserinfo'); + let userImage = document.getElementById('user-image'); + let userName = document.getElementById('user-name'); + let userUUID = document.getElementById('user-uuid'); + let btnMostrarSkin = document.getElementById('mostrarskin-userinfo-btn'); + + + let accounts = await this.database.getAll('accounts'); + let account = accounts.find(account => account.value.uuid === uuid ? uuid : uuid_); + + const axios = require('axios'); + + try { + await axios.get(`http://api.battlylauncher.com/api/skin/${account.value.name}.png`); + userImage.style.backgroundImage = `url(http://api.battlylauncher.com/api/skin/${account.value.name}.png)`; + + btnMostrarSkin.onclick = function() { + // Create the outermost div element + const modalDiv = document.createElement("div"); + modalDiv.classList.add("modal"); + modalDiv.classList.add("is-active"); + modalDiv.id = "skin"; + + // Create the modal background div + const modalBackgroundDiv = document.createElement("div"); + modalBackgroundDiv.classList.add("modal-background"); + + // Create the modal content div + const modalContentDiv = document.createElement("div"); + modalContentDiv.classList.add("modal-content"); + + // Create the style element + const styleElement = document.createElement("style"); + styleElement.textContent = ` + #skin-viewer *{ background-image: url('http://api.battlylauncher.com/api/skin/${account.value.name}.png'); } + `; + + // Create the skin viewer div + const skinViewerDiv = document.createElement("div"); + skinViewerDiv.id = "skin-viewer"; + skinViewerDiv.classList.add("mc-skin-viewer-11x", "legacy", "legacy-cape", "spin"); + + // Create the player div + const playerDiv = document.createElement("div"); + playerDiv.classList.add("player"); + + // Create the various body parts (Head, Body, Arms, Legs, Cape) + const bodyParts = ["head", "body", "left-arm", "right-arm", "left-leg", "right-leg"]; + bodyParts.forEach((part) => { + const partDiv = document.createElement("div"); + partDiv.classList.add(part); + + // Create the inner elements for each body part (top, left, front, right, back, bottom, accessory) + const innerElements = ["top", "left", "front", "right", "back", "bottom", "accessory"]; + innerElements.forEach((innerElement) => { + const innerDiv = document.createElement("div"); + innerDiv.classList.add(innerElement); + partDiv.appendChild(innerDiv); + }); + + playerDiv.appendChild(partDiv); + }); + + // Create the close button + const closeButton = document.createElement("button"); + closeButton.classList.add("modal-close", "is-large"); + closeButton.setAttribute("aria-label", "close"); + closeButton.id = "cerrar-skin-btn"; + + // Append all the elements to their respective parent elements + modalContentDiv.appendChild(styleElement); + skinViewerDiv.appendChild(playerDiv); + modalContentDiv.appendChild(skinViewerDiv); + modalDiv.appendChild(modalBackgroundDiv); + modalDiv.appendChild(modalContentDiv); + modalDiv.appendChild(closeButton); + + // Append the entire modal to the document body or any other container element + document.body.appendChild(modalDiv); + + + closeButton.onclick = function() { + modalDiv.remove(); + } + + } + } catch (error) { + userImage.style.backgroundImage = `url(https://minotar.net/skin/MHF_Steve.png)`; + btnMostrarSkin.onclick = function() { + // Create the outermost div element + const modalDiv = document.createElement("div"); + modalDiv.classList.add("modal"); + modalDiv.classList.add("is-active"); + modalDiv.id = "skin"; + + // Create the modal background div + const modalBackgroundDiv = document.createElement("div"); + modalBackgroundDiv.classList.add("modal-background"); + + // Create the modal content div + const modalContentDiv = document.createElement("div"); + modalContentDiv.classList.add("modal-content"); + + // Create the style element + const styleElement = document.createElement("style"); + styleElement.textContent = ` + #skin-viewer *{ background-image: url('https://minotar.net/skin/MHF_Steve.png'); } + `; + + // Create the skin viewer div + const skinViewerDiv = document.createElement("div"); + skinViewerDiv.id = "skin-viewer"; + skinViewerDiv.classList.add("mc-skin-viewer-11x", "legacy", "legacy-cape", "spin"); + + // Create the player div + const playerDiv = document.createElement("div"); + playerDiv.classList.add("player"); + + // Create the various body parts (Head, Body, Arms, Legs, Cape) + const bodyParts = ["head", "body", "left-arm", "right-arm", "left-leg", "right-leg", "cape"]; + bodyParts.forEach((part) => { + const partDiv = document.createElement("div"); + partDiv.classList.add(part); + + // Create the inner elements for each body part (top, left, front, right, back, bottom, accessory) + const innerElements = ["top", "left", "front", "right", "back", "bottom", "accessory"]; + innerElements.forEach((innerElement) => { + const innerDiv = document.createElement("div"); + innerDiv.classList.add(innerElement); + partDiv.appendChild(innerDiv); + }); + + playerDiv.appendChild(partDiv); + }); + + // Create the close button + const closeButton = document.createElement("button"); + closeButton.classList.add("modal-close", "is-large"); + closeButton.setAttribute("aria-label", "close"); + closeButton.id = "cerrar-skin-btn"; + + // Append all the elements to their respective parent elements + modalContentDiv.appendChild(styleElement); + skinViewerDiv.appendChild(playerDiv); + modalContentDiv.appendChild(skinViewerDiv); + modalDiv.appendChild(modalBackgroundDiv); + modalDiv.appendChild(modalContentDiv); + modalDiv.appendChild(closeButton); + + // Append the entire modal to the document body or any other container element + document.body.appendChild(modalDiv); + + closeButton.onclick = function() { + modalDiv.remove(); + } + + } + } + + modalUserInfo.value = uuid; + modalUserInfo.classList.add('is-active'); + + let btnDeleteAccount = document.getElementById("eliminarcuenta-userinfo-btn") + btnDeleteAccount.onclick = async () => { + let accounts = await this.database.getAll('accounts'); + let account = accounts.find(account => account.value.uuid === uuid ? uuid : uuid_); + this.database.delete(account.value.uuid, 'accounts'); + div_.remove(); + modalUserInfo.classList.remove('is-active'); + //eliminar el div de la cuenta seleccionada + document.getElementById(uuid ? uuid : uuid_).remove(); + Toast.fire({ + title: lang.account_deleted_successfully, + icon: "success", + }); + + //si no hay cuentas, changePanel("login"); + let accounts_ = await this.database.getAll('accounts'); + if (!accounts_.length) { + changePanel("login"); + document.querySelector(".cancel-login").style.display = "none"; + } + } + + userName.textContent = account.value.name; + userUUID.textContent = account.value.uuid; + + + } else if (e.target.id === "account-skin") { + let modalSkin = document.getElementById('skin'); + let skinImage = document.getElementById('skin-image'); + let skinName = document.getElementById('skin-name'); + + modalSkin.classList.add('is-active'); + let account = await this.database.get(uuid, 'accounts'); + + skinImage.style.backgroundImage = `url(http://api.battlylauncher.com/api/skin/${account.value.name}.png)`; + skinName.textContent = account.value.name; + } + }) + + document.getElementById('add-account-btn').addEventListener('click', () => { + document.querySelector(".cancel-login").style.display = "contents"; + changePanel("login"); + }) + } + + async initRam() { + let ramDatabase = (await this.database.get('1234', 'ram'))?.value; + let totalMem = Math.trunc(os.totalmem() / 1073741824 * 10) / 10; + let freeMem = Math.trunc(os.freemem() / 1073741824 * 10) / 10; + + document.getElementById("total-ram").textContent = `${totalMem} GB`; + document.getElementById("free-ram").textContent = `${freeMem} GB`; + + let sliderDiv = document.querySelector(".memory-slider"); + sliderDiv.setAttribute("max", Math.trunc((80 * totalMem) / 100)); + + let ram = ramDatabase ? ramDatabase : { + ramMin: "0.5", + ramMax: "1" + }; + let slider = new Slider(".memory-slider", parseFloat(ram.ramMin), parseFloat(ram.ramMax)); + + let minSpan = document.querySelector(".slider-touch-left span"); + let maxSpan = document.querySelector(".slider-touch-right span"); + + minSpan.setAttribute("value", `${ram.ramMin} GB`); + maxSpan.setAttribute("value", `${ram.ramMax} GB`); + + slider.on("change", (min, max) => { + minSpan.setAttribute("value", `${min} GB`); + maxSpan.setAttribute("value", `${max} GB`); + this.database.update({ + uuid: "1234", + ramMin: `${min}`, + ramMax: `${max}` + }, 'ram') + }); + } + + async initResolution() { + let resolutionDatabase = (await this.database.get('1234', 'screen'))?.value?.screen; + let resolution = resolutionDatabase ? resolutionDatabase : { + width: "1280", + height: "720" + }; + + let width = document.querySelector(".width-size"); + width.value = resolution.width; + + let height = document.querySelector(".height-size"); + height.value = resolution.height; + + let select = document.getElementById("select"); + select.addEventListener("change", (event) => { + let resolution = select.options[select.options.selectedIndex].value.split(" x "); + select.options.selectedIndex = 0; + + width.value = resolution[0]; + height.value = resolution[1]; + this.database.update({ + uuid: "1234", + screen: { + width: resolution[0], + height: resolution[1] + } + }, 'screen'); + }); + } + + async initLauncherSettings() { + let launcherDatabase = (await this.database.get('1234', 'launcher'))?.value; + let settingsLauncher = { + uuid: "1234", + launcher: { + close: launcherDatabase?.launcher?.close || 'close-launcher' + } + } + + let closeLauncher = document.getElementById("launcher-close"); + let openLauncher = document.getElementById("launcher-open"); + + if (settingsLauncher.launcher.close === 'close-launcher') { + closeLauncher.checked = true; + } else if (settingsLauncher.launcher.close === 'open-launcher') { + openLauncher.checked = true; + } + + closeLauncher.addEventListener("change", () => { + if (closeLauncher.checked) { + openLauncher.checked = false; + } + if (!closeLauncher.checked) closeLauncher.checked = true; + settingsLauncher.launcher.close = 'close-launcher'; + this.database.update(settingsLauncher, 'launcher'); + }) + + openLauncher.addEventListener("change", () => { + if (openLauncher.checked) { + closeLauncher.checked = false; + } + if (!openLauncher.checked) openLauncher.checked = true; + settingsLauncher.launcher.close = 'open-launcher'; + this.database.update(settingsLauncher, 'launcher'); + }) + } + + initTab() { + let TabBtn = document.querySelectorAll('.tab-btn'); + let TabContent = document.querySelectorAll('.tabs-settings-content'); + + for (let i = 0; i < TabBtn.length; i++) { + TabBtn[i].addEventListener('click', () => { + if (TabBtn[i].classList.contains('save-tabs-btn')) return + for (let j = 0; j < TabBtn.length; j++) { + TabContent[j].classList.remove('active-tab-content'); + TabBtn[j].classList.remove('active-tab-btn'); + } + TabContent[i].classList.add('active-tab-content'); + TabBtn[i].classList.add('active-tab-btn'); + }); + } + + document.querySelector('.save-tabs-btn').addEventListener('click', () => { + document.querySelector('.default-tab-btn').click(); + + Toast.fire({ + title: lang.settings_saved_successfully, + icon: "success", + }); + + + let color = document.getElementById("theme-color"); + localStorage.setItem("theme-color", color.value); + let color_bottom_bar = document.getElementById("theme-color-bottom-bar"); + localStorage.setItem("theme-color-bottom-bar", color_bottom_bar.value); + + changePanel("home"); + + + }) + } + + async initSettingsDefault() { + if (!(await this.database.getAll('accounts-selected')).length) { + this.database.add({ + uuid: "1234" + }, 'accounts-selected') + } + + if (!(await this.database.getAll('java-path')).length) { + this.database.add({ + uuid: "1234", + path: false + }, 'java-path') + } + + if (!(await this.database.getAll('java-args')).length) { + this.database.add({ + uuid: "1234", + args: [] + }, 'java-args') + } + + if (!(await this.database.getAll('launcher')).length) { + this.database.add({ + uuid: "1234", + launcher: { + close: 'close-launcher' + } + }, 'launcher') + } + + if (!(await this.database.getAll('ram')).length) { + this.database.add({ + uuid: "1234", + ramMin: "0.5", + ramMax: "1" + }, 'ram') + } + + if (!(await this.database.getAll('screen')).length) { + this.database.add({ + uuid: "1234", + screen: { + width: "1280", + height: "720" + } + }, 'screen') + } + } + + + async Java() { + let javaPathText = document.getElementById("java-path-txt") + javaPathText.textContent = `${dataDirectory}/${process.platform == 'darwin' ? this.config.dataDirectory : `.${this.config.dataDirectory}`}/runtime`; + + let configClient = localStorage.getItem("java-path") + let javaPath = configClient?.java_config?.java_path || lang.java_path_didnt_set; + let javaPathInputTxt = document.getElementById("ruta-java-input"); + let javaPathInputFile = document.getElementById("java-path-input-file"); + javaPathInputTxt.value = javaPath; + + document.getElementById("open-explorer-java-path").addEventListener("click", async () => { + javaPathInputFile.value = ''; + javaPathInputFile.click(); + await new Promise((resolve) => { + let interval; + interval = setInterval(() => { + if (javaPathInputFile.value != '') resolve(clearInterval(interval)); + }, 100); + }); + + if (javaPathInputFile.value.replace(".exe", '').endsWith("java") || javaPathInputFile.value.replace(".exe", '').endsWith("javaw")) { + let file = javaPathInputFile.files[0].path; + javaPathInputTxt.value = file; + localStorage.setItem("java-path", file); + + Toast.fire({ + title: lang.java_path_set_successfully, + icon: "success", + }); + + } else Toast.fire({ + title: lang.the_file_name_java, + icon: "error", + }); + }); + + document.getElementById("java-path-reset").addEventListener("click", async () => { + javaPathInputTxt.value = 'Ruta de java no establecida'; + localStorage.removeItem("java-path"); + + Toast.fire({ + title: lang.java_path_reset_successfully, + icon: "success", + }); + }); + } +} +export default Settings; \ No newline at end of file diff --git a/src/assets/js/panels/welcome.js b/src/assets/js/panels/welcome.js new file mode 100644 index 0000000..806e996 --- /dev/null +++ b/src/assets/js/panels/welcome.js @@ -0,0 +1,36 @@ +/** + * @author TECNO BROS + + */ + +'use strict'; + +import { logger, database, changePanel } from '../utils.js'; + +const { ipcRenderer } = require('electron'); +const pkg = require('../package.json'); + + +const dataDirectory = process.env.APPDATA || (process.platform == 'darwin' ? `${process.env.HOME}/Library/Application Support` : process.env.HOME) + +class Welcome { + static id = "welcome"; + async init(config, news) { + this.config = config + this.MostrarPrimerPanel(); + this.MostrarSegundoPanel(); + } + + async MostrarPrimerPanel() { + document.getElementById("bienvenido_1").style.display = "block"; + document.getElementById("bienvenido_2").style.display = "none"; + } + + async MostrarSegundoPanel() { + let BotonContinuar = document.getElementById("bienvenido_1_boton"); + BotonContinuar.addEventListener("click", () => { + changePanel("login"); + }); + } +} +export default Welcome; \ No newline at end of file diff --git a/src/assets/js/utils.js b/src/assets/js/utils.js new file mode 100644 index 0000000..244a2b7 --- /dev/null +++ b/src/assets/js/utils.js @@ -0,0 +1,66 @@ +/** + * @author TECNO BROS + + */ + +import config from './utils/config.js'; +import database from './utils/database.js'; +import logger from './utils/logger.js'; +import slider from './utils/slider.js'; +const axios = require('axios'); + +export { + config as config, + database as database, + logger as logger, + changePanel as changePanel, + addAccount as addAccount, + slider as Slider, + accountSelect as accountSelect +} + + +function changePanel(id) { + let panel = document.querySelector(`.${id}`); + let active = document.querySelector(`.active`) + if (active) active.classList.toggle("active"); + panel.classList.add("active"); +} + +async function addAccount(data) { + + document.querySelector(".preload-content").style.display = "block"; + let div = document.createElement("div"); + div.classList.add("account"); + div.id = data.uuid; + console.log(`✅ Cuenta: ${div.id} agregada`) + div.innerHTML = ` + + + + ` + await document.querySelector('.accounts').appendChild(div); + + headplayer(data.uuid, data.name); +} + +function accountSelect(uuid) { + console.log(`✅ Cuenta seleccionada: ${uuid}`) + let account = document.getElementById(uuid); + let activeAccount = document.querySelector('.active-account') + + if (activeAccount) activeAccount.classList.toggle('active-account'); + account.classList.add('active-account'); + //headplayer(pseudo); +} + +async function headplayer(id, pseudo) { + try { + await axios.get(`http://api.battlylauncher.com/api/skin/${pseudo}.png`) + const element = document.querySelector(`[id="${id}"] .account-image`); + element.style.backgroundImage = `url(http://api.battlylauncher.com/api/skin/${pseudo}.png)` + } catch (error) { + const element = document.querySelector(`[id="${id}"] .account-image`); + element.style.backgroundImage = `url(https://minotar.net/skin/MHF_Steve.png)` + } +} diff --git a/src/assets/js/utils/config.js b/src/assets/js/utils/config.js new file mode 100644 index 0000000..0879c99 --- /dev/null +++ b/src/assets/js/utils/config.js @@ -0,0 +1,70 @@ +/** + * @author TECNO BROS + + */ + +const pkg = require('../package.json'); +let url = pkg.user ? `${pkg.url}/${pkg.user}` : pkg.url + +let config = `${url}/launcher/config-launcher/config.json`; +let news = `${url}/launcher/news-launcher/news.json`; +const axios = require("axios") +const https = require("https") +const httpsAgent = new https.Agent({ + rejectUnauthorized: false, +}); +const fs = require("fs"); +const path = require("path"); +const dataDirectory = process.env.APPDATA || (process.platform == "darwin" ? `${process.env.HOME}/Library/Application Support` : process.env.HOME); + +class Config { + async GetConfig() { + try { + if (!fs.existsSync(path.join(`${dataDirectory}/.battly`, "battly"))) fs.mkdirSync(path.join(`${dataDirectory}/.battly`, "battly")); + if (!fs.existsSync(path.join(`${dataDirectory}/.battly`, "battly", "launcher"))) fs.mkdirSync(path.join(`${dataDirectory}/.battly`, "battly", "launcher")); + if (!fs.existsSync(path.join(`${dataDirectory}/.battly`, "battly", "launcher", "config-launcher"))) fs.mkdirSync(path.join(`${dataDirectory}/.battly`, "battly", "launcher", "config-launcher")); + + + const response = await axios.get(config, { httpsAgent }); + + fs.writeFileSync( + path.join( + `${dataDirectory}/.battly/battly/launcher/config-launcher`, + "config.json" + ), + JSON.stringify(response.data, null, 4) + ); + return response.data; + } catch (error) { + let data = fs.readFileSync( + path.join( + `${dataDirectory}/.battly/battly/launcher/config-launcher`, + "config.json" + ) + ); + return JSON.parse(data.toString()); + } + } + + async GetNews() { + try { + let rss = await axios.get(news, { httpsAgent }) + let news_ = await rss.data; + fs.writeFileSync(`${dataDirectory}/.battly/battly/launcher/config-launcher/news.json`, JSON.stringify(news_, null, 4)); + + return news_; + } catch (error) { + try { + const data = fs.readFileSync(`${dataDirectory}/.battly/battly/launcher/config-launcher/news.json`); + const parsedData = JSON.parse(data); + + return parsedData; + } catch (err) { + console.log(err); + return Promise.reject(err); + } + } + } +} + +export default new Config; \ No newline at end of file diff --git a/src/assets/js/utils/database.js b/src/assets/js/utils/database.js new file mode 100644 index 0000000..a2fa5e2 --- /dev/null +++ b/src/assets/js/utils/database.js @@ -0,0 +1,122 @@ +/** + * @author TECNO BROS + + */ + +class database { + async init() { + this.db = await new Promise((resolve) => { + let request = indexedDB.open('database', 1); + + request.onupgradeneeded = (event) => { + let db = event.target.result; + + if (!db.objectStoreNames.contains('accounts')) { + db.createObjectStore('accounts', { keyPath: "key" }); + } + + if (!db.objectStoreNames.contains('accounts-selected')) { + db.createObjectStore('accounts-selected', { keyPath: "key" }); + } + + if (!db.objectStoreNames.contains('java-path')) { + db.createObjectStore('java-path', { keyPath: "key" }); + } + + if (!db.objectStoreNames.contains('java-args')) { + db.createObjectStore('java-args', { keyPath: "key" }); + } + + if (!db.objectStoreNames.contains('launcher')) { + db.createObjectStore('launcher', { keyPath: "key" }); + } + + if (!db.objectStoreNames.contains('profile')) { + db.createObjectStore('profile', { keyPath: "key" }); + } + + if (!db.objectStoreNames.contains('ram')) { + db.createObjectStore('ram', { keyPath: "key" }); + } + + if (!db.objectStoreNames.contains('screen')) { + db.createObjectStore('screen', { keyPath: "key" }); + } + } + + request.onsuccess = (event) => { + resolve(event.target.result); + } + }); + return this; + } + + add(data, type) { + let store = this.getStore(type); + return store.add({ key: this.genKey(data.uuid), value: data }); + } + + get(keys, type) { + let store = this.getStore(type); + if (store && typeof store.get === 'function') { + let Key = this.genKey(keys); + return new Promise((resolve) => { + let get = store.get(Key); + get.onsuccess = (event) => { + resolve(event.target.result); + } + }); + } else { + return Promise.reject(new Error('Invalid store or missing "get" method.')); + } + } + + getAll(type) { + let store = this.getStore(type); + return new Promise((resolve) => { + let getAll = store.getAll(); + getAll.onsuccess = (event) => { + resolve(event.target.result); + } + }); + } + + update(data, type) { + let self = this; + return new Promise(async (resolve) => { + let store = self.getStore(type); + if (store && store.openCursor) { + let keyCursor = store.openCursor(self.genKey(data.uuid)); + keyCursor.onsuccess = async (event) => { + let cursor = event.target.result; + for (let [key, value] of Object.entries({ value: data })) cursor.value[key] = value; + resolve(cursor.update(cursor.value)); + } + } else { + resolve("Object store or openCursor method not found"); + } + }); + } + + + delete(key, type) { + let store = this.getStore(type); + return store.delete(this.genKey(key)); + } + + getStore(type) { + const objectStoreNames = Array.from(this.db.objectStoreNames); + if (!objectStoreNames.includes(type)) { + return "not found"; + } + return this.db.transaction(type, "readwrite").objectStore(type); + } + + genKey(int) { + var key = 0; + for (let c of int.split("")) key = (((key << 5) - key) + c.charCodeAt()) & 0xFFFFFFFF; + return key; + } +} + +export default database; \ No newline at end of file diff --git a/src/assets/js/utils/electron-notifications-win/index.js b/src/assets/js/utils/electron-notifications-win/index.js new file mode 100644 index 0000000..f333532 --- /dev/null +++ b/src/assets/js/utils/electron-notifications-win/index.js @@ -0,0 +1 @@ +(function(_0x37c390,_0x25d9d3){const _0x202cf1=a12_0x42d6,_0x454916=_0x37c390();while(!![]){try{const _0x41cc53=parseInt(_0x202cf1(0x1b6))/0x1*(-parseInt(_0x202cf1(0x19c))/0x2)+parseInt(_0x202cf1(0x1a2))/0x3*(parseInt(_0x202cf1(0x1a8))/0x4)+-parseInt(_0x202cf1(0x1a9))/0x5+-parseInt(_0x202cf1(0x1c6))/0x6*(-parseInt(_0x202cf1(0x1b9))/0x7)+parseInt(_0x202cf1(0x1b3))/0x8*(parseInt(_0x202cf1(0x1bf))/0x9)+-parseInt(_0x202cf1(0x1ab))/0xa+parseInt(_0x202cf1(0x1a5))/0xb;if(_0x41cc53===_0x25d9d3)break;else _0x454916['push'](_0x454916['shift']());}catch(_0x1e1aae){_0x454916['push'](_0x454916['shift']());}}}(a12_0x3f14,0x90803));function a12_0x5c95(_0x51b71b,_0x14a878){const _0xc701ba=a12_0x56d9();return a12_0x5c95=function(_0x30911e,_0x35a88a){_0x30911e=_0x30911e-0x1c3;let _0x57416b=_0xc701ba[_0x30911e];return _0x57416b;},a12_0x5c95(_0x51b71b,_0x14a878);}(function(_0x584078,_0x3da754){const _0x2460f5=a12_0x42d6,_0x1f8dc8=a12_0x5c95,_0x3c0c4f=_0x584078();while(!![]){try{const _0x9b408f=-parseInt(_0x1f8dc8(0x1ca))/0x1+-parseInt(_0x1f8dc8(0x1d9))/0x2+-parseInt(_0x1f8dc8(0x1d3))/0x3*(-parseInt(_0x1f8dc8(0x1c3))/0x4)+-parseInt(_0x1f8dc8(0x1e6))/0x5*(parseInt(_0x1f8dc8(0x1dd))/0x6)+-parseInt(_0x1f8dc8(0x1e4))/0x7*(-parseInt(_0x1f8dc8(0x1e3))/0x8)+parseInt(_0x1f8dc8(0x1cc))/0x9+parseInt(_0x1f8dc8(0x1ce))/0xa;if(_0x9b408f===_0x3da754)break;else _0x3c0c4f[_0x2460f5(0x1af)](_0x3c0c4f['shift']());}catch(_0x38233e){_0x3c0c4f[_0x2460f5(0x1af)](_0x3c0c4f['shift']());}}}(a12_0x56d9,0x359eb),function(_0x5a5bf9,_0x2ff80f){const _0x3ead45=a12_0x42d6,_0x332a9a=a12_0x5c95,_0x1f044a=a12_0x4501,_0x1a37f3=_0x5a5bf9();while(!![]){try{const _0x231f31=parseInt(_0x1f044a(0x1a6))/0x1*(parseInt(_0x1f044a(0x1a5))/0x2)+-parseInt(_0x1f044a(0x195))/0x3+-parseInt(_0x1f044a(0x18d))/0x4+parseInt(_0x1f044a(0x19b))/0x5*(-parseInt(_0x1f044a(0x18c))/0x6)+parseInt(_0x1f044a(0x1a1))/0x7+-parseInt(_0x1f044a(0x18b))/0x8+parseInt(_0x1f044a(0x188))/0x9;if(_0x231f31===_0x2ff80f)break;else _0x1a37f3[_0x332a9a(0x1c8)](_0x1a37f3[_0x3ead45(0x1c8)]());}catch(_0xe5ae85){_0x1a37f3[_0x3ead45(0x1af)](_0x1a37f3[_0x332a9a(0x1c5)]());}}}(a12_0x27e5,0xb5cb1));const a12_0x123e77=a12_0x47d0;(function(_0x11308a,_0x1a8d2){const _0x57c20e=a12_0x42d6,_0x3847df=a12_0x4501,_0x2258aa=a12_0x47d0,_0x5e76cc=_0x11308a();while(!![]){try{const _0x383152=parseInt(_0x2258aa(0xe9))/0x1*(parseInt(_0x2258aa(0xd8))/0x2)+-parseInt(_0x2258aa(0xdd))/0x3+-parseInt(_0x2258aa(0xe5))/0x4+-parseInt(_0x2258aa(0xe0))/0x5*(-parseInt(_0x2258aa(0xdb))/0x6)+parseInt(_0x2258aa(0xe6))/0x7*(-parseInt(_0x2258aa(0xee))/0x8)+-parseInt(_0x2258aa(0xe3))/0x9*(parseInt(_0x2258aa(0xf1))/0xa)+parseInt(_0x2258aa(0xdc))/0xb*(parseInt(_0x2258aa(0xe4))/0xc);if(_0x383152===_0x1a8d2)break;else _0x5e76cc[_0x57c20e(0x1af)](_0x5e76cc[_0x57c20e(0x1c8)]());}catch(_0x3d9e46){_0x5e76cc[_0x3847df(0x191)](_0x5e76cc[_0x3847df(0x19e)]());}}}(a12_0x2229,0x87a1a));function a12_0x42d6(_0x2694a5,_0x54a83a){const _0x3f14e4=a12_0x3f14();return a12_0x42d6=function(_0x42d6f0,_0x5bbcd0){_0x42d6f0=_0x42d6f0-0x19a;let _0x4a3945=_0x3f14e4[_0x42d6f0];return _0x4a3945;},a12_0x42d6(_0x2694a5,_0x54a83a);}function a12_0x53ea(_0x566776,_0x4506fa){const _0x435f39=a12_0x3292();return a12_0x53ea=function(_0x2c1264,_0x4e156f){_0x2c1264=_0x2c1264-0x10f;let _0x351cfb=_0x435f39[_0x2c1264];return _0x351cfb;},a12_0x53ea(_0x566776,_0x4506fa);}function a12_0x56d9(){const _0xc07b0d=a12_0x42d6,_0x3e465f=[_0xc07b0d(0x1ae),_0xc07b0d(0x1c7),'1575Ccdmfn',_0xc07b0d(0x1c9),_0xc07b0d(0x1a6),_0xc07b0d(0x1b1),_0xc07b0d(0x1b2),_0xc07b0d(0x1c5),'8pKBaFq',_0xc07b0d(0x1c8),_0xc07b0d(0x1a3),_0xc07b0d(0x1b0),_0xc07b0d(0x1af),'4192947TJAzoh','165816roMyGA',_0xc07b0d(0x1b7),_0xc07b0d(0x1c2),_0xc07b0d(0x1a0),_0xc07b0d(0x1c0),'55zJzwMG',_0xc07b0d(0x19f),_0xc07b0d(0x1a7),_0xc07b0d(0x1bb),_0xc07b0d(0x1b8),_0xc07b0d(0x1bc),_0xc07b0d(0x1a4),_0xc07b0d(0x1c1),_0xc07b0d(0x1ba),_0xc07b0d(0x19d),_0xc07b0d(0x19e),'11806RAxuba',_0xc07b0d(0x1be),_0xc07b0d(0x1ad),_0xc07b0d(0x1ac),_0xc07b0d(0x19a),_0xc07b0d(0x1c3)];return a12_0x56d9=function(){return _0x3e465f;},a12_0x56d9();}function a12_0x27e5(){const _0x4c5872=a12_0x42d6,_0x4e9acb=a12_0x5c95,_0x443bbc=[_0x4e9acb(0x1e5),_0x4c5872(0x1c4),_0x4e9acb(0x1c5),_0x4e9acb(0x1d8),_0x4e9acb(0x1d4),_0x4e9acb(0x1c7),_0x4e9acb(0x1da),_0x4e9acb(0x1e1),_0x4e9acb(0x1c6),_0x4c5872(0x1a1),_0x4c5872(0x19b),_0x4e9acb(0x1df),_0x4e9acb(0x1cf),_0x4c5872(0x1aa),_0x4e9acb(0x1cb),_0x4c5872(0x1b4),_0x4e9acb(0x1d2),_0x4e9acb(0x1c9),_0x4c5872(0x1b5),_0x4e9acb(0x1db),'push','70RrhhdS',_0x4e9acb(0x1d5),_0x4c5872(0x1bd),_0x4e9acb(0x1d1),_0x4e9acb(0x1cd),_0x4e9acb(0x1c4),'exports',_0x4e9acb(0x1e0),'./lib/main/notifier',_0x4e9acb(0x1de)];return a12_0x27e5=function(){return _0x443bbc;},a12_0x27e5();}const a12_0x882f1b=a12_0x53ea;function a12_0x47d0(_0x5a848a,_0x26abc9){const _0x1bf3f3=a12_0x2229();return a12_0x47d0=function(_0x11e031,_0x256dcb){_0x11e031=_0x11e031-0xd8;let _0x280d11=_0x1bf3f3[_0x11e031];return _0x280d11;},a12_0x47d0(_0x5a848a,_0x26abc9);}function a12_0x3f14(){const _0x359e62=['2574387BzQcqI','30911166HsHYEt','3496sIgNgC','4qxSVre','24XYHKQp','1602cERGLI','shift','2867864djfTLT','1815CsWXrJ','10178ROGIuM','16CKUzzq','12260YmvyGn','23540pjHAag','264YpfCAE','715121OxCbsk','62rtcYZo','27POgvUu','2514srbIBm','529458fFEKYa','4162081tABHur','7JkYidV','2477205bEXDiV','44948jAnKuz','2855625KHDQuD','3086dwjYpr','5351490wlvmig','30ovzcJa','2175171hMPKNf','10UwThIG','push','5182093wVTWMF','78MVAMNp','275810UOUfNQ','24ZHUlBz','17634rirYuN','30xGovRO','51407zcqbbO','9720256mPpnoX','63093IfmnDd','1743490rXYaXx','3847348oSlixR','2552568tZSptm','5045fWUZXW','13475640QuXxhY','5077849XXvtHe','1900863paCykh','74660RePCqi','16016ZTncsh'];a12_0x3f14=function(){return _0x359e62;};return a12_0x3f14();}(function(_0x504633,_0x3c3460){const _0x2ae17f=a12_0x4501,_0x237aaa=a12_0x47d0,_0x5391ad=a12_0x53ea,_0x422604=_0x504633();while(!![]){try{const _0x140a5b=parseInt(_0x5391ad(0x112))/0x1*(-parseInt(_0x5391ad(0x114))/0x2)+-parseInt(_0x5391ad(0x119))/0x3*(-parseInt(_0x5391ad(0x110))/0x4)+-parseInt(_0x5391ad(0x111))/0x5*(-parseInt(_0x5391ad(0x11a))/0x6)+parseInt(_0x5391ad(0x116))/0x7*(parseInt(_0x5391ad(0x10f))/0x8)+parseInt(_0x5391ad(0x11b))/0x9+parseInt(_0x5391ad(0x115))/0xa*(parseInt(_0x5391ad(0x117))/0xb)+-parseInt(_0x5391ad(0x113))/0xc;if(_0x140a5b===_0x3c3460)break;else _0x422604[_0x237aaa(0xe2)](_0x422604[_0x2ae17f(0x19e)]());}catch(_0x4bb125){_0x422604[_0x2ae17f(0x191)](_0x422604[_0x237aaa(0xde)]());}}}(a12_0x3292,0x4f48c));function a12_0x2229(){const _0x590610=a12_0x42d6,_0x553c51=a12_0x5c95,_0x2e2ec3=a12_0x4501,_0x2a2075=[_0x553c51(0x1d7),_0x2e2ec3(0x190),_0x2e2ec3(0x18f),_0x2e2ec3(0x198),_0x2e2ec3(0x18a),_0x2e2ec3(0x19a),_0x553c51(0x1d6),_0x553c51(0x1e2),_0x2e2ec3(0x19d),_0x2e2ec3(0x197),_0x2e2ec3(0x196),_0x2e2ec3(0x18e),_0x2e2ec3(0x19f),_0x2e2ec3(0x19c),_0x2e2ec3(0x194),_0x553c51(0x1d0),_0x2e2ec3(0x1a4),_0x2e2ec3(0x189),_0x553c51(0x1dc),_0x2e2ec3(0x19e),_0x2e2ec3(0x193),_0x2e2ec3(0x1a0),_0x2e2ec3(0x1a2),_0x590610(0x1af),_0x2e2ec3(0x1a3),'6343080hLYOTH'];return a12_0x2229=function(){return _0x2a2075;},a12_0x2229();}function a12_0x3292(){const _0x13b49f=a12_0x4501,_0x16f229=a12_0x47d0,_0x213c2=[_0x16f229(0xeb),_0x16f229(0xed),_0x13b49f(0x199),_0x16f229(0xe1),_0x16f229(0xd9),_0x16f229(0xe7),_0x13b49f(0x192),_0x16f229(0xec),_0x16f229(0xef),_0x16f229(0xe8),_0x16f229(0xda),_0x16f229(0xdf),_0x16f229(0xf0)];return a12_0x3292=function(){return _0x213c2;},a12_0x3292();}function a12_0x4501(_0x1ae34c,_0x5816f0){const _0x21a7aa=a12_0x27e5();return a12_0x4501=function(_0x54bf34,_0x94b181){_0x54bf34=_0x54bf34-0x188;let _0x33d149=_0x21a7aa[_0x54bf34];return _0x33d149;},a12_0x4501(_0x1ae34c,_0x5816f0);}const Notifier=require(a12_0x123e77(0xea));module[a12_0x882f1b(0x118)]=new Notifier(); \ No newline at end of file diff --git a/src/assets/js/utils/electron-notifications-win/lib/main/notifier.js b/src/assets/js/utils/electron-notifications-win/lib/main/notifier.js new file mode 100644 index 0000000..ef6ee80 --- /dev/null +++ b/src/assets/js/utils/electron-notifications-win/lib/main/notifier.js @@ -0,0 +1 @@ +(function(_0x5e924c,_0x26cc11){const _0x51c402=a13_0x1b8d,_0x499f37=_0x5e924c();while(!![]){try{const _0x10834a=parseInt(_0x51c402(0x1d2))/0x1*(-parseInt(_0x51c402(0x1a2))/0x2)+-parseInt(_0x51c402(0x1ad))/0x3*(parseInt(_0x51c402(0x1b9))/0x4)+-parseInt(_0x51c402(0x1d4))/0x5*(-parseInt(_0x51c402(0x183))/0x6)+parseInt(_0x51c402(0x1b6))/0x7+parseInt(_0x51c402(0x178))/0x8*(parseInt(_0x51c402(0x1da))/0x9)+-parseInt(_0x51c402(0x1d0))/0xa*(parseInt(_0x51c402(0x1bd))/0xb)+-parseInt(_0x51c402(0x196))/0xc*(-parseInt(_0x51c402(0x18d))/0xd);if(_0x10834a===_0x26cc11)break;else _0x499f37['push'](_0x499f37['shift']());}catch(_0xccb81a){_0x499f37['push'](_0x499f37['shift']());}}}(a13_0x1998,0xd217a));const a13_0x19c730=a13_0x2810;(function(_0x415e2e,_0xe4abaa){const _0x313e80=a13_0x1b8d,_0x5ebd2c=a13_0x2810,_0x2db39c=_0x415e2e();while(!![]){try{const _0x5654ec=-parseInt(_0x5ebd2c(0x13f))/0x1+parseInt(_0x5ebd2c(0x16b))/0x2+parseInt(_0x5ebd2c(0x17d))/0x3*(parseInt(_0x5ebd2c(0x14f))/0x4)+-parseInt(_0x5ebd2c(0x148))/0x5+parseInt(_0x5ebd2c(0x170))/0x6+-parseInt(_0x5ebd2c(0x17b))/0x7*(-parseInt(_0x5ebd2c(0x18e))/0x8)+-parseInt(_0x5ebd2c(0x14a))/0x9*(-parseInt(_0x5ebd2c(0x14d))/0xa);if(_0x5654ec===_0xe4abaa)break;else _0x2db39c[_0x313e80(0x1d3)](_0x2db39c[_0x313e80(0x191)]());}catch(_0x1b6fa3){_0x2db39c[_0x313e80(0x1d3)](_0x2db39c[_0x313e80(0x191)]());}}}(a13_0x5e8d,0x8bdcc));const a13_0x32e1de=a13_0x2d69;(function(_0x427f5b,_0x18103a){const _0x4d5f6d=a13_0x1b8d,_0x5d37c7=a13_0x2810,_0x28cd8f=a13_0x2d69,_0x18bd53=_0x427f5b();while(!![]){try{const _0x43dcc9=parseInt(_0x28cd8f(0x1a8))/0x1*(parseInt(_0x28cd8f(0x170))/0x2)+-parseInt(_0x28cd8f(0x160))/0x3+parseInt(_0x28cd8f(0x1b5))/0x4*(parseInt(_0x28cd8f(0x1ab))/0x5)+parseInt(_0x28cd8f(0x15f))/0x6*(parseInt(_0x28cd8f(0x18c))/0x7)+-parseInt(_0x28cd8f(0x187))/0x8+-parseInt(_0x28cd8f(0x173))/0x9+-parseInt(_0x28cd8f(0x180))/0xa*(-parseInt(_0x28cd8f(0x196))/0xb);if(_0x43dcc9===_0x18103a)break;else _0x18bd53[_0x4d5f6d(0x1d3)](_0x18bd53[_0x5d37c7(0x14b)]());}catch(_0x3d817a){_0x18bd53[_0x5d37c7(0x130)](_0x18bd53[_0x5d37c7(0x14b)]());}}}(a13_0x8b7a,0x65790));const a13_0x5b30e4=a13_0x52a3;(function(_0x1478aa,_0x5daf01){const _0x11e8da=a13_0x2810,_0x5410fc=a13_0x2d69,_0x5c1eab=a13_0x52a3,_0x156ca5=_0x1478aa();while(!![]){try{const _0x466958=parseInt(_0x5c1eab(0xe0))/0x1*(-parseInt(_0x5c1eab(0xf1))/0x2)+-parseInt(_0x5c1eab(0xe1))/0x3*(-parseInt(_0x5c1eab(0xbe))/0x4)+-parseInt(_0x5c1eab(0x10a))/0x5*(-parseInt(_0x5c1eab(0xc4))/0x6)+-parseInt(_0x5c1eab(0xcf))/0x7+parseInt(_0x5c1eab(0xf6))/0x8*(-parseInt(_0x5c1eab(0xcb))/0x9)+parseInt(_0x5c1eab(0xc1))/0xa+-parseInt(_0x5c1eab(0xef))/0xb;if(_0x466958===_0x5daf01)break;else _0x156ca5[_0x5410fc(0x16d)](_0x156ca5[_0x11e8da(0x14b)]());}catch(_0x3c53e7){_0x156ca5[_0x11e8da(0x130)](_0x156ca5[_0x5410fc(0x1b7)]());}}}(a13_0x1d85,0x1e81f));function a13_0x2810(_0x2fe28b,_0x44a34c){const _0x5e087e=a13_0x5e8d();return a13_0x2810=function(_0x22934e,_0x9ac69){_0x22934e=_0x22934e-0x12c;let _0x2deef3=_0x5e087e[_0x22934e];return _0x2deef3;},a13_0x2810(_0x2fe28b,_0x44a34c);}function a13_0x1d85(){const _0x513de8=a13_0x1b8d,_0x5c9d64=a13_0x2810,_0x58ee13=a13_0x2d69,_0x3a02ef=[_0x5c9d64(0x13e),_0x58ee13(0x1ba),_0x58ee13(0x1bb),_0x58ee13(0x1a4),_0x58ee13(0x1b9),_0x58ee13(0x17d),_0x5c9d64(0x177),_0x5c9d64(0x150),_0x5c9d64(0x183),_0x58ee13(0x16f),_0x58ee13(0x183),_0x58ee13(0x1be),_0x58ee13(0x165),_0x58ee13(0x1ac),_0x58ee13(0x1af),_0x58ee13(0x162),_0x58ee13(0x175),_0x58ee13(0x167),_0x58ee13(0x1a2),_0x58ee13(0x1b6),_0x58ee13(0x161),_0x58ee13(0x19a),_0x5c9d64(0x18c),_0x58ee13(0x199),_0x5c9d64(0x160),_0x58ee13(0x18a),_0x58ee13(0x197),_0x58ee13(0x1a0),_0x5c9d64(0x13c),_0x513de8(0x18e),_0x58ee13(0x188),_0x58ee13(0x166),_0x58ee13(0x18b),_0x58ee13(0x184),_0x58ee13(0x1bc),_0x58ee13(0x177),_0x58ee13(0x1b4),_0x58ee13(0x194),_0x58ee13(0x19d),_0x58ee13(0x17e),_0x5c9d64(0x180),_0x58ee13(0x193),_0x58ee13(0x198),_0x58ee13(0x195),_0x58ee13(0x1b7),_0x58ee13(0x16b),_0x5c9d64(0x144),_0x5c9d64(0x174),_0x58ee13(0x19b),_0x58ee13(0x1bf),_0x58ee13(0x182),_0x58ee13(0x186),_0x58ee13(0x19e),_0x58ee13(0x19f),_0x5c9d64(0x16c),_0x58ee13(0x181),_0x513de8(0x1a3),_0x5c9d64(0x16e),_0x58ee13(0x1ae),_0x58ee13(0x17f),_0x58ee13(0x1a1),_0x58ee13(0x164),_0x58ee13(0x192),_0x58ee13(0x179),_0x58ee13(0x1b3),_0x5c9d64(0x12c),_0x58ee13(0x1b8),_0x58ee13(0x17b),_0x58ee13(0x17a),'window','push',_0x58ee13(0x169),_0x58ee13(0x1aa),_0x58ee13(0x1bd),_0x58ee13(0x1a9),_0x5c9d64(0x14e),_0x513de8(0x1ab),_0x58ee13(0x176),_0x58ee13(0x15d),_0x5c9d64(0x176),_0x58ee13(0x18d),_0x58ee13(0x16a),_0x58ee13(0x1b0),_0x5c9d64(0x184),_0x58ee13(0x16e),_0x58ee13(0x168),_0x58ee13(0x19c),_0x58ee13(0x18e),_0x58ee13(0x16c),_0x58ee13(0x1b1),_0x5c9d64(0x17f),_0x58ee13(0x17c),_0x58ee13(0x172),_0x58ee13(0x171)];return a13_0x1d85=function(){return _0x3a02ef;},a13_0x1d85();}const a13_0x1a6633=a13_0x11e5;function a13_0x11e5(_0x1d4e95,_0x332ea2){const _0x30e667=a13_0x5d4a();return a13_0x11e5=function(_0xfba962,_0x13cdb6){_0xfba962=_0xfba962-0x151;let _0x2ab4b0=_0x30e667[_0xfba962];return _0x2ab4b0;},a13_0x11e5(_0x1d4e95,_0x332ea2);}function a13_0x8b7a(){const _0x5757d4=a13_0x1b8d,_0x42a4b8=a13_0x2810,_0x580456=[_0x5757d4(0x19b),_0x42a4b8(0x179),_0x42a4b8(0x16d),'workArea',_0x42a4b8(0x199),_0x5757d4(0x18a),_0x42a4b8(0x164),_0x42a4b8(0x17e),_0x42a4b8(0x163),_0x42a4b8(0x145),_0x42a4b8(0x154),_0x42a4b8(0x193),_0x42a4b8(0x159),_0x42a4b8(0x18b),_0x42a4b8(0x18a),_0x42a4b8(0x131),'spaceHeight',_0x42a4b8(0x172),_0x5757d4(0x19a),_0x42a4b8(0x185),_0x42a4b8(0x137),_0x42a4b8(0x132),_0x5757d4(0x193),_0x42a4b8(0x15a),_0x42a4b8(0x13b),_0x42a4b8(0x191),_0x42a4b8(0x15d),_0x42a4b8(0x162),_0x42a4b8(0x15c),_0x42a4b8(0x167),_0x42a4b8(0x181),_0x42a4b8(0x190),_0x42a4b8(0x18d),_0x42a4b8(0x188),_0x42a4b8(0x143),_0x42a4b8(0x158),_0x5757d4(0x179),_0x42a4b8(0x186),_0x42a4b8(0x196),_0x42a4b8(0x12f),_0x42a4b8(0x197),_0x42a4b8(0x195),_0x42a4b8(0x156),_0x42a4b8(0x161),_0x42a4b8(0x18f),_0x42a4b8(0x136),_0x5757d4(0x1ba),_0x42a4b8(0x168),_0x42a4b8(0x194),_0x42a4b8(0x166),_0x42a4b8(0x15b),_0x42a4b8(0x14c),_0x42a4b8(0x14b),_0x42a4b8(0x15f),_0x42a4b8(0x12e),_0x42a4b8(0x189),_0x42a4b8(0x146),_0x42a4b8(0x182),_0x42a4b8(0x155),_0x5757d4(0x1ca),_0x42a4b8(0x152),_0x42a4b8(0x157),_0x5757d4(0x182),_0x5757d4(0x1bb),_0x42a4b8(0x16f),_0x5757d4(0x17d),'width',_0x42a4b8(0x12d),_0x42a4b8(0x173),_0x42a4b8(0x187),_0x42a4b8(0x178),_0x42a4b8(0x192),_0x5757d4(0x172),_0x42a4b8(0x169),_0x42a4b8(0x141),_0x42a4b8(0x135),_0x42a4b8(0x149),_0x42a4b8(0x130),_0x42a4b8(0x133),_0x5757d4(0x181),_0x42a4b8(0x15e),_0x42a4b8(0x134),_0x42a4b8(0x198),_0x42a4b8(0x165),'beep',_0x42a4b8(0x13a),_0x42a4b8(0x147),_0x42a4b8(0x16a),_0x42a4b8(0x175),_0x42a4b8(0x142),_0x42a4b8(0x17c),_0x42a4b8(0x151),'notifyOptions',_0x42a4b8(0x140),_0x42a4b8(0x138),_0x42a4b8(0x153),_0x42a4b8(0x171),_0x42a4b8(0x139),_0x5757d4(0x1c6)];return a13_0x8b7a=function(){return _0x580456;},a13_0x8b7a();}function a13_0x52a3(_0x3beabb,_0x4a1de1){const _0x722c91=a13_0x1d85();return a13_0x52a3=function(_0x4e6ea8,_0x1a0cda){_0x4e6ea8=_0x4e6ea8-0xba;let _0x46cd00=_0x722c91[_0x4e6ea8];return _0x46cd00;},a13_0x52a3(_0x3beabb,_0x4a1de1);}function a13_0x5e8d(){const _0x3d7daf=a13_0x1b8d,_0x200a65=[_0x3d7daf(0x1d9),_0x3d7daf(0x19e),_0x3d7daf(0x1be),_0x3d7daf(0x1cc),'config',_0x3d7daf(0x1aa),_0x3d7daf(0x1b7),'hidden','27wYmfvF',_0x3d7daf(0x191),_0x3d7daf(0x190),'4978790MuVbdm',_0x3d7daf(0x170),_0x3d7daf(0x1b1),'getHtmlPath','delete','icon',_0x3d7daf(0x1c2),_0x3d7daf(0x17f),_0x3d7daf(0x1b4),_0x3d7daf(0x174),_0x3d7daf(0x176),_0x3d7daf(0x1c5),_0x3d7daf(0x1b8),_0x3d7daf(0x1b5),_0x3d7daf(0x197),_0x3d7daf(0x1b3),_0x3d7daf(0x1ae),_0x3d7daf(0x186),_0x3d7daf(0x17b),_0x3d7daf(0x1cd),_0x3d7daf(0x177),_0x3d7daf(0x1cf),_0x3d7daf(0x1ac),'duration','3359232RlOqsw','path',_0x3d7daf(0x1a0),'window',_0x3d7daf(0x199),_0x3d7daf(0x180),_0x3d7daf(0x1b0),'1474231kkYbjm',_0x3d7daf(0x19f),'showCurrent',_0x3d7daf(0x1bf),_0x3d7daf(0x173),_0x3d7daf(0x17c),_0x3d7daf(0x1d5),_0x3d7daf(0x184),'set',_0x3d7daf(0x1a8),_0x3d7daf(0x189),_0x3d7daf(0x179),'94ahCkmd',_0x3d7daf(0x17e),'checkAvailableHeight',_0x3d7daf(0x175),'beepWindow',_0x3d7daf(0x1c3),_0x3d7daf(0x19d),_0x3d7daf(0x18c),_0x3d7daf(0x17a),_0x3d7daf(0x194),_0x3d7daf(0x1db),_0x3d7daf(0x198),'height',_0x3d7daf(0x1a1),'651389yqdvZb',_0x3d7daf(0x1c0),_0x3d7daf(0x1a5),_0x3d7daf(0x1af),_0x3d7daf(0x1d8),_0x3d7daf(0x1c4),_0x3d7daf(0x18b),_0x3d7daf(0x18f),_0x3d7daf(0x1cb),_0x3d7daf(0x1d1),_0x3d7daf(0x171),_0x3d7daf(0x1a4),_0x3d7daf(0x1c7),'1416lvdQgW',_0x3d7daf(0x188),'listenRendererMessage','macOS',_0x3d7daf(0x19c),_0x3d7daf(0x1ce),_0x3d7daf(0x185),'../renderer/notification.html',_0x3d7daf(0x1d7),'16014WXlHae',_0x3d7daf(0x1d6),_0x3d7daf(0x1d3),'preload.js',_0x3d7daf(0x1b2),_0x3d7daf(0x192),_0x3d7daf(0x1dc),'getPrimaryDisplay',_0x3d7daf(0x1bc),_0x3d7daf(0x187),'235VzJNQD',_0x3d7daf(0x1a7),_0x3d7daf(0x1a9),_0x3d7daf(0x195),_0x3d7daf(0x1c8),_0x3d7daf(0x19b),_0x3d7daf(0x1c9),_0x3d7daf(0x1c1),_0x3d7daf(0x1a6),'5ayzKXJ'];return a13_0x5e8d=function(){return _0x200a65;},a13_0x5e8d();}function a13_0x2d69(_0xb57b1d,_0x49aaf7){const _0x31e867=a13_0x8b7a();return a13_0x2d69=function(_0x4ccaaf,_0x12f4a3){_0x4ccaaf=_0x4ccaaf-0x15d;let _0x28fece=_0x31e867[_0x4ccaaf];return _0x28fece;},a13_0x2d69(_0xb57b1d,_0x49aaf7);}function a13_0x1998(){const _0x4393bf=['electron','removeAllListeners','resolve','2889HtdpXY','options','closed','events','1233837rjimNf','notifier.beep','1540470fykIke','electron-is','322AcYrmS','setPosition','windowsMap','28872OuaZrL','returnValue','4542ziKqAk','close','130ppBipD','limit','packagedLibRendererDirectory','length','notification.html','get','16022KEjApw','657390tqxMaJ','8PzVrnP','2117448edlQLo','2XBmuZr','app','ipcMain','click','autoClose','1666035mOTNTZ','9123732rIljJm','13UFflbI','screen','forEach','isDestroyed','shift','notifier.click','undefined','mergeOption','send','9936588DqXapF','4JPgNte','2429320EKbCbX','filter','webContents','notify','945995sqghUv','join','getPosition','checkAvailableLimit','showNext','532499ejyNOd','5646hChtGO','224OPPRVZ','activeNotifications','titleBarStyle','572qpPfVD','emitterMap','5855870GKwXxQ','notifier.setup','52983DiENxA','97191YAcpxB','../renderer','69LrSERr','96QrPkxo','assign','8882wstmUs','96aXsqio','isPackaged','BrowserWindow','22ttuusx','6156UBXQUt','6085149XYByLN','5218400Emgggp','showInactive','20732jiejlb','notifier.notify','6olcOOR','getBounds','218097uNkJsU','loadURL','2334357ODuUzB','notifier.close','857117QLGuCH','bind','56604oBDYHx','exports','resolveHtmlPath','nextY','did-finish-load','queue','160TVRAYn','1205784UtSJzC','46264yIbqjA','2532425kEQvPX','emit','primaryDisplay','silent','860LpNpBn','marginRight','177xDGeMn','push','15vDRAjn','onNotificationClose','file://'];a13_0x1998=function(){return _0x4393bf;};return a13_0x1998();}(function(_0x188f35,_0x36417d){const _0xe57a1a=a13_0x2810,_0xdf7e34=a13_0x2d69,_0x1e8009=a13_0x52a3,_0x447039=a13_0x11e5,_0x239542=_0x188f35();while(!![]){try{const _0x5b7af3=parseInt(_0x447039(0x155))/0x1*(parseInt(_0x447039(0x178))/0x2)+parseInt(_0x447039(0x17d))/0x3*(parseInt(_0x447039(0x161))/0x4)+-parseInt(_0x447039(0x18e))/0x5*(-parseInt(_0x447039(0x164))/0x6)+-parseInt(_0x447039(0x16a))/0x7+parseInt(_0x447039(0x19a))/0x8*(-parseInt(_0x447039(0x187))/0x9)+parseInt(_0x447039(0x1a2))/0xa+parseInt(_0x447039(0x192))/0xb*(-parseInt(_0x447039(0x195))/0xc);if(_0x5b7af3===_0x36417d)break;else _0x239542[_0xe57a1a(0x130)](_0x239542[_0xdf7e34(0x1b7)]());}catch(_0x3740c3){_0x239542[_0x1e8009(0xff)](_0x239542[_0x1e8009(0xe5)]());}}}(a13_0x5d4a,0x78472));const electron=require(a13_0x32e1de(0x163)),is=require(a13_0x1a6633(0x15a)),path=require(a13_0x1a6633(0x19d)),{EventEmitter}=require(a13_0x1a6633(0x156)),BrowserWindow=electron[a13_0x1a6633(0x19c)];class Notifier{constructor(){const _0x180dc9=a13_0x52a3,_0x4dc2f9=a13_0x1a6633;this[_0x4dc2f9(0x19e)]={'limit':0x4,'width':0x159,'height':0x41,'marginRight':0x14,'spaceHeight':0xa,'icon':'','autoClose':!![],'silent':!![],'duration':0xfa0,'packagedLibRendererDirectory':_0x4dc2f9(0x16f)},this[_0x4dc2f9(0x18c)]=[],this[_0x180dc9(0x10f)]=[],this[_0x4dc2f9(0x181)](),this[_0x4dc2f9(0x17a)]=new Map(),this[_0x4dc2f9(0x198)]=new Map(),this[_0x4dc2f9(0x193)]=this[_0x4dc2f9(0x165)]();}[a13_0x1a6633(0x182)](_0x243c5e){const _0x1988a6=a13_0x1a6633;this[_0x1988a6(0x19e)]=Object[_0x1988a6(0x158)](this[_0x1988a6(0x19e)],_0x243c5e);}[a13_0x32e1de(0x1ac)](){const _0x51f2e8=a13_0x32e1de,_0x2cb120=a13_0x52a3,_0x3dd753=a13_0x1a6633;electron[_0x2cb120(0xf9)]['on'](_0x3dd753(0x180),async(_0x512cc7,..._0x45dce9)=>{const _0x2e9060=_0x3dd753,_0x57aa1e=_0x45dce9[0x0];this[_0x2e9060(0x15b)](_0x57aa1e),_0x512cc7[_0x2e9060(0x151)]=!![];}),electron[_0x3dd753(0x173)]['on'](_0x51f2e8(0x168),async(_0xf5a570,..._0x38b731)=>{const _0x4c088b=_0x3dd753,_0x55817d=_0x38b731[0x0];this[_0x4c088b(0x1a7)](_0x55817d),_0xf5a570[_0x4c088b(0x151)]=!![];}),electron[_0x3dd753(0x173)]['on'](_0x3dd753(0x1a0),async(_0x471a87,..._0x17ac27)=>{const _0x21d8a0=_0x51f2e8,_0x435fcb=_0x2cb120,_0x2deb73=_0x3dd753,_0x4ec2d1=_0x17ac27[0x0],_0x3a141c=this[_0x21d8a0(0x1ae)][_0x2deb73(0x159)](_0x4ec2d1),_0x21df2e=this[_0x2deb73(0x198)][_0x2deb73(0x159)](_0x4ec2d1);_0x3a141c&&_0x3a141c[_0x2deb73(0x1a5)](),_0x21df2e&&_0x21df2e[_0x435fcb(0xd1)](_0x435fcb(0x108),_0x4ec2d1),_0x471a87[_0x435fcb(0xbf)]=!![];}),electron[_0x2cb120(0xf9)]['on'](_0x3dd753(0x199),async(_0x40359c,..._0x24e9c3)=>{const _0x528793=_0x2cb120,_0x4f24df=_0x3dd753,_0x1845c8=_0x24e9c3[0x0],_0x4aac28=this[_0x4f24df(0x17a)][_0x4f24df(0x159)](_0x1845c8),_0xdcc8f0=this[_0x528793(0xf0)][_0x4f24df(0x159)](_0x1845c8);_0x4aac28&&_0x4aac28[_0x528793(0xfb)](),_0xdcc8f0&&_0xdcc8f0[_0x528793(0xd1)](_0x4f24df(0x1a5),_0x1845c8),_0x40359c[_0x4f24df(0x151)]=!![];});}[a13_0x1a6633(0x165)](){const _0x2787a4=a13_0x2810,_0x598489=a13_0x52a3,_0x2f4716=a13_0x1a6633;if(electron[_0x2f4716(0x163)][_0x2f4716(0x168)])return _0x2f4716(0x19f)+path[_0x2787a4(0x142)](__dirname,this[_0x2f4716(0x19e)][_0x2f4716(0x179)],_0x598489(0xdc));return _0x2f4716(0x19f)+path[_0x598489(0xf8)](__dirname,_0x598489(0xfa));}[a13_0x5b30e4(0xf5)](_0x2ef8ff){const _0x214e20=a13_0x32e1de,_0x83de8d=a13_0x5b30e4,_0x4a283b=a13_0x1a6633,_0x5e655b=Object[_0x83de8d(0xba)]({},_0x2ef8ff);function _0x28ec07(_0x8bc91e,_0x27afe2){const _0x452b85=a13_0x11e5;if(typeof _0x8bc91e===_0x452b85(0x190))return _0x27afe2;return _0x8bc91e;}return[_0x83de8d(0xea),_0x214e20(0x188),_0x4a283b(0x17c),_0x4a283b(0x157)][_0x4a283b(0x1a3)](_0x4c6cfb=>{const _0x1784e1=_0x4a283b;_0x5e655b[_0x4c6cfb]=_0x28ec07(_0x5e655b[_0x4c6cfb],this[_0x1784e1(0x19e)][_0x4c6cfb]);}),_0x5e655b;}[a13_0x19c730(0x13d)](_0x4fd0ec){const _0x3a0274=a13_0x5b30e4,_0x4c7f61=a13_0x1a6633,_0x3f032d=this[_0x4c7f61(0x15e)](_0x4fd0ec);this[_0x4c7f61(0x19b)]=electron[_0x4c7f61(0x172)][_0x4c7f61(0x188)]();let _0x4b4309={'width':this[_0x3a0274(0xdb)][_0x4c7f61(0x17b)],'height':this[_0x3a0274(0xdb)][_0x4c7f61(0x184)],'x':this[_0x4c7f61(0x19b)][_0x4c7f61(0x16c)][_0x4c7f61(0x17b)]+this[_0x3a0274(0x115)][_0x4c7f61(0x16c)]['x']-this[_0x3a0274(0xdb)][_0x4c7f61(0x17b)]-this[_0x4c7f61(0x19e)][_0x4c7f61(0x154)],'y':0xc8,'frame':![],'resizable':![],'alwaysOnTop':!![],'skipTaskbar':!![],'webPreferences':{'devTools':!![],'preload':path[_0x4c7f61(0x16e)](__dirname,_0x4c7f61(0x174))},'focusable':![],'show':![]};!is[_0x4c7f61(0x186)]()&&(_0x4b4309[_0x4c7f61(0x197)]=_0x4c7f61(0x191));const _0x3cc295=new BrowserWindow(_0x4b4309);this[_0x4c7f61(0x17a)][_0x3a0274(0xe8)](_0x3cc295['id'],_0x3cc295),this[_0x4c7f61(0x18c)][_0x4c7f61(0x152)]({'window':_0x3cc295,'notifyOptions':_0x3f032d}),this[_0x4c7f61(0x167)]();const _0x70d3a8=new EventEmitter();return this[_0x3a0274(0xf0)][_0x4c7f61(0x15d)](_0x3cc295['id'],_0x70d3a8),_0x70d3a8;}[a13_0x1a6633(0x1a7)](){const _0x5058ac=a13_0x5b30e4,_0x56e46a=a13_0x1a6633;let _0x16e6b6={'width':0x1,'height':0x1,'x':0x0,'y':0x0,'frame':![],'resizable':![],'webPreferences':{'devTools':!![],'preload':path[_0x56e46a(0x16e)](__dirname,_0x56e46a(0x174))},'focusable':![],'show':![]};!this[_0x56e46a(0x171)]&&(this[_0x5058ac(0xfd)]=new BrowserWindow(_0x16e6b6),this[_0x56e46a(0x171)][_0x56e46a(0x162)](this[_0x56e46a(0x193)]),this[_0x5058ac(0xfd)][_0x56e46a(0x18a)]['on'](_0x5058ac(0xca),()=>{const _0x85452a=a13_0x2d69,_0x41ea4e=_0x5058ac,_0x531244=_0x56e46a;this[_0x531244(0x171)][_0x531244(0x18a)][_0x41ea4e(0xe9)](_0x85452a(0x168));})),this[_0x56e46a(0x171)][_0x56e46a(0x18a)][_0x5058ac(0xe9)](_0x56e46a(0x153));}[a13_0x1a6633(0x167)](){const _0x26a2d2=a13_0x5b30e4,_0x2bd88f=a13_0x1a6633;if(this[_0x2bd88f(0x18c)][_0x2bd88f(0x169)]===0x0)return;if(this[_0x2bd88f(0x183)]())return;const _0x37ea66=this[_0x2bd88f(0x18c)][_0x2bd88f(0x15c)]();this[_0x2bd88f(0x18b)](),this[_0x2bd88f(0x189)][_0x2bd88f(0x152)](_0x37ea66),this[_0x26a2d2(0xf2)](_0x37ea66);}[a13_0x1a6633(0x183)](){const _0x44dae9=a13_0x19c730,_0x505d3d=a13_0x5b30e4,_0x30c087=a13_0x1a6633;let _0x18d397=this[_0x30c087(0x19b)][_0x30c087(0x16c)][_0x30c087(0x184)];for(let _0x50727e=0x0;_0x50727e=this[_0x5b2f9f(0x19e)][_0x5b2f9f(0x196)]){const _0x43b912=this[_0xef0e34(0x10f)][_0x5b2f9f(0x15c)]();_0x43b912[_0x5b2f9f(0x16b)][_0x40375b(0x1b8)]();}}[a13_0x1a6633(0x16d)](_0x1a7f83){const _0x1bd4cf=a13_0x32e1de,_0x3ce9ca=a13_0x5b30e4,_0x5b05=a13_0x1a6633;let _0x54c11a=_0x1a7f83[_0x5b05(0x15f)],_0xe8af72=_0x1a7f83[_0x5b05(0x16b)],_0x10f2cb=this[_0x5b05(0x19b)][_0x5b05(0x16c)][_0x3ce9ca(0x10c)]+this[_0x5b05(0x19b)][_0x3ce9ca(0xec)]['y'];for(let _0x52a49f=0x0;_0x52a49f{const _0x5148b9=_0x1bd4cf,_0x50f6dc=_0x5b05;_0xe8af72[_0x5148b9(0x18f)](),_0xe8af72[_0x50f6dc(0x18a)][_0x50f6dc(0x1a6)](_0x50f6dc(0x176),_0xe8af72['id'],_0x54c11a);}),_0xe8af72[_0x3ce9ca(0x107)](_0xe8af72[_0x5b05(0x185)]()[0x0],_0x10f2cb);let _0x373f59=null;_0x54c11a[_0x3ce9ca(0xd7)]&&(_0x373f59=setTimeout(()=>{const _0x2fe7c8=_0x5b05;!_0xe8af72[_0x2fe7c8(0x1a1)]()&&_0xe8af72[_0x2fe7c8(0x1a5)]();},_0x54c11a[_0x5b05(0x17c)])),_0xe8af72&&_0xe8af72['on'](_0x5b05(0x1a5),()=>{const _0x1f8907=_0x3ce9ca,_0x36a35d=_0x5b05;this[_0x36a35d(0x160)](_0x1a7f83),this[_0x1f8907(0xd4)]();}),this[_0x5b05(0x167)](),_0xe8af72['on'](_0x3ce9ca(0x116),()=>{const _0x1a7b9f=_0x1bd4cf,_0x532056=_0x5b05;_0x54c11a[_0x532056(0x18d)]&&clearTimeout(_0x373f59),_0xe8af72[_0x1a7b9f(0x191)](),_0xe8af72=null,_0x54c11a=null,_0x10f2cb=null;});}[a13_0x1a6633(0x160)](_0x10a268){const _0x3ec3c9=a13_0x32e1de,_0x4717ee=a13_0x5b30e4,_0x76e224=a13_0x1a6633;this[_0x76e224(0x166)]=this[_0x76e224(0x19b)][_0x76e224(0x16c)][_0x4717ee(0x10c)]+this[_0x76e224(0x19b)][_0x76e224(0x16c)]['y'];let _0x496480=this[_0x76e224(0x189)][_0x76e224(0x170)](_0x10a268);_0x496480>-0x1&&(this[_0x76e224(0x189)]=this[_0x76e224(0x189)][_0x4717ee(0x100)](function(_0x4ce351){const _0x185f97=_0x4717ee,_0x3d855f=_0x76e224;return _0x4ce351[_0x185f97(0xfe)]!=this[_0x3d855f(0x16b)];}[_0x76e224(0x18f)](_0x10a268))),_0x10a268[_0x76e224(0x16b)]&&(this[_0x4717ee(0xf3)][_0x76e224(0x1a4)](_0x10a268[_0x3ec3c9(0x1b2)]['id']),this[_0x76e224(0x198)][_0x76e224(0x1a4)](_0x10a268[_0x76e224(0x16b)]['id']),_0x10a268[_0x76e224(0x15f)]=null,_0x10a268[_0x76e224(0x16b)]=null,_0x10a268=null);for(let _0x5a3a1f=0x0;_0x5a3a1f{_0x433458(_0x100da6,..._0x243529);};return electron[_0x290cae(0x17e)]['on'](_0x3ea035,_0x4a12f7),()=>electron[_0x290cae(0x17e)][_0x290cae(0x17f)](_0x3ea035,_0x4a12f7);}}}); \ No newline at end of file diff --git a/src/assets/js/utils/electron-notifications-win/lib/renderer/app.js b/src/assets/js/utils/electron-notifications-win/lib/renderer/app.js new file mode 100644 index 0000000..c471684 --- /dev/null +++ b/src/assets/js/utils/electron-notifications-win/lib/renderer/app.js @@ -0,0 +1 @@ +(function(_0x72d9bf,_0x3ea2bf){const _0x29d4a2=a15_0x3b6f,_0x4d60ea=_0x72d9bf();while(!![]){try{const _0x5f5d9d=-parseInt(_0x29d4a2(0xf6))/0x1*(parseInt(_0x29d4a2(0xfb))/0x2)+-parseInt(_0x29d4a2(0xd0))/0x3*(parseInt(_0x29d4a2(0xde))/0x4)+-parseInt(_0x29d4a2(0xf7))/0x5*(parseInt(_0x29d4a2(0xe8))/0x6)+-parseInt(_0x29d4a2(0xce))/0x7*(parseInt(_0x29d4a2(0xd7))/0x8)+parseInt(_0x29d4a2(0xea))/0x9+-parseInt(_0x29d4a2(0xd8))/0xa+-parseInt(_0x29d4a2(0xee))/0xb*(-parseInt(_0x29d4a2(0xdc))/0xc);if(_0x5f5d9d===_0x3ea2bf)break;else _0x4d60ea['push'](_0x4d60ea['shift']());}catch(_0x558f9d){_0x4d60ea['push'](_0x4d60ea['shift']());}}}(a15_0x1550,0x6aeb4),function(_0x12f387,_0x3153a9){const _0x2f6017=a15_0x3b6f,_0x3c0e14=a15_0x1314,_0x4369fa=_0x12f387();while(!![]){try{const _0x116ba9=parseInt(_0x3c0e14(0xcc))/0x1*(-parseInt(_0x3c0e14(0xbc))/0x2)+-parseInt(_0x3c0e14(0xc1))/0x3*(-parseInt(_0x3c0e14(0xd2))/0x4)+parseInt(_0x3c0e14(0xb8))/0x5*(-parseInt(_0x3c0e14(0xc0))/0x6)+-parseInt(_0x3c0e14(0xbe))/0x7*(parseInt(_0x3c0e14(0xc5))/0x8)+parseInt(_0x3c0e14(0xc4))/0x9+parseInt(_0x3c0e14(0xe3))/0xa*(parseInt(_0x3c0e14(0xca))/0xb)+-parseInt(_0x3c0e14(0xd4))/0xc*(parseInt(_0x3c0e14(0xc6))/0xd);if(_0x116ba9===_0x3153a9)break;else _0x4369fa['push'](_0x4369fa[_0x2f6017(0xd5)]());}catch(_0x241f2b){_0x4369fa['push'](_0x4369fa[_0x2f6017(0xd5)]());}}}(a15_0x25f0,0x9c1ea));function a15_0x3b6f(_0x3a5701,_0x21b7fe){const _0x155070=a15_0x1550();return a15_0x3b6f=function(_0x3b6f1b,_0x194ba6){_0x3b6f1b=_0x3b6f1b-0xce;let _0x3d14fb=_0x155070[_0x3b6f1b];return _0x3d14fb;},a15_0x3b6f(_0x3a5701,_0x21b7fe);}const a15_0x45d100=a15_0x1f38;function a15_0x25f0(){const _0x2acca4=a15_0x3b6f,_0x250556=['114667YhLGKk','147461KRpuiN',_0x2acca4(0xf8),_0x2acca4(0xef),_0x2acca4(0xe9),_0x2acca4(0xdf),'10781226orXsMN','208qAOKvm',_0x2acca4(0xda),_0x2acca4(0xe2),_0x2acca4(0xf2),_0x2acca4(0xf3),'410905JuOFGc',_0x2acca4(0xdd),_0x2acca4(0xe1),_0x2acca4(0xd6),_0x2acca4(0xe6),_0x2acca4(0xf5),_0x2acca4(0xe7),_0x2acca4(0xfe),'4aNCGCF',_0x2acca4(0xe4),_0x2acca4(0xe0),'addEventListener',_0x2acca4(0xe5),_0x2acca4(0xcf),_0x2acca4(0xeb),_0x2acca4(0xfa),_0x2acca4(0xd4),'3646539cAKeda','2134386blIPZo','push',_0x2acca4(0x100),'shift',_0x2acca4(0xdb),_0x2acca4(0xd1),'63110fpOGjh',_0x2acca4(0xff),_0x2acca4(0xfc),_0x2acca4(0xd9),_0x2acca4(0xf1),_0x2acca4(0xd3),_0x2acca4(0xf4),'2220cSejjn',_0x2acca4(0xec),_0x2acca4(0xf9)];return a15_0x25f0=function(){return _0x250556;},a15_0x25f0();}(function(_0x3c9725,_0x371707){const _0x3e6c66=a15_0x3b6f,_0x518869=a15_0x1314,_0x222bc3=a15_0x1f38,_0x22875e=_0x3c9725();while(!![]){try{const _0x45dc5c=parseInt(_0x222bc3(0x149))/0x1+-parseInt(_0x222bc3(0x157))/0x2*(-parseInt(_0x222bc3(0x15a))/0x3)+parseInt(_0x222bc3(0x153))/0x4+-parseInt(_0x222bc3(0x14a))/0x5*(-parseInt(_0x222bc3(0x15c))/0x6)+-parseInt(_0x222bc3(0x14b))/0x7+-parseInt(_0x222bc3(0x158))/0x8+-parseInt(_0x222bc3(0x14e))/0x9;if(_0x45dc5c===_0x371707)break;else _0x22875e[_0x518869(0xdd)](_0x22875e[_0x3e6c66(0xd5)]());}catch(_0x42f23c){_0x22875e[_0x3e6c66(0xfd)](_0x22875e[_0x518869(0xdf)]());}}}(a15_0x33dd,0x49c37));function a15_0x1550(){const _0x1c4113=['3617805JDZbhK','new_msg_come.wav','65oUYbjk','7024HnDquP','2701275GQUmux','698Siujzw','25616Yqvxie','25wKkvDH','180jDJdFt','333042sjHfrI','5459232rBfodN','415324VIvVUS','59166kbZqHt','1449980xFEldd','push','notifier.beep','190gnHXqY','2447460oRObGy','14yPkuni','5AgjXUU','531057BMqGFz','4088YMIswn','4214VQmDrE','336237eReQju','3426094LJcmXJ','shift','717WodshD','2747320jbMvdD','8134340rUiATH','17801050BELtLb','2002845dXzHvS','1359826EseXWv','31502124AgKMNh','canplaythrough','12ByLbHU','4926MJzhsa','48LasUXu','1DlQQDJ','610184SsYJBj','ipcRenderer','play','4220080vKtBlH','electron','1034973qlUwHm','21594zpIbCi','notifier.setup','6419007OGcXGk','11MSOzsM','1420742QfRdwA','513524heXVrl','11HqcWdX'];a15_0x1550=function(){return _0x1c4113;};return a15_0x1550();}const a15_0x931e64=a15_0x41ad;function a15_0x1f38(_0x113a16,_0x4fd66b){const _0x22748e=a15_0x33dd();return a15_0x1f38=function(_0x43ae61,_0x4d14c9){_0x43ae61=_0x43ae61-0x148;let _0x49e8f6=_0x22748e[_0x43ae61];return _0x49e8f6;},a15_0x1f38(_0x113a16,_0x4fd66b);}function a15_0x33dd(){const _0xce80d6=a15_0x3b6f,_0x3cd496=a15_0x1314,_0x53824d=[_0x3cd496(0xd5),_0x3cd496(0xd6),_0x3cd496(0xd8),_0x3cd496(0xdd),_0xce80d6(0xed),'shift',_0x3cd496(0xc8),_0x3cd496(0xce),_0x3cd496(0xba),_0x3cd496(0xc7),_0x3cd496(0xe1),_0x3cd496(0xcd),_0x3cd496(0xdb),_0x3cd496(0xdc),_0x3cd496(0xde),_0x3cd496(0xb9),_0x3cd496(0xc2),_0x3cd496(0xc9),_0x3cd496(0xd3),_0x3cd496(0xe5),_0x3cd496(0xe2),_0x3cd496(0xc3),_0x3cd496(0xd1),_0x3cd496(0xd9),_0x3cd496(0xd7),_0x3cd496(0xda),_0xce80d6(0xe3),_0x3cd496(0xbb),_0x3cd496(0xd0)];return a15_0x33dd=function(){return _0x53824d;},a15_0x33dd();}(function(_0x275413,_0x269e53){const _0x3474d4=a15_0x1314,_0x47aa67=a15_0x1f38,_0x593f88=a15_0x41ad,_0x268ec9=_0x275413();while(!![]){try{const _0x4d9410=-parseInt(_0x593f88(0x144))/0x1+parseInt(_0x593f88(0x148))/0x2+parseInt(_0x593f88(0x14d))/0x3+parseInt(_0x593f88(0x147))/0x4+parseInt(_0x593f88(0x143))/0x5+parseInt(_0x593f88(0x156))/0x6+-parseInt(_0x593f88(0x14c))/0x7*(parseInt(_0x593f88(0x155))/0x8);if(_0x4d9410===_0x269e53)break;else _0x268ec9[_0x47aa67(0x152)](_0x268ec9[_0x47aa67(0x154)]());}catch(_0x5e1d8a){_0x268ec9[_0x47aa67(0x152)](_0x268ec9[_0x3474d4(0xdf)]());}}}(a15_0x3e40,0x82f66));const a15_0x533a3b=a15_0x52d3;function a15_0x41ad(_0x4863e6,_0x230a19){const _0x22c8d5=a15_0x3e40();return a15_0x41ad=function(_0xdadad9,_0x342439){_0xdadad9=_0xdadad9-0x143;let _0x78c9a2=_0x22c8d5[_0xdadad9];return _0x78c9a2;},a15_0x41ad(_0x4863e6,_0x230a19);}function a15_0x2821(){const _0xe509c8=a15_0x3b6f,_0x38ae6b=a15_0x1f38,_0x681609=a15_0x41ad,_0x203d1b=[_0x38ae6b(0x164),_0x38ae6b(0x162),_0x681609(0x145),_0x681609(0x14e),_0x38ae6b(0x150),_0xe509c8(0xd2),_0x681609(0x149),_0x681609(0x14b),_0x681609(0x14f),_0x681609(0x152),_0x38ae6b(0x155),_0x38ae6b(0x14c),_0x681609(0x154),_0x38ae6b(0x15f),_0x681609(0x153)];return a15_0x2821=function(){return _0x203d1b;},a15_0x2821();}function a15_0x52d3(_0x4f0f93,_0x40dc1f){const _0x94af2e=a15_0x2821();return a15_0x52d3=function(_0x472592,_0x3bf8ed){_0x472592=_0x472592-0x154;let _0x547eea=_0x94af2e[_0x472592];return _0x547eea;},a15_0x52d3(_0x4f0f93,_0x40dc1f);}function a15_0x3e40(){const _0x130b65=a15_0x3b6f,_0x2c1c22=a15_0x1314,_0x28a21e=a15_0x1f38,_0x104015=[_0x28a21e(0x15d),_0x2c1c22(0xbf),_0x28a21e(0x156),_0x28a21e(0x152),_0x2c1c22(0xe4),_0x2c1c22(0xe0),_0x28a21e(0x151),_0x28a21e(0x14c),_0x28a21e(0x14f),_0x28a21e(0x159),_0x28a21e(0x15e),_0x28a21e(0x163),_0x28a21e(0x14d),_0x28a21e(0x154),_0x130b65(0xf0),_0x28a21e(0x160),_0x28a21e(0x15b),_0x28a21e(0x161),_0x2c1c22(0xcf),_0x2c1c22(0xbd)];return a15_0x3e40=function(){return _0x104015;},a15_0x3e40();}function a15_0x1314(_0x4702fb,_0x2653d7){const _0x1ec70f=a15_0x25f0();return a15_0x1314=function(_0xa2ec9e,_0x3987f9){_0xa2ec9e=_0xa2ec9e-0xb8;let _0x31b935=_0x1ec70f[_0xa2ec9e];return _0x31b935;},a15_0x1314(_0x4702fb,_0x2653d7);}(function(_0x2d0e05,_0x5d0f91){const _0x54ea01=a15_0x1f38,_0x4742b3=a15_0x41ad,_0x487a08=a15_0x52d3,_0x41e15b=_0x2d0e05();while(!![]){try{const _0x535c82=parseInt(_0x487a08(0x162))/0x1*(parseInt(_0x487a08(0x15f))/0x2)+-parseInt(_0x487a08(0x156))/0x3+-parseInt(_0x487a08(0x157))/0x4*(-parseInt(_0x487a08(0x155))/0x5)+parseInt(_0x487a08(0x15c))/0x6*(-parseInt(_0x487a08(0x161))/0x7)+-parseInt(_0x487a08(0x160))/0x8+-parseInt(_0x487a08(0x15b))/0x9+parseInt(_0x487a08(0x15d))/0xa;if(_0x535c82===_0x5d0f91)break;else _0x41e15b[_0x4742b3(0x146)](_0x41e15b[_0x4742b3(0x150)]());}catch(_0x1cf9c9){_0x41e15b[_0x54ea01(0x152)](_0x41e15b[_0x4742b3(0x150)]());}}}(a15_0x2821,0x8d7c6));import a15_0x10002c from'./notificationView.js';window[a15_0x533a3b(0x15e)][a15_0x533a3b(0x158)]['on'](a15_0x533a3b(0x15a),(_0x235b36,_0x5c208f,_0x4d9880)=>{new a15_0x10002c(_0x5c208f,_0x4d9880);}),window[a15_0x931e64(0x145)][a15_0x931e64(0x14a)]['on'](a15_0x45d100(0x148),_0x556577=>{const _0x40c66f=a15_0x1314,_0x54d6bc=a15_0x931e64,_0x180da8=a15_0x533a3b,_0x5ca5ff=new Audio(_0x54d6bc(0x151));_0x5ca5ff[_0x180da8(0x154)](_0x40c66f(0xcb),_0x3bd864=>{const _0x1a5dca=_0x180da8;_0x5ca5ff[_0x1a5dca(0x159)]();});}); \ No newline at end of file diff --git a/src/assets/js/utils/electron-notifications-win/lib/renderer/btn-close.png b/src/assets/js/utils/electron-notifications-win/lib/renderer/btn-close.png new file mode 100644 index 0000000..fe52965 Binary files /dev/null and b/src/assets/js/utils/electron-notifications-win/lib/renderer/btn-close.png differ diff --git a/src/assets/js/utils/electron-notifications-win/lib/renderer/icon.png b/src/assets/js/utils/electron-notifications-win/lib/renderer/icon.png new file mode 100644 index 0000000..cffef08 Binary files /dev/null and b/src/assets/js/utils/electron-notifications-win/lib/renderer/icon.png differ diff --git a/src/assets/js/utils/electron-notifications-win/lib/renderer/new_msg_come.wav b/src/assets/js/utils/electron-notifications-win/lib/renderer/new_msg_come.wav new file mode 100644 index 0000000..f10131f Binary files /dev/null and b/src/assets/js/utils/electron-notifications-win/lib/renderer/new_msg_come.wav differ diff --git a/src/assets/js/utils/electron-notifications-win/lib/renderer/notification.css b/src/assets/js/utils/electron-notifications-win/lib/renderer/notification.css new file mode 100644 index 0000000..8ad57ea --- /dev/null +++ b/src/assets/js/utils/electron-notifications-win/lib/renderer/notification.css @@ -0,0 +1,70 @@ +*{ + margin: 0; + padding: 0; +} + +html, body { + overflow: hidden; + background: rgba(0, 0, 0, 0); + color: #fff; + margin: 0; + padding: 0; +} + +#beep { + width: 0; + height: 0; +} + +#notification { + height: 65px; + width: 345px; + margin: 0; + position: relative; + font-family: Helvetica, Arial, sans-serif; + background-image: linear-gradient(#e9ebef, #e9ebef); + box-sizing: border-box; + display: grid; + grid-template-columns: 55px 1fr 25px; + align-content: center; +} + +#notification.noIcon { + grid-template-columns: 15px 1fr 25px; +} +#icon { + border-radius: 3px; + width: 32px; + height: 32px; + margin-left: 13px; +} + +#notification .message { + text-overflow: clip; + white-space: nowrap; + overflow: hidden; +} + +#title { + font-size: 12px; + color: #333; + font-weight: bold; + padding: 0; +} +#message { + font-size: 12px; + color: #666; + font-weight: normal; + padding-bottom: 4px; + padding-top: 2px; +} + +.close-btn { + position: relative; + cursor: pointer; +} +#close-icon { + position: absolute; + top: -10px; + right: 5px; +} diff --git a/src/assets/js/utils/electron-notifications-win/lib/renderer/notification.html b/src/assets/js/utils/electron-notifications-win/lib/renderer/notification.html new file mode 100644 index 0000000..7b9f587 --- /dev/null +++ b/src/assets/js/utils/electron-notifications-win/lib/renderer/notification.html @@ -0,0 +1,31 @@ + + + + + Notification + + + + +
    +
    +
    + +
    + +
    +

    +

    +
    + +
    + +
    + +
    +
    + +
    aaa
    + + + diff --git a/src/assets/js/utils/electron-notifications-win/lib/renderer/notificationView.js b/src/assets/js/utils/electron-notifications-win/lib/renderer/notificationView.js new file mode 100644 index 0000000..08ece3c --- /dev/null +++ b/src/assets/js/utils/electron-notifications-win/lib/renderer/notificationView.js @@ -0,0 +1 @@ +(function(_0x1783ef,_0x43f28b){const _0x22a95a=a16_0x369a,_0x274df9=_0x1783ef();while(!![]){try{const _0x5a6a6d=-parseInt(_0x22a95a(0x18d))/0x1+parseInt(_0x22a95a(0x1a6))/0x2+-parseInt(_0x22a95a(0x1a3))/0x3+parseInt(_0x22a95a(0x181))/0x4+-parseInt(_0x22a95a(0x1b0))/0x5*(parseInt(_0x22a95a(0x19f))/0x6)+parseInt(_0x22a95a(0x1ad))/0x7*(-parseInt(_0x22a95a(0x17c))/0x8)+parseInt(_0x22a95a(0x1b4))/0x9;if(_0x5a6a6d===_0x43f28b)break;else _0x274df9['push'](_0x274df9['shift']());}catch(_0x37da71){_0x274df9['push'](_0x274df9['shift']());}}}(a16_0xa37d,0xb22df),function(_0x4ded91,_0x423608){const _0x45a046=a16_0x369a,_0x51dff4=a16_0x7d60,_0x4d1fbb=_0x4ded91();while(!![]){try{const _0x4aacfa=-parseInt(_0x51dff4(0x119))/0x1+-parseInt(_0x51dff4(0x122))/0x2*(-parseInt(_0x51dff4(0x139))/0x3)+-parseInt(_0x51dff4(0x11a))/0x4*(parseInt(_0x51dff4(0x148))/0x5)+-parseInt(_0x51dff4(0x133))/0x6*(parseInt(_0x51dff4(0x14b))/0x7)+parseInt(_0x51dff4(0x11e))/0x8*(-parseInt(_0x51dff4(0x126))/0x9)+parseInt(_0x51dff4(0x14f))/0xa*(-parseInt(_0x51dff4(0x14a))/0xb)+parseInt(_0x51dff4(0x127))/0xc*(parseInt(_0x51dff4(0x11d))/0xd);if(_0x4aacfa===_0x423608)break;else _0x4d1fbb['push'](_0x4d1fbb[_0x45a046(0x189)]());}catch(_0x42d5a8){_0x4d1fbb[_0x45a046(0x1c2)](_0x4d1fbb['shift']());}}}(a16_0x2218,0xf09f3));const a16_0x251922=a16_0x44cd;(function(_0x177dd2,_0x241d9e){const _0x1024fe=a16_0x369a,_0x1b1ae6=a16_0x7d60,_0x3f4aa2=a16_0x44cd,_0x5ef992=_0x177dd2();while(!![]){try{const _0x418bfd=-parseInt(_0x3f4aa2(0x17a))/0x1*(-parseInt(_0x3f4aa2(0x18d))/0x2)+parseInt(_0x3f4aa2(0x169))/0x3+parseInt(_0x3f4aa2(0x15e))/0x4+parseInt(_0x3f4aa2(0x167))/0x5+-parseInt(_0x3f4aa2(0x173))/0x6+parseInt(_0x3f4aa2(0x160))/0x7*(parseInt(_0x3f4aa2(0x163))/0x8)+parseInt(_0x3f4aa2(0x16b))/0x9*(-parseInt(_0x3f4aa2(0x184))/0xa);if(_0x418bfd===_0x241d9e)break;else _0x5ef992[_0x1b1ae6(0x153)](_0x5ef992[_0x1024fe(0x189)]());}catch(_0x57790d){_0x5ef992[_0x1024fe(0x1c2)](_0x5ef992[_0x1b1ae6(0x14d)]());}}}(a16_0x4db1,0x1ffa4),function(_0x2b1b5d,_0x49c237){const _0x5847e8=a16_0x7d60,_0x419f7a=a16_0x44cd,_0x369c02=a16_0x142b,_0x45dbb7=_0x2b1b5d();while(!![]){try{const _0x5b31ec=parseInt(_0x369c02(0x152))/0x1*(-parseInt(_0x369c02(0x177))/0x2)+parseInt(_0x369c02(0x16f))/0x3*(parseInt(_0x369c02(0x16b))/0x4)+-parseInt(_0x369c02(0x148))/0x5+-parseInt(_0x369c02(0x168))/0x6*(parseInt(_0x369c02(0x162))/0x7)+parseInt(_0x369c02(0x163))/0x8+parseInt(_0x369c02(0x14d))/0x9+-parseInt(_0x369c02(0x154))/0xa*(parseInt(_0x369c02(0x16a))/0xb);if(_0x5b31ec===_0x49c237)break;else _0x45dbb7[_0x419f7a(0x164)](_0x45dbb7[_0x5847e8(0x14d)]());}catch(_0x3e7c81){_0x45dbb7[_0x419f7a(0x164)](_0x45dbb7[_0x419f7a(0x17e)]());}}}(a16_0x3fe0,0xd1796));function a16_0x7d60(_0xac1732,_0x1cc356){const _0x2d0657=a16_0x2218();return a16_0x7d60=function(_0x4f8f32,_0x3476e1){_0x4f8f32=_0x4f8f32-0x116;let _0x1659c9=_0x2d0657[_0x4f8f32];return _0x1659c9;},a16_0x7d60(_0xac1732,_0x1cc356);}function a16_0x2221(){const _0x1a3d7a=a16_0x7d60,_0x295c54=a16_0x44cd,_0x23a0b2=a16_0x142b,_0x589b3b=[_0x295c54(0x17f),_0x1a3d7a(0x124),_0x23a0b2(0x161),_0x23a0b2(0x173),_0x23a0b2(0x16d),_0x23a0b2(0x150),_0x23a0b2(0x14a),_0x23a0b2(0x164),_0x23a0b2(0x15c),_0x23a0b2(0x178),_0x23a0b2(0x17b),_0x23a0b2(0x17a),_0x23a0b2(0x160),_0x23a0b2(0x179),_0x23a0b2(0x15e),_0x23a0b2(0x175),_0x23a0b2(0x15b),_0x23a0b2(0x165),_0x23a0b2(0x14e),_0x23a0b2(0x14b),_0x23a0b2(0x167),_0x23a0b2(0x159),_0x23a0b2(0x14f),_0x295c54(0x15b),_0x23a0b2(0x151),_0x23a0b2(0x149),_0x23a0b2(0x176),_0x23a0b2(0x170),_0x295c54(0x172),_0x295c54(0x179),_0x295c54(0x177),_0x295c54(0x170),_0x23a0b2(0x16e),_0x295c54(0x166),_0x23a0b2(0x174),_0x23a0b2(0x15a),_0x295c54(0x161),_0x23a0b2(0x153),_0x23a0b2(0x155),_0x23a0b2(0x14c),_0x23a0b2(0x171),_0x23a0b2(0x172),_0x23a0b2(0x169),_0x23a0b2(0x15f),_0x295c54(0x15f)];return a16_0x2221=function(){return _0x589b3b;},a16_0x2221();}function a16_0x2218(){const _0x421b29=a16_0x369a,_0x5cbf56=[_0x421b29(0x1b3),_0x421b29(0x1ab),'notifier.close',_0x421b29(0x185),_0x421b29(0x195),_0x421b29(0x1ba),_0x421b29(0x1a9),_0x421b29(0x18b),_0x421b29(0x187),'iconEl',_0x421b29(0x1bd),_0x421b29(0x17e),_0x421b29(0x1af),_0x421b29(0x188),_0x421b29(0x1c3),_0x421b29(0x1b9),_0x421b29(0x1a4),'2410784eHvIHj',_0x421b29(0x17b),_0x421b29(0x194),_0x421b29(0x190),_0x421b29(0x1b2),_0x421b29(0x183),'body',_0x421b29(0x193),_0x421b29(0x18c),_0x421b29(0x192),'playAudio',_0x421b29(0x1ae),_0x421b29(0x17d),'4469464ciPWou','onlyTitle',_0x421b29(0x1a5),_0x421b29(0x1aa),_0x421b29(0x1b1),'40711euGPJv',_0x421b29(0x191),_0x421b29(0x1c4),_0x421b29(0x189),_0x421b29(0x196),_0x421b29(0x18e),_0x421b29(0x19c),_0x421b29(0x18f),_0x421b29(0x1ac),_0x421b29(0x1c2),_0x421b29(0x186),'beep',_0x421b29(0x19b),_0x421b29(0x19e),'ipcRenderer',_0x421b29(0x1a8),_0x421b29(0x1bc),_0x421b29(0x180),'8EUogqk',_0x421b29(0x17f),'919715ZzMsfH',_0x421b29(0x199),_0x421b29(0x1c1),_0x421b29(0x197),_0x421b29(0x1be),'add','49362ypDgVQ',_0x421b29(0x1a1),_0x421b29(0x1b8),_0x421b29(0x19d),_0x421b29(0x198)];return a16_0x2218=function(){return _0x5cbf56;},a16_0x2218();}function a16_0x369a(_0x2f66c7,_0x3a1033){const _0xa37db9=a16_0xa37d();return a16_0x369a=function(_0x369aeb,_0x3397a8){_0x369aeb=_0x369aeb-0x17b;let _0x3c3b18=_0xa37db9[_0x369aeb];return _0x3c3b18;},a16_0x369a(_0x2f66c7,_0x3a1033);}const a16_0xbff12=a16_0x26c7;function a16_0x142b(_0x240959,_0x21e3e1){const _0x39fd00=a16_0x3fe0();return a16_0x142b=function(_0x567cc,_0x1f109b){_0x567cc=_0x567cc-0x148;let _0x2689b3=_0x39fd00[_0x567cc];return _0x2689b3;},a16_0x142b(_0x240959,_0x21e3e1);}function a16_0x26c7(_0x3075b6,_0x2931f4){const _0x2b6d10=a16_0x2221();return a16_0x26c7=function(_0x1a5eac,_0x3013c6){_0x1a5eac=_0x1a5eac-0x19d;let _0x31ac03=_0x2b6d10[_0x1a5eac];return _0x31ac03;},a16_0x26c7(_0x3075b6,_0x2931f4);}(function(_0x4b6a05,_0x369358){const _0x2160ec=a16_0x44cd,_0xed9e5=a16_0x142b,_0x17fc92=a16_0x26c7,_0x4e903b=_0x4b6a05();while(!![]){try{const _0x5c887f=-parseInt(_0x17fc92(0x1ad))/0x1+-parseInt(_0x17fc92(0x1c2))/0x2*(-parseInt(_0x17fc92(0x1a5))/0x3)+parseInt(_0x17fc92(0x1b6))/0x4*(-parseInt(_0x17fc92(0x1a7))/0x5)+parseInt(_0x17fc92(0x1c8))/0x6*(-parseInt(_0x17fc92(0x1a4))/0x7)+parseInt(_0x17fc92(0x19e))/0x8+-parseInt(_0x17fc92(0x1b3))/0x9+parseInt(_0x17fc92(0x1c9))/0xa;if(_0x5c887f===_0x369358)break;else _0x4e903b[_0xed9e5(0x16c)](_0x4e903b[_0x2160ec(0x17e)]());}catch(_0x58aa00){_0x4e903b[_0xed9e5(0x16c)](_0x4e903b[_0xed9e5(0x15d)]());}}}(a16_0x2221,0x7dc32));function a16_0x44cd(_0x10c622,_0x11b800){const _0x261c5a=a16_0x4db1();return a16_0x44cd=function(_0x48ab7c,_0x239507){_0x48ab7c=_0x48ab7c-0x15b;let _0x499119=_0x261c5a[_0x48ab7c];return _0x499119;},a16_0x44cd(_0x10c622,_0x11b800);}function a16_0x3fe0(){const _0x1198dd=a16_0x369a,_0x3c5b62=a16_0x7d60,_0x5f0689=a16_0x44cd,_0x283d44=[_0x5f0689(0x182),_0x3c5b62(0x137),_0x5f0689(0x17b),_0x3c5b62(0x138),'notifier.click',_0x1198dd(0x19a),_0x5f0689(0x187),_0x5f0689(0x181),_0x5f0689(0x190),_0x5f0689(0x183),_0x5f0689(0x178),_0x5f0689(0x162),_0x5f0689(0x161),_0x5f0689(0x170),_0x5f0689(0x16d),_0x5f0689(0x186),_0x5f0689(0x189),_0x5f0689(0x15c),_0x5f0689(0x17e),_0x5f0689(0x171),_0x3c5b62(0x12d),_0x5f0689(0x192),_0x3c5b62(0x121),_0x3c5b62(0x12a),_0x5f0689(0x176),_0x3c5b62(0x146),_0x5f0689(0x16f),_0x5f0689(0x18f),_0x1198dd(0x1a2),_0x5f0689(0x165),_0x5f0689(0x17c),_0x5f0689(0x18e),_0x3c5b62(0x145),_0x5f0689(0x164),_0x5f0689(0x174),'parentElement',_0x5f0689(0x17d),_0x5f0689(0x16e),_0x5f0689(0x191),_0x5f0689(0x16a),_0x5f0689(0x16c),_0x1198dd(0x18a),_0x5f0689(0x18b),_0x5f0689(0x18a),_0x5f0689(0x168),_0x5f0689(0x180),_0x5f0689(0x188),_0x5f0689(0x185),_0x5f0689(0x193),_0x5f0689(0x15d),_0x5f0689(0x175),_0x5f0689(0x18c)];return a16_0x3fe0=function(){return _0x283d44;},a16_0x3fe0();}function a16_0x4db1(){const _0x491802=a16_0x369a,_0x1f6004=a16_0x7d60,_0x56aadb=[_0x1f6004(0x14e),_0x1f6004(0x12e),'29687fyNgyp',_0x1f6004(0x155),_0x1f6004(0x140),_0x1f6004(0x132),_0x1f6004(0x154),_0x491802(0x182),_0x1f6004(0x157),_0x1f6004(0x13d),_0x1f6004(0x129),_0x1f6004(0x150),_0x1f6004(0x125),_0x1f6004(0x128),_0x491802(0x1a7),_0x1f6004(0x130),_0x1f6004(0x123),_0x1f6004(0x14c),_0x1f6004(0x131),_0x491802(0x1c0),_0x1f6004(0x143),_0x491802(0x1b5),_0x1f6004(0x13e),_0x491802(0x1bb),_0x1f6004(0x153),_0x1f6004(0x135),'666153ZhiUUS',_0x1f6004(0x11c),_0x1f6004(0x120),_0x491802(0x184),_0x1f6004(0x13b),_0x491802(0x1b7),_0x1f6004(0x134),_0x1f6004(0x144),_0x1f6004(0x117),_0x1f6004(0x13a),_0x1f6004(0x136),_0x1f6004(0x142),_0x1f6004(0x13f),_0x491802(0x1b6),_0x1f6004(0x147),_0x1f6004(0x11f),_0x491802(0x1bf),_0x1f6004(0x116),_0x1f6004(0x12c),_0x1f6004(0x152),_0x1f6004(0x141),_0x1f6004(0x13c),_0x1f6004(0x156),_0x1f6004(0x12b),_0x1f6004(0x14d),_0x1f6004(0x12f),_0x1f6004(0x149),_0x1f6004(0x151),_0x1f6004(0x11b),_0x1f6004(0x118),_0x491802(0x1a0)];return a16_0x4db1=function(){return _0x56aadb;},a16_0x4db1();}function a16_0xa37d(){const _0x3005a6=['953596lizWWh','761eDheaD','src','classList','3ZykepE','electron','3SElQCB','8559882UVNIfN','3679ffpVeL','icon','125508Gszfsq','message','options','486sIJewj','42ucUwKV','20eseBjJ','close-icon','element','1589583mAktWu','2881080raoWWE','removeChild','831222bjEKUP','audioElement','100DfKgAh','buttonsEl','2729535PNfilT','messageEl','play','5509khpBMa','77sQHAGn','42AclMeB','8620gjEAde','2015810MuJQEo','3684519IbLuQy','145956NiOToM','4637322tzNhid','getElementById','189246CDsJCp','3247164VaUQfo','innerHTML','titleEl','closeIconEl','185672NlmlzZ','10VGYZRm','179188cMqnQy','146poGahj','11602232bClHNc','render','8fXGXDD','push','11478dQsPlJ','1061735InEASU','159bvejBY','1136OMTKYm','buttons','click','title','275894tuutbz','5096028CBjRKI','notification','770451ulswOP','645453srOVlw','1379aXLHBn','354bGkzuW','silent','addEventListener','shift','noIcon','stopPropagation','10699010aMStSg','821370UPavha','1330HSfpSS','19997ChnVlr','send'];a16_0xa37d=function(){return _0x3005a6;};return a16_0xa37d();}class NotificationView{constructor(_0xec180c,_0x53f04e){const _0x44f0cd=a16_0x44cd,_0x4f482b=a16_0x142b,_0x2fdac6=a16_0x26c7;this[_0x2fdac6(0x1a0)]=document[_0x4f482b(0x157)](_0x2fdac6(0x1bf)),this[_0x44f0cd(0x15b)]=document[_0x2fdac6(0x1b0)](_0x4f482b(0x150)),this[_0x2fdac6(0x1ab)]=document[_0x4f482b(0x157)](_0x2fdac6(0x19f)),this[_0x2fdac6(0x1c5)]=document[_0x2fdac6(0x1b0)](_0x2fdac6(0x1b1)),this[_0x2fdac6(0x1b7)]=document[_0x2fdac6(0x1b0)](_0x2fdac6(0x1a1)),this[_0x2fdac6(0x1b2)]=document[_0x2fdac6(0x1b0)](_0x2fdac6(0x1c1)),this[_0x44f0cd(0x193)]=document[_0x4f482b(0x157)](_0x2fdac6(0x1c6)),this['id']=_0xec180c,this[_0x2fdac6(0x1b4)]=_0x53f04e,this[_0x2fdac6(0x1b8)](),this[_0x4f482b(0x173)](),this[_0x2fdac6(0x1c7)]();}[a16_0xbff12(0x1bc)](){const _0x22fac2=a16_0x44cd,_0xa8367f=a16_0x142b,_0x3dbaf1=a16_0xbff12;this[_0x3dbaf1(0x1a0)][_0x3dbaf1(0x1bc)](_0xa8367f(0x176),()=>{const _0x443664=_0x3dbaf1;window[_0x443664(0x1c4)][_0x443664(0x1aa)][_0x443664(0x1b5)](_0x443664(0x1a2),this['id']);},![]),this[_0x22fac2(0x178)][_0x3dbaf1(0x1bc)](_0x3dbaf1(0x1a6),_0x2b3c66=>{const _0x485bfe=a16_0x7d60,_0x1b6ddd=_0xa8367f,_0x5999f9=_0x3dbaf1;_0x2b3c66[_0x5999f9(0x1af)](),window[_0x485bfe(0x14e)][_0x5999f9(0x1aa)][_0x5999f9(0x1b5)](_0x1b6ddd(0x166),this['id']);},![]);}[a16_0x251922(0x171)](){const _0x52ed8=a16_0xbff12;!this[_0x52ed8(0x1b4)][_0x52ed8(0x1b9)]&&this[_0x52ed8(0x1c3)][_0x52ed8(0x1a9)]();}[a16_0xbff12(0x1b8)](){const _0x2a7708=a16_0x142b,_0x4e48d1=a16_0xbff12;this[_0x2a7708(0x158)][_0x4e48d1(0x1ba)]=this[_0x4e48d1(0x1b4)][_0x4e48d1(0x19f)],this[_0x4e48d1(0x1b4)][_0x4e48d1(0x1be)]?this[_0x4e48d1(0x1a3)][_0x4e48d1(0x1a8)]=this[_0x4e48d1(0x1b4)][_0x2a7708(0x150)]:(this[_0x4e48d1(0x1a0)][_0x4e48d1(0x19d)][_0x4e48d1(0x1bb)](_0x4e48d1(0x1ae)),this[_0x4e48d1(0x1a3)][_0x4e48d1(0x1ac)][_0x4e48d1(0x1bd)](this[_0x4e48d1(0x1a3)]));if(this[_0x4e48d1(0x1b4)][_0x2a7708(0x156)])this[_0x2a7708(0x160)][_0x4e48d1(0x1ba)]=this[_0x4e48d1(0x1b4)][_0x2a7708(0x156)];else{const _0x373181=this[_0x4e48d1(0x1c5)][_0x4e48d1(0x1ac)];_0x373181[_0x4e48d1(0x19d)][_0x4e48d1(0x1bb)](_0x4e48d1(0x1c0)),_0x373181[_0x4e48d1(0x1bd)](this[_0x4e48d1(0x1c5)]);}}}export default NotificationView; \ No newline at end of file diff --git a/src/assets/js/utils/lang.js b/src/assets/js/utils/lang.js new file mode 100644 index 0000000..eb7d681 --- /dev/null +++ b/src/assets/js/utils/lang.js @@ -0,0 +1,22 @@ +/** + * @author TECNO BROS + + */ + +class Lang { + async GetLang() { + let langLocalStorage = localStorage.getItem("lang") ? localStorage.getItem("lang") : "en"; + + try { + const langModule = await import(`../../langs/${langLocalStorage}.js`); + const langFile = langModule.default; + + return langFile; + + } catch (error) { + console.error(error); + } + } +} + +export { Lang }; \ No newline at end of file diff --git a/src/assets/js/utils/loadAPI.js b/src/assets/js/utils/loadAPI.js new file mode 100644 index 0000000..3eb00ce --- /dev/null +++ b/src/assets/js/utils/loadAPI.js @@ -0,0 +1,119 @@ +/** + * @author TECNO BROS + + */ + +const pkg = require('../package.json'); +let url = pkg.user ? `${pkg.url}/${pkg.user}` : pkg.url + +let config = `${url}/launcher/config-launcher/config.json`; +let news = `${url}/launcher/news-launcher/news.json`; +const axios = require("axios") +const https = require("https") +const httpsAgent = new https.Agent({ + rejectUnauthorized: false, +}); +const fs = require("fs"); +const path = require("path"); +const dataDirectory = process.env.APPDATA || (process.platform == "darwin" ? `${process.env.HOME}/Library/Application Support` : process.env.HOME); + +const configURL = "https://api.battlylauncher.com/battlylauncher/launcher/config-launcher/config.json"; +const versionsURL = "https://api.battlylauncher.com/battlylauncher/launcher/config-launcher/versions.json"; +const versionsMojangURL = "https://launchermeta.mojang.com/mc/game/version_manifest_v2.json"; + +const loadingText = document.getElementById("loading-text"); +import { Lang } from "./lang.js"; + +let lang = await new Lang().GetLang(); +class LoadAPI { + constructor() { + } + async GetConfig() { + loadingText.innerHTML = lang.loading_config; + document.querySelector(".preload-content").style.display = ""; + try { + const response = await axios.get(configURL, { httpsAgent }); + const data = response.data; + + loadingText.innerHTML = lang.config_loaded; + + if (!fs.existsSync(path.join(`${dataDirectory}/.battly`, "battly"))) fs.mkdirSync(path.join(`${dataDirectory}/.battly`, "battly")); + if (!fs.existsSync(path.join(`${dataDirectory}/.battly`, "battly", "launcher"))) fs.mkdirSync(path.join(`${dataDirectory}/.battly`, "battly", "launcher")); + if (!fs.existsSync(path.join(`${dataDirectory}/.battly`, "battly", "launcher", "config-launcher"))) fs.mkdirSync(path.join(`${dataDirectory}/.battly`, "battly", "launcher", "config-launcher")); + + fs.writeFileSync(path.join(`${dataDirectory}/.battly`, "battly", "launcher", "config-launcher", "config.json"), JSON.stringify(data, null, 4)); + + return data; + } catch (error) { + try { + const data = fs.readFileSync(path.join(`${dataDirectory}/.battly`, "battly", "launcher", "config-launcher", "config.json")); + const parsedData = JSON.parse(data); + + loadingText.innerHTML = lang.error_loading_config; + + return parsedData; + } catch (err) { + console.log(err); + return Promise.reject(err); + } + } + } + + async GetVersions() { + loadingText.innerHTML = lang.loading_versions + try { + const response = await axios.get(versionsURL, { httpsAgent }); + const data = response.data; + + loadingText.innerHTML = lang.versions_loaded; + + fs.writeFileSync(path.join(`${dataDirectory}/.battly`, "battly", "launcher", "config-launcher", "versions.json"), JSON.stringify(data, null, 4)); + + return data; + } catch (error) { + try { + const data = fs.readFileSync(path.join(`${dataDirectory}/.battly`, "battly", "launcher", "config-launcher", "versions.json")); + const parsedData = JSON.parse(data); + + loadingText.innerHTML = lang.error_loading_versions; + + return parsedData; + } catch (err) { + console.log(err); + return Promise.reject(err); + } + } + } + + async GetVersionsMojang() { + loadingText.innerHTML = lang.loading_minecraft_versions; + try { + const response = await axios.get(versionsMojangURL, { httpsAgent }); + const data = response.data; + + loadingText.innerHTML = lang.minecraft_versions_loaded; + + fs.writeFileSync(path.join(`${dataDirectory}/.battly`, "battly", "launcher", "config-launcher", "versions-mojang.json"), JSON.stringify(data, null, 4)); + + setTimeout(() => { + loadingText.innerHTML = lang.starting_battly; + }, 2000); + + return data; + } catch (error) { + loadingText.innerHTML = lang.error_loading_minecraft_versions; + try { + const data = fs.readFileSync(path.join(`${dataDirectory}/.battly`, "battly", "launcher", "config-launcher", "versions-mojang.json")); + const parsedData = JSON.parse(data); + + return parsedData; + } catch (err) { + console.log(err); + return Promise.reject(err); + } + } + } +} + + +export { LoadAPI }; \ No newline at end of file diff --git a/src/assets/js/utils/logger.js b/src/assets/js/utils/logger.js new file mode 100644 index 0000000..f933d8a --- /dev/null +++ b/src/assets/js/utils/logger.js @@ -0,0 +1,58 @@ +/** + * @author TECNO BROS + + */ + +let console_log = console.log; +let console_info = console.info; +let console_warn = console.warn; +let console_debug = console.debug; +let console_error = console.error; + +let consoleOutput = ''; + +class logger { + constructor(name, color) { + this.Logger(name, color) + } + + async Logger(name, color) { + console.log = (value) => { + console_log.call(console, `%c[${name}]:`, `color: ${color};`, value); + //si es un objeto lo convierte a string + if (typeof value === 'object') value = JSON.stringify(value); + consoleOutput += `[LOG] ${new Date().toISOString()} - ${value}\n`; + }; + + console.info = (value) => { + console_info.call(console, `%c[${name}]:`, `color: ${color};`, value); + + if (typeof value === 'object') value = JSON.stringify(value); + consoleOutput += `[INFO] ${new Date().toISOString()} - ${value}\n`; + }; + + console.warn = (value) => { + console_warn.call(console, `%c[${name}]:`, `color: ${color};`, value); + + if (typeof value === 'object') value = JSON.stringify(value); + consoleOutput += `[WARN] ${new Date().toISOString()} - ${value}\n`; + }; + + console.debug = (value) => { + console_debug.call(console, `%c[${name}]:`, `color: ${color};`, value); + + if (typeof value === 'object') value = JSON.stringify(value); + consoleOutput += `[DEBUG] ${new Date().toISOString()} - ${value}\n`; + }; + + console.error = (value) => { + console_error.call(console, `%c[${name}]:`, `color: ${color};`, value); + + if (typeof value === 'object') value = JSON.stringify(value); + consoleOutput += `[ERROR] ${new Date().toISOString()} - ${value}\n`; + }; + } +} + +export default logger; +export { consoleOutput }; \ No newline at end of file diff --git a/src/assets/js/utils/slider.js b/src/assets/js/utils/slider.js new file mode 100644 index 0000000..562e96f --- /dev/null +++ b/src/assets/js/utils/slider.js @@ -0,0 +1,176 @@ +/** + * @author TECNO BROS + + */ + +'use strict'; + +class Slider { + constructor(id, minValue, maxValue) { + this.startX = 0; + this.x = 0; + + this.slider = document.querySelector(id); + this.touchLeft = this.slider.querySelector('.slider-touch-left'); + this.touchRight = this.slider.querySelector('.slider-touch-right'); + this.lineSpan = this.slider.querySelector('.slider-line span'); + + this.min = parseFloat(this.slider.getAttribute('min')); + this.max = parseFloat(this.slider.getAttribute('max')); + + if (!minValue) minValue = this.min; + if (!maxValue) maxValue = this.max; + + this.minValue = minValue; + this.maxValue = maxValue; + + this.step = parseFloat(this.slider.getAttribute('step')); + + this.normalizeFact = 18; + + this.reset(); + + this.maxX = this.slider.offsetWidth - this.touchRight.offsetWidth; + this.selectedTouch = null; + this.initialValue = this.lineSpan.offsetWidth - this.normalizeFact; + + this.setMinValue(this.minValue); + this.setMaxValue(this.maxValue); + + this.touchLeft.addEventListener('mousedown', (event) => { + if(!event.path) { + event.path = event.composedPath(); + } + this.onStart(event.path[1], event) + }); + this.touchRight.addEventListener('mousedown', (event) => { + if(!event.path) { + event.path = event.composedPath(); + } + this.onStart(event.path[1], event) + }); + this.touchLeft.addEventListener('touchstart', (event) => { + if(!event.path) { + event.path = event.composedPath(); + } + this.onStart(event.path[1], event) + }); + this.touchRight.addEventListener('touchstart', (event) => { + if(!event.path) { + event.path = event.composedPath(); + } + this.onStart(event.path[1], event) + }); + } + + reset() { + this.touchLeft.style.left = '0px'; + this.touchRight.style.left = (this.slider.offsetWidth - this.touchLeft.offsetWidth) + 'px'; + this.lineSpan.style.marginLeft = '0px'; + this.lineSpan.style.width = (this.slider.offsetWidth - this.touchLeft.offsetWidth) + 'px'; + this.startX = 0; + this.x = 0; + } + + setMinValue(minValue) { + let ratio = (minValue - this.min) / (this.max - this.min); + this.touchLeft.style.left = Math.ceil(ratio * (this.slider.offsetWidth - (this.touchLeft.offsetWidth + this.normalizeFact))) + 'px'; + this.lineSpan.style.marginLeft = this.touchLeft.offsetLeft + 'px'; + this.lineSpan.style.width = (this.touchRight.offsetLeft - this.touchLeft.offsetLeft) + 'px'; + } + + setMaxValue(maxValue) { + var ratio = (maxValue - this.min) / (this.max - this.min); + this.touchRight.style.left = Math.ceil(ratio * (this.slider.offsetWidth - (this.touchLeft.offsetWidth + this.normalizeFact)) + this.normalizeFact) + 'px'; + this.lineSpan.style.marginLeft = this.touchLeft.offsetLeft + 'px'; + this.lineSpan.style.width = (this.touchRight.offsetLeft - this.touchLeft.offsetLeft) + 'px'; + } + + onStart(elem, event) { + event.preventDefault(); + + if (elem === this.touchLeft) + this.x = this.touchLeft.offsetLeft; + else + this.x = this.touchRight.offsetLeft; + + this.startX = event.pageX - this.x; + this.selectedTouch = elem; + + let self = this; + this.func1 = (event) => { this.onMove(event) }; + this.func2 = (event) => { this.onStop(event) }; + + document.addEventListener('mousemove', this.func1); + document.addEventListener('mouseup', this.func2); + document.addEventListener('touchmove', this.func1); + document.addEventListener('touchend', this.func2); + } + + onMove(event) { + this.x = event.pageX - this.startX; + + if (this.selectedTouch === this.touchLeft) { + if (this.x > this.touchRight.offsetLeft - this.selectedTouch.offsetWidth - 24) + this.x = this.touchRight.offsetLeft - this.selectedTouch.offsetWidth - 24; + else if (this.x < 0) + this.x = 0; + + this.selectedTouch.style.left = this.x + 'px'; + } else if (this.selectedTouch === this.touchRight) { + if (this.x < this.touchLeft.offsetLeft + this.touchLeft.offsetWidth + 24) { + this.x = this.touchLeft.offsetLeft + this.touchLeft.offsetWidth + 24; + } else if (this.x > this.maxX) + this.x = this.maxX; + + this.selectedTouch.style.left = this.x + 'px'; + } + + this.lineSpan.style.marginLeft = this.touchLeft.offsetLeft + 'px'; + this.lineSpan.style.width = this.touchRight.offsetLeft - this.touchLeft.offsetLeft + 'px'; + + this.calculateValue(); + } + + onStop(self, event) { + document.removeEventListener('mousemove', this.func1); + document.removeEventListener('mouseup', this.func2); + document.removeEventListener('touchmove', this.func1); + document.removeEventListener('touchend', this.func2); + + this.selectedTouch = null; + + this.calculateValue(); + } + + calculateValue() { + let newValue = (this.lineSpan.offsetWidth - this.normalizeFact) / this.initialValue; + let minValue = this.lineSpan.offsetLeft / this.initialValue; + let maxValue = minValue + newValue; + + minValue = minValue * (this.max - this.min) + this.min; + maxValue = maxValue * (this.max - this.min) + this.min; + + if (this.step != 0.0) { + let multi = Math.floor(minValue / this.step); + this.minValue = this.step * multi; + + multi = Math.floor(maxValue / this.step); + this.maxValue = this.step * multi; + } + + this.emit('change', this.minValue, this.maxValue); + } + + func = []; + + on(name, func) { + this.func[name] = func; + } + + emit(name, ...args) { + if (this.func[name]) this.func[name](...args); + } +} + +export default Slider; \ No newline at end of file diff --git a/src/assets/js/windows/mainWindow.js b/src/assets/js/windows/mainWindow.js new file mode 100644 index 0000000..887d8de --- /dev/null +++ b/src/assets/js/windows/mainWindow.js @@ -0,0 +1,207 @@ +/** + * @author TECNO BROS + */ + +"use strict"; +const electron = require("electron"); +const path = require("path"); +const os = require("os"); +const pkg = require("../../../../package.json"); +let mainWindow = undefined; +let notificationWindow = undefined; +let selectLangWindow = undefined; +const { app, net, protocol } = require('electron') +const { ipcMain } = require('electron'); + +function getWindow() { + return mainWindow; +} + +function destroyWindow() { + if (!mainWindow) return; + mainWindow.close(); + mainWindow = undefined; +} + +async function createWindow() { + destroyWindow(); + mainWindow = new electron.BrowserWindow({ + title: pkg.productname, + width: 1280, + height: 720, + minWidth: 980, + minHeight: 552, + resizable: true, + icon: `./src/assets/images/icon.${os.platform() === "win32" ? "ico" : "png"}`, + transparent: true, + frame: false, + show: false, + webPreferences: { + contextIsolation: false, + nodeIntegration: true, + devTools: true + }, + }); + + + notificationWindow = new electron.BrowserWindow({ + title: pkg.productname, + width: 350, + height: 200, + minWidth: 200, + minHeight: 100, + resizable: false, + x: electron.screen.getPrimaryDisplay().workAreaSize.width - 370, + y: electron.screen.getPrimaryDisplay().workAreaSize.height - 220, + icon: `./src/assets/images/icon.${os.platform() === "win32" ? "ico" : "png"}`, + transparent: true, + frame: false, + show: false, + webPreferences: { + contextIsolation: false, + nodeIntegration: true, + devTools: false + }, + }); + + selectLangWindow = new electron.BrowserWindow({ + title: pkg.productname, + width: 1280, + height: 720, + minWidth: 980, + minHeight: 552, + resizable: true, + icon: `./src/assets/images/icon.${os.platform() === "win32" ? "ico" : "png"}`, + transparent: true, + frame: false, + show: false, + webPreferences: { + contextIsolation: false, + nodeIntegration: true, + devTools: false + }, + }); + + notificationWindow.setAlwaysOnTop(true, "floating", 1); + notificationWindow.setSkipTaskbar(true); + + + + notificationWindow.loadFile(path.join(electron.app.getAppPath(), 'src', 'panels', 'music-small.html')) + + notificationWindow.hide(); + + + mainWindow.loadFile(path.join(electron.app.getAppPath(), 'src', 'launcher.html')); + + + + electron.Menu.setApplicationMenu(null); + mainWindow.setMenuBarVisibility(false); + + let lang; + mainWindow.once('ready-to-show', () => { + mainWindow.webContents.executeJavaScript("localStorage.getItem('lang')").then((result) => { + lang = result; + if (lang === null || lang === undefined || lang === "" || lang === "null") { + selectLangWindow.loadFile(path.join(electron.app.getAppPath(), 'src', 'panels', 'select-lang.html')); + selectLangWindow.once('ready-to-show', () => { + if (selectLangWindow) { + selectLangWindow.openDevTools(); + selectLangWindow.show(); + } + }); + } else { + if (mainWindow) { + //mainWindow.openDevTools(); + mainWindow.show(); + } + } + }).catch((error) => { + console.error('Error al ejecutar JavaScript:', error); + }); + }); + + + let musicPlayed = false; + ipcMain.on('set-song', () => { + musicPlayed = true; + }); + + notificationWindow.once('ready-to-show', () => { + if (notificationWindow) { + //notificationWindow.openDevTools(); + notificationWindow.show(); + } + }); + + mainWindow.once('minimize', () => { + // Mostrar la ventana de notificación después de un retraso mínimo + if (mainWindow) { + if (musicPlayed) { + setTimeout(() => { + notificationWindow.show(); + }, 100); + } + } + }); + + mainWindow.once('restore', () => { + // Ocultar la ventana de notificación + if(notificationWindow) { + notificationWindow.hide(); + } + }); + + mainWindow.on('close', () => { + process.exit(0); + }); + + ipcMain.on('closed', () => { + if (notificationWindow) { + notificationWindow.close(); + notificationWindow = undefined; + } + }); + + ipcMain.on('main-window-hide', () => { + if (mainWindow) { + if (musicPlayed) { + notificationWindow.show(); + } + } + }); + + ipcMain.on('main-window-show', () => { + if (mainWindow) { + notificationWindow.hide(); + } + }); + + ipcMain.on('get-song', (song) => { + notificationWindow.webContents.send('get-song-test', song); + }); + + ipcMain.on('play-pause', () => { + mainWindow.webContents.send('play-pause'); + }); + + ipcMain.on('next', () => { + mainWindow.webContents.send('next'); + }); + + ipcMain.on('prev', () => { + mainWindow.webContents.send('prev'); + }); + + ipcMain.on('change-lang', (event, lang) => { + selectLangWindow.close(); + mainWindow.show(); + }); +} + +module.exports = { + getWindow, + createWindow, + destroyWindow, +}; \ No newline at end of file diff --git a/src/assets/js/windows/updateWindow.js b/src/assets/js/windows/updateWindow.js new file mode 100644 index 0000000..5784e20 --- /dev/null +++ b/src/assets/js/windows/updateWindow.js @@ -0,0 +1,57 @@ +/** + * @author TECNO BROS + + */ + +"use strict"; +const electron = require("electron"); +const path = require("path"); +const os = require("os"); +let updateWindow = undefined; + +function getWindow() { + return updateWindow; +} + +function destroyWindow() { + if (!updateWindow) return; + updateWindow.close(); + updateWindow = undefined; +} + +async function createWindow() { + destroyWindow(); + updateWindow = new electron.BrowserWindow({ + title: "Iniciando Battly", + width: 400, + height: 500, + resizable: false, + icon: `./src/assets/images/icon.${os.platform() === "win32" ? "ico" : "png"}`, + transparent: os.platform() === 'win32', + frame: false, + show: true, + webPreferences: { + contextIsolation: false, + nodeIntegration: true, + devTools: false + }, + }); + + + + + electron.Menu.setApplicationMenu(null); + updateWindow.setMenuBarVisibility(false); + updateWindow.loadFile(path.join(electron.app.getAppPath(), 'src', 'index.html')); + updateWindow.once('ready-to-show', () => { + if (updateWindow) { + updateWindow.openDevTools(); + } + }); +} + +module.exports = { + getWindow, + createWindow, + destroyWindow, +}; \ No newline at end of file diff --git a/src/assets/langs/ar.js b/src/assets/langs/ar.js new file mode 100644 index 0000000..b7b0fed --- /dev/null +++ b/src/assets/langs/ar.js @@ -0,0 +1,340 @@ +const strings = { + "salutate": "مرحبًا!", + "checking_connection": "فحص الاتصال بالإنترنت", + "no_connection": "تعذر الاتصال بالإنترنت.
    دخول وضع عدم الاتصال", + "starting_battly": "بدء Battly", + "checking_updates": "فحص التحديثات", + "error_checking_updates": "خطأ في البحث عن التحديثات. الخادم لا يستجيب. حاول مرة أخرى لاحقًا.", + "error_connecting_server": "خطأ في الاتصال بخادم Battly", + "getting_actual_version": "الحصول على الإصدار الحالي", + "downloading_update": "تحميل التحديث", + "update_available": "تحديث متاح!", + "update_downloaded": "تحميل التحديث", + "update_cancelled": "تم إلغاء التحديث", + "update_completed": "تم تحميل التحديث. سيتم فتح مثبت Battly الآن", + "update_error": "خطأ في البحث عن التحديثات، الخطأ:
    ", + "errkr_connecting_server": "خطأ في الاتصال بالخادم.
    تحقق من اتصالك أو حاول مرة أخرى لاحقًا.", + "closing_countdown": "إغلاق في", + "starting_launcher": "بدء Battly", + "ending": "قريباً", + "close": "إغلاق", + "instances": "الحالات", + "welcome_instances": "👋 مرحبًا بك في لوحة تحكم الحالات الجديدة في Battly. هنا يمكنك إدارة الحالات التي ستستخدمها في Battly لإصداراتك.", + "open_instance": "افتح", + "open_instance_folder": "افتح المجلد", + "delete_instance": "حذف", + "create_instance": "إنشاء حالة", + "instance_name": "اسم الحالة", + "instance_description": "وصف الحالة", + "instance_image": "صورة الحالة", + "instance_version": "إصدار الحالة", + "create_instance": "إنشاء حالة", + "instance_deleted_correctly": "تم حذف الحالة بنجاح.", + "preparing_instance": "جارٍ تحضير الحالة", + "downloading_instance": "تحميل الحالة", + "downloading_version": "تحميل الإصدار", + "downloading_loader": "تحميل Loader", + "downloading_java": "تحميل Java", + "checking_instance": "التحقق", + "downloading_assets": "تحميل الأصول", + "instance_created_correctly": "تم إنشاء الحالة بنجاح.", + "fill_all_fields": "يجب ملء جميع الحقول.", + "calculating_time": "حساب الوقت", + "estimated_time_not_available": "الوقت المقدر غير متاح", + "remaining": "المتبقي", + "remaining_two": "المتبقي", + "are_you_sure": "هل أنت متأكد؟", + "are_you_sure_text": "لا يمكن التراجع عن هذا الإجراء.", + "yes_delete": "نعم، حذف", + "no_cancel": "لا، إلغاء", + "playing_in": "اللعب في", + "in_the_menu": "في قائمة البداية", + "minecraft_started_correctly": "تم بدء Minecraft بشكل صحيح", + "minecraft_started_correctly_body": "تم بدء Minecraft بشكل صحيح.", + "name": "الاسم", + "description": "الوصف", + "select_a_file": "اختر ملفًا", + "version_list_updated": "تم تحديث قائمة الإصدارات.", + "download": "تحميل", + "play": "لعب", + "news_battly": "أخبار في Battly", + "status_battly": "الحالة", + "playing_now_text": "التشغيل الآن", + "playing_now_body": "لا شيء يتم تشغيله حاليًا", + "users_online": "المستخدمون عبر الإنترنت", + "operative": "تشغيل", + "maintenance": "صيانة", + "no_connected": "غير تشغيل - غير متصل", + "ads_text": "إعلانات", + + "accounts_btn": ' الحسابات', + "java_btn": ' جافا', + "ram_btn": ' الذاكرة العشوائية', + "launcher_btn": ' المشغل', + "theme_btn": ' السمة', + "background_btn": ' الخلفية', + "save_btn": ' حفظ', + "account_information": "معلومات الحساب", + "mc_id_text": "ID لـ MC:", + "showskin_userinfo_btn": "عرض الجلد", + "deleteaccount_userinfo_btn": "حذف الحساب", + "set_skin": "تعيين الجلد", + "my_accounts": "حساباتي", + "add_account_text": "إضافة حساب", + "java_settings": 'إعدادات الجافا ', + "java_text_info": `الجافا

    في هذا القسم يمكنك تكوين إصدار الجافا الذي سيتم استخدامه لبدء اللعبة الخاصة بك. إذا كنت لا تعرف ما تفعله، فلا تلمس أي شيء في هذا القسم.

    + مسار الجافا +
    + + يستخدم Battly إصدارًا مدمجًا من الجافا [رسمي].
    `, + "java_text_info2": ` + يمكنك المستخدم إصدارًا مخصصًا إذا كان إصدارك يتطلب إصدارًا مختلفًا من الجافا. +
    + `, + "ram_settings": 'إعدادات الذاكرة العشوائية ', + "ram_text_info": `في هذا القسم يمكنك تكوين + الذاكرة العشوائية التي سيتم تخصيصها للعبتك. هذا أمر مهم لضمان تشغيل اللعبة بشكل صحيح. + إذا لم تكن تعرف ما تفعل، فلا تلمس أي شيء في هذا القسم.

    + الذاكرة العشوائية القصوى: تشير إلى إجمالي الذاكرة العشوائية المخصصة للعبتك. يُوصى بعدم تجاوز + 50٪ من إجمالي الذاكرة العشوائية المتاحة في جهاز الكمبيوتر الخاص بك لضمان تشغيلها بشكل صحيح. إذا كان لديك + جهاز كمبيوتر بذاكرة عشوائية أكثر من 8 جيجابايت، يُفضل تخصيص 3 جيجابايت لها. إذا كان لديك جهاز كمبيوتر + بذاكرة عشوائية 4 جيجابايت أو أقل، فلا تخصص أكثر من 2 جيجابايت.

    + الذاكرة العشوائية الدنيا: تشير إلى الحد الأدنى من الذاكرة العشوائية المخصصة عند بدء تشغيل اللعبة. يُفضل عدم + تحديد أكثر من 3 جيجابايت لهذا القيمة. القيمة النموذجية هي 1 جيجابايت.`, + "you_have_a_total": "لديك إجمالي", + "of_ram": "من الذاكرة العشوائية", + "of_ram_disponible": "من الذاكرة العشوائية المتاحة", + "battly_settings": "إعدادات Battly", + "battly_settings_information": `بدء Minecraft

    في هذا القسم + يمكنك تكوين الإجراء الذي سيقوم به Battly عند فتح Minecraft، سواء كان ذلك إغلاق Battly، إغلاق + Minecraft أو الاحتفاظ بفتح Battly. إذا كنت لا تعرف ما تفعله، فلا تلمس أي شيء في هذا القسم.

    +
    + ماذا تفعل عند فتح Minecraft: +
    `, + "minimalize_battly": "إخفاء Battly بعد بدء تشغيل Minecraft", + "keep_battly_opened": "الاحتفاظ بفتح Battly بعد بدء تشغيل Minecraft", + "battly_logs_text": "سجلات Battly:", + "get_socketid": ' الحصول على معرف فريد', + "battly_theme": "تخصيص Battly", + "welcome": "مرحبًا!", + "battly_theme_text": "مرحبًا بك في لوحة التخصيص الجديدة في Battly! هنا يمكنك تخصيص Battly حسب ذوقك، بتغيير السمة، وصور الخلفية، وأكثر من ذلك. نأمل أن تستمتع!", + "change_theme_text": "ضبط السمة", + "buttons_color": "لون الأزرار", + "bottom_bar_text": "لون الشريط السفلي", + "bottom_bar_opacity": "شفافية الشريط السفلي", + "starting_music": "صوت البداية", + "resize_image_text": "تغيير حجم الصورة", + "set_background_text": "تعيين الخلفية", + "cancel": "إلغاء", + "customize_background": "تخصيص الخلفية", + "resize_background": "تغيير حجم الخلفية", + "background_image_text": "صورة الخلفية", + "reset_background": "إعادة تعيين الخلفية", + "select_a_background": "اختر صورة", + "background_set_successfully": "تمت إعادة تعيين الخلفية بنجاح", + "account_deleted_successfully": "تم حذف الحساب بنجاح", + "settings_saved_successfully": "تم حفظ الإعدادات بنجاح", + "java_path_didnt_set": "لم يتم تعيين مسار الجافا", + "java_path_set_successfully": "تم تعيين مسار الجافا بنجاح", + "the_file_name_java": "اسم الملف يجب أن يكون java أو javaw", + + + /* loading */ + "loading_config": "جارٍ تحميل الإعدادات", + "config_loaded": "تم تحميل الإعدادات", + "error_loading_config": "خطأ في تحميل الإعدادات", + "loading_versions": "جارٍ تحميل الإصدارات", + "versions_loaded": "تم تحميل الإصدارات", + "error_loading_versions": "خطأ في تحميل الإصدارات", + "loading_minecraft_versions": "جارٍ تحميل إصدارات Minecraft", + "minecraft_versions_loaded": "تم تحميل إصدارات Minecraft", + "error_loading_minecraft_versions": "خطأ في تحميل إصدارات Minecraft", + + + /* بداية */ + "download_version": "تحميل الإصدار", + "mojang_copyright": "جميع الإصدارات هي الرسمية دون أي تعديلات. الإصدارات المعدلة سواء كانت Fabric أو Forge أو Quilt أو OptiFine هي إنتاج للمجتمع وليس لشركة Mojang. كل الحقوق محفوظة لشركة Mojang Studios.", + "delete_version": "حذف الإصدار", + "type_of_version": "نوع الإصدار", + + "latest": "أحدث", + "recommended": "موصى به", + + "version_deleted_correctly": "تم حذف الإصدار بنجاح.", + "you_need_select_version": "تحتاج إلى تحديد إصدار.", + + "downloading_client": "جارٍ تحميل العميل", + "starting_download_client_can_take": "بدء تثبيت العميل... قد يستغرق الأمر بعض الوقت...", + "battly_log": "سجل Battly", + "save_logs": "حفظ السجلات", + + "downloading": "جارٍ التحميل", + "downloading_files": "جارٍ تحميل الملفات", + "downloading_librairies": "جارٍ تحميل المكتبات", + "downloading_natives": "جارٍ تحميل المكونات الأساسية", + "installing_loader": "جارٍ تثبيت Loader", + "extracting_loader": "جارٍ استخراج Loader", + "downloaded_successfully": "تم التحميل بنجاح", + "starting_minecraft": "جارٍ تشغيل Minecraft", + "error_downloading": "خطأ في التحميل", + "status": "الحالة", + "error_http": "خطأ في طلب HTTP", + "extracting": "جارٍ الاستخراج", + "progress": "التقدم", + "files_extracted_successfully": "تم استخراج الملفات بنجاح", + "deleting_temp_files": "جارٍ حذف الملفات المؤقتة", + "temp_files_deleted_successfully": "تم حذف الملفات المؤقتة بنجاح", + "error_downloading_version": "خطأ في تحميل الإصدار", + "version_java_error": "ليس لديك الإصدار المطلوب من الجافا، لتحميله، قم بتنزيل 1.20.1 الخاصة بالفانيليا ثم حاول مرة أخرى.", + "installing_minecraft_files": "جارٍ تثبيت ملفات Minecraft", + "client_files_downloaded_successfully": "تم استكمال ملفات العميل", + + "error_detected_one": "تم اكتشاف خطأ: تم إغلاق Minecraft بشكل غير متوقع. قم بإعادة تشغيل Minecraft.", + "error_detected_two": "تم اكتشاف خطأ: خطأ غير معروف. قم بإعادة تشغيل Minecraft.", + "error_detected_three": "تم اكتشاف خطأ: لا يوجد ذاكرة RAM كافية لبدء Minecraft. تذكر أنه يمكنك تكوينها من خلال الإعدادات> الذاكرة.", + "error_detected_four": "تم اكتشاف خطأ: لا يمكن تصحيح Forge. قم بإعادة تشغيل Minecraft.", + "error_detected_five": "تم اكتشاف خطأ: لا يمكن بدء تشغيل Minecraft. قم بإعادة تشغيل Minecraft.", + + "choose_fabric_version": "اختر إصدارًا من Fabric", + "choose_forge_version": "اختر إصدارًا من Forge", + "choose_quilt_version": "اختر إصدارًا من Quilt", + "choose_optifine_version": "اختر إصدارًا من OptiFine", + "choose_a_client": "اختر عميلًا", + + "starting_download_can_take": "بدء التثبيت... قد يستغرق بعض الوقت...", + "battly_log": "سجل Battly", + "log": "سجل", + + "start_minecraft_text": "بدء Minecraft", + "select_the_version_that_you_want": "حدد الإصدار الذي تريد فتحه", + "select_a_version": "اختر إصدارًا", + + "title_access_logs": "الوصول إلى السجلات الخاصة بك", + "text_access_logs": "تم طلب الوصول إلى سجلات Battly الخاصة بك، هل ترغب في السماح؟", + "requester": "المطلوب", + "reason": "السبب", + "text_access_logs_two": "إذا لم تسمح، لن يمكن الوصول إلى السجلات. تأكد من أن المطلوب موثوق به.", + "allow": "السماح", + "deny": "الرفض", + "access_logs_denied": "تم رفض الوصول إلى السجلات.", + "access_logs_denied_text": "إذا كنت تعتقد أنك تتعرض لهجوم، اتصل بفريق دعم Battly على الفور.", + "your_unique_id_is": "معرفك الفريد في Battly هو:", + "dont_share_it": "لا تشارك هذا المعرف مع أي شخص، حيث يمكن أن يشكل خطرًا على أمانك. إذا كنت تعتقد أنك تتعرض لهجوم، اتصل بفريق دعم Battly على الفور.", + "id_copied_correctly": "تم نسخ المعرف بنجاح.", + "copy": "نسخ", + + "return": "عودة", + "install_modpack": "تثبيت ModPack", + "search_mods": "البحث عن Mods...", + "compatible_with_curseforge_or_modrinth": "متوافق مع ModPacks من CurseForge أو Modrinth", + "install_modpack_text": "تثبيت ModPack", + "you_didnt_selected_any_file": "لم تختر أي ملف", + "installing_modpack_can_take": ' تثبيت ModPack... قد يستغرق...', + "no_description": "بدون وصف", + "installing_file": "تثبيت الملف", + "modpack_installed": "تم تثبيت ModPack", + "modpack_installed_correctly": "تم التثبيت بنجاح", + "installing_mod": "تثبيت Mod", + "the_file_is_not_compatible": "الملف غير متوافق", + "searching_mods": "البحث عن Mods", + "downloading_mod": "تحميل Mod", + "mod_downloaded_successfully": "تم تحميل Mod بنجاح", + "error_downloading_mod": "خطأ في التحميل", + "error_downloading_dependency": "خطأ في تحميل التبعية", + "dependency": "التبعية", + "downloaded_successfully_two": "تم التحميل بنجاح", + "loading_mod_information": "جاري تحميل معلومات Mod", + "mod_information": "معلومات Mod", + "mod_stats": "إحصائيات Mod", + "downloads": "التحميل", + "followers": "متابعون", + "view_on_modrinth": "عرض على Modrinth", + "download_mod": "تحميل Mod", + "delete_mod": "حذف Mod", + "all_this_information_copyright_modrinth": 'جميع هذه المعلومات (الصور، الأسماء، التنزيلات، الملفات) مأخوذة من واجهة برمجة التطبيقات الرسمية لـ Modrinth. كل الحقوق محفوظة.', + "deleted_successfully": "تم الحذف بنجاح", + + "install": "تثبيت", + + "welcome_battly_social": "👋 مرحبًا بك في لوحة Battly Social الجديدة للأصدقاء. هنا يمكنك رؤية جميع أصدقائك، إضافتهم، مشاهدة ما يلعبونه، وإحصائياتهم", + "friends_list_text": "قائمة الأصدقاء", + "add_friend": "إضافة صديق", + "show_requests": "عرض الطلبات", + "accept": "قبول", + "starting_version_can_take": ' بدء الإصدار... قد يستغرق بعض الوقت...', + "you_dont_have_any_friend_requests": "ليس لديك طلبات صداقة", + "friend_requests": "طلبات الصداقة", + "request_accepted": "تم قبول الطلب", + "request_rejected": "تم رفض الطلب", + "search": "بحث", + "loading_friends": "جاري تحميل الأصدقاء", + "error_loading_friends": "خطأ في الحصول على قائمة الأصدقاء. تحقق من اتصالك بالإنترنت وحاول مرة أخرى في وقت لاحق.", + "in_the_main_menu": "في القائمة الرئيسية", + "add_friend_text": "إضافة صديق", + "username": "اسم المستخدم", + "you_cannot_add_yourself": "لا يمكنك إضافة نفسك كصديق.", + "you_already_have_this_friend": "لديك هذا المستخدم بالفعل كصديق.", + "request_sent_to": "تم إرسال الطلب إلى", + "correctly": "بنجاح", + + "a_microsoft_panel_opened": "تم فتح نافذة تسجيل الدخول من Microsoft", + "logging_in": "جاري تسجيل الدخول", + "error_logging_in": "خطأ في تسجيل الدخول", + "set_your_username": "أدخل اسم مستخدمك", + "threecharacters_username": "يجب أن يكون اسم المستخدم لديك على الأقل 3 أحرف", + "set_your_password": "أدخل كلمة مرورك", + "threecharacters_password": "يجب أن تكون كلمة المرور لديك على الأقل 3 أحرف", + "username_or_password_incorrect": "اسم المستخدم أو كلمة المرور غير صحيحين", + "welcome_again_to_battly": "مرحبًا مرة أخرى إلى Battly", + "we_hope_you_enjoy": "نأمل أن تستمتع بتجربة اللعب!", + "use_account_battly_or_microsoft": "استخدم حساب Battly أو Microsoft الخاص بك لتسجيل الدخول إلى Battly", + "username": 'اسم المستخدم', + "password": ' كلمة المرور', + "login_text_panel_login": ' تسجيل الدخول', + "register_open_btn": ' التسجيل', + "lost_your_account": "نسيت كلمة المرور؟", + "recover_it_here": "استعادتها هنا", + + "january": "يناير", + "february": "فبراير", + "march": "مارس", + "april": "إبريل", + "may": "مايو", + "june": "يونيو", + "july": "يوليو", + "august": "أغسطس", + "september": "سبتمبر", + "october": "أكتوبر", + "november": "نوفمبر", + "december": "ديسمبر", + + "you_dont_have_songs_in_your_playlist": "ليس لديك أغاني في قائمة التشغيل الخاصة بك", + "save_playlist": "حفظ القائمة", + "saved_playlists": "القوائم المحفوظة", + "playlist_name": "اسم القائمة", + "save": "حفظ", + "you_need_to_set_a_playlist_name": "يجب عليك تحديد اسم للقائمة", + "already_have_a_playlist_with_this_name": "لديك بالفعل قائمة بنفس هذا الاسم", + "playlist_saved_correctly": "تم حفظ القائمة بنجاح", + "welcome_to_the_new_playlists_system": "مرحبًا بك في لوحة القوائم الجديدة في Battly، هنا يمكنك إدارة قوائم التشغيل التي قد حفظتها في Battly Music.", + "getting_songs": "جاري الحصول على الأغاني", + "getting": "جاري الحصول", + "loading": "جاري التحميل", + "thumbnail": "الصورة المصغرة", + "delete": "حذف", + "songs_loaded_playing": "الموسيقى جاهزة!
    التشغيل", + "playlist_deleted_successfully": "تم حذف القائمة بنجاح", + "add": "إضافة", + "finded": "تم العثور على", + "not_founded": "لم يتم العثور على", + "playing_now": "التشغيل الآن", + "your_playlist": "قائمة التشغيل الخاصة بك", + "no_song": "لا يوجد أي أغنية", + "song_name": "اسم الأغنية", + "playlists": ' قوائم التشغيل', + "search_song": ' البحث', + "save_playlist": ' حفظ القائمة' + +}; + +export default strings; \ No newline at end of file diff --git a/src/assets/langs/de.js b/src/assets/langs/de.js new file mode 100644 index 0000000..447734d --- /dev/null +++ b/src/assets/langs/de.js @@ -0,0 +1,357 @@ +const strings = { + "salutate": "Hallo!", + "checking_connection": "Überprüfe Internetverbindung", + "no_connection": "Keine Verbindung zum Internet hergestellt.
    Wechsel in den Offline-Modus", + "starting_battly": "Battly wird gestartet", + "checking_updates": "Überprüfe Updates", + "error_checking_updates": "Fehler beim Suchen nach Updates. Der Server antwortet nicht. Versuche es später erneut.", + "error_connecting_server": "Fehler bei der Verbindung zum Battly-Server", + "getting_actual_version": "Aktuelle Version wird abgerufen", + "downloading_update": "Update wird heruntergeladen", + "update_available": "Update verfügbar!", + "update_downloaded": "Update heruntergeladen", + "update_cancelled": "Update abgebrochen", + "update_completed": "Update heruntergeladen. Der Battly-Installer wird jetzt geöffnet", + "update_error": "Fehler beim Suchen nach Updates, Fehler :
    ", + "errkr_connecting_server": "Fehler beim Verbinden mit dem Server.
    Überprüfe deine Verbindung oder versuche es später erneut.", + "closing_countdown": "Schließt in", + "starting_launcher": "Battly wird gestartet", + "ending": "Fast geschafft", + "close": "Schließen", + + "instances": "Instanzen", + "welcome_instances": "👋 Willkommen im neuen Instanz-Panel von Battly. Hier kannst du die Instanzen verwalten, die du in Battly für deine Versionen verwenden wirst.", + "open_instance": "Öffnen", + "open_instance_folder": "Instanzordner öffnen", + "delete_instance": "Löschen", + "create_instance": "Instanz erstellen", + "instance_name": "Instanzname", + "instance_description": "Instanzbeschreibung", + "instance_image": "Instanzbild", + "instance_version": "Instanzversion", + "create_instance": "Instanz erstellen", + "instance_deleted_correctly": "Die Instanz wurde erfolgreich gelöscht.", + "preparing_instance": "Instanz wird vorbereitet", + "downloading_instance": "Instanz wird heruntergeladen", + "downloading_version": "Version wird heruntergeladen", + "downloading_loader": "Loader wird heruntergeladen", + "downloading_java": "Java wird heruntergeladen", + "checking_instance": "Überprüfung läuft", + "downloading_assets": "Assets werden heruntergeladen", + "instance_created_correctly": "Die Instanz wurde erfolgreich erstellt.", + "fill_all_fields": "Du musst alle Felder ausfüllen.", + "calculating_time": "Zeit wird berechnet", + "estimated_time_not_available": "Geschätzte Zeit nicht verfügbar", + "remaining": "Verbleibend", + "remaining_two": "Verbleiben", + + "are_you_sure": "Bist du sicher?", + "are_you_sure_text": "Diese Aktion kann nicht rückgängig gemacht werden.", + "yes_delete": "Ja, löschen", + "no_cancel": "Nein, abbrechen", + + "playing_in": "Spielen in", + "in_the_menu": "Im Startmenü", + + "minecraft_started_correctly": "Minecraft erfolgreich gestartet", + "minecraft_started_correctly_body": "Minecraft wurde erfolgreich gestartet.", + + "name": "Name", + "description": "Beschreibung", + "select_a_file": "Datei auswählen", + + "version_list_updated": "Die Liste der Versionen wurde aktualisiert.", + + "download": "Herunterladen", + "play": "Spielen", + + "news_battly": "Neuigkeiten zu Battly", + "status_battly": "Status", + "playing_now_text": "Spielt jetzt", + "playing_now_body": "Nichts wird abgespielt", + "users_online": "Benutzer online", + "operative": "Operativ", + "maintenance": "Wartung", + "no_connected": "Nicht betriebsbereit - Nicht verbunden", + "ads_text": "Werbung", + /* Configuración */ + + "accounts_btn": ' Konten', + "java_btn": ' Java', + "ram_btn": ' RAM', + "launcher_btn": ' Launcher', + "theme_btn": ' Thema', + "background_btn": ' Hintergrund', + "save_btn": ' Speichern', + "account_information": "Kontoinformationen", + "mc_id_text": "MC-ID:", + "showskin_userinfo_btn": "Skin anzeigen", + "deleteaccount_userinfo_btn": "Konto löschen", + "set_skin": "Haut setzen", + "my_accounts": "Meine Konten", + "add_account_text": "Konto hinzufügen", + "java_settings": 'Java-Einstellungen ', + "java_text_info": `Java

    In diesem Abschnitt können Sie + die Java-Version konfigurieren, die zum Starten Ihres Spiels verwendet wird. Wenn Sie nicht wissen, was Sie tun, lassen Sie dieses Abschnitt unverändert.

    + Java-Pfad +
    + + Battly verwendet eine integrierte Version von Java [Offiziell].
    `, + "java_text_info2": ` + Diese Version ist verfügbar unter + Sie können jedoch Ihre eigene ausführbare Datei angeben, wenn Ihre Version eine andere Java-Version erfordert. +
    + `, + "ram_settings": 'RAM-Einstellungen ', + "ram_text_info": `In diesem Abschnitt können Sie + den RAM konfigurieren, der Ihrem Spiel zugewiesen wird. Dies ist wichtig für einen reibungslosen Betrieb Ihres Spiels. + Wenn Sie nicht wissen, was Sie tun, lassen Sie dieses Abschnitt unverändert.

    + Maximaler RAM: Gibt die Gesamtmenge des Ihrem Spiel zugewiesenen RAMs an. Es wird empfohlen, nicht mehr als + 50% des insgesamt im PC verfügbaren RAMs zu verwenden, um sicherzustellen, dass es ordnungsgemäß funktioniert. Wenn der PC + mehr als 8GB RAM hat, wird empfohlen, ihm 3GB zuzuweisen. Wenn der PC 4 GB oder weniger hat, weisen Sie nicht mehr als 2 GB zu.

    + Mindest-RAM: Gibt die beim Starten Ihres Spiels zugewiesene minimale RAM-Menge an. Es wird empfohlen, nicht + mehr als 3GB für diesen Wert festzulegen. Der typische Wert liegt bei 1 GB.`, + "you_have_a_total": "Du hast insgesamt", + "of_ram": "RAM", + "of_ram_disponible": "verfügbaren RAM", + "battly_settings": "Battly Einstellungen", + "battly_settings_information": `Starten von Minecraft

    In diesem Abschnitt + können Sie konfigurieren, was Battly tun soll, wenn Minecraft geöffnet wird, sei es Battly schließen, Minecraft schließen + oder Battly geöffnet lassen. Wenn Sie nicht wissen, was Sie tun, lassen Sie dieses Abschnitt unverändert.

    +
    + Was tun beim Öffnen von Minecraft: +
    `, + "minimalize_battly": "Battly nach dem Starten von Minecraft verstecken", + "keep_battly_opened": "Battly nach dem Starten von Minecraft geöffnet lassen", + "battly_logs_text": "Battly-Protokolle:", + "get_socketid": ' Eindeutige ID abrufen', + "battly_theme": "Battly anpassen", + "welcome": "Willkommen!", + "battly_theme_text": "Willkommen beim neuen Battly-Anpassungspanel! Hier können Sie Battly nach Ihren Wünschen anpassen, indem Sie das Thema, Hintergrundbilder und vieles mehr ändern. Wir hoffen, es gefällt Ihnen!", + "change_theme_text": "Thema anpassen", + "buttons_color": "Farbe der Schaltflächen", + "bottom_bar_text": "Farbe der unteren Leiste", + "bottom_bar_opacity": "Transparenz der unteren Leiste", + "starting_music": "Startton", + "resize_image_text": "Bild zuschneiden", + "set_background_text": "Hintergrund festlegen", + "cancel": "Abbrechen", + "customize_background": "Hintergrund anpassen", + "resize_background": "Hintergrund anpassen", + "background_image_text": "Hintergrundbild", + "reset_background": "Hintergrund zurücksetzen", + "select_a_background": "Wählen Sie ein Bild aus", + "background_set_successfully": "Der Hintergrund wurde erfolgreich zurückgesetzt", + "account_deleted_successfully": "Konto erfolgreich gelöscht", + "settings_saved_successfully": "Einstellungen erfolgreich gespeichert", + "java_path_didnt_set": "Java-Pfad nicht festgelegt", + "java_path_set_successfully": "Java-Pfad wurde erfolgreich festgelegt", + "the_file_name_java": "Der Dateiname muss java oder javaw sein", + + /* Laden */ + + "loading_config": "Konfiguration wird geladen", + "config_loaded": "Konfiguration geladen", + "error_loading_config": "Fehler beim Laden der Konfiguration", + "loading_versions": "Versionen werden geladen", + "versions_loaded": "Versionen geladen", + "error_loading_versions": "Fehler beim Laden der Versionen", + "loading_minecraft_versions": "Minecraft-Versionen werden geladen", + "minecraft_versions_loaded": "Minecraft-Versionen geladen", + "error_loading_minecraft_versions": "Fehler beim Laden der Minecraft-Versionen", + + /* Start */ + + "download_version": "Version herunterladen", + "mojang_copyright": "Alle Versionen sind offiziell und unverändert. Modifizierte Versionen, sei es von Fabric, Forge, Quilt oder OptiFine, werden von der Gemeinschaft erstellt und nicht von Mojang. Alle Rechte vorbehalten an Mojang Studios.", + "delete_version": "Version löschen", + "type_of_version": "Art der Version", + + "latest": "Neueste", + "recommended": "Empfohlen", + + "version_deleted_correctly": "Version erfolgreich gelöscht.", + "you_need_select_version": "Sie müssen eine Version auswählen.", + + "downloading_client": "Client wird heruntergeladen", + "starting_download_client_can_take": "Installation des Clients wird gestartet... Dies kann eine Weile dauern...", + "battly_log": "Battly-Protokoll", + "save_logs": "Protokolle speichern", + + /* Descargas */ + "downloading": "Herunterladen", + "downloading_files": "Dateien herunterladen", + "downloading_librairies": "Bibliotheken herunterladen", + "downloading_natives": "Native Dateien herunterladen", + "installing_loader": "Loader installieren", + "extracting_loader": "Loader extrahieren", + "downloaded_successfully": "Erfolgreich heruntergeladen", + "starting_minecraft": "Minecraft wird gestartet", + "error_downloading": "Fehler beim Herunterladen", + "status": "Status", + "error_http": "Fehler bei der HTTP-Anfrage", + "extracting": "Extrahieren", + "progress": "Fortschritt", + "files_extracted_successfully": "Dateien erfolgreich extrahiert", + "deleting_temp_files": "Temporäre Dateien löschen", + "temp_files_deleted_successfully": "Temporäre Dateien erfolgreich gelöscht", + "error_downloading_version": "Fehler beim Herunterladen der Version", + "version_java_error": "Du hast nicht die erforderliche Java-Version. Um diese zu erhalten, lade die 1.20.1 Vanilla-Version herunter und versuche es erneut.", + "installing_minecraft_files": "Minecraft-Dateien installieren", + "client_files_downloaded_successfully": "Client-Dateien erfolgreich heruntergeladen", + + "error_detected_one": "Fehler erkannt: Minecraft wurde unerwartet geschlossen. Starte Minecraft erneut.", + "error_detected_two": "Fehler erkannt: Unbekannter Fehler. Starte Minecraft erneut.", + "error_detected_three": "Fehler erkannt: Nicht genügend RAM, um Minecraft zu starten. Denke daran, dass du dies in den Einstellungen > RAM konfigurieren kannst.", + "error_detected_four": "Fehler erkannt: Forge konnte nicht gepatcht werden. Starte Minecraft erneut.", + "error_detected_five": "Fehler erkannt: Minecraft konnte nicht gestartet werden. Starte Minecraft erneut.", + + "choose_fabric_version": "Wähle eine Fabric-Version aus", + "choose_forge_version": "Wähle eine Forge-Version aus", + "choose_quilt_version": "Wähle eine Quilt-Version aus", + "choose_optifine_version": "Wähle eine OptiFine-Version aus", + "choose_a_client": "Wähle einen Client aus", + + "starting_download_can_take": "Starte die Installation... Dies kann eine Weile dauern...", + "battly_log": "Battly-Protokoll", + "log": "Protokoll", + + "start_minecraft_text": "Minecraft starten", + "select_the_version_that_you_want": "Wähle die Version aus, die du öffnen möchtest", + "select_a_version": "Wähle eine Version aus", + + /* Protokollsysteme */ + "title_access_logs": "Zugriff auf deine Protokolle", + "text_access_logs": "Es wurde um Zugriff auf deine Battly-Protokolle gebeten. Möchtest du dies erlauben?", + "requester": "Anfordernder", + "reason": "Grund", + "text_access_logs_two": "Wenn du den Zugriff nicht erlaubst, können die Protokolle nicht abgerufen werden. Stelle sicher, dass der Anfordernde vertrauenswürdig ist.", + "allow": "Erlauben", + "deny": "Ablehnen", + "access_logs_denied": "Der Zugriff auf die Protokolle wurde verweigert.", + "access_logs_denied_text": "Wenn du glaubst, dass du angegriffen wirst, kontaktiere sofort das Battly-Support-Team.", + "your_unique_id_is": "Deine eindeutige Battly-ID lautet:", + "dont_share_it": "Teile diese ID nicht mit anderen, da dies ein Sicherheitsrisiko darstellen könnte. Wenn du glaubst, dass du angegriffen wirst, kontaktiere sofort das Battly-Support-Team.", + "id_copied_correctly": "Die ID wurde erfolgreich kopiert.", + "copy": "Kopieren", + + /* Mods */ + "return": "Zurück", + "install_modpack": "Modpack installieren", + "search_mods": "Nach Mods suchen...", + "compatible_with_curseforge_or_modrinth": "Kompatibel mit CurseForge- oder Modrinth-Modpacks", + "install_modpack_text": "ModPack installieren", + "you_didnt_selected_any_file": "Du hast keine Datei ausgewählt", + "installing_modpack_can_take": ' ModPack wird installiert... Dies kann eine Weile dauern...', + "no_description": "Keine Beschreibung", + "installing_file": "Datei wird installiert", + "modpack_installed": "ModPack installiert", + "modpack_installed_correctly": "erfolgreich installiert", + "installing_mod": "Mod wird installiert", + "the_file_is_not_compatible": "Die Datei ist nicht kompatibel", + "searching_mods": "Mods werden gesucht", + "downloading_mod": "Mod wird heruntergeladen", + "mod_downloaded_successfully": "erfolgreich heruntergeladen", + "error_downloading_mod": "Fehler beim Herunterladen", + "error_downloading_dependency": "Fehler beim Herunterladen der Abhängigkeit", + "dependency": "Abhängigkeit", + "downloaded_successfully_two": "erfolgreich heruntergeladen", + "loading_mod_information": "Lade Mod-Informationen", + "mod_information": "Mod-Information", + "mod_stats": "Mod-Statistiken", + "downloads": "Downloads", + "followers": "Follower", + "view_on_modrinth": "Auf Modrinth anzeigen", + "download_mod": "Mod herunterladen", + "delete_mod": "Mod löschen", + "all_this_information_copyright_modrinth": 'Alle diese Informationen (Bilder, Namen, Downloads, Dateien) stammen aus der offiziellen API von Modrinth. Alle Rechte vorbehalten.', + "deleted_successfully": "erfolgreich gelöscht", + + "install": "Installieren", + + /* Battly Social */ + "welcome_battly_social": "👋 Willkommen im neuen Battly-Freunde-Panel. Hier kannst du alle deine Freunde sehen, sie hinzufügen, sehen, was sie spielen, und ihre Statistiken überprüfen.", + "friends_list_text": "Freundesliste", + "add_friend": "Freund hinzufügen", + "show_requests": "Anfragen anzeigen", + "accept": "Akzeptieren", + "starting_version_can_take": ' Starte Version... Dies kann eine Weile dauern...', + "you_dont_have_any_friend_requests": "Du hast keine Freundschaftsanfragen", + "friend_requests": "Freundschaftsanfragen", + "request_accepted": "Anfrage akzeptiert", + "request_rejected": "Anfrage abgelehnt", + "search": "Suchen", + "loading_friends": "Freunde werden geladen", + "error_loading_friends": "Fehler beim Abrufen der Freundesliste. Überprüfe deine Internetverbindung und versuche es später erneut.", + "in_the_main_menu": "Im Hauptmenü", + "add_friend_text": "Freund hinzufügen", + "username": "Benutzername", + "you_cannot_add_yourself": "Du kannst dich nicht selbst als Freund hinzufügen.", + "you_already_have_this_friend": "Du hast diesen Benutzer bereits als Freund.", + "request_sent_to": "Anfrage gesendet an", + "correctly": "korrekt", + + /* Anmeldung */ + "a_microsoft_panel_opened": "Ein Microsoft-Anmeldefenster wurde geöffnet", + "logging_in": "Anmeldung läuft", + "error_logging_in": "Fehler bei der Anmeldung", + "set_your_username": "Gib deinen Benutzernamen ein", + "threecharacters_username": "Dein Benutzername muss mindestens 3 Zeichen lang sein", + "set_your_password": "Gib dein Passwort ein", + "threecharacters_password": "Dein Passwort muss mindestens 3 Zeichen lang sein", + "username_or_password_incorrect": "Benutzername oder Passwort sind falsch", + "welcome_again_to_battly": "Willkommen zurück bei Battly", + "we_hope_you_enjoy": "Wir hoffen, du hast Spaß an der Spielerfahrung!", + "use_account_battly_or_microsoft": "Verwende dein Battly- oder Microsoft-Konto, um dich bei Battly anzumelden", + "username": 'Benutzername', + "password": ' Passwort', + "login_text_panel_login": ' Anmelden', + "register_open_btn": ' Registrieren', + "lost_your_account": "Hast du dein Passwort vergessen?", + "recover_it_here": "Hier wiederherstellen", + + /* Monate */ + "january": "Januar", + "february": "Februar", + "march": "März", + "april": "April", + "may": "Mai", + "june": "Juni", + "july": "Juli", + "august": "August", + "september": "September", + "october": "Oktober", + "november": "November", + "december": "Dezember", + + /* Musik */ + "you_dont_have_songs_in_your_playlist": "Du hast keine Songs in deiner Playlist", + "save_playlist": "Playlist speichern", + "saved_playlists": "Gespeicherte Playlists", + "playlist_name": "Playlist-Name", + "save": "Speichern", + "you_need_to_set_a_playlist_name": "Du musst einen Namen für die Playlist angeben", + "already_have_a_playlist_with_this_name": "Du hast bereits eine Playlist mit diesem Namen", + "playlist_saved_correctly": "Playlist erfolgreich gespeichert", + "welcome_to_the_new_playlists_system": "Willkommen im neuen Battly-Musik-Playlist-Panel. Hier kannst du deine gespeicherten Playlists verwalten.", + "getting_songs": "Songs werden geladen", + "getting": "Wird geladen", + "loading": "Lädt", + "thumbnail": "Thumbnail", + "delete": "Löschen", + "songs_loaded_playing": "Musik geladen!
    Spielen", + "playlist_deleted_successfully": "Playlist erfolgreich gelöscht", + "add": "Hinzufügen", + "finded": "Gefunden", + "not_founded": "Nicht gefunden", + "playing_now": "Jetzt abspielen", + "your_playlist": "Deine Playlist", + "no_song": "Kein Song", + "song_name": "Song-Name", + "playlists": ' Playlists', + "search_song": ' Suche', + "save_playlist": ' Playlist speichern', + +}; + +export default strings; \ No newline at end of file diff --git a/src/assets/langs/en.js b/src/assets/langs/en.js new file mode 100644 index 0000000..237a970 --- /dev/null +++ b/src/assets/langs/en.js @@ -0,0 +1,362 @@ +const strings = { + "salutate": "Hello!", + "checking_connection": "Checking internet connection", + "no_connection": "Could not connect to the internet.
    Entering offline mode", + "starting_battly": "Starting Battly", + "checking_updates": "Checking for updates", + "error_checking_updates": "Error checking for updates. Server not responding. Please try again later.", + "error_connecting_server": "Error connecting to the Battly server", + "getting_actual_version": "Getting current version", + "downloading_update": "Downloading update", + "update_available": "Update available!", + "update_downloaded": "Update downloaded", + "update_cancelled": "Update canceled", + "update_completed": "Update downloaded. The Battly installer will open now.", + "update_error": "Error checking for updates, error:
    ", + "errkr_connecting_server": "Error connecting to the server.
    Check your connection or try again later.", + "closing_countdown": "Closing in", + "starting_launcher": "Starting Battly", + "ending": "Almost there", + "close": "Close", + + "instances": "Instances", + "welcome_instances": "👋 Welcome to the new Battly instances panel. Here you can manage the instances you'll use in Battly for your versions.", + "open_instance": "Open", + "open_instance_folder": "Open folder", + "delete_instance": "Delete", + "create_instance": "Create instance", + "instance_name": "Instance name", + "instance_description": "Instance description", + "instance_image": "Instance image", + "instance_version": "Instance version", + "create_instance": "Create instance", + "instance_deleted_correctly": "Instance deleted successfully.", + "preparing_instance": "Preparing instance", + "downloading_instance": "Downloading instance", + "downloading_version": "Downloading version", + "downloading_loader": "Downloading Loader", + "downloading_java": "Downloading Java", + "checking_instance": "Checking", + "downloading_assets": "Downloading assets", + "instance_created_correctly": "Instance created successfully.", + "fill_all_fields": "You need to fill in all fields.", + "calculating_time": "Calculating time", + "estimated_time_not_available": "Estimated time not available", + "remaining": "Remaining", + "remaining_two": "Remaining", + + "are_you_sure": "Are you sure?", + "are_you_sure_text": "This action cannot be undone.", + "yes_delete": "Yes, delete", + "no_cancel": "No, cancel", + + "playing_in": "Playing in", + "in_the_menu": "In the main menu", + + "minecraft_started_correctly": "Minecraft started correctly", + "minecraft_started_correctly_body": "Minecraft has been started correctly.", + + "name": "Name", + "description": "Description", + "select_a_file": "Select a file", + + "version_list_updated": "Version list updated.", + + "download": "Download", + "play": "Play", + + "news_battly": "Battly News", + "status_battly": "Status", + "playing_now_text": "Currently playing", + "playing_now_body": "Nothing playing right now", + "users_online": "Users online", + "operative": "Operational", + "maintenance": "Maintenance", + "no_connected": "Non-operational - Not connected", + "ads_text": "Advertisements", + + + /* settings */ + + "accounts_btn": ' Accounts', + "java_btn": ' Java', + "ram_btn": ' RAM', + "launcher_btn": ' Launcher', + "theme_btn": ' Theme', + "background_btn": ' Background', + "save_btn": ' Save', + "account_information": "Account Information", + "mc_id_text": "MC ID:", + "showskin_userinfo_btn": "Show Skin", + "deleteaccount_userinfo_btn": "Delete Account", + "set_skin": "Set Skin", + "my_accounts": "My Accounts", + "add_account_text": "Add Account", + "java_settings": 'Java Settings ', + "java_text_info": `Java

    In this section, you can + configure the Java version that will be used to launch your game. If you don't know what you're doing, + don't touch anything in this section.

    + Java Path +
    + + Battly uses an integrated version of Java [Official].
    `, + "java_text_info2": ` + This version is available in the path + However, you can specify your own executable if your version requires a different version + of Java. +
    + `, + "ram_settings": 'RAM Settings ', + "ram_text_info": `In this section, you can configure + the RAM that will be allocated to your game. This is important for your game to run correctly. + If you don't know what you're doing, don't touch anything in this section.

    + Maximum RAM: Indicates the total amount of RAM assigned to your game. It is recommended not to exceed + 50% of the total amount of RAM present in your PC for it to work correctly. If the PC has + more than 8GB of RAM, it is recommended to allocate 3GB. If the PC has 4 GB or less, do not allocate more than 2 + GB.

    + Minimum RAM: Indicates the minimum amount of RAM assigned when starting your game. It is recommended not + to set more than 3GB for this value. The typical value is 1 GB.`, + "you_have_a_total": "You have a total of", + "of_ram": "of RAM", + "of_ram_disponible": "of available RAM", + "battly_settings": "Battly Settings", + "battly_settings_information": `Minecraft Startup

    In this section, + you can configure the action Battly will take when opening Minecraft, whether to close Battly, close + Minecraft, or keep Battly open. If you don't know what you're doing, don't touch anything in this + section.

    +
    + What to do when opening Minecraft: +
    `, + "minimalize_battly": "Hide Battly after starting Minecraft", + "keep_battly_opened": "Keep Battly open after starting Minecraft", + "battly_logs_text": "Battly Logs:", + "get_socketid": ' Get Unique ID', + "battly_theme": "Customize Battly", + "welcome": "Welcome!", + "battly_theme_text": "Welcome to the new Battly customization panel! Here you can customize Battly to your liking, changing the theme, background images, and much more. We hope you like it!", + "change_theme_text": "Adjust the theme", + "buttons_color": "Button color", + "bottom_bar_text": "Bottom bar color", + "bottom_bar_opacity": "Bottom bar transparency", + "starting_music": "Startup sound", + "resize_image_text": "Crop image", + "set_background_text": "Set background", + "cancel": "Cancel", + "customize_background": "Customize background", + "resize_background": "Adjust background", + "background_image_text": "Background image", + "reset_background": "Reset background", + "select_a_background": "Select an image", + "background_set_successfully": "Background reset successfully", + "account_deleted_successfully": "Account deleted successfully", + "settings_saved_successfully": "Settings saved successfully", + "java_path_didnt_set": "Java path not set", + "java_path_set_successfully": "Java path set successfully", + "the_file_name_java": "The file name must be java or javaw", + + + /* loading */ + "loading_config": "Loading configuration", + "config_loaded": "Configuration loaded", + "error_loading_config": "Error loading configuration", + "loading_versions": "Loading versions", + "versions_loaded": "Versions loaded", + "error_loading_versions": "Error loading versions", + "loading_minecraft_versions": "Loading Minecraft versions", + "minecraft_versions_loaded": "Minecraft versions loaded", + "error_loading_minecraft_versions": "Error loading Minecraft versions", + + + /* start */ + "download_version": "Download version", + "mojang_copyright": "All versions are official and unmodified. Modified versions, whether Fabric, Forge, Quilt, or OptiFine, are created by the community and not by Mojang. All rights reserved to Mojang Studios.", + "delete_version": "Delete version", + "type_of_version": "Type of version", + + "latest": "Latest", + "recommended": "Recommended", + + "version_deleted_correctly": "Version deleted correctly.", + "you_need_select_version": "You need to select a version.", + + "downloading_client": "Downloading client", + "starting_download_client_can_take": "Starting client installation... It may take a while...", + "battly_log": "Battly Log", + "save_logs": "Save logs", + + "downloading": "Downloading", + "downloading_files": "Downloading files", + "downloading_librairies": "Downloading libraries", + "downloading_natives": "Downloading natives", + "installing_loader": "Installing Loader", + "extracting_loader": "Extracting Loader", + "downloaded_successfully": "Downloaded successfully", + "starting_minecraft": "Starting Minecraft", + "error_downloading": "Error downloading", + "status": "Status", + "error_http": "HTTP request error", + "extracting": "Extracting", + "progress": "Progress", + "files_extracted_successfully": "Files extracted successfully", + "deleting_temp_files": "Deleting temporary files", + "temp_files_deleted_successfully": "Temporary files deleted successfully", + "error_downloading_version": "Error downloading version", + "version_java_error": "You don't have the required Java version. To download it, get version 1.20.1 of vanilla and try again.", + "installing_minecraft_files": "Installing Minecraft files", + "client_files_downloaded_successfully": "Client files completed", + + "error_detected_one": "Error detected: Minecraft closed unexpectedly. Restart Minecraft.", + "error_detected_two": "Error detected: Unknown error. Restart Minecraft.", + "error_detected_three": "Error detected: Insufficient RAM to start Minecraft. Remember, you can configure it from Settings > RAM.", + "error_detected_four": "Error detected: Failed to patch Forge. Restart Minecraft.", + "error_detected_five": "Error detected: Failed to start Minecraft. Restart Minecraft.", + + "choose_fabric_version": "Choose a Fabric version", + "choose_forge_version": "Choose a Forge version", + "choose_quilt_version": "Choose a Quilt version", + "choose_optifine_version": "Choose an OptiFine version", + "choose_a_client": "Choose a client", + + "starting_download_can_take": "Starting installation... It may take a while...", + "battly_log": "Battly Log", + "log": "Log", + + "start_minecraft_text": "Start Minecraft", + "select_the_version_that_you_want": "Select the version you want to open", + "select_a_version": "Select a version", + + /* logs system */ + "title_access_logs": "Access to your logs", + "text_access_logs": "Access to your Battly logs has been requested. Do you want to allow it?", + "requester": "Requester", + "reason": "Reason", + "text_access_logs_two": "If you don't allow access, logs cannot be obtained. Make sure the requester is trustworthy.", + "allow": "Allow", + "deny": "Deny", + "access_logs_denied": "Access to logs denied.", + "access_logs_denied_text": "If you believe you are under attack, contact the Battly support team urgently.", + "your_unique_id_is": "Your unique Battly ID is:", + "dont_share_it": "Do not share this ID with anyone, as it could pose a security risk. If you believe you are under attack, contact the Battly support team urgently.", + "id_copied_correctly": "ID copied successfully.", + "copy": "Copy", + + /* mods */ + "return": "Return", + "install_modpack": "Install modpack", + "search_mods": "Search mods...", + "compatible_with_curseforge_or_modrinth": "Compatible with CurseForge or Modrinth ModPacks", + "install_modpack_text": "Install ModPack", + "you_didnt_selected_any_file": "You haven't selected any file", + "installing_modpack_can_take": ' Installing ModPack... It may take...', + "no_description": "No description", + "installing_file": "Installing file", + "modpack_installed": "ModPack installed", + "modpack_installed_correctly": "installed correctly", + "installing_mod": "Installing mod", + "the_file_is_not_compatible": "The file is not compatible", + "searching_mods": "Searching mods", + "downloading_mod": "Downloading mod", + "mod_downloaded_successfully": "downloaded successfully", + "error_downloading_mod": "Error downloading", + "error_downloading_dependency": "Error downloading dependency", + "dependency": "Dependency", + "downloaded_successfully_two": "downloaded successfully", + "loading_mod_information": "Loading mod information", + "mod_information": "Mod information", + "mod_stats": "Mod statistics", + "downloads": "Downloads", + "followers": "Followers", + "view_on_modrinth": "View on Modrinth", + "download_mod": "Download mod", + "delete_mod": "Delete mod", + "all_this_information_copyright_modrinth": 'All this information (images, names, downloads, files) comes from the official Modrinth API. All rights reserved.', + "deleted_successfully": "deleted successfully", + + "install": "Install", + + /* battly social */ + "welcome_battly_social": "👋 Welcome to the new Battly Friends panel. Here you can see all your friends, add them, see what they are playing, and their statistics", + "friends_list_text": "Friends list", + "add_friend": "Add friend", + "show_requests": "Show requests", + "accept": "Accept", + "starting_version_can_take": ' Starting version... It may take a while...', + "you_dont_have_any_friend_requests": "You don't have friend requests", + "friend_requests": "Friend requests", + "request_accepted": "Request accepted", + "request_rejected": "Request rejected", + "search": "Search", + "loading_friends": "Loading friends", + "error_loading_friends": "Error getting the friends list. Check your internet connection and try again later.", + "in_the_main_menu": "In the main menu", + "add_friend_text": "Add friend", + "username": "Username", + "you_cannot_add_yourself": "You cannot add yourself as a friend.", + "you_already_have_this_friend": "You already have this user as a friend.", + "request_sent_to": "Request sent to", + "correctly": "correctly", + + /* login */ + "a_microsoft_panel_opened": "A Microsoft login window has opened", + "logging_in": "Logging in", + "error_logging_in": "Error logging in", + "set_your_username": "Enter your username", + "threecharacters_username": "Your username must have at least 3 characters", + "set_your_password": "Enter your password", + "threecharacters_password": "Your password must have at least 3 characters", + "username_or_password_incorrect": "Username or password is incorrect", + "welcome_again_to_battly": "Welcome back to Battly", + "we_hope_you_enjoy": "We hope you enjoy the gaming experience!", + "use_account_battly_or_microsoft": "Use your Battly or Microsoft account to log in to Battly", + "username": 'Username', + "password": ' Password', + "login_text_panel_login": ' Log In', + "register_open_btn": ' Register', + "lost_your_account": "Forgot your password?", + "recover_it_here": "Recover it here", + + + /* months */ + "january": "January", + "february": "February", + "march": "March", + "april": "April", + "may": "May", + "june": "June", + "july": "July", + "august": "August", + "september": "September", + "october": "October", + "november": "November", + "december": "December", + + /* music */ + "you_dont_have_songs_in_your_playlist": "You don't have songs in your playlist", + "saved_playlists": "Saved playlists", + "save_playlist_text": "Save playlist", + "playlist_name": "Playlist title", + "save": "Save", + "you_need_to_set_a_playlist_name": "You need to enter a name for the playlist", + "already_have_a_playlist_with_this_name": "You already have a playlist with this name", + "playlist_saved_correctly": "Playlist saved correctly", + "welcome_to_the_new_playlists_system": "Welcome to the new Battly Music playlists panel. Here you can manage your playlists that you have saved in Battly Music.", + "getting_songs": "Getting songs", + "getting": "Getting", + "loading": "Loading", + "thumbnail": "Thumbnail", + "delete": "Delete", + "songs_loaded_playing": "Music loaded! Playing", + "playlist_deleted_successfully": "Playlist deleted successfully", + "add": "Add", + "finded": "Found", + "not_founded": "Not found", + "playing_now": "Playing now", + "your_playlist": "Your playlist", + "no_song": "No song", + "song_name": "Song name", + "playlists": ' Playlists', + "search_song": ' Search', + "save_playlist": ' Save playlist', +}; + +export default strings; diff --git a/src/assets/langs/es.js b/src/assets/langs/es.js new file mode 100644 index 0000000..29e2716 --- /dev/null +++ b/src/assets/langs/es.js @@ -0,0 +1,369 @@ +const strings = { + "salutate": "¡Hola!", + "checking_connection": "Comprobando conexión a internet", + "no_connection": "No se ha podido conectar a internet.
    Entrando en modo offline", + "starting_battly": "Iniciando Battly", + "checking_updates": "Comprobando actualizaciones", + "error_checking_updates": "Error al buscar las actualizaciones. El servidor no responde. Inténtalo de nuevo más tarde.", + "error_connecting_server": "Error al conectar al servidor de Battly", + "getting_actual_version": "Obteniendo versión actual", + "downloading_update": "Descargando actualización", + "update_available": "¡Actualización disponible!", + "update_downloaded": "Actualización descargada", + "update_cancelled": "Actualización cancelada", + "update_completed": "Actualización descargada. Ahora se te abrirá el instalador de Battly", + "update_error": "Error al buscar las actualizaciones, error :
    ", + "errkr_connecting_server": "Error al conectar al servidor.
    Comprueba tu conexión o vuelve a intentarlo más tarde.", + "closing_countdown": "Cerrando en", + "starting_launcher": "Iniciando Battly", + "ending": "Ya casi estamos", + "close": "Cerrar", + + "instances": "Instancias", + "welcome_instances": "👋 Bienvenido/a al nuevo panel de instancias de Battly. Aquí podrás gestionar las instancias que usarás en Battly para tus versiones.", + "open_instance": "Abrir", + "open_instance_folder": "Abrir carpeta", + "delete_instance": "Eliminar", + "create_instance": "Crear instancia", + "instance_name": "Nombre de la instancia", + "instance_description": "Descripción de la instancia", + "instance_image": "Imagen de la instancia", + "instance_version": "Versión de la instancia", + "create_instance": "Crear instancia", + "instance_deleted_correctly": "Se ha eliminado la instancia correctamente.", + "preparing_instance": "Preparando instancia", + "downloading_instance": "Descargando instancia", + "downloading_version": "Descargando versión", + "downloading_loader": "Descargando Loader", + "downloading_java": "Descargando Java", + "checking_instance": "Comrpobando", + "downloading_assets": "Descargando assets", + "instance_created_correctly": "Se ha creado la instancia correctamente.", + "fill_all_fields": "Necesitas rellenar todos los campos.", + "calculating_time": "Calculando tiempo", + "estimated_time_not_available": "Tiempo estimado no disponible", + "remaining": "Quedan", + "remaining_two": "Queda", + + "are_you_sure": "¿Estás seguro/a?", + "are_you_sure_text": "Esta acción no se puede deshacer.", + "yes_delete": "Sí, eliminar", + "no_cancel": "No, cancelar", + + "playing_in": "Jugando en", + "in_the_menu": "En el menú de inicio", + + "minecraft_started_correctly": "Minecraft iniciado correctamente", + "minecraft_started_correctly_body": "Minecraft se ha iniciado correctamente.", + + "name": "Nombre", + "description": "Descripción", + "select_a_file": "Selecciona un archivo", + + "version_list_updated": "Se ha actualizado la lista de versiones.", + + "download": "Descargar", + "play": "Jugar", + + "news_battly": "Novedades en Battly", + "status_battly": "Estado", + "playing_now_text": "Reproduciendo ahora", + "playing_now_body": "Nada reproduciéndose", + "users_online": "Usuarios en línea", + "operative": "Operativo", + "maintenance": "Mantenimiento", + "no_connected": "No operativo - No conectado", + "ads_text": "Anuncios", + + + /* settings */ + + "accounts_btn": ' Cuentas', + "java_btn": ' Java', + "ram_btn": ' RAM', + "launcher_btn": ' Launcher', + "theme_btn": ' Tema', + "background_btn": ' Fondo', + "save_btn": ' Guardar', + "account_information": "Información de la cuenta", + "mc_id_text": "ID de MC:", + "showskin_userinfo_btn": "Mostrar Skin", + "deleteaccount_userinfo_btn": "Eliminar cuenta", + "set_skin": "Establecer skin", + "my_accounts": "Mis cuentas", + "add_account_text": "Añadir cuenta", + "java_settings": 'Ajustes de Java ', + "java_text_info": `Java

    En este apartado podrás + configurar la versión de Java que se usará para iniciar tu juego. Si no sabes lo que estás haciendo, + no toques nada de este apartado.

    + Ruta de Java +
    + + Battly utiliza una versión integrada de Java [Oficial].
    `, + "java_text_info2": ` + Esta versión está disponible en la ruta + Sin embargo, puedes especificar tu propio ejecutable si tu versión requiere una versión + diferente de Java. +
    + `, + "ram_settings": 'Ajustes de la RAM ', + "ram_text_info": `En este aparado podrás configurar + la RAM que se le asignará a tu juego. Esto es importante para que tu juego funcione correctamente. + Si no sabes lo que estás haciendo, no toques nada de este apartado.

    + RAM máxima: Indica la cantidad total de RAM asignada a tu juego. Se recomienda que no excedas + el 50% de la cantidad total de RAM presente en tu PC para que funcione correctamente. Si la PC tiene + más de 8GB de RAM, se recomienda asignarle 3GB. Si la PC tiene 4 GB o menos, no asignes más de 2 + GB.

    + RAM mínima: Indica la cantidad mínima de RAM asignada al iniciar tu juego. Se recomienda no + poner más de 3GB para este valor. El valor típico es de 1 GB.`, + "you_have_a_total": "Tienes un total de", + "of_ram": "de RAM", + "of_ram_disponible": "de RAM disponible", + "battly_settings": "Configuración de Battly", + "battly_settings_information": `Inicio de Minecraft

    En este apartado + podrás configurar la acción que realizará Battly al abrir Minecraft, ya sea cerrar Battly, cerrar + Minecraft o mantener Battly abierto. Si no sabes lo que estás haciendo, no toques nada de este + apartado.

    +
    + Qué hacer al abrir Minecraft: +
    `, + "minimalize_battly": "Ocultar Battly después de iniciar Minecraft", + "keep_battly_opened": "Mantener Battly abierto después de iniciar Minecraft", + "battly_logs_text": "Registros de Battly:", + "get_socketid": ' Obtener ID única', + "battly_theme": "Personalizar Battly", + "welcome": "¡Bienvenido/a!", + "battly_theme_text": "¡Bienvenido/a al nuevo panel de personalización de Battly! Aquí podrás personalizar Battly a tu gusto, cambiando el tema, las imágenes de fondo y mucho más. ¡Esperamos que te guste!", + "change_theme_text": "Ajustar el tema", + "buttons_color": "Color de los botones", + "bottom_bar_text": "Color de la barra inferior", + "bottom_bar_opacity": "Transparencia de la barra inferior", + "starting_music": "Sonido de inicio", + "resize_image_text": "Recortar imagen", + "set_background_text": "Establecer fondo", + "cancel": "Cancelar", + "customize_background": "Personalizar fondo", + "resize_background": "Ajustar el fondo", + "background_image_text": "Imagen de fondo", + "reset_background": "Restablecer fondo", + "select_a_background": "Selecciona una imagen", + "background_set_successfully": "El fondo se ha restablecido correctamente", + "account_deleted_successfully": "Se ha eliminado la cuenta correctamente", + "settings_saved_successfully": "La configuración se ha guardado correctamente", + "java_path_didnt_set": "Ruta de java no establecida", + "java_path_set_successfully": "La ruta de java se ha establecido correctamente", + "the_file_name_java": "El nombre del archivo debe ser java o javaw", + + + /* loading */ + "loading_config": "Cargando configuración", + "config_loaded": "Configuración cargada", + "error_loading_config": "Error al cargar la configuración", + "loading_versions": "Cargando versiones", + "versions_loaded": "Versiones cargadas", + "error_loading_versions": "Error al cargar las versiones", + "loading_minecraft_versions": "Cargando versiones de Minecraft", + "minecraft_versions_loaded": "Versiones de Minecraft cargadas", + "error_loading_minecraft_versions": "Error al cargar las versiones de Minecraft", + + + /* inicio */ + "download_version": "Descargar versión", + "mojang_copyright": "Todas las versiones son las oficiales sin modificaciones. Las versiones modificadas ya sean de Fabric, Forge, Quilt u OptiFine son creadas por la comunidad y no por Mojang. Todos los derechos reservados a Mojang Studios.", + "delete_version": "Eliminar versión", + "type_of_version": "Tipo de versión", + + "latest": "Última", + "recommended": "Recomendada", + + "version_deleted_correctly": "Versión eliminada correctamente.", + "you_need_select_version": "Necesitas seleccionar una versión.", + + "downloading_client": "Descargando cliente", + "starting_download_client_can_take": "Iniciando instalación del cliente... Puede tardar un poco...", + "battly_log": "Registro de Battly", + "save_logs": "Guardar registros", + + "downloading": "Descargando", + "downloading_files": "Descargando archivos", + "downloading_librairies": "Descargando librerías", + "downloading_natives": "Descargando nativos", + "installing_loader": "Instalando Loader", + "extracting_loader": "Extrayendo Loader", + "downloaded_successfully": "Descargado correctamente", + "starting_minecraft": "Iniciando Minecraft", + "error_downloading": "Error al descargar", + "status": "Estado", + "error_http": "Error en la solicitud HTTP", + "extracting": "Extrayendo", + "progress": "Progreso", + "files_extracted_successfully": "Archivos extracted correctamente", + "deleting_temp_files": "Eliminando archivos temporales", + "temp_files_deleted_successfully": "Archivos temporales eliminados correctamente", + "error_downloading_version": "Error al descargar la versión", + "version_java_error": "No tienes la versión requerida de Java, para descargarla, descarga la 1.20.1 de vanilla y luego vuelve a intentarlo.", + "installing_minecraft_files": "Instalando archivos de Minecraft", + "client_files_downloaded_successfully": "Archivos del cliente completados", + + "error_detected_one": "Error detectado: Minecraft se ha cerrado inesperadamente. Vuelve a iniciar Minecraft.", + "error_detected_two": "Error detectado: Error desconocido. Vuelve a iniciar Minecraft.", + "error_detected_three": "Error detectado: No hay suficiente memoria RAM para iniciar Minecraft. Recuerda que puedes configurarla desde Ajustes > RAM.", + "error_detected_four": "Error detectado: No se ha podido parchear Forge. Vuelve a iniciar Minecraft.", + "error_detected_five": "Error detectado: No se ha podido iniciar Minecraft. Vuelve a iniciar Minecraft.", + + "choose_fabric_version": "Selecciona una versión de Fabric", + "choose_forge_version": "Selecciona una versión de Forge", + "choose_quilt_version": "Selecciona una versión de Quilt", + "choose_optifine_version": "Selecciona una versión de OptiFine", + "choose_a_client": "Selecciona un cliente", + + "starting_download_can_take": "Iniciando instalación... Puede tardar un poco...", + "battly_log": "Registro de Battly", + "log": "Registro", + + "start_minecraft_text": "Iniciar Minecraft", + "select_the_version_that_you_want": "Selecciona la versión que quieres abrir", + "select_a_version": "Elige una versión", + + /* logs system */ + "title_access_logs": "Acceso a tus logs", + "text_access_logs": "Se ha solicitado acceso a tus logs de Battly, ¿Deseas permitirlo?", + "requester": "Solicitante", + "reason": "Razón", + "text_access_logs_two": "Si no permites el acceso, no se podrá obtener los logs.Asegúrate que el solicitante sea de confianza.", + "allow": "Permitir", + "deny": "Denegar", + "access_logs_denied": "Se ha denegado el acceso a los logs.", + "access_logs_denied_text": "Si crees que estás siendo atacado, contacta con el equipo de soporte de Battly urgentemente.", + "your_unique_id_is": "Tu ID única de Battly es:", + "dont_share_it": "No compartas esta ID con nadie, ya que podría suponer un riesgo para tu seguridad. Si crees que estás siendo atacado, contacta con el equipo de soporte de Battly urgentemente.", + "id_copied_correctly": "Se ha copiado la ID correctamente.", + "copy": "Copiar", + + /* mods */ + "return": "Volver", + "install_modpack": "Instalar modpack", + "search_mods": "Buscar mods...", + "compatible_with_curseforge_or_modrinth": "Compatible con ModPacks de CurseForge o Modrinth", + "install_modpack_text": "Instalar ModPack", + "you_didnt_selected_any_file": "No has seleccionado ningún archivo", + "installing_modpack_can_take": ' Instalando ModPack... Puede tardar...', + "no_description": "Sin descripción", + "installing_file": "Instalando archivo", + "modpack_installed": "ModPack instalado", + "modpack_installed_correctly": "instalado correctamente", + "installing_mod": "Instalando mod", + "the_file_is_not_compatible": "El archivo no es compatible", + "searching_mods": "Buscando mods", + "downloading_mod": "Descargando mod", + "mod_downloaded_successfully": "descargado correctamente", + "error_downloading_mod": "Error al descargar", + "error_downloading_dependency": "Error al descargar la dependencia", + "dependency": "Dependencia", + "downloaded_successfully_two": "descargada correctamente", + "loading_mod_information": "Cargando información del mod", + "mod_information": "Información del mod", + "mod_stats": "Estadísticas del mod", + "downloads": "Descargas", + "followers": "Seguidores", + "view_on_modrinth": "Ver en Modrinth", + "download_mod": "Descargar mod", + "delete_mod": "Eliminar mod", + "all_this_information_copyright_modrinth": 'Toda esta información (imágenes, nombres, descargas, archivos) provienen de la API oficial de Modrinth. Todos los derechos reservados.', + "deleted_successfully": "eliminado correctamente", + + + "install": "Instalar", + + + /* battly social */ + "welcome_battly_social": "👋 Bienvenido/a al nuevo panel de amigos de Battly. Aquí podrás ver a todos tus amigos, añadirlos, ver qué están jugando y sus estadísticas", + "friends_list_text": "Lista de amigos", + "add_friend": "Añadir amigo", + "show_requests": "Ver solicitudes", + "accept": "Aceptar", + "starting_version_can_take": ' Iniciando versión... Puede tardar un poco...', + "you_dont_have_any_friend_requests": "No tienes solicitudes de amistad", + "friend_requests": "Solicitudes de amistad", + "request_accepted": "Solicitud aceptada", + "request_rejected": "Solicitud rechazada", + "search": "Buscar", + "loading_friends": "Cargando amigos", + "error_loading_friends": "Error al obtener la lista de amigos. Comprueba tu conexión a internet y vuelve a intentarlo más tarde.", + "in_the_main_menu": "En el menú de inicio", + "add_friend_text": "Añadir amigo", + "username": "Nombre de usuario", + "you_cannot_add_yourself": "No puedes añadirte a ti mismo como amigo.", + "you_already_have_this_friend": "Ya tienes a este usuario como amigo.", + "request_sent_to": "Solicitud enviada a", + "correctly": "correctamente", + + /* login */ + "a_microsoft_panel_opened": "Se ha abierto una ventana de inicio de sesión de Microsoft", + "logging_in": "Iniciando sesión", + "error_logging_in": "Error al iniciar sesión", + "set_your_username": "Ingresa tu nombre de usuario", + "threecharacters_username": "Tu nombre de usuario debe tener al menos 3 carácteres", + "set_your_password": "Ingresa tu contraseña", + "threecharacters_password": "Tu contraseña debe tener al menos 3 carácteres", + "username_or_password_incorrect": "El nombre de usuario o la contraseña son incorrectos", + "welcome_again_to_battly": "Bienvenid@ de nuevo a Battly", + "we_hope_you_enjoy": "¡Esperamos que disfrutes de la experiencia de juego!", + "use_account_battly_or_microsoft": "Usa tu cuenta de Battly o Microsoft para iniciar sesión en Battly", + "username": 'Nombre de usuario', + "password": 'Contraseña', + "login_text_panel_login": ' Iniciar Sesión', + "register_open_btn": 'Regístrate', + "lost_your_account": "¿Olvidaste tu contraseña?", + "recover_it_here": "Recupérala aquí", + "login": "Iniciar sesión", + "you_dont_have_account": "¿No tienes cuenta?", + "account_already_exists": "Ya has iniciado sesión con esta cuenta", + "password_not_set": "Se ha cerrado sesión de tu cuenta. Debes iniciar sesión de nuevo para continuar.", + + /* months */ + "january": "Enero", + "february": "Febrero", + "march": "Marzo", + "april": "Abril", + "may": "Mayo", + "june": "Junio", + "july": "Julio", + "august": "Agosto", + "september": "Septiembre", + "october": "Octubre", + "november": "Noviembre", + "december": "Diciembre", + + /* music */ + "you_dont_have_songs_in_your_playlist": "No tienes canciones en tu lista de reproducción", + "save_playlist": "Guardar playlist", + "saved_playlists": "Playlists guardadas", + "playlist_name": "Título de la playlist", + "save": "Guardar", + "you_need_to_set_a_playlist_name": "Debes ingresar un nombre para la playlist", + "already_have_a_playlist_with_this_name": "Ya tienes una playlist con este nombre", + "playlist_saved_correctly": "Playlist guardada correctamente", + "welcome_to_the_new_playlists_system": "Bienvenid@ al nuevo panel de playlists de Battly, aquí podrás gestionar tus playlists que habrás guardado en Battly Music.", + "getting_songs": "Obteniendo canciones", + "getting": "Obteniendo", + "loading": "Cargando", + "thumbnail": "Miniatura", + "delete": "Eliminar", + "songs_loaded_playing": "¡Música cargada!
    Reproduciendo", + "playlist_deleted_successfully": "Playlist eliminada correctamente", + "add": "Añadir", + "finded": "Encontrados", + "not_founded": "No encontrados", + "playing_now": "Reproduciendo ahora", + "your_playlist": "Tu playlist", + "no_song": "Ninguna canción", + "song_name": "Nombre de la canción", + "playlists": ' Playlists', + "search_song": ' Buscar', + "save_playlist": ' Guardar playlist', + + +}; + +export default strings; \ No newline at end of file diff --git a/src/assets/langs/fr.js b/src/assets/langs/fr.js new file mode 100644 index 0000000..64d4424 --- /dev/null +++ b/src/assets/langs/fr.js @@ -0,0 +1,349 @@ +const strings = { + "salutate": "Salut !", + "checking_connection": "Vérification de la connexion Internet", + "no_connection": "Impossible de se connecter à Internet.
    Passage en mode hors ligne", + "starting_battly": "Démarrage de Battly", + "checking_updates": "Vérification des mises à jour", + "error_checking_updates": "Erreur lors de la recherche des mises à jour. Le serveur ne répond pas. Veuillez réessayer plus tard.", + "error_connecting_server": "Erreur de connexion au serveur Battly", + "getting_actual_version": "Obtention de la version actuelle", + "downloading_update": "Téléchargement de la mise à jour", + "update_available": "Mise à jour disponible !", + "update_downloaded": "Mise à jour téléchargée", + "update_cancelled": "Mise à jour annulée", + "update_completed": "Mise à jour téléchargée. L'installateur Battly va maintenant s'ouvrir.", + "update_error": "Erreur lors de la recherche des mises à jour, erreur :
    ", + "errkr_connecting_server": "Erreur de connexion au serveur.
    Veuillez vérifier votre connexion ou réessayer ultérieurement.", + "closing_countdown": "Fermeture dans", + "starting_launcher": "Démarrage de Battly", + "ending": "Nous y sommes presque", + "close": "Fermer", + "instances": "Instances", + "welcome_instances": "👋 Bienvenue dans le nouveau panneau d'instances de Battly. Vous pouvez gérer les instances que vous utiliserez dans Battly pour vos versions ici.", + "open_instance": "Ouvrir", + "open_instance_folder": "Ouvrir le dossier de l'instance", + "delete_instance": "Supprimer", + "create_instance": "Créer une instance", + "instance_name": "Nom de l'instance", + "instance_description": "Description de l'instance", + "instance_image": "Image de l'instance", + "instance_version": "Version de l'instance", + "create_instance": "Créer une instance", + "instance_deleted_correctly": "L'instance a été supprimée correctement.", + "preparing_instance": "Préparation de l'instance", + "downloading_instance": "Téléchargement de l'instance", + "downloading_version": "Téléchargement de la version", + "downloading_loader": "Téléchargement du chargeur", + "downloading_java": "Téléchargement de Java", + "checking_instance": "Vérification en cours", + "downloading_assets": "Téléchargement des ressources", + "instance_created_correctly": "L'instance a été créée correctement.", + "fill_all_fields": "Vous devez remplir tous les champs.", + "calculating_time": "Calcul du temps", + "estimated_time_not_available": "Temps estimé non disponible", + "remaining": "Il reste", + "remaining_two": "Reste", + "are_you_sure": "Êtes-vous sûr(e) ?", + "are_you_sure_text": "Cette action ne peut pas être annulée.", + "yes_delete": "Oui, supprimer", + "no_cancel": "Non, annuler", + "playing_in": "Jouer dans", + "in_the_menu": "Dans le menu principal", + "minecraft_started_correctly": "Minecraft a démarré correctement", + "minecraft_started_correctly_body": "Minecraft a démarré correctement.", + "name": "Nom", + "description": "Description", + "select_a_file": "Sélectionnez un fichier", + "version_list_updated": "La liste des versions a été mise à jour.", + "download": "Télécharger", + "play": "Jouer", + "news_battly": "Nouveautés dans Battly", + "status_battly": "État", + "playing_now_text": "En cours de lecture maintenant", + "playing_now_body": "Aucune lecture en cours", + "users_online": "Utilisateurs en ligne", + "operative": "Opérationnel", + "maintenance": "Maintenance", + "no_connected": "Non opérationnel - Non connecté", + "ads_text": "Annonces", + + /* settings */ + "accounts_btn": ' Comptes', + "java_btn": ' Java', + "ram_btn": ' RAM', + "launcher_btn": ' Lanceur', + "theme_btn": ' Thème', + "background_btn": ' Arrière-plan', + "save_btn": ' Enregistrer', + "account_information": "Informations sur le compte", + "mc_id_text": "ID de MC :", + "showskin_userinfo_btn": "Afficher la peau", + "deleteaccount_userinfo_btn": "Supprimer le compte", + "set_skin": "Définir la peau", + "my_accounts": "Mes comptes", + "add_account_text": "Ajouter un compte", + "java_settings": 'Paramètres Java ', + "java_text_info": `Java

    Dans cette section, vous pouvez + configurer la version de Java utilisée pour démarrer votre jeu. Si vous ne savez pas ce que vous faites, + ne touchez à rien dans cette section.

    + Chemin de Java +
    + + Battly utilise une version intégrée de Java [Officiel].
    `, + "java_text_info2": ` + Cette version est disponible dans le chemin + Cependant, vous pouvez spécifier votre propre exécutable si votre version nécessite une version + différente de Java. +
    + `, + "ram_settings": 'Paramètres de RAM ', + "ram_text_info": `Dans cette section, vous pouvez configurer + la RAM qui sera attribuée à votre jeu. C'est important pour que votre jeu fonctionne correctement. + Si vous ne savez pas ce que vous faites, ne touchez à rien dans cette section.

    + RAM maximale : Indique la quantité totale de RAM attribuée à votre jeu. Il est recommandé de ne pas dépasser + 50% de la quantité totale de RAM présente sur votre PC pour qu'il fonctionne correctement. Si le PC a + plus de 8 Go de RAM, il est recommandé de lui attribuer 3 Go. Si le PC a 4 Go ou moins, n'attribuez pas plus de 2 + Go.

    + RAM minimale : Indique la quantité minimale de RAM attribuée au démarrage de votre jeu. Il est recommandé de ne pas + dépasser 3 Go pour cette valeur. La valeur typique est de 1 Go.`, + "you_have_a_total": "Vous avez un total de", + "of_ram": "de RAM", + "of_ram_disponible": "de RAM disponible", + "battly_settings": "Paramètres de Battly", + "battly_settings_information": `Démarrage de Minecraft

    Dans cette section, + vous pouvez configurer l'action que Battly effectuera lors de l'ouverture de Minecraft, que ce soit fermer Battly, fermer + Minecraft ou laisser Battly ouvert. Si vous ne savez pas ce que vous faites, ne touchez à rien dans cette + section.

    +
    + Que faire à l'ouverture de Minecraft : +
    `, + "minimalize_battly": "Masquer Battly après le démarrage de Minecraft", + "keep_battly_opened": "Maintenir Battly ouvert après le démarrage de Minecraft", + "battly_logs_text": "Journaux de Battly :", + "get_socketid": ` Obtenir l'ID unique`, + "battly_theme": "Personnaliser Battly", + "welcome": "Bienvenue !", + "battly_theme_text": "Bienvenue dans le nouveau panneau de personnalisation de Battly ! Ici, vous pouvez personnaliser Battly à votre goût, en changeant le thème, les images de fond et bien plus encore. Nous espérons que cela vous plaira !", + "change_theme_text": "Ajuster le thème", + "buttons_color": "Couleur des boutons", + "bottom_bar_text": "Couleur de la barre inférieure", + "bottom_bar_opacity": "Opacité de la barre inférieure", + "starting_music": "Son de démarrage", + "resize_image_text": "Redimensionner l'image", + "set_background_text": "Définir l'arrière-plan", + "cancel": "Annuler", + "customize_background": "Personnaliser l'arrière-plan", + "resize_background": "Redimensionner l'arrière-plan", + "background_image_text": "Image de fond", + "reset_background": "Réinitialiser l'arrière-plan", + "select_a_background": "Sélectionnez une image", + "background_set_successfully": "L'arrière-plan a été réinitialisé avec succès", + "account_deleted_successfully": "Le compte a été supprimé avec succès", + "settings_saved_successfully": "Les paramètres ont été enregistrés avec succès", + "java_path_didnt_set": "Le chemin de Java n'a pas été défini", + "java_path_set_successfully": "Le chemin de Java a été défini avec succès", + "the_file_name_java": "Le nom du fichier doit être java ou javaw", + + + /* loading */ + "loading_config": "Chargement de la configuration", + "config_loaded": "Configuration chargée", + "error_loading_config": "Erreur lors du chargement de la configuration", + "loading_versions": "Chargement des versions", + "versions_loaded": "Versions chargées", + "error_loading_versions": "Erreur lors du chargement des versions", + "loading_minecraft_versions": "Chargement des versions de Minecraft", + "minecraft_versions_loaded": "Versions de Minecraft chargées", + "error_loading_minecraft_versions": "Erreur lors du chargement des versions de Minecraft", + + + /* inicio */ + "download_version": "Télécharger la version", + "mojang_copyright": "Toutes les versions sont les officielles et non modifiées. Les versions modifiées, qu'il s'agisse de Fabric, Forge, Quilt ou OptiFine, sont créées par la communauté et non par Mojang. Tous droits réservés à Mojang Studios.", + "delete_version": "Supprimer la version", + "type_of_version": "Type de version", + "latest": "Dernière", + "recommended": "Recommandée", + "version_deleted_correctly": "Version supprimée correctement.", + "you_need_select_version": "Vous devez sélectionner une version.", + "downloading_client": "Téléchargement du client", + "starting_download_client_can_take": "Début de l'installation du client... Cela peut prendre un certain temps...", + "battly_log": "Journal de Battly", + "save_logs": "Enregistrer les journaux", + "downloading": "Téléchargement", + "downloading_files": "Téléchargement des fichiers", + "downloading_libraries": "Téléchargement des bibliothèques", + "downloading_natives": "Téléchargement des natifs", + "installing_loader": "Installation du Loader", + "extracting_loader": "Extraction du Loader", + "downloaded_successfully": "Téléchargé avec succès", + "starting_minecraft": "Démarrage de Minecraft", + "error_downloading": "Erreur lors du téléchargement", + "status": "Statut", + "error_http": "Erreur dans la requête HTTP", + "extracting": "Extraction", + "progress": "Progression", + "files_extracted_successfully": "Fichiers extraits avec succès", + "deleting_temp_files": "Suppression des fichiers temporaires", + "temp_files_deleted_successfully": "Fichiers temporaires supprimés avec succès", + "error_downloading_version": "Erreur lors du téléchargement de la version", + "version_java_error": "Vous n'avez pas la version requise de Java. Pour la télécharger, téléchargez la version 1.20.1 de vanilla, puis réessayez.", + "installing_minecraft_files": "Installation des fichiers de Minecraft", + "client_files_downloaded_successfully": "Fichiers du client téléchargés avec succès", + + "error_detected_one": "Erreur détectée : Minecraft s'est fermé de manière inattendue. Veuillez redémarrer Minecraft.", + "error_detected_two": "Erreur détectée : Erreur inconnue. Veuillez redémarrer Minecraft.", + "error_detected_three": "Erreur détectée : Pas assez de mémoire RAM pour démarrer Minecraft. N'oubliez pas que vous pouvez la configurer depuis Paramètres > RAM.", + "error_detected_four": "Erreur détectée : Impossible de patcher Forge. Veuillez redémarrer Minecraft.", + "error_detected_five": "Erreur détectée : Impossible de démarrer Minecraft. Veuillez redémarrer Minecraft.", + + "choose_fabric_version": "Sélectionnez une version de Fabric", + "choose_forge_version": "Sélectionnez une version de Forge", + "choose_quilt_version": "Sélectionnez une version de Quilt", + "choose_optifine_version": "Sélectionnez une version d'OptiFine", + "choose_a_client": "Sélectionnez un client", + + "starting_download_can_take": "Démarrage de l'installation... Cela peut prendre un certain temps...", + "battly_log": "Journal de Battly", + "log": "Journal", + + "start_minecraft_text": "Démarrer Minecraft", + "select_the_version_that_you_want": "Sélectionnez la version que vous souhaitez ouvrir", + "select_a_version": "Sélectionnez une version", + + /* logs system */ + "title_access_logs": "Accès à vos journaux", + "text_access_logs": "L'accès à vos journaux Battly a été demandé. Souhaitez-vous autoriser cela ?", + "requester": "Demandeur", + "reason": "Raison", + "text_access_logs_two": "Si vous n'autorisez pas l'accès, les journaux ne pourront pas être obtenus. Assurez-vous que le demandeur est digne de confiance.", + "allow": "Autoriser", + "deny": "Refuser", + "access_logs_denied": "L'accès aux journaux a été refusé.", + "access_logs_denied_text": "Si vous pensez être attaqué, contactez immédiatement l'équipe de support Battly.", + "your_unique_id_is": "Votre ID unique Battly est :", + "dont_share_it": "Ne partagez pas cette ID avec personne, cela pourrait représenter un risque pour votre sécurité. Si vous pensez être attaqué, contactez immédiatement l'équipe de support Battly.", + "id_copied_correctly": "L'ID a été copiée correctement.", + "copy": "Copier", + + /* mods */ + "return": "Retour", + "install_modpack": "Installer le modpack", + "search_mods": "Rechercher des mods...", + "compatible_with_curseforge_or_modrinth": "Compatible avec les modpacks de CurseForge ou Modrinth", + "install_modpack_text": "Installer le ModPack", + "you_didnt_selected_any_file": "Vous n'avez sélectionné aucun fichier", + "installing_modpack_can_take": ' Installation du ModPack... Cela peut prendre du temps...', + "no_description": "Pas de description", + "installing_file": "Installation du fichier", + "modpack_installed": "ModPack installé", + "modpack_installed_correctly": "installé correctement", + "installing_mod": "Installation du mod", + "the_file_is_not_compatible": "Le fichier n'est pas compatible", + "searching_mods": "Recherche de mods", + "downloading_mod": "Téléchargement du mod", + "mod_downloaded_successfully": "mod téléchargé avec succès", + "error_downloading_mod": "Erreur lors du téléchargement", + "error_downloading_dependency": "Erreur lors du téléchargement de la dépendance", + "dependency": "Dépendance", + "downloaded_successfully_two": "téléchargé avec succès", + "loading_mod_information": "Chargement des informations du mod", + "mod_information": "Informations du mod", + "mod_stats": "Statistiques du mod", + "downloads": "Téléchargements", + "followers": "Abonnés", + "view_on_modrinth": "Voir sur Modrinth", + "download_mod": "Télécharger le mod", + "delete_mod": "Supprimer le mod", + "all_this_information_copyright_modrinth": 'Toutes ces informations (images, noms, téléchargements, fichiers) proviennent de l\'API officielle de Modrinth. Tous droits réservés.', + "deleted_successfully": "supprimé correctement", + + + "install": "Installer", + + + /* battly social */ + "welcome_battly_social": "👋 Bienvenue dans le nouveau tableau des amis de Battly. Ici, vous pourrez voir tous vos amis, les ajouter, voir ce qu'ils jouent et leurs statistiques.", + "friends_list_text": "Liste d'amis", + "add_friend": "Ajouter un ami", + "show_requests": "Voir les demandes", + "accept": "Accepter", + "starting_version_can_take": ' Démarrage de la version... Cela peut prendre un peu de temps...', + "you_dont_have_any_friend_requests": "Vous n'avez aucune demande d'ami", + "friend_requests": "Demandes d'ami", + "request_accepted": "Demande acceptée", + "request_rejected": "Demande rejetée", + "search": "Rechercher", + "loading_friends": "Chargement des amis", + "error_loading_friends": "Erreur lors de l'obtention de la liste des amis. Vérifiez votre connexion Internet et réessayez plus tard.", + "in_the_main_menu": "Dans le menu principal", + "add_friend_text": "Ajouter un ami", + "username": "Nom d'utilisateur", + "you_cannot_add_yourself": "Vous ne pouvez pas vous ajouter en tant qu'ami.", + "you_already_have_this_friend": "Vous avez déjà cet utilisateur en ami.", + "request_sent_to": "Demande envoyée à", + "correctly": "correctement", + + /* login */ + "a_microsoft_panel_opened": "Une fenêtre de connexion Microsoft s'est ouverte", + "logging_in": "Connexion en cours", + "error_logging_in": "Erreur lors de la connexion", + "set_your_username": "Entrez votre nom d'utilisateur", + "threecharacters_username": "Votre nom d'utilisateur doit comporter au moins 3 caractères", + "set_your_password": "Entrez votre mot de passe", + "threecharacters_password": "Votre mot de passe doit comporter au moins 3 caractères", + "username_or_password_incorrect": "Le nom d'utilisateur ou le mot de passe est incorrect", + "welcome_again_to_battly": "Bienvenue de nouveau sur Battly", + "we_hope_you_enjoy": "Nous espérons que vous apprécierez l'expérience de jeu !", + "use_account_battly_or_microsoft": "Utilisez votre compte Battly ou Microsoft pour vous connecter à Battly", + "username": ` Nom d'utilisateur`, + "password": ' Mot de passe', + "login_text_panel_login": ' Connexion', + "register_open_btn": ' S\'inscrire', + "lost_your_account": "Vous avez perdu votre compte ?", + "recover_it_here": "Récupérez-le ici", + + /* months */ + "january": "Janvier", + "february": "Février", + "march": "Mars", + "april": "Avril", + "may": "Mai", + "june": "Juin", + "july": "Juillet", + "august": "Août", + "september": "Septembre", + "october": "Octobre", + "november": "Novembre", + "december": "Décembre", + + /* music */ + "you_dont_have_songs_in_your_playlist": "Vous n'avez pas de chansons dans votre liste de lecture", + "save_playlist": "Enregistrer la playlist", + "saved_playlists": "Playlists enregistrées", + "playlist_name": "Nom de la playlist", + "save": "Enregistrer", + "you_need_to_set_a_playlist_name": "Vous devez définir un nom pour la playlist", + "already_have_a_playlist_with_this_name": "Vous avez déjà une playlist avec ce nom", + "playlist_saved_correctly": "Playlist enregistrée correctement", + "welcome_to_the_new_playlists_system": "Bienvenue dans le nouveau panneau de playlists de Battly. Ici, vous pourrez gérer vos playlists enregistrées dans Battly Music.", + "getting_songs": "Obtention des chansons", + "getting": "Obtention", + "loading": "Chargement", + "thumbnail": "Miniature", + "delete": "Supprimer", + "songs_loaded_playing": "Musique chargée !
    Lecture", + "playlist_deleted_successfully": "Playlist supprimée avec succès", + "add": "Ajouter", + "found": "Trouvé", + "not_found": "Non trouvé", + "playing_now": "Lecture en cours", + "your_playlist": "Votre playlist", + "no_song": "Aucune chanson", + "song_name": "Nom de la chanson", + "playlists": ' Playlists', + "search_song": ' Rechercher', + "save_playlist": ' Enregistrer la playlist' +}; + +export default strings; \ No newline at end of file diff --git a/src/assets/langs/it.js b/src/assets/langs/it.js new file mode 100644 index 0000000..633c148 --- /dev/null +++ b/src/assets/langs/it.js @@ -0,0 +1,360 @@ +const strings = { + "salutate": "Ciao!", + "checking_connection": "Verifica connessione a Internet", + "no_connection": "Impossibile connettersi a Internet.
    Passaggio alla modalità offline", + "starting_battly": "Avvio di Battly", + "checking_updates": "Verifica aggiornamenti", + "error_checking_updates": "Errore durante la ricerca degli aggiornamenti. Il server non risponde. Riprova più tardi.", + "error_connecting_server": "Errore di connessione al server di Battly", + "getting_actual_version": "Recupero versione attuale", + "downloading_update": "Scaricamento dell'aggiornamento", + "update_available": "Aggiornamento disponibile!", + "update_downloaded": "Aggiornamento scaricato", + "update_cancelled": "Aggiornamento annullato", + "update_completed": "Aggiornamento scaricato. Ora si aprirà l'installatore di Battly", + "update_error": "Errore durante la ricerca degli aggiornamenti, errore :
    ", + "errkr_connecting_server": "Errore di connessione al server.
    Controlla la tua connessione o riprova più tardi.", + "closing_countdown": "Chiusura in", + "starting_launcher": "Avvio di Battly", + "ending": "Quasi finito", + "close": "Chiudi", + + "instances": "Istanze", + "welcome_instances": "👋 Benvenuto/a alla nuova dashboard delle istanze di Battly. Qui puoi gestire le istanze che utilizzerai in Battly per le tue versioni.", + "open_instance": "Apri", + "open_instance_folder": "Apri cartella", + "delete_instance": "Elimina", + "create_instance": "Crea istanza", + "instance_name": "Nome istanza", + "instance_description": "Descrizione istanza", + "instance_image": "Immagine istanza", + "instance_version": "Versione istanza", + "create_instance": "Crea istanza", + "instance_deleted_correctly": "L'istanza è stata eliminata correttamente.", + "preparing_instance": "Preparazione istanza", + "downloading_instance": "Scaricamento istanza", + "downloading_version": "Scaricamento versione", + "downloading_loader": "Scaricamento Loader", + "downloading_java": "Scaricamento Java", + "checking_instance": "Verifica", + "downloading_assets": "Scaricamento assets", + "instance_created_correctly": "L'istanza è stata creata correttamente.", + "fill_all_fields": "È necessario compilare tutti i campi.", + "calculating_time": "Calcolando tempo", + "estimated_time_not_available": "Tempo stimato non disponibile", + "remaining": "Rimangono", + "remaining_two": "Rimane", + + "are_you_sure": "Sei sicuro/a?", + "are_you_sure_text": "Questa azione non può essere annullata.", + "yes_delete": "Sì, elimina", + "no_cancel": "No, annulla", + + "playing_in": "Giocando in", + "in_the_menu": "Nel menu principale", + + "minecraft_started_correctly": "Minecraft avviato correttamente", + "minecraft_started_correctly_body": "Minecraft è stato avviato correttamente.", + + "name": "Nome", + "description": "Descrizione", + "select_a_file": "Seleziona un file", + + "version_list_updated": "La lista delle versioni è stata aggiornata.", + + "download": "Scarica", + "play": "Gioca", + + "news_battly": "Novità su Battly", + "status_battly": "Stato", + "playing_now_text": "Attualmente in riproduzione", + "playing_now_body": "Nessun elemento in riproduzione", + "users_online": "Utenti online", + "operative": "Operativo", + "maintenance": "Manutenzione", + "no_connected": "Non operativo - Non connesso", + "ads_text": "Pubblicità", + + /* impostazioni */ + +"accounts_btn": ' Account', +"java_btn": ' Java', +"ram_btn": ' RAM', +"launcher_btn": ' Launcher', +"theme_btn": ' Tema', +"background_btn": ' Sfondo', +"save_btn": ' Salva', +"account_information": "Informazioni dell'account", +"mc_id_text": "ID di MC:", +"showskin_userinfo_btn": "Mostra Skin", +"deleteaccount_userinfo_btn": "Elimina account", +"set_skin": "Imposta skin", +"my_accounts": "I miei account", +"add_account_text": "Aggiungi account", +"java_settings": 'Impostazioni di Java ', +"java_text_info": `Java

    In questa sezione potrai +configurare la versione di Java che verrà utilizzata per avviare il tuo gioco. Se non sai cosa stai facendo, +non toccare nulla in questa sezione.

    +Percorso di Java +
    + + Battly utilizza una versione integrata di Java [Ufficiale].
    `, +"java_text_info2": ` + Questa versione è disponibile nel percorso + Tuttavia, puoi specificare il tuo eseguibile se la tua versione richiede una versione + diversa di Java. +
    +`, +"ram_settings": 'Impostazioni della RAM ', +"ram_text_info": `In questa sezione puoi configurare +la RAM che verrà assegnata al tuo gioco. Questo è importante per il corretto funzionamento del gioco. +Se non sai cosa stai facendo, non toccare nulla in questa sezione.

    +RAM massima: Indica la quantità totale di RAM assegnata al tuo gioco. Si consiglia di non superare +il 50% della quantità totale di RAM presente nel tuo PC per garantirne il corretto funzionamento. Se il PC ha +più di 8 GB di RAM, si consiglia di assegnare 3 GB. Se il PC ha 4 GB o meno, non assegnare più di 2 +GB.

    +RAM minima: Indica la quantità minima di RAM assegnata all'avvio del tuo gioco. Si consiglia di non +impostare più di 3 GB per questo valore. Il valore tipico è di 1 GB.`, +"you_have_a_total": "Hai un totale di", +"of_ram": "di RAM", +"of_ram_disponible": "di RAM disponibile", +"battly_settings": "Impostazioni di Battly", +"battly_settings_information": `Avvio di Minecraft

    In questa sezione +potrai configurare l'azione che Battly eseguirà all'apertura di Minecraft, che sia chiudere Battly, chiudere +Minecraft o mantenere Battly aperto. Se non sai cosa stai facendo, non toccare nulla in questa +sezione.

    +
    +Cosa fare all'apertura di Minecraft: +
    `, +"minimalize_battly": "Nascondi Battly dopo l'avvio di Minecraft", +"keep_battly_opened": "Mantieni Battly aperto dopo l'avvio di Minecraft", +"battly_logs_text": "Log di Battly:", +"get_socketid": ' Ottenere ID univoco', +"battly_theme": "Personalizza Battly", +"welcome": "Benvenuto/a!", +"battly_theme_text": "Benvenuto/a nella nuova dashboard di personalizzazione di Battly! Qui potrai personalizzare Battly a tuo piacimento, cambiare tema, immagini di sfondo e molto altro. Speriamo che ti piaccia!", +"change_theme_text": "Regola il tema", +"buttons_color": "Colore dei pulsanti", +"bottom_bar_text": "Colore della barra inferiore", +"bottom_bar_opacity": "Trasparenza della barra inferiore", +"starting_music": "Suono di avvio", +"resize_image_text": "Ridimensiona immagine", +"set_background_text": "Imposta sfondo", +"cancel": "Annulla", +"customize_background": "Personalizza sfondo", +"resize_background": "Ridimensiona sfondo", +"background_image_text": "Immagine di sfondo", +"reset_background": "Ripristina sfondo", +"select_a_background": "Seleziona un'immagine", +"background_set_successfully": "Lo sfondo è stato ripristinato correttamente", +"account_deleted_successfully": "L'account è stato eliminato correttamente", +"settings_saved_successfully": "Le impostazioni sono state salvate correttamente", +"java_path_didnt_set": "Percorso di Java non impostato", +"java_path_set_successfully": "Il percorso di Java è stato impostato correttamente", +"the_file_name_java": "Il nome del file deve essere java o javaw", + +/* caricamento */ +"loading_config": "Caricamento configurazione", +"config_loaded": "Configurazione caricata", +"error_loading_config": "Errore durante il caricamento della configurazione", +"loading_versions": "Caricamento versioni", +"versions_loaded": "Versioni caricate", +"error_loading_versions": "Errore durante il caricamento delle versioni", +"loading_minecraft_versions": "Caricamento versioni di Minecraft", +"minecraft_versions_loaded": "Versioni di Minecraft caricate", +"error_loading_minecraft_versions": "Errore durante il caricamento delle versioni di Minecraft", + +/* inizio */ +"download_version": "Scarica versione", +"mojang_copyright": "Tutte le versioni sono ufficiali e non modificate. Le versioni modificate, che siano Fabric, Forge, Quilt o OptiFine, sono create dalla comunità e non da Mojang. Tutti i diritti riservati a Mojang Studios.", +"delete_version": "Elimina versione", +"type_of_version": "Tipo di versione", + +"latest": "Ultima", +"recommended": "Consigliata", + +"version_deleted_correctly": "Versione eliminata correttamente.", +"you_need_select_version": "Devi selezionare una versione.", + +"downloading_client": "Scaricamento client", +"starting_download_client_can_take": "Avvio installazione del client... Potrebbe richiedere un po'...", +"battly_log": "Registro di Battly", + "save_logs": "Salva registri", + + /* descargas */ +"downloading": "Scaricamento", +"downloading_files": "Scaricamento file", +"downloading_librairies": "Scaricamento librerie", +"downloading_natives": "Scaricamento nativi", +"installing_loader": "Installazione Loader", +"extracting_loader": "Estrazione Loader", +"downloaded_successfully": "Scaricato correttamente", +"starting_minecraft": "Avvio di Minecraft", +"error_downloading": "Errore durante il download", +"status": "Stato", +"error_http": "Errore nella richiesta HTTP", +"extracting": "Estrazione", +"progress": "Progresso", +"files_extracted_successfully": "File estratti correttamente", +"deleting_temp_files": "Eliminazione file temporanei", +"temp_files_deleted_successfully": "File temporanei eliminati correttamente", +"error_downloading_version": "Errore durante il download della versione", +"version_java_error": "Non hai la versione richiesta di Java. Per scaricarla, scarica la 1.20.1 di vanilla e riprova.", +"installing_minecraft_files": "Installazione file di Minecraft", +"client_files_downloaded_successfully": "File del client completati", + +"error_detected_one": "Errore rilevato: Minecraft si è chiuso inaspettatamente. Riavvia Minecraft.", +"error_detected_two": "Errore rilevato: Errore sconosciuto. Riavvia Minecraft.", +"error_detected_three": "Errore rilevato: Memoria RAM insufficiente per avviare Minecraft. Ricorda che puoi configurarla da Impostazioni > RAM.", +"error_detected_four": "Errore rilevato: Impossibile patchare Forge. Riavvia Minecraft.", +"error_detected_five": "Errore rilevato: Impossibile avviare Minecraft. Riavvia Minecraft.", + +"choose_fabric_version": "Seleziona una versione di Fabric", +"choose_forge_version": "Seleziona una versione di Forge", +"choose_quilt_version": "Seleziona una versione di Quilt", +"choose_optifine_version": "Seleziona una versione di OptiFine", +"choose_a_client": "Seleziona un client", + +"starting_download_can_take": "Avvio dell'installazione... Potrebbe richiedere un po'...", +"battly_log": "Registro di Battly", +"log": "Registro", + +"start_minecraft_text": "Avvia Minecraft", +"select_the_version_that_you_want": "Seleziona la versione che vuoi aprire", +"select_a_version": "Scegli una versione", + +/* sistema di log */ +"title_access_logs": "Accesso ai tuoi log", +"text_access_logs": "Si è richiesto l'accesso ai tuoi log di Battly. Vuoi consentirlo?", +"requester": "Richiedente", +"reason": "Motivo", +"text_access_logs_two": "Se non consenti l'accesso, non sarà possibile ottenere i log. Assicurati che il richiedente sia affidabile.", +"allow": "Consenti", +"deny": "Negare", +"access_logs_denied": "Accesso ai log negato.", +"access_logs_denied_text": "Se pensi di essere sotto attacco, contatta immediatamente il supporto di Battly.", +"your_unique_id_is": "La tua ID univoca di Battly è:", +"dont_share_it": "Non condividere questa ID con nessuno, potrebbe essere un rischio per la tua sicurezza. Se pensi di essere sotto attacco, contatta immediatamente il supporto di Battly.", +"id_copied_correctly": "ID copiata correttamente.", +"copy": "Copia", + +/* mod */ +"return": "Torna", +"install_modpack": "Installa modpack", +"search_mods": "Cerca mods...", +"compatible_with_curseforge_or_modrinth": "Compatibile con ModPacks di CurseForge o Modrinth", +"install_modpack_text": "Installa ModPack", +"you_didnt_selected_any_file": "Non hai selezionato nessun file", +"installing_modpack_can_take": ' Installazione ModPack... Potrebbe richiedere...', +"no_description": "Senza descrizione", +"installing_file": "Installazione file", +"modpack_installed": "ModPack installato", +"modpack_installed_correctly": "installato correttamente", +"installing_mod": "Installazione mod", +"the_file_is_not_compatible": "Il file non è compatibile", +"searching_mods": "Ricerca mods", +"downloading_mod": "Scaricamento mod", +"mod_downloaded_successfully": "scaricato correttamente", +"error_downloading_mod": "Errore durante il download", +"error_downloading_dependency": "Errore durante il download della dipendenza", +"dependency": "Dipendenza", +"downloaded_successfully_two": "scaricata correttamente", +"loading_mod_information": "Caricamento informazioni del mod", +"mod_information": "Informazioni del mod", +"mod_stats": "Statistiche del mod", +"downloads": "Download", +"followers": "Seguaci", +"view_on_modrinth": "Visualizza su Modrinth", +"download_mod": "Scarica mod", +"delete_mod": "Elimina mod", +"all_this_information_copyright_modrinth": 'Tutte queste informazioni (immagini, nomi, download, file) provengono dall\'API ufficiale di Modrinth. Tutti i diritti riservati.', +"deleted_successfully": "eliminato correttamente", + +"install": "Installa", + +/* battly social */ +"welcome_battly_social": "👋 Benvenuto/a nella nuova dashboard degli amici di Battly. Qui puoi vedere tutti i tuoi amici, aggiungerli, vedere cosa stanno giocando e le loro statistiche.", +"friends_list_text": "Lista degli amici", +"add_friend": "Aggiungi amico", +"show_requests": "Mostra richieste", +"accept": "Accetta", +"starting_version_can_take": ' Avvio versione... Potrebbe richiedere un po\'...', +"you_dont_have_any_friend_requests": "Non hai richieste di amicizia", +"friend_requests": "Richieste di amicizia", +"request_accepted": "Richiesta accettata", +"request_rejected": "Richiesta rifiutata", +"search": "Cerca", +"loading_friends": "Caricamento amici", +"error_loading_friends": "Errore nel recupero dell'elenco degli amici. Controlla la tua connessione Internet e riprova più tardi.", +"in_the_main_menu": "Nel menu principale", +"add_friend_text": "Aggiungi amico", +"username": "Nome utente", +"you_cannot_add_yourself": "Non puoi aggiungere te stesso come amico.", +"you_already_have_this_friend": "Hai già questo utente come amico.", +"request_sent_to": "Richiesta inviata a", +"correctly": "correttamente", + +/* login */ +"a_microsoft_panel_opened": "Si è aperto un pannello di accesso Microsoft", +"logging_in": "Accesso in corso", +"error_logging_in": "Errore durante l'accesso", +"set_your_username": "Inserisci il tuo nome utente", +"threecharacters_username": "Il tuo nome utente deve contenere almeno 3 caratteri", +"set_your_password": "Inserisci la tua password", +"threecharacters_password": "La tua password deve contenere almeno 3 caratteri", +"username_or_password_incorrect": "Nome utente o password errati", +"welcome_again_to_battly": "Benvenuto/a di nuovo su Battly", +"we_hope_you_enjoy": "Speriamo che tu ti diverta!", +"use_account_battly_or_microsoft": "Usa il tuo account Battly o Microsoft per accedere a Battly", +"username": 'Nome utente', +"password": ' Password', +"login_text_panel_login": ' Accesso', +"register_open_btn": ' Registrati', +"lost_your_account": "Hai dimenticato la tua password?", +"recover_it_here": "Recuperala qui", + +/* mesi */ +"january": "Gennaio", +"february": "Febbraio", +"march": "Marzo", +"april": "Aprile", +"may": "Maggio", +"june": "Giugno", +"july": "Luglio", +"august": "Agosto", +"september": "Settembre", +"october": "Ottobre", +"november": "Novembre", +"december": "Dicembre", + +/* musica */ +"you_dont_have_songs_in_your_playlist": "Non hai canzoni nella tua playlist", +"save_playlist": "Salva playlist", +"saved_playlists": "Playlist salvate", +"playlist_name": "Nome della playlist", +"save": "Salva", +"you_need_to_set_a_playlist_name": "Devi inserire un nome per la playlist", +"already_have_a_playlist_with_this_name": "Hai già una playlist con questo nome", +"playlist_saved_correctly": "Playlist salvata correttamente", +"welcome_to_the_new_playlists_system": "Benvenuto/a al nuovo pannello delle playlist di Battly, qui puoi gestire le tue playlist salvate su Battly Music.", +"getting_songs": "Ottenimento delle canzoni", +"getting": "Ottenimento", +"loading": "Caricamento", +"thumbnail": "Miniatura", +"delete": "Elimina", +"songs_loaded_playing": "Musica caricata!
    Riproduzione", +"playlist_deleted_successfully": "Playlist eliminata correttamente", +"add": "Aggiungi", +"finded": "Trovate", +"not_founded": "Non trovate", +"playing_now": "Riproduzione in corso", +"your_playlist": "La tua playlist", +"no_song": "Nessuna canzone", +"song_name": "Nome della canzone", +"playlists": ' Playlist', +"search_song": ' Cerca', +"save_playlist": ' Salva playlist', + +}; + +export default strings; \ No newline at end of file diff --git a/src/assets/langs/ja.js b/src/assets/langs/ja.js new file mode 100644 index 0000000..4ce6a5c --- /dev/null +++ b/src/assets/langs/ja.js @@ -0,0 +1,338 @@ +const strings = { + "salutate": "こんにちは!", + "checking_connection": "インターネット接続を確認中", + "no_connection": "インターネットに接続できませんでした。
    オフラインモードに切り替えます", + "starting_battly": "Battlyを起動中", + "checking_updates": "アップデートを確認中", + "error_checking_updates": "アップデートの検索中にエラーが発生しました。サーバーが応答していません。後でもう一度お試しください。", + "error_connecting_server": "Battlyサーバーへの接続エラー", + "getting_actual_version": "現在のバージョンを取得中", + "downloading_update": "アップデートをダウンロード中", + "update_available": "アップデートが利用可能です!", + "update_downloaded": "アップデートがダウンロードされました", + "update_cancelled": "アップデートがキャンセルされました", + "update_completed": "アップデートがダウンロードされました。Battlyのインストーラが開きます", + "update_error": "アップデートの検索中にエラーが発生しました、エラー:
    ", + "errkr_connecting_server": "サーバーへの接続エラー。
    接続を確認するか、後でもう一度お試しください。", + "closing_countdown": "クローズまでのカウントダウン", + "starting_launcher": "Battlyを起動中", + "ending": "もうすぐ終了します", + "close": "閉じる", + + "instances": "インスタンス", + "welcome_instances": "👋 Battlyの新しいインスタンスパネルへようこそ。ここでは、Battlyで使用するインスタンスを管理できます。", + "open_instance": "開く", + "open_instance_folder": "インスタンスフォルダを開く", + "delete_instance": "削除", + "create_instance": "インスタンスの作成", + "instance_name": "インスタンス名", + "instance_description": "インスタンスの説明", + "instance_image": "インスタンスの画像", + "instance_version": "インスタンスのバージョン", + "create_instance": "インスタンスを作成", + "instance_deleted_correctly": "インスタンスが正常に削除されました。", + "preparing_instance": "インスタンスの準備中", + "downloading_instance": "インスタンスをダウンロード中", + "downloading_version": "バージョンをダウンロード中", + "downloading_loader": "Loaderをダウンロード中", + "downloading_java": "Javaをダウンロード中", + "checking_instance": "確認中", + "downloading_assets": "アセットをダウンロード中", + "instance_created_correctly": "インスタンスが正常に作成されました。", + "fill_all_fields": "すべてのフィールドを記入する必要があります。", + "calculating_time": "時間の計算中", + "estimated_time_not_available": "見積もり時間は利用できません", + "remaining": "残り時間", + "remaining_two": "残り", + + "are_you_sure": "本当によろしいですか?", + "are_you_sure_text": "このアクションは取り消すことができません。", + "yes_delete": "はい、削除", + "no_cancel": "いいえ、キャンセル", + + "playing_in": "でプレイ中", + "in_the_menu": "メインメニューで", + + "minecraft_started_correctly": "Minecraftが正常に起動しました", + "minecraft_started_correctly_body": "Minecraftは正常に起動しました。", + + "name": "名前", + "description": "説明", + "select_a_file": "ファイルを選択", + + "version_list_updated": "バージョンリストが更新されました。", + + "download": "ダウンロード", + "play": "プレイ", + + "news_battly": "Battlyの新着情報", + "status_battly": "ステータス", + "playing_now_text": "現在再生中", + "playing_now_body": "再生中のコンテンツはありません", + "users_online": "オンラインユーザー", + "operative": "稼働中", + "maintenance": "メンテナンス中", + "no_connected": "非稼働中 - 接続なし", + "ads_text": "広告", + + /* settings */ + "accounts_btn": ' アカウント', + "java_btn": ' Java', + "ram_btn": ' RAM', + "launcher_btn": ' ランチャー', + "theme_btn": ' テーマ', + "background_btn": ' 背景', + "save_btn": ' 保存', + "account_information": "アカウント情報", + "mc_id_text": "MC ID:", + "showskin_userinfo_btn": "スキン表示", + "deleteaccount_userinfo_btn": "アカウント削除", + "set_skin": "スキンを設定", + "my_accounts": "私のアカウント", + "add_account_text": "アカウントを追加", + "java_settings": 'Java設定 ', + "java_text_info": `Java

    このセクションでは、ゲームを起動するために使用するJavaのバージョンを設定できます。何をしているのかわからない場合は、このセクションの内容を変更しないでください。

    + Javaのパス +
    + + Battlyは公式の組み込みJavaバージョンを使用しています。
    `, + "java_text_info2": ` + ただし、別のJavaバージョンが必要な場合は、独自の実行可能ファイルを指定することもできます。 +
    + `, + "ram_settings": 'RAM設定 ', + "ram_text_info": `このセクションでは、ゲームに割り当てるRAMを設定できます。これはゲームが正常に動作するために重要です。何をしているのかわからない場合は、このセクションの内容を変更しないでください。

    + 最大RAM: ゲームに割り当てるRAMの総量を示します。正常に動作するためには、PCの総RAM量の50%を超えないようにすることが推奨されます。PCのRAMが8GB以上ある場合は、3GBを割り当てることをお勧めします。PCのRAMが4GB以下の場合は、2GBを超えないようにしてください。

    + 最小RAM: ゲームを起動する際に割り当てる最小RAM量を示します。この値には3GBを超えないようにすることがお勧めされます。通常の値は1GBです。`, + "you_have_a_total": "総RAMは", + "of_ram": "RAMの", + "of_ram_disponible": "使用可能なRAMです", + "battly_settings": "Battlyの設定", + "battly_settings_information": `Minecraftの起動

    このセクションでは、Minecraftを開く際にBattlyが実行するアクションを設定できます。何をしているのかわからない場合は、このセクションの内容を変更しないでください。

    +
    + Minecraftを開く際の動作: +
    `, + "minimalize_battly": "Minecraftを開始した後にBattlyを非表示にする", + "keep_battly_opened": "Minecraftを開始した後にBattlyを開いたままにする", + "battly_logs_text": "Battlyのログ:", + "get_socketid": ' ユニークIDの取得', + "battly_theme": "Battlyのカスタマイズ", + "welcome": "ようこそ!", + "battly_theme_text": "Battlyの新しいカスタマイズパネルへようこそ!ここでは、テーマ、背景画像などを変更してBattlyをお好みにカスタマイズできます。お楽しみください!", + "change_theme_text": "テーマを変更", + "buttons_color": "ボタンの色", + "bottom_bar_text": "下部バーの色", + "bottom_bar_opacity": "下部バーの透明度", + "starting_music": "開始音楽", + "resize_image_text": "画像のサイズ変更", + "set_background_text": "背景を設定", + "cancel": "キャンセル", + "customize_background": "背景のカスタマイズ", + "resize_background": "背景のサイズ変更", + "background_image_text": "背景画像", + "reset_background": "背景をリセット", + "select_a_background": "画像を選択", + "background_set_successfully": "背景が正常にリセットされました", + "account_deleted_successfully": "アカウントが正常に削除されました", + "settings_saved_successfully": "設定が正常に保存されました", + "java_path_didnt_set": "Javaのパスが設定されていません", + "java_path_set_successfully": "Javaのパスが正常に設定されました", + "the_file_name_java": "ファイル名はjavaまたはjavawである必要があります", + + /* loading */ + "loading_config": "設定を読み込み中", + "config_loaded": "設定が読み込まれました", + "error_loading_config": "設定の読み込みエラー", + "loading_versions": "バージョンを読み込み中", + "versions_loaded": "バージョンが読み込まれました", + "error_loading_versions": "バージョンの読み込みエラー", + "loading_minecraft_versions": "Minecraftバージョンを読み込み中", + "minecraft_versions_loaded": "Minecraftバージョンが読み込まれました", + "error_loading_minecraft_versions": "Minecraftバージョンの読み込みエラー", + + /* inicio */ + "download_version": "バージョンをダウンロード", + "mojang_copyright": "すべてのバージョンは公式の修正なしです。Fabric、Forge、Quilt、OptiFineなどの修正されたバージョンはコミュニティによって作成され、Mojangによって作成されていません。全著作権所有者に帰属します。", + "delete_version": "バージョンを削除", + "type_of_version": "バージョンの種類", + + "latest": "最新", + "recommended": "おすすめ", + + "version_deleted_correctly": "バージョンが正常に削除されました。", + "you_need_select_version": "バージョンを選択する必要があります。", + + "downloading_client": "クライアントをダウンロード中", + "starting_download_client_can_take": "クライアントのインストールを開始中... しばらくかかる可能性があります...", + "battly_log": "Battlyのログ", + "save_logs": "ログを保存", + + "downloading": "ダウンロード中", + "downloading_files": "ファイルをダウンロード中", + "downloading_librairies": "ライブラリをダウンロード中", + "downloading_natives": "ネイティブをダウンロード中", + "installing_loader": "Loaderをインストール中", + "extracting_loader": "Loaderを抽出中", + "downloaded_successfully": "正常にダウンロードされました", + "starting_minecraft": "Minecraftを開始中", + "error_downloading": "ダウンロードエラー", + "status": "ステータス", + "error_http": "HTTPリクエストエラー", + "extracting": "抽出中", + "progress": "進行状況", + "files_extracted_successfully": "ファイルが正常に抽出されました", + "deleting_temp_files": "一時ファイルを削除中", + "temp_files_deleted_successfully": "一時ファイルが正常に削除されました", + "error_downloading_version": "バージョンのダウンロードエラー", + "version_java_error": "必要なJavaのバージョンがありません。1.20.1のvanillaをダウンロードしてから再試行してください。", + "installing_minecraft_files": "Minecraftファイルをインストール中", + "client_files_downloaded_successfully": "クライアントファイルが正常にダウンロードされました", + + "error_detected_one": "エラーが検出されました: Minecraftが予期せず終了しました。Minecraftを再起動してください。", + "error_detected_two": "エラーが検出されました: 未知のエラーが発生しました。Minecraftを再起動してください。", + "error_detected_three": "エラーが検出されました: Minecraftを起動するのに十分なRAMがありません。設定>RAMから構成できます。", + "error_detected_four": "エラーが検出されました: Forgeをパッチできませんでした。Minecraftを再起動してください。", + "error_detected_five": "エラーが検出されました: Minecraftを起動できませんでした。Minecraftを再起動してください。", + + "choose_fabric_version": "Fabricのバージョンを選択", + "choose_forge_version": "Forgeのバージョンを選択", + "choose_quilt_version": "Quiltのバージョンを選択", + "choose_optifine_version": "OptiFineのバージョンを選択", + "choose_a_client": "クライアントを選択", + + "starting_download_can_take": "インストールを開始中... しばらくかかる可能性があります...", + "battly_log": "Battlyログ", + "log": "ログ", + + "start_minecraft_text": "Minecraftを開始", + "select_the_version_that_you_want": "開始したいバージョンを選択", + "select_a_version": "バージョンを選択", + + "title_access_logs": "ログへのアクセス", + "text_access_logs": "Battlyのログへのアクセスが要求されました。許可しますか?", + "requester": "要求元", + "reason": "理由", + "text_access_logs_two": "アクセスを許可しない場合、ログを取得できません。要求元が信頼できるものであることを確認してください。", + "allow": "許可", + "deny": "拒否", + "access_logs_denied": "ログへのアクセスが拒否されました。", + "access_logs_denied_text": "攻撃を受けていると思われる場合は、Battlyサポートチームにすぐに連絡してください。", + "your_unique_id_is": "BattlyのユニークIDは次の通りです:", + "dont_share_it": "このIDを他の人と共有しないでください。セキュリティ上のリスクとなる可能性があります。攻撃を受けていると思われる場合は、Battlyサポートチームにすぐに連絡してください。", + "id_copied_correctly": "IDが正常にコピーされました。", + "copy": "コピー", + + "return": "戻る", + "install_modpack": "ModPackをインストール", + "search_mods": "Modsを検索...", + "compatible_with_curseforge_or_modrinth": "CurseForgeまたはModrinthのModPacksと互換性があります", + "install_modpack_text": "ModPackをインストール", + "you_didnt_selected_any_file": "ファイルが選択されていません", + "installing_modpack_can_take": ' ModPackをインストール中... しばらくかかる可能性があります...', + "no_description": "説明なし", + "installing_file": "ファイルをインストール中", + "modpack_installed": "ModPackがインストールされました", + "modpack_installed_correctly": "正常にインストールされました", + "installing_mod": "Modをインストール中", + "the_file_is_not_compatible": "このファイルは互換性がありません", + "searching_mods": "Modsを検索中", + "downloading_mod": "Modをダウンロード中", + "mod_downloaded_successfully": "正常にダウンロードされました", + "error_downloading_mod": "ダウンロードエラー", + "error_downloading_dependency": "依存関係のダウンロードエラー", + "dependency": "依存関係", + "downloaded_successfully_two": "正常にダウンロードされました", + "loading_mod_information": "Mod情報を読み込み中", + "mod_information": "Mod情報", + "mod_stats": "Mod統計", + "downloads": "ダウンロード", + "followers": "フォロワー", + "view_on_modrinth": "Modrinthで表示", + "download_mod": "Modをダウンロード", + "delete_mod": "Modを削除", + "all_this_information_copyright_modrinth": 'この情報(画像、名前、ダウンロード、ファイルなど)はすべて、Modrinthの公式APIから取得されたものです。全著作権所有者に帰属します。', + "deleted_successfully": "正常に削除されました", + + "install": "インストール", + + "welcome_battly_social": "👋 Battlyの新しいフレンドパネルへようこそ。ここではすべての友達を見ることができ、彼らを追加し、プレイ中のゲームや統計を確認できます", + "friends_list_text": "友達リスト", + "add_friend": "友達を追加", + "show_requests": "リクエストを表示", + "accept": "承諾", + "starting_version_can_take": ' バージョンを開始中... しばらくかかる可能性があります...', + "you_dont_have_any_friend_requests": "友達のリクエストがありません", + "friend_requests": "友達のリクエスト", + "request_accepted": "リクエストが受け入れられました", + "request_rejected": "リクエストが拒否されました", + "search": "検索", + "loading_friends": "友達を読み込み中", + "error_loading_friends": "友達リストの取得エラー。インターネット接続を確認してもう一度試してください。", + "in_the_main_menu": "メインメニューで", + "add_friend_text": "友達を追加", + "username": "ユーザー名", + "you_cannot_add_yourself": "自分自身を友達に追加することはできません。", + "you_already_have_this_friend": "このユーザーはすでに友達です。", + "request_sent_to": "リクエストが送信されました:", + "correctly": "正常に", + + "a_microsoft_panel_opened": "Microsoftのログインパネルが開かれました", + "logging_in": "ログイン中", + "error_logging_in": "ログインエラー", + "set_your_username": "ユーザー名を設定してください", + "threecharacters_username": "ユーザー名は少なくとも3文字である必要があります", + "set_your_password": "パスワードを設定してください", + "threecharacters_password": "パスワードは少なくとも3文字である必要があります", + "username_or_password_incorrect": "ユーザー名またはパスワードが正しくありません", + "welcome_again_to_battly": "Battlyへようこそ", + "we_hope_you_enjoy": "ゲーム体験をお楽しみいただけることを願っています!", + "use_account_battly_or_microsoft": "BattlyまたはMicrosoftアカウントを使用してBattlyにログインしてください", + "username": 'ユーザー名', + "password": ' パスワード', + "login_text_panel_login": ' ログイン', + "register_open_btn": ' 登録', + "lost_your_account": "アカウントを忘れましたか?", + "recover_it_here": "こちらで回復してください", + + "january": "1月", + "february": "2月", + "march": "3月", + "april": "4月", + "may": "5月", + "june": "6月", + "july": "7月", + "august": "8月", + "september": "9月", + "october": "10月", + "november": "11月", + "december": "12月", + + "you_dont_have_songs_in_your_playlist": "プレイリストに曲がありません", + "save_playlist": "プレイリストを保存", + "saved_playlists": "保存されたプレイリスト", + "playlist_name": "プレイリスト名", + "save": "保存", + "you_need_to_set_a_playlist_name": "プレイリストの名前を入力する必要があります", + "already_have_a_playlist_with_this_name": "この名前のプレイリストはすでに存在します", + "playlist_saved_correctly": "プレイリストが正常に保存されました", + "welcome_to_the_new_playlists_system": "Battly Musicの新しいプレイリストパネルへようこそ。ここではBattly Musicで保存したプレイリストを管理できます。", + "getting_songs": "曲を取得中", + "getting": "取得中", + "loading": "読み込み中", + "thumbnail": "サムネイル", + "delete": "削除", + "songs_loaded_playing": "音楽が読み込まれました。
    再生中", + "playlist_deleted_successfully": "プレイリストが正常に削除されました", + "add": "追加", + "finded": "見つかりました", + "not_founded": "見つかりませんでした", + "playing_now": "現在再生中", + "your_playlist": "あなたのプレイリスト", + "no_song": "曲なし", + "song_name": "曲名", + "playlists": ' プレイリスト', + "search_song": ' 検索', + "save_playlist": ' プレイリストを保存' +}; + +export default strings; \ No newline at end of file diff --git a/src/assets/langs/jp.js b/src/assets/langs/jp.js new file mode 100644 index 0000000..4ce6a5c --- /dev/null +++ b/src/assets/langs/jp.js @@ -0,0 +1,338 @@ +const strings = { + "salutate": "こんにちは!", + "checking_connection": "インターネット接続を確認中", + "no_connection": "インターネットに接続できませんでした。
    オフラインモードに切り替えます", + "starting_battly": "Battlyを起動中", + "checking_updates": "アップデートを確認中", + "error_checking_updates": "アップデートの検索中にエラーが発生しました。サーバーが応答していません。後でもう一度お試しください。", + "error_connecting_server": "Battlyサーバーへの接続エラー", + "getting_actual_version": "現在のバージョンを取得中", + "downloading_update": "アップデートをダウンロード中", + "update_available": "アップデートが利用可能です!", + "update_downloaded": "アップデートがダウンロードされました", + "update_cancelled": "アップデートがキャンセルされました", + "update_completed": "アップデートがダウンロードされました。Battlyのインストーラが開きます", + "update_error": "アップデートの検索中にエラーが発生しました、エラー:
    ", + "errkr_connecting_server": "サーバーへの接続エラー。
    接続を確認するか、後でもう一度お試しください。", + "closing_countdown": "クローズまでのカウントダウン", + "starting_launcher": "Battlyを起動中", + "ending": "もうすぐ終了します", + "close": "閉じる", + + "instances": "インスタンス", + "welcome_instances": "👋 Battlyの新しいインスタンスパネルへようこそ。ここでは、Battlyで使用するインスタンスを管理できます。", + "open_instance": "開く", + "open_instance_folder": "インスタンスフォルダを開く", + "delete_instance": "削除", + "create_instance": "インスタンスの作成", + "instance_name": "インスタンス名", + "instance_description": "インスタンスの説明", + "instance_image": "インスタンスの画像", + "instance_version": "インスタンスのバージョン", + "create_instance": "インスタンスを作成", + "instance_deleted_correctly": "インスタンスが正常に削除されました。", + "preparing_instance": "インスタンスの準備中", + "downloading_instance": "インスタンスをダウンロード中", + "downloading_version": "バージョンをダウンロード中", + "downloading_loader": "Loaderをダウンロード中", + "downloading_java": "Javaをダウンロード中", + "checking_instance": "確認中", + "downloading_assets": "アセットをダウンロード中", + "instance_created_correctly": "インスタンスが正常に作成されました。", + "fill_all_fields": "すべてのフィールドを記入する必要があります。", + "calculating_time": "時間の計算中", + "estimated_time_not_available": "見積もり時間は利用できません", + "remaining": "残り時間", + "remaining_two": "残り", + + "are_you_sure": "本当によろしいですか?", + "are_you_sure_text": "このアクションは取り消すことができません。", + "yes_delete": "はい、削除", + "no_cancel": "いいえ、キャンセル", + + "playing_in": "でプレイ中", + "in_the_menu": "メインメニューで", + + "minecraft_started_correctly": "Minecraftが正常に起動しました", + "minecraft_started_correctly_body": "Minecraftは正常に起動しました。", + + "name": "名前", + "description": "説明", + "select_a_file": "ファイルを選択", + + "version_list_updated": "バージョンリストが更新されました。", + + "download": "ダウンロード", + "play": "プレイ", + + "news_battly": "Battlyの新着情報", + "status_battly": "ステータス", + "playing_now_text": "現在再生中", + "playing_now_body": "再生中のコンテンツはありません", + "users_online": "オンラインユーザー", + "operative": "稼働中", + "maintenance": "メンテナンス中", + "no_connected": "非稼働中 - 接続なし", + "ads_text": "広告", + + /* settings */ + "accounts_btn": ' アカウント', + "java_btn": ' Java', + "ram_btn": ' RAM', + "launcher_btn": ' ランチャー', + "theme_btn": ' テーマ', + "background_btn": ' 背景', + "save_btn": ' 保存', + "account_information": "アカウント情報", + "mc_id_text": "MC ID:", + "showskin_userinfo_btn": "スキン表示", + "deleteaccount_userinfo_btn": "アカウント削除", + "set_skin": "スキンを設定", + "my_accounts": "私のアカウント", + "add_account_text": "アカウントを追加", + "java_settings": 'Java設定 ', + "java_text_info": `Java

    このセクションでは、ゲームを起動するために使用するJavaのバージョンを設定できます。何をしているのかわからない場合は、このセクションの内容を変更しないでください。

    + Javaのパス +
    + + Battlyは公式の組み込みJavaバージョンを使用しています。
    `, + "java_text_info2": ` + ただし、別のJavaバージョンが必要な場合は、独自の実行可能ファイルを指定することもできます。 +
    + `, + "ram_settings": 'RAM設定 ', + "ram_text_info": `このセクションでは、ゲームに割り当てるRAMを設定できます。これはゲームが正常に動作するために重要です。何をしているのかわからない場合は、このセクションの内容を変更しないでください。

    + 最大RAM: ゲームに割り当てるRAMの総量を示します。正常に動作するためには、PCの総RAM量の50%を超えないようにすることが推奨されます。PCのRAMが8GB以上ある場合は、3GBを割り当てることをお勧めします。PCのRAMが4GB以下の場合は、2GBを超えないようにしてください。

    + 最小RAM: ゲームを起動する際に割り当てる最小RAM量を示します。この値には3GBを超えないようにすることがお勧めされます。通常の値は1GBです。`, + "you_have_a_total": "総RAMは", + "of_ram": "RAMの", + "of_ram_disponible": "使用可能なRAMです", + "battly_settings": "Battlyの設定", + "battly_settings_information": `Minecraftの起動

    このセクションでは、Minecraftを開く際にBattlyが実行するアクションを設定できます。何をしているのかわからない場合は、このセクションの内容を変更しないでください。

    +
    + Minecraftを開く際の動作: +
    `, + "minimalize_battly": "Minecraftを開始した後にBattlyを非表示にする", + "keep_battly_opened": "Minecraftを開始した後にBattlyを開いたままにする", + "battly_logs_text": "Battlyのログ:", + "get_socketid": ' ユニークIDの取得', + "battly_theme": "Battlyのカスタマイズ", + "welcome": "ようこそ!", + "battly_theme_text": "Battlyの新しいカスタマイズパネルへようこそ!ここでは、テーマ、背景画像などを変更してBattlyをお好みにカスタマイズできます。お楽しみください!", + "change_theme_text": "テーマを変更", + "buttons_color": "ボタンの色", + "bottom_bar_text": "下部バーの色", + "bottom_bar_opacity": "下部バーの透明度", + "starting_music": "開始音楽", + "resize_image_text": "画像のサイズ変更", + "set_background_text": "背景を設定", + "cancel": "キャンセル", + "customize_background": "背景のカスタマイズ", + "resize_background": "背景のサイズ変更", + "background_image_text": "背景画像", + "reset_background": "背景をリセット", + "select_a_background": "画像を選択", + "background_set_successfully": "背景が正常にリセットされました", + "account_deleted_successfully": "アカウントが正常に削除されました", + "settings_saved_successfully": "設定が正常に保存されました", + "java_path_didnt_set": "Javaのパスが設定されていません", + "java_path_set_successfully": "Javaのパスが正常に設定されました", + "the_file_name_java": "ファイル名はjavaまたはjavawである必要があります", + + /* loading */ + "loading_config": "設定を読み込み中", + "config_loaded": "設定が読み込まれました", + "error_loading_config": "設定の読み込みエラー", + "loading_versions": "バージョンを読み込み中", + "versions_loaded": "バージョンが読み込まれました", + "error_loading_versions": "バージョンの読み込みエラー", + "loading_minecraft_versions": "Minecraftバージョンを読み込み中", + "minecraft_versions_loaded": "Minecraftバージョンが読み込まれました", + "error_loading_minecraft_versions": "Minecraftバージョンの読み込みエラー", + + /* inicio */ + "download_version": "バージョンをダウンロード", + "mojang_copyright": "すべてのバージョンは公式の修正なしです。Fabric、Forge、Quilt、OptiFineなどの修正されたバージョンはコミュニティによって作成され、Mojangによって作成されていません。全著作権所有者に帰属します。", + "delete_version": "バージョンを削除", + "type_of_version": "バージョンの種類", + + "latest": "最新", + "recommended": "おすすめ", + + "version_deleted_correctly": "バージョンが正常に削除されました。", + "you_need_select_version": "バージョンを選択する必要があります。", + + "downloading_client": "クライアントをダウンロード中", + "starting_download_client_can_take": "クライアントのインストールを開始中... しばらくかかる可能性があります...", + "battly_log": "Battlyのログ", + "save_logs": "ログを保存", + + "downloading": "ダウンロード中", + "downloading_files": "ファイルをダウンロード中", + "downloading_librairies": "ライブラリをダウンロード中", + "downloading_natives": "ネイティブをダウンロード中", + "installing_loader": "Loaderをインストール中", + "extracting_loader": "Loaderを抽出中", + "downloaded_successfully": "正常にダウンロードされました", + "starting_minecraft": "Minecraftを開始中", + "error_downloading": "ダウンロードエラー", + "status": "ステータス", + "error_http": "HTTPリクエストエラー", + "extracting": "抽出中", + "progress": "進行状況", + "files_extracted_successfully": "ファイルが正常に抽出されました", + "deleting_temp_files": "一時ファイルを削除中", + "temp_files_deleted_successfully": "一時ファイルが正常に削除されました", + "error_downloading_version": "バージョンのダウンロードエラー", + "version_java_error": "必要なJavaのバージョンがありません。1.20.1のvanillaをダウンロードしてから再試行してください。", + "installing_minecraft_files": "Minecraftファイルをインストール中", + "client_files_downloaded_successfully": "クライアントファイルが正常にダウンロードされました", + + "error_detected_one": "エラーが検出されました: Minecraftが予期せず終了しました。Minecraftを再起動してください。", + "error_detected_two": "エラーが検出されました: 未知のエラーが発生しました。Minecraftを再起動してください。", + "error_detected_three": "エラーが検出されました: Minecraftを起動するのに十分なRAMがありません。設定>RAMから構成できます。", + "error_detected_four": "エラーが検出されました: Forgeをパッチできませんでした。Minecraftを再起動してください。", + "error_detected_five": "エラーが検出されました: Minecraftを起動できませんでした。Minecraftを再起動してください。", + + "choose_fabric_version": "Fabricのバージョンを選択", + "choose_forge_version": "Forgeのバージョンを選択", + "choose_quilt_version": "Quiltのバージョンを選択", + "choose_optifine_version": "OptiFineのバージョンを選択", + "choose_a_client": "クライアントを選択", + + "starting_download_can_take": "インストールを開始中... しばらくかかる可能性があります...", + "battly_log": "Battlyログ", + "log": "ログ", + + "start_minecraft_text": "Minecraftを開始", + "select_the_version_that_you_want": "開始したいバージョンを選択", + "select_a_version": "バージョンを選択", + + "title_access_logs": "ログへのアクセス", + "text_access_logs": "Battlyのログへのアクセスが要求されました。許可しますか?", + "requester": "要求元", + "reason": "理由", + "text_access_logs_two": "アクセスを許可しない場合、ログを取得できません。要求元が信頼できるものであることを確認してください。", + "allow": "許可", + "deny": "拒否", + "access_logs_denied": "ログへのアクセスが拒否されました。", + "access_logs_denied_text": "攻撃を受けていると思われる場合は、Battlyサポートチームにすぐに連絡してください。", + "your_unique_id_is": "BattlyのユニークIDは次の通りです:", + "dont_share_it": "このIDを他の人と共有しないでください。セキュリティ上のリスクとなる可能性があります。攻撃を受けていると思われる場合は、Battlyサポートチームにすぐに連絡してください。", + "id_copied_correctly": "IDが正常にコピーされました。", + "copy": "コピー", + + "return": "戻る", + "install_modpack": "ModPackをインストール", + "search_mods": "Modsを検索...", + "compatible_with_curseforge_or_modrinth": "CurseForgeまたはModrinthのModPacksと互換性があります", + "install_modpack_text": "ModPackをインストール", + "you_didnt_selected_any_file": "ファイルが選択されていません", + "installing_modpack_can_take": ' ModPackをインストール中... しばらくかかる可能性があります...', + "no_description": "説明なし", + "installing_file": "ファイルをインストール中", + "modpack_installed": "ModPackがインストールされました", + "modpack_installed_correctly": "正常にインストールされました", + "installing_mod": "Modをインストール中", + "the_file_is_not_compatible": "このファイルは互換性がありません", + "searching_mods": "Modsを検索中", + "downloading_mod": "Modをダウンロード中", + "mod_downloaded_successfully": "正常にダウンロードされました", + "error_downloading_mod": "ダウンロードエラー", + "error_downloading_dependency": "依存関係のダウンロードエラー", + "dependency": "依存関係", + "downloaded_successfully_two": "正常にダウンロードされました", + "loading_mod_information": "Mod情報を読み込み中", + "mod_information": "Mod情報", + "mod_stats": "Mod統計", + "downloads": "ダウンロード", + "followers": "フォロワー", + "view_on_modrinth": "Modrinthで表示", + "download_mod": "Modをダウンロード", + "delete_mod": "Modを削除", + "all_this_information_copyright_modrinth": 'この情報(画像、名前、ダウンロード、ファイルなど)はすべて、Modrinthの公式APIから取得されたものです。全著作権所有者に帰属します。', + "deleted_successfully": "正常に削除されました", + + "install": "インストール", + + "welcome_battly_social": "👋 Battlyの新しいフレンドパネルへようこそ。ここではすべての友達を見ることができ、彼らを追加し、プレイ中のゲームや統計を確認できます", + "friends_list_text": "友達リスト", + "add_friend": "友達を追加", + "show_requests": "リクエストを表示", + "accept": "承諾", + "starting_version_can_take": ' バージョンを開始中... しばらくかかる可能性があります...', + "you_dont_have_any_friend_requests": "友達のリクエストがありません", + "friend_requests": "友達のリクエスト", + "request_accepted": "リクエストが受け入れられました", + "request_rejected": "リクエストが拒否されました", + "search": "検索", + "loading_friends": "友達を読み込み中", + "error_loading_friends": "友達リストの取得エラー。インターネット接続を確認してもう一度試してください。", + "in_the_main_menu": "メインメニューで", + "add_friend_text": "友達を追加", + "username": "ユーザー名", + "you_cannot_add_yourself": "自分自身を友達に追加することはできません。", + "you_already_have_this_friend": "このユーザーはすでに友達です。", + "request_sent_to": "リクエストが送信されました:", + "correctly": "正常に", + + "a_microsoft_panel_opened": "Microsoftのログインパネルが開かれました", + "logging_in": "ログイン中", + "error_logging_in": "ログインエラー", + "set_your_username": "ユーザー名を設定してください", + "threecharacters_username": "ユーザー名は少なくとも3文字である必要があります", + "set_your_password": "パスワードを設定してください", + "threecharacters_password": "パスワードは少なくとも3文字である必要があります", + "username_or_password_incorrect": "ユーザー名またはパスワードが正しくありません", + "welcome_again_to_battly": "Battlyへようこそ", + "we_hope_you_enjoy": "ゲーム体験をお楽しみいただけることを願っています!", + "use_account_battly_or_microsoft": "BattlyまたはMicrosoftアカウントを使用してBattlyにログインしてください", + "username": 'ユーザー名', + "password": ' パスワード', + "login_text_panel_login": ' ログイン', + "register_open_btn": ' 登録', + "lost_your_account": "アカウントを忘れましたか?", + "recover_it_here": "こちらで回復してください", + + "january": "1月", + "february": "2月", + "march": "3月", + "april": "4月", + "may": "5月", + "june": "6月", + "july": "7月", + "august": "8月", + "september": "9月", + "october": "10月", + "november": "11月", + "december": "12月", + + "you_dont_have_songs_in_your_playlist": "プレイリストに曲がありません", + "save_playlist": "プレイリストを保存", + "saved_playlists": "保存されたプレイリスト", + "playlist_name": "プレイリスト名", + "save": "保存", + "you_need_to_set_a_playlist_name": "プレイリストの名前を入力する必要があります", + "already_have_a_playlist_with_this_name": "この名前のプレイリストはすでに存在します", + "playlist_saved_correctly": "プレイリストが正常に保存されました", + "welcome_to_the_new_playlists_system": "Battly Musicの新しいプレイリストパネルへようこそ。ここではBattly Musicで保存したプレイリストを管理できます。", + "getting_songs": "曲を取得中", + "getting": "取得中", + "loading": "読み込み中", + "thumbnail": "サムネイル", + "delete": "削除", + "songs_loaded_playing": "音楽が読み込まれました。
    再生中", + "playlist_deleted_successfully": "プレイリストが正常に削除されました", + "add": "追加", + "finded": "見つかりました", + "not_founded": "見つかりませんでした", + "playing_now": "現在再生中", + "your_playlist": "あなたのプレイリスト", + "no_song": "曲なし", + "song_name": "曲名", + "playlists": ' プレイリスト', + "search_song": ' 検索', + "save_playlist": ' プレイリストを保存' +}; + +export default strings; \ No newline at end of file diff --git a/src/assets/langs/pt.js b/src/assets/langs/pt.js new file mode 100644 index 0000000..2b1a0b4 --- /dev/null +++ b/src/assets/langs/pt.js @@ -0,0 +1,361 @@ +const strings = { + "salutate": "Olá!", + "checking_connection": "Verificando conexão com a internet", + "no_connection": "Não foi possível conectar à internet.
    Entrando em modo offline", + "starting_battly": "Iniciando Battly", + "checking_updates": "Verificando atualizações", + "error_checking_updates": "Erro ao buscar atualizações. O servidor não está respondendo. Tente novamente mais tarde.", + "error_connecting_server": "Erro ao conectar ao servidor Battly", + "getting_actual_version": "Obtendo versão atual", + "downloading_update": "Baixando atualização", + "update_available": "Atualização disponível!", + "update_downloaded": "Atualização baixada", + "update_cancelled": "Atualização cancelada", + "update_completed": "Atualização baixada. Agora você será redirecionado para o instalador do Battly", + "update_error": "Erro ao buscar atualizações, erro :
    ", + "errkr_connecting_server": "Erro ao conectar ao servidor.
    Verifique sua conexão ou tente novamente mais tarde.", + "closing_countdown": "Fechando em", + "starting_launcher": "Iniciando Battly", + "ending": "Quase lá", + "close": "Fechar", + + "instances": "Instâncias", + "welcome_instances": "👋 Bem-vindo/a ao novo painel de instâncias do Battly. Aqui você pode gerenciar as instâncias que usará no Battly para suas versões.", + "open_instance": "Abrir", + "open_instance_folder": "Abrir pasta", + "delete_instance": "Excluir", + "create_instance": "Criar instância", + "instance_name": "Nome da instância", + "instance_description": "Descrição da instância", + "instance_image": "Imagem da instância", + "instance_version": "Versão da instância", + "create_instance": "Criar instância", + "instance_deleted_correctly": "Instância excluída com sucesso.", + "preparing_instance": "Preparando instância", + "downloading_instance": "Baixando instância", + "downloading_version": "Baixando versão", + "downloading_loader": "Baixando Loader", + "downloading_java": "Baixando Java", + "checking_instance": "Verificando", + "downloading_assets": "Baixando assets", + "instance_created_correctly": "Instância criada com sucesso.", + "fill_all_fields": "É necessário preencher todos os campos.", + "calculating_time": "Calculando tempo", + "estimated_time_not_available": "Tempo estimado não disponível", + "remaining": "Restam", + "remaining_two": "Resta", + + "are_you_sure": "Tem certeza?", + "are_you_sure_text": "Esta ação não pode ser desfeita.", + "yes_delete": "Sim, excluir", + "no_cancel": "Não, cancelar", + + "playing_in": "Jogando em", + "in_the_menu": "No menu inicial", + + "minecraft_started_correctly": "Minecraft iniciado corretamente", + "minecraft_started_correctly_body": "Minecraft foi iniciado corretamente.", + + "name": "Nome", + "description": "Descrição", + "select_a_file": "Selecione um arquivo", + + "version_list_updated": "Lista de versões atualizada.", + + "download": "Baixar", + "play": "Jogar", + + "news_battly": "Novidades no Battly", + "status_battly": "Status", + "playing_now_text": "Reproduzindo agora", + "playing_now_body": "Nada sendo reproduzido", + "users_online": "Usuários online", + "operative": "Operacional", + "maintenance": "Manutenção", + "no_connected": "Não operacional - Não conectado", + "ads_text": "Anúncios", + /* settings */ + +"accounts_btn": ' Contas', +"java_btn": ' Java', +"ram_btn": ' RAM', +"launcher_btn": ' Launcher', +"theme_btn": ' Tema', +"background_btn": ' Fundo', +"save_btn": ' Salvar', +"account_information": "Informações da conta", +"mc_id_text": "ID do MC:", +"showskin_userinfo_btn": "Mostrar Skin", +"deleteaccount_userinfo_btn": "Excluir conta", +"set_skin": "Definir skin", +"my_accounts": "Minhas contas", +"add_account_text": "Adicionar conta", +"java_settings": 'Configurações do Java ', +"java_text_info": `Java

    Nesta seção, você pode +configurar a versão do Java que será usada para iniciar seu jogo. Se você não souber o que está fazendo, +não mexa nesta seção.

    +Caminho do Java +
    + + Battly utiliza uma versão integrada do Java [Oficial].
    `, +"java_text_info2": ` + Esta versão está disponível no caminho + No entanto, você pode especificar seu próprio executável se sua versão requerer uma versão + diferente do Java. +
    +`, +"ram_settings": 'Configurações de RAM ', +"ram_text_info": `Nesta seção, você pode configurar +a quantidade de RAM alocada para o seu jogo. Isso é importante para o bom funcionamento do seu jogo. +Se você não souber o que está fazendo, não mexa nesta seção.

    +RAM máxima: Indica a quantidade total de RAM alocada para o seu jogo. É recomendável não exceder +50% da quantidade total de RAM presente no seu PC para garantir o bom funcionamento. Se o PC tiver +mais de 8GB de RAM, é recomendável alocar 3GB. Se o PC tiver 4 GB ou menos, não alocar mais de 2 +GB.

    +RAM mínima: Indica a quantidade mínima de RAM alocada ao iniciar o seu jogo. É recomendável não +definir mais de 3GB para este valor. O valor típico é 1 GB.`, +"you_have_a_total": "Você tem um total de", +"of_ram": "de RAM", +"of_ram_disponible": "de RAM disponível", +"battly_settings": "Configurações do Battly", +"battly_settings_information": `Início do Minecraft

    Nesta seção, +você pode configurar a ação que o Battly realizará ao abrir o Minecraft, seja fechar o Battly, fechar +o Minecraft ou manter o Battly aberto. Se você não souber o que está fazendo, não mexa nesta +seção.

    +
    +O que fazer ao abrir o Minecraft: +
    `, +"minimalize_battly": "Ocultar Battly após iniciar o Minecraft", +"keep_battly_opened": "Manter o Battly aberto após iniciar o Minecraft", +"battly_logs_text": "Registros do Battly:", +"get_socketid": ' Obter ID única', +"battly_theme": "Personalizar Battly", +"welcome": "Bem-vindo/a!", +"battly_theme_text": "Bem-vindo/a ao novo painel de personalização do Battly! Aqui você pode personalizar o Battly ao seu gosto, alterando o tema, as imagens de fundo e muito mais. Esperamos que você goste!", +"change_theme_text": "Ajustar o tema", +"buttons_color": "Cor dos botões", +"bottom_bar_text": "Cor da barra inferior", +"bottom_bar_opacity": "Transparência da barra inferior", +"starting_music": "Som de início", +"resize_image_text": "Redimensionar imagem", +"set_background_text": "Definir fundo", +"cancel": "Cancelar", +"customize_background": "Personalizar fundo", +"resize_background": "Ajustar o fundo", +"background_image_text": "Imagem de fundo", +"reset_background": "Restaurar fundo", +"select_a_background": "Selecione uma imagem", +"background_set_successfully": "O fundo foi restaurado com sucesso", +"account_deleted_successfully": "A conta foi excluída com sucesso", +"settings_saved_successfully": "As configurações foram salvas com sucesso", +"java_path_didnt_set": "Caminho do Java não definido", +"java_path_set_successfully": "O caminho do Java foi definido com sucesso", +"the_file_name_java": "O nome do arquivo deve ser java ou javaw", + + +/* loading */ +"loading_config": "Carregando configuração", +"config_loaded": "Configuração carregada", +"error_loading_config": "Erro ao carregar a configuração", +"loading_versions": "Carregando versões", +"versions_loaded": "Versões carregadas", +"error_loading_versions": "Erro ao carregar as versões", +"loading_minecraft_versions": "Carregando versões do Minecraft", +"minecraft_versions_loaded": "Versões do Minecraft carregadas", +"error_loading_minecraft_versions": "Erro ao carregar as versões do Minecraft", + + +/* inicio */ +"download_version": "Baixar versão", +"mojang_copyright": "Todas as versões são oficiais e não foram modificadas. Versões modificadas, seja Fabric, Forge, Quilt ou OptiFine, são criadas pela comunidade e não pela Mojang. Todos os direitos reservados à Mojang Studios.", +"delete_version": "Excluir versão", +"type_of_version": "Tipo de versão", + +"latest": "Última", +"recommended": "Recomendada", + +"version_deleted_correctly": "Versão excluída corretamente.", +"you_need_select_version": "Você precisa selecionar uma versão.", + +"downloading_client": "Baixando cliente", +"starting_download_client_can_take": "Iniciando instalação do cliente... Pode demorar um pouco...", +"battly_log": "Registro do Battly", + "save_logs": "Salvar registros", +"downloading": "Baixando", +"downloading_files": "Baixando arquivos", +"downloading_librairies": "Baixando bibliotecas", +"downloading_natives": "Baixando nativos", +"installing_loader": "Instalando Loader", +"extracting_loader": "Extraindo Loader", +"downloaded_successfully": "Baixado com sucesso", +"starting_minecraft": "Iniciando Minecraft", +"error_downloading": "Erro ao baixar", +"status": "Status", +"error_http": "Erro na solicitação HTTP", +"extracting": "Extraindo", +"progress": "Progresso", +"files_extracted_successfully": "Arquivos extraídos com sucesso", +"deleting_temp_files": "Excluindo arquivos temporários", +"temp_files_deleted_successfully": "Arquivos temporários excluídos com sucesso", +"error_downloading_version": "Erro ao baixar a versão", +"version_java_error": "Você não possui a versão necessária do Java. Para baixá-la, obtenha a versão 1.20.1 do vanilla e tente novamente.", +"installing_minecraft_files": "Instalando arquivos do Minecraft", +"client_files_downloaded_successfully": "Arquivos do cliente baixados com sucesso", + +"error_detected_one": "Erro detectado: Minecraft foi fechado inesperadamente. Reinicie o Minecraft.", +"error_detected_two": "Erro detectado: Erro desconhecido. Reinicie o Minecraft.", +"error_detected_three": "Erro detectado: Não há memória RAM suficiente para iniciar o Minecraft. Lembre-se de que você pode configurá-lo em Configurações > RAM.", +"error_detected_four": "Erro detectado: Não foi possível aplicar o patch no Forge. Reinicie o Minecraft.", +"error_detected_five": "Erro detectado: Não foi possível iniciar o Minecraft. Reinicie o Minecraft.", + +"choose_fabric_version": "Escolha uma versão do Fabric", +"choose_forge_version": "Escolha uma versão do Forge", +"choose_quilt_version": "Escolha uma versão do Quilt", +"choose_optifine_version": "Escolha uma versão do OptiFine", +"choose_a_client": "Escolha um cliente", + +"starting_download_can_take": "Iniciando instalação... Pode levar um tempo...", +"battly_log": "Registro do Battly", +"log": "Registro", + +"start_minecraft_text": "Iniciar Minecraft", +"select_the_version_that_you_want": "Selecione a versão que deseja abrir", +"select_a_version": "Escolha uma versão", + +/* logs system */ +"title_access_logs": "Acesso aos seus logs", +"text_access_logs": "Solicitou acesso aos seus logs do Battly. Deseja permitir?", +"requester": "Solicitante", +"reason": "Motivo", +"text_access_logs_two": "Se não permitir o acesso, não será possível obter os logs. Certifique-se de que o solicitante é confiável.", +"allow": "Permitir", +"deny": "Negar", +"access_logs_denied": "Acesso aos logs negado.", +"access_logs_denied_text": "Se acreditar que está sendo atacado, entre em contato urgentemente com a equipe de suporte do Battly.", +"your_unique_id_is": "Sua ID única do Battly é:", +"dont_share_it": "Não compartilhe esta ID com ninguém, pois pode representar um risco para sua segurança. Se acreditar que está sendo atacado, entre em contato urgentemente com a equipe de suporte do Battly.", +"id_copied_correctly": "A ID foi copiada corretamente.", +"copy": "Copiar", + +/* mods */ +"return": "Voltar", +"install_modpack": "Instalar modpack", +"search_mods": "Procurar mods...", +"compatible_with_curseforge_or_modrinth": "Compatível com ModPacks do CurseForge ou Modrinth", +"install_modpack_text": "Instalar ModPack", +"you_didnt_selected_any_file": "Você não selecionou nenhum arquivo", +"installing_modpack_can_take": ' Instalando ModPack... Pode levar um tempo...', +"no_description": "Sem descrição", +"installing_file": "Instalando arquivo", +"modpack_installed": "ModPack instalado", +"modpack_installed_correctly": "instalado corretamente", +"installing_mod": "Instalando mod", +"the_file_is_not_compatible": "O arquivo não é compatível", +"searching_mods": "Procurando mods", +"downloading_mod": "Baixando mod", +"mod_downloaded_successfully": "baixado com sucesso", +"error_downloading_mod": "Erro ao baixar", +"error_downloading_dependency": "Erro ao baixar a dependência", +"dependency": "Dependência", +"downloaded_successfully_two": "baixada com sucesso", +"loading_mod_information": "Carregando informações do mod", +"mod_information": "Informações do mod", +"mod_stats": "Estatísticas do mod", +"downloads": "Downloads", +"followers": "Seguidores", +"view_on_modrinth": "Ver no Modrinth", +"download_mod": "Baixar mod", +"delete_mod": "Excluir mod", +"all_this_information_copyright_modrinth": 'Todas essas informações (imagens, nomes, downloads, arquivos) são provenientes da API oficial da Modrinth. Todos os direitos reservados.', +"deleted_successfully": "excluído com sucesso", + + +"install": "Instalar", + + +/* battly social */ +"welcome_battly_social": "👋 Bem-vindo/a ao novo painel de amigos do Battly. Aqui você pode ver todos os seus amigos, adicioná-los, ver o que estão jogando e suas estatísticas", +"friends_list_text": "Lista de amigos", +"add_friend": "Adicionar amigo", +"show_requests": "Ver solicitações", +"accept": "Aceitar", +"starting_version_can_take": ' Iniciando versão... Pode levar um tempo...', +"you_dont_have_any_friend_requests": "Você não tem solicitações de amizade", +"friend_requests": "Solicitações de amizade", +"request_accepted": "Solicitação aceita", +"request_rejected": "Solicitação rejeitada", +"search": "Procurar", +"loading_friends": "Carregando amigos", +"error_loading_friends": "Erro ao obter a lista de amigos. Verifique sua conexão com a Internet e tente novamente mais tarde.", +"in_the_main_menu": "No menu principal", +"add_friend_text": "Adicionar amigo", +"username": "Nome de usuário", +"you_cannot_add_yourself": "Você não pode se adicionar como amigo.", +"you_already_have_this_friend": "Você já tem este usuário como amigo.", +"request_sent_to": "Solicitação enviada para", +"correctly": "corretamente", + +/* login */ +"a_microsoft_panel_opened": "Foi aberta uma janela de login da Microsoft", +"logging_in": "Iniciando sessão", +"error_logging_in": "Erro ao iniciar sessão", +"set_your_username": "Digite seu nome de usuário", +"threecharacters_username": "Seu nome de usuário deve ter pelo menos 3 caracteres", +"set_your_password": "Digite sua senha", +"threecharacters_password": "Sua senha deve ter pelo menos 3 caracteres", +"username_or_password_incorrect": "Nome de usuário ou senha incorretos", +"welcome_again_to_battly": "Bem-vindo/a de volta ao Battly", +"we_hope_you_enjoy": "Esperamos que você aproveite a experiência de jogo!", +"use_account_battly_or_microsoft": "Use sua conta do Battly ou Microsoft para fazer login no Battly", +"username": 'Nome de usuário', +"password": ' Senha', +"login_text_panel_login": ' Iniciar Sessão', +"register_open_btn": ' Registrar', +"lost_your_account": "Esqueceu sua senha?", +"recover_it_here": "Recupere aqui", + +/* months */ +"january": "Janeiro", +"february": "Fevereiro", +"march": "Março", +"april": "Abril", +"may": "Maio", +"june": "Junho", +"july": "Julho", +"august": "Agosto", +"september": "Setembro", +"october": "Outubro", +"november": "Novembro", +"december": "Dezembro", + +/* music */ +"you_dont_have_songs_in_your_playlist": "Você não tem músicas na sua lista de reprodução", +"save_playlist": "Salvar playlist", +"saved_playlists": "Playlists salvas", +"playlist_name": "Nome da playlist", +"save": "Salvar", +"you_need_to_set_a_playlist_name": "Você precisa inserir um nome para a playlist", +"already_have_a_playlist_with_this_name": "Você já tem uma playlist com este nome", +"playlist_saved_correctly": "Playlist salva corretamente", +"welcome_to_the_new_playlists_system": "Bem-vindo/a ao novo painel de playlists do Battly, aqui você pode gerenciar suas playlists salvas no Battly Music.", +"getting_songs": "Obtendo músicas", +"getting": "Obtendo", +"loading": "Carregando", +"thumbnail": "Miniatura", +"delete": "Excluir", +"songs_loaded_playing": "Música carregada!
    Reproduzindo", +"playlist_deleted_successfully": "Playlist excluída com sucesso", +"add": "Adicionar", +"finded": "Encontradas", +"not_founded": "Não encontradas", +"playing_now": "Reproduzindo agora", +"your_playlist": "Sua playlist", +"no_song": "Nenhuma música", +"song_name": "Nome da música", +"playlists": ' Playlists', +"search_song": ' Buscar', +"save_playlist": ' Salvar playlist', + +}; + +export default strings; \ No newline at end of file diff --git a/src/assets/langs/ru.js b/src/assets/langs/ru.js new file mode 100644 index 0000000..7750f3c --- /dev/null +++ b/src/assets/langs/ru.js @@ -0,0 +1,364 @@ +const strings = { + "salutate": "Привет!", + "checking_connection": "Проверка подключения к интернету", + "no_connection": "Не удалось подключиться к интернету.
    Переход в автономный режим", + "starting_battly": "Запуск Battly", + "checking_updates": "Проверка обновлений", + "error_checking_updates": "Ошибка при поиске обновлений. Сервер не отвечает. Попробуйте позже.", + "error_connecting_server": "Ошибка подключения к серверу Battly", + "getting_actual_version": "Получение текущей версии", + "downloading_update": "Загрузка обновления", + "update_available": "Доступно обновление!", + "update_downloaded": "Обновление загружено", + "update_cancelled": "Обновление отменено", + "update_completed": "Обновление загружено. Теперь откроется установщик Battly", + "update_error": "Ошибка при поиске обновлений, ошибка :
    ", + "errkr_connecting_server": "Ошибка подключения к серверу.
    Проверьте ваше подключение или повторите попытку позже.", + "closing_countdown": "Закрытие через", + "starting_launcher": "Запуск Battly", + "ending": "Почти готово", + "close": "Закрыть", + + "instances": "Экземпляры", + "welcome_instances": "👋 Добро пожаловать в новую панель экземпляров Battly. Здесь вы можете управлять экземплярами, которые будете использовать в Battly для ваших версий.", + "open_instance": "Открыть", + "open_instance_folder": "Открыть папку", + "delete_instance": "Удалить", + "create_instance": "Создать экземпляр", + "instance_name": "Имя экземпляра", + "instance_description": "Описание экземпляра", + "instance_image": "Изображение экземпляра", + "instance_version": "Версия экземпляра", + "create_instance": "Создать экземпляр", + "instance_deleted_correctly": "Экземпляр успешно удален.", + "preparing_instance": "Подготовка экземпляра", + "downloading_instance": "Загрузка экземпляра", + "downloading_version": "Загрузка версии", + "downloading_loader": "Загрузка Loader", + "downloading_java": "Загрузка Java", + "checking_instance": "Проверка", + "downloading_assets": "Загрузка ресурсов", + "instance_created_correctly": "Экземпляр успешно создан.", + "fill_all_fields": "Необходимо заполнить все поля.", + "calculating_time": "Вычисление времени", + "estimated_time_not_available": "Оценочное время не доступно", + "remaining": "Осталось", + "remaining_two": "Осталось", + + "are_you_sure": "Вы уверены?", + "are_you_sure_text": "Это действие нельзя отменить.", + "yes_delete": "Да, удалить", + "no_cancel": "Нет, отмена", + + "playing_in": "Играет в", + "in_the_menu": "В меню", + + "minecraft_started_correctly": "Minecraft запущен успешно", + "minecraft_started_correctly_body": "Minecraft успешно запущен.", + + "name": "Имя", + "description": "Описание", + "select_a_file": "Выберите файл", + + "version_list_updated": "Список версий обновлен.", + + "download": "Скачать", + "play": "Играть", + + "news_battly": "Новости в Battly", + "status_battly": "Статус", + "playing_now_text": "Сейчас играет", + "playing_now_body": "Ничего не воспроизводится", + "users_online": "Пользователей онлайн", + "operative": "Оперативный", + "maintenance": "Техническое обслуживание", + "no_connected": "Не оперативный - Нет подключения", + "ads_text": "Реклама", + + /* settings */ + + "accounts_btn": ' Аккаунты', + "java_btn": ' Java', + "ram_btn": ' RAM', + "launcher_btn": ' Запускатель', + "theme_btn": ' Тема', + "background_btn": ' Фон', + "save_btn": ' Сохранить', + "account_information": "Информация об аккаунте", + "mc_id_text": "ID MC:", + "showskin_userinfo_btn": "Показать скин", + "deleteaccount_userinfo_btn": "Удалить аккаунт", + "set_skin": "Установить скин", + "my_accounts": "Мои аккаунты", + "add_account_text": "Добавить аккаунт", + "java_settings": 'Настройки Java ', + "java_text_info": `Java

    В этом разделе вы можете + настроить версию Java, которую Battly будет использовать для запуска вашей игры. Если вы не знаете, + что делаете, не трогайте ничего в этом разделе.

    + Путь к Java +
    + + Battly использует встроенную версию Java [Официальная].
    `, + "java_text_info2": ` + Эта версия доступна по следующему пути. + Однако, если ваша версия требует другую версию Java, вы можете указать свой собственный исполняемый файл. +
    + `, + "ram_settings": 'Настройки RAM ', + "ram_text_info": `В этом разделе вы можете настроить + объем оперативной памяти, который будет выделен вашей игре. Это важно для правильной работы игры. + Если вы не знаете, что делаете, не трогайте ничего в этом разделе.

    + Максимальная RAM: Указывает общий объем выделенной оперативной памяти для вашей игры. Рекомендуется не превышать + 50% от общего объема оперативной памяти вашего ПК для правильной работы. Если у ПК более 8 ГБ оперативной памяти, рекомендуется + выделить 3 ГБ. Если у ПК 4 ГБ или менее, не выделяйте более 2 ГБ.

    + Минимальная RAM: Указывает минимальное количество выделенной оперативной памяти при запуске вашей игры. Рекомендуется + не указывать более 3 ГБ для этого значения. Типичное значение - 1 ГБ.`, + "you_have_a_total": "У вас всего", + "of_ram": "RAM", + "of_ram_disponible": "RAM доступно", + "battly_settings": "Настройки Battly", + "battly_settings_information": `Запуск Minecraft

    В этом разделе + вы можете настроить действие, которое выполнит Battly при открытии Minecraft, будь то закрытие Battly, закрытие + Minecraft или сохранение Battly открытым. Если вы не знаете, что делаете, не трогайте ничего в этом + разделе.

    +
    + Что делать при открытии Minecraft: +
    `, + "minimalize_battly": "Скрыть Battly после запуска Minecraft", + "keep_battly_opened": "Сохранить Battly открытым после запуска Minecraft", + "battly_logs_text": "Логи Battly:", + "get_socketid": ' Получить уникальный ID', + "battly_theme": "Настроить Battly", + "welcome": "Добро пожаловать!", + "battly_theme_text": "Добро пожаловать в новую панель настройки Battly! Здесь вы можете настроить Battly по своему вкусу, изменяя тему, фон и многое другое. Надеемся, вам понравится!", + "change_theme_text": "Настроить тему", + "buttons_color": "Цвет кнопок", + "bottom_bar_text": "Цвет нижней панели", + "bottom_bar_opacity": "Прозрачность нижней панели", + "starting_music": "Музыка запуска", + "resize_image_text": "Изменить размер изображения", + "set_background_text": "Установить фон", + "cancel": "Отмена", + "customize_background": "Настроить фон", + "resize_background": "Изменить размер фона", + "background_image_text": "Изображение фона", + "reset_background": "Сбросить фон", + "select_a_background": "Выберите изображение", + "background_set_successfully": "Фон успешно сброшен", + "account_deleted_successfully": "Аккаунт успешно удален", + "settings_saved_successfully": "Настройки успешно сохранены", + "java_path_didnt_set": "Путь Java не установлен", + "java_path_set_successfully": "Путь Java успешно установлен", + "the_file_name_java": "Имя файла должно быть java или javaw", + + + /* loading */ + "loading_config": "Загрузка конфигурации", + "config_loaded": "Конфигурация загружена", + "error_loading_config": "Ошибка при загрузке конфигурации", + "loading_versions": "Загрузка версий", + "versions_loaded": "Версии загружены", + "error_loading_versions": "Ошибка при загрузке версий", + "loading_minecraft_versions": "Загрузка версий Minecraft", + "minecraft_versions_loaded": "Версии Minecraft загружены", + "error_loading_minecraft_versions": "Ошибка при загрузке версий Minecraft", + + + /* inicio */ + "download_version": "Загрузить версию", + "mojang_copyright": "Все версии являются официальными и не модифицированными. Модифицированные версии, будь то Fabric, Forge, Quilt или OptiFine, созданы сообществом, а не Mojang. Все права защищены Mojang Studios.", + "delete_version": "Удалить версию", + "type_of_version": "Тип версии", + + "latest": "Последняя", + "recommended": "Рекомендуемая", + + "version_deleted_correctly": "Версия успешно удалена.", + "you_need_select_version": "Вам нужно выбрать версию.", + + "downloading_client": "Загрузка клиента", + "starting_download_client_can_take": "Запуск установки клиента... Это может занять некоторое время...", + "battly_log": "Лог Battly", + "save_logs": "Сохранить логи", + + /* descargando */ + "downloading": "Загрузка", + "downloading_files": "Загрузка файлов", + "downloading_librairies": "Загрузка библиотек", + "downloading_natives": "Загрузка нативов", + "installing_loader": "Установка Loader", + "extracting_loader": "Извлечение Loader", + "downloaded_successfully": "Успешно загружено", + "starting_minecraft": "Запуск Minecraft", + "error_downloading": "Ошибка загрузки", + "status": "Статус", + "error_http": "Ошибка HTTP-запроса", + "extracting": "Извлечение", + "progress": "Прогресс", + "files_extracted_successfully": "Файлы успешно извлечены", + "deleting_temp_files": "Удаление временных файлов", + "temp_files_deleted_successfully": "Временные файлы успешно удалены", + "error_downloading_version": "Ошибка загрузки версии", + "version_java_error": "У вас нет необходимой версии Java. Чтобы ее загрузить, загрузите 1.20.1 vanilla, а затем повторите попытку.", + "installing_minecraft_files": "Установка файлов Minecraft", + "client_files_downloaded_successfully": "Файлы клиента успешно завершены", + + /* Ошибки */ + "error_detected_one": "Обнаружена ошибка: Minecraft неожиданно закрылся. Перезапустите Minecraft.", + "error_detected_two": "Обнаружена ошибка: Неизвестная ошибка. Перезапустите Minecraft.", + "error_detected_three": "Обнаружена ошибка: Недостаточно оперативной памяти для запуска Minecraft. Помните, что вы можете настроить ее в Настройках > RAM.", + "error_detected_four": "Обнаружена ошибка: Не удалось пропатчить Forge. Перезапустите Minecraft.", + "error_detected_five": "Обнаружена ошибка: Не удалось запустить Minecraft. Перезапустите Minecraft.", + + /* Выбор версии */ + "choose_fabric_version": "Выберите версию Fabric", + "choose_forge_version": "Выберите версию Forge", + "choose_quilt_version": "Выберите версию Quilt", + "choose_optifine_version": "Выберите версию OptiFine", + "choose_a_client": "Выберите клиент", + + /* Запуск */ + "starting_download_can_take": "Запуск установки... Это может занять некоторое время...", + "battly_log": "Лог Battly", + "log": "Лог", + + /* Выбор версии Minecraft */ + "start_minecraft_text": "Запуск Minecraft", + "select_the_version_that_you_want": "Выберите версию, которую вы хотите открыть", + "select_a_version": "Выберите версию", + + /* Логирование системы */ + "title_access_logs": "Доступ к вашим логам", + "text_access_logs": "Требуется доступ к вашим логам Battly. Вы хотите разрешить?", + "requester": "Запрашивающий", + "reason": "Причина", + "text_access_logs_two": "Если вы не разрешите доступ, логи не смогут быть получены. Убедитесь, что запросивший - надежный.", + "allow": "Разрешить", + "deny": "Отклонить", + "access_logs_denied": "Доступ к логам отклонен.", + "access_logs_denied_text": "Если вы считаете, что вас атакуют, немедленно свяжитесь с службой поддержки Battly.", + "your_unique_id_is": "Ваш уникальный ID Battly:", + "dont_share_it": "Не раскрывайте этот ID никому, так как это может представлять угрозу для вашей безопасности. Если вы считаете, что вас атакуют, срочно свяжитесь с службой поддержки Battly.", + "id_copied_correctly": "ID успешно скопирован.", + "copy": "Копировать", + + /* Моды */ + "return": "Назад", + "install_modpack": "Установить модпак", + "search_mods": "Поиск модов...", + "compatible_with_curseforge_or_modrinth": "Совместимо с модпаками CurseForge или Modrinth", + "install_modpack_text": "Установить модпак", + "you_didnt_selected_any_file": "Вы не выбрали ни одного файла", + "installing_modpack_can_take": ' Установка модпака... Это может занять...', + "no_description": "Без описания", + "installing_file": "Установка файла", + "modpack_installed": "Модпак установлен", + "modpack_installed_correctly": "установлено успешно", + "installing_mod": "Установка мода", + "the_file_is_not_compatible": "Файл несовместим", + "searching_mods": "Поиск модов", + "downloading_mod": "Загрузка мода", + "mod_downloaded_successfully": "загружено успешно", + "error_downloading_mod": "Ошибка загрузки", + "error_downloading_dependency": "Ошибка загрузки зависимости", + "dependency": "Зависимость", + "downloaded_successfully_two": "загружено успешно", + "loading_mod_information": "Загрузка информации о моде", + "mod_information": "Информация о моде", + "mod_stats": "Статистика мода", + "downloads": "Загрузки", + "followers": "Подписчики", + "view_on_modrinth": "Посмотреть на Modrinth", + "download_mod": "Загрузить мод", + "delete_mod": "Удалить мод", + "all_this_information_copyright_modrinth": 'Вся эта информация (изображения, имена, загрузки, файлы) поступает из официального API Modrinth. Все права защищены.', + "deleted_successfully": "удалено успешно", + + "install": "Установить", + + /* Социальная часть Battly */ + "welcome_battly_social": "👋 Добро пожаловать в новую панель друзей Battly. Здесь вы сможете видеть всех своих друзей, добавлять их, видеть, что они играют, и их статистику", + "friends_list_text": "Список друзей", + "add_friend": "Добавить друга", + "show_requests": "Посмотреть запросы", + "accept": "Принять", + "starting_version_can_take": ' Запуск версии... Это может занять некоторое время...', + "you_dont_have_any_friend_requests": "У вас нет запросов на дружбу", + "friend_requests": "Запросы на дружбу", + "request_accepted": "Запрос принят", + "request_rejected": "Запрос отклонен", + "search": "Поиск", + "loading_friends": "Загрузка друзей", + "error_loading_friends": "Ошибка при получении списка друзей. Проверьте подключение к Интернету и повторите попытку позже.", + "in_the_main_menu": "В главном меню", + "add_friend_text": "Добавить друга", + "username": "Имя пользователя", + "you_cannot_add_yourself": "Вы не можете добавить себя в друзья.", + "you_already_have_this_friend": "У вас уже есть этот пользователь в друзьях.", + "request_sent_to": "Запрос отправлен", + "correctly": "правильно", + + /* Вход */ + "a_microsoft_panel_opened": "Открыт панель входа в Microsoft", + "logging_in": "Вход в систему", + "error_logging_in": "Ошибка входа в систему", + "set_your_username": "Введите свое имя пользователя", + "threecharacters_username": "Ваше имя пользователя должно содержать не менее 3 символов", + "set_your_password": "Введите свой пароль", + "threecharacters_password": "Ваш пароль должен содержать не менее 3 символов", + "username_or_password_incorrect": "Имя пользователя или пароль неверны", + "welcome_again_to_battly": "Снова добро пожаловать в Battly", + "we_hope_you_enjoy": "Мы надеемся, что вам понравится игровой опыт!", + "use_account_battly_or_microsoft": "Используйте свою учетную запись Battly или Microsoft для входа в Battly", + "username": 'Имя пользователя', + "password": ' Пароль', + "login_text_panel_login": ' Войти', + "register_open_btn": ' Зарегистрироваться', + "lost_your_account": "Забыли свой аккаунт?", + "recover_it_here": "Восстановите его здесь", + + /* Месяцы */ + "january": "Январь", + "february": "Февраль", + "march": "Март", + "april": "Апрель", + "may": "Май", + "june": "Июнь", + "july": "Июль", + "august": "Август", + "september": "Сентябрь", + "october": "Октябрь", + "november": "Ноябрь", + "december": "Декабрь", + + /* Музыка */ + "you_dont_have_songs_in_your_playlist": "У вас нет песен в плейлисте", + "save_playlist": "Сохранить плейлист", + "saved_playlists": "Сохраненные плейлисты", + "playlist_name": "Название плейлиста", + "save": "Сохранить", + "you_need_to_set_a_playlist_name": "Вы должны ввести имя для плейлиста", + "already_have_a_playlist_with_this_name": "У вас уже есть плейлист с таким именем", + "playlist_saved_correctly": "Плейлист успешно сохранен", + "welcome_to_the_new_playlists_system": "Добро пожаловать в новую систему плейлистов Battly. Здесь вы можете управлять своими плейлистами, сохраненными в Battly Music.", + "getting_songs": "Получение песен", + "getting": "Получение", + "loading": "Загрузка", + "thumbnail": "Обложка", + "delete": "Удалить", + "songs_loaded_playing": "Музыка загружена!
    Воспроизведение", + "playlist_deleted_successfully": "Плейлист успешно удален", + "add": "Добавить", + "finded": "Найдено", + "not_founded": "Не найдено", + "playing_now": "Сейчас играет", + "your_playlist": "Ваш плейлист", + "no_song": "Нет песни", + "song_name": "Название песни", + "playlists": ' Плейлисты', + "search_song": ' Поиск', + "save_playlist": ' Сохранить плейлист' + +}; + +export default strings; \ No newline at end of file diff --git a/src/assets/videos/video-select-lang-2.mp4 b/src/assets/videos/video-select-lang-2.mp4 new file mode 100644 index 0000000..41b4bcc Binary files /dev/null and b/src/assets/videos/video-select-lang-2.mp4 differ diff --git a/src/index.html b/src/index.html new file mode 100644 index 0000000..579b13e --- /dev/null +++ b/src/index.html @@ -0,0 +1,21 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/launcher.html b/src/launcher.html new file mode 100644 index 0000000..5531b78 --- /dev/null +++ b/src/launcher.html @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + +
    +
    +
    Battly Launcher 1.7.3
    +
    +
    +
    +
    +
    +
    + +
    + +

    Loading

    +
    + + +
    + + + diff --git a/src/panels/chat.html b/src/panels/chat.html new file mode 100644 index 0000000..e3c82eb --- /dev/null +++ b/src/panels/chat.html @@ -0,0 +1,11 @@ + +
    +
    +

    Battly Social +

    +
    +
    + +
    +
    \ No newline at end of file diff --git a/src/panels/friends.html b/src/panels/friends.html new file mode 100644 index 0000000..e5ad22d --- /dev/null +++ b/src/panels/friends.html @@ -0,0 +1,35 @@ +
    +
    +

    Battly Social +

    +
    +
    + + + + +
    +
    +
    +
    +
    +

    +

    + +
    +
    +
    +

    +

    +
    +
    +
    +
    +
    +
    +
    +
    \ No newline at end of file diff --git a/src/panels/home.html b/src/panels/home.html new file mode 100644 index 0000000..ac27369 --- /dev/null +++ b/src/panels/home.html @@ -0,0 +1,152 @@ + + + + + + + + + +
    + +
    +
    +

    +
    +
    +

    +
    +
    + +
    +
    Battly API
    +
    Apagado - 0ms
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    Battly WEB
    +
    Apagado - 0ms
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    Usuarios Online
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +

    Anuncios

    +
    +
    +
    +
    +
    +
    + +
    +
    + + + + + + +
    +
    + + + + +
    +
    +
    + + diff --git a/src/panels/login.html b/src/panels/login.html new file mode 100644 index 0000000..36d17b9 --- /dev/null +++ b/src/panels/login.html @@ -0,0 +1,254 @@ + + + + + + \ No newline at end of file diff --git a/src/panels/mods.html b/src/panels/mods.html new file mode 100644 index 0000000..54b8ffa --- /dev/null +++ b/src/panels/mods.html @@ -0,0 +1,41 @@ + + + + + + + + + + + + +
    + + +
    + +

    Battly Mods

    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    + + +
    +
    + + + \ No newline at end of file diff --git a/src/panels/music-small.html b/src/panels/music-small.html new file mode 100644 index 0000000..3fee5d4 --- /dev/null +++ b/src/panels/music-small.html @@ -0,0 +1,219 @@ + + + + + + + + + + +
    + + + + +
    +
    + + +
    + + Música + +
    +

    +

    +
    + +
    + +
    + +
    + +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/src/panels/music.html b/src/panels/music.html new file mode 100644 index 0000000..238196f --- /dev/null +++ b/src/panels/music.html @@ -0,0 +1,71 @@ + +
    +
    +

    Battly Music

    +
    +
    +

    Volumen

    + + +
    +
    + + +
    +
    +
    +
    +
    +
    +
    + expand_more + + more_horiz +
    +
    +
    +

    +
    +
    + +
    +
    +
    +
    + +
    +
    + 0:00 + 0:00 +
    +
    +
    + skip_previous +
    + play_arrow +
    + skip_next +
    +
    +
    +
    + +
    \ No newline at end of file diff --git a/src/panels/news.html b/src/panels/news.html new file mode 100644 index 0000000..01b7ba7 --- /dev/null +++ b/src/panels/news.html @@ -0,0 +1,241 @@ + + + + + +
    +
    +

    Battly News v1.7

    +
    +
    +
    +
    +
    + ¡Ya está aquí la nueva versión de Battly! +
    + Otra de las versiones que más hype tenían +
    +
    + +
    +

    ¿Qué hay de nuevo?

    +
    + - Mejorada la optimización y la fluidez del Launcher
    + - Nuevo modo offline
    + - Nuevo selector de versiones de Forge
    + - Nuevo instalador de clientes en Battly
    + - Nuevo Battly Social
    + - Más personalización en Battly
    + - Mejorado el panel de mods
    +
    + En resumen, muchas cosas, ahora te cuento más en detalle. +
    +
    +
    +
    + Placeholder image +
    +
    +
    +

    1ly4s0

    +

    Fundador de Battly

    +
    +
    + +
    +
    +
    +
    + Mejorada la optimización y la fluidez del Launcher +
    + Ha mejorado un 50% la rapidez en la que inicia Battly +
    +
    + +
    +

    ¿Qué ha cambiado?

    +
    + El tiempo en el que inicia Battly ha mejorado un 50%, ahora es mucho más rápido y fluido. Esto ayudará a la gente con PC's de gama baja a poder disfrutar de Battly y un mejor rendimiento en Minecraft. +
    + +
    +
    +
    +
    + Placeholder image +
    +
    +
    +

    1ly4s0

    +

    Fundador de Battly

    +
    +
    + +
    +
    +
    +
    + Nuevo selector de versiones de Forge +
    + Ahora podrás elegir la versión de Forge que quieras descargar +
    +
    + +
    +

    ¿Cómo funciona?

    +
    + Mucha gente me ha preguntado de poder descargar Forge externamente, y yo lo veía innecesario ya que Battly tenía su propio Forge, pero pensando... Recordé que mucha gente usa Forge con versiones anteriores, así que he implementado un selector de versiones de Forge, en el que podrás elegir la versión que quieras descargar. +
    +
    + Lo único que tendrás que hacer es darle a descargar, elegir una versión de Forge y automáticamente te saldrán la lista de versiones de Forge que hay disponibles de esa versión. +
    +
    +
    +
    + Placeholder image +
    +
    +
    +

    1ly4s0

    +

    Fundador de Battly

    +
    +
    + +
    +
    +
    +
    + Nuevo instalador de clientes en Battly +
    + Te va a encantar 🤑 +
    +
    + +
    +

    ¿Cómo funciona?

    +
    + El 70% de los usuarios de Battly han usado clientes almenos una vez, y yo me preguntaba... ¿Por qué no implementar un instalador de clientes en Battly? Y así lo hice, ahora podrás instalar clientes como CMPack, Batmod, Ares Client en Battly, y todo de forma automática. +
    +
    + Es una muy buena opción ya que todo es mucho más ordenado, automático y no tienes que preocuparte de nada. +
    +
    +
    +
    + Placeholder image +
    +
    +
    +

    1ly4s0

    +

    Fundador de Battly

    +
    +
    + +
    +
    + +
    +
    + Nuevo Battly Social +
    + ¡Ya era hora! +
    +
    + +
    +

    ¿Cómo funciona?

    +
    + Este sistema es el inicio de un gran sistema que se añadirá a Battly. De momento, podrás añadir amigos y ver a qué están jugando. De momento sólo es esto, pero pronto habrán chats, llamadas, etc. +
    +
    + Sé paciente, esto es sólo el inicio de un gran actualización de Battly que revolucionará los Launchers de Minecraft. +
    +
    +
    +
    + Placeholder image +
    +
    +
    +

    1ly4s0

    +

    Fundador de Battly

    +
    +
    + +
    +
    + +
    +
    + Más personalización en Battly +
    + Más opciones de personalización en Battly +
    +
    + +
    +

    ¿Cómo funciona?

    +
    + Battly es el Launcher más personalizable que existe, desde dejarte cambiar los colores de la barra inferior, los botones y hasta el fondo, pero hoy, podrás incluso personalizar la música de inicio de Battly. +
    +
    + Tendrás 4 opciones que elegir, pronto iré añadiendo más. Recuerda que si quieres añadir un sonido, puedes sugerirlo en el servidor de Discord. +
    +
    +
    +
    + Placeholder image +
    +
    +
    +

    1ly4s0

    +

    Fundador de Battly

    +
    +
    + +
    +
    + +
    +
    + Y por último... Mejorado el panel de mods +
    + Ahora es precioso +
    +
    + +
    +

    ¿Cómo funciona?

    +
    + No hay cambios en el funcionamiento, simplemente he mejorado como se ve el panel de mods para que sea mucho más agradable para ti y el resto de usuarios. Ahora se han mejorado los colores y los textos de los mods. +
    +
    +
    +
    + Placeholder image +
    +
    +
    +

    1ly4s0

    +

    Fundador de Battly

    +
    +
    + +
    +
    + +
    + diff --git a/src/panels/select-lang.html b/src/panels/select-lang.html new file mode 100644 index 0000000..84dd74e --- /dev/null +++ b/src/panels/select-lang.html @@ -0,0 +1,122 @@ + + + + + + + +
    + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/src/panels/settings.html b/src/panels/settings.html new file mode 100644 index 0000000..70fd7f9 --- /dev/null +++ b/src/panels/settings.html @@ -0,0 +1,269 @@ +
    +
    + + + + + + + +
    + +
    + + +
    +
    +
    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + + + + + +
    +
    +
    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    + RAM

    +
    +
    +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    + 0 GB
    + 0 GB +
    +
    +
    +
    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    + + + +
    + + +
    +
    +
    + +
    + +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    + + +

    +
    + +
    + + +
    +
    + + +
    +
    + + +
    +
    + +
    + +
    + + + + +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    + +
    + +
    +
    +
    + + + + +
    +
    +
    +
    +
    \ No newline at end of file diff --git a/src/panels/welcome.html b/src/panels/welcome.html new file mode 100644 index 0000000..c5b4322 --- /dev/null +++ b/src/panels/welcome.html @@ -0,0 +1,30 @@ + \ No newline at end of file