From 6c7002e78826b591acbaa87759988d59f29670db Mon Sep 17 00:00:00 2001 From: Lawin0129 Date: Mon, 28 Feb 2022 19:39:25 +0000 Subject: [PATCH] =?UTF-8?q?LawinServer=20XMPP=20=F0=9F=94=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CloudStorage/DefaultEngine.ini | 11 + CloudStorage/DefaultGame.ini | 2 + CloudStorage/DefaultRuntimeOptions.ini | 2 +- index.js | 3 +- package-lock.json | 615 ++++++++++++++++++++++++- package.json | 6 +- responses/account.json | 12 + responses/friendslist.json | 46 +- responses/friendslist2.json | 56 +-- structure/friends.js | 95 +++- structure/functions.js | 23 +- structure/user.js | 277 +++-------- structure/xmpp.js | 267 +++++++++++ 13 files changed, 1087 insertions(+), 328 deletions(-) create mode 100644 CloudStorage/DefaultEngine.ini create mode 100644 CloudStorage/DefaultGame.ini create mode 100644 responses/account.json create mode 100644 structure/xmpp.js diff --git a/CloudStorage/DefaultEngine.ini b/CloudStorage/DefaultEngine.ini new file mode 100644 index 0000000..46e8702 --- /dev/null +++ b/CloudStorage/DefaultEngine.ini @@ -0,0 +1,11 @@ +# Do not remove/change, this redirects epicgames xmpp to lawinserver xmpp +[OnlineSubsystemMcp.Xmpp] +bUseSSL=false +ServerAddr="ws://127.0.0.1" +ServerPort=80 + +# Do not remove/change, this redirects epicgames xmpp to lawinserver xmpp +[OnlineSubsystemMcp.Xmpp Prod] +bUseSSL=false +ServerAddr="ws://127.0.0.1" +ServerPort=80 \ No newline at end of file diff --git a/CloudStorage/DefaultGame.ini b/CloudStorage/DefaultGame.ini new file mode 100644 index 0000000..7030d53 --- /dev/null +++ b/CloudStorage/DefaultGame.ini @@ -0,0 +1,2 @@ +[/Script/FortniteGame.FortGlobals] +bAllowLogout=true \ No newline at end of file diff --git a/CloudStorage/DefaultRuntimeOptions.ini b/CloudStorage/DefaultRuntimeOptions.ini index 8d2f731..a7162d9 100644 --- a/CloudStorage/DefaultRuntimeOptions.ini +++ b/CloudStorage/DefaultRuntimeOptions.ini @@ -1,7 +1,7 @@ [/Script/FortniteGame.FortRuntimeOptions] bEnableMexiCola=true # Enable the new friends tab (v19.00+). bLoadDirectlyIntoLobby=false # Enable the Select Game Mode screen. -bEnableSocialTab=true # Enable the Rift Tour frontend section (v17.30) +bEnableSocialTab=true # Enable the Rift Tour frontend section (v17.30). !SocialRTInfo=ClearArray +SocialRTInfo=(SlotId=1,StartsAtUTC=9999.08.06-22.00.00) +SocialRTInfo=(SlotId=2,StartsAtUTC=9999.08.07-18.00.00) diff --git a/index.js b/index.js index 48b6918..ed8f74e 100644 --- a/index.js +++ b/index.js @@ -40,7 +40,8 @@ express.use(require("./structure/cloudstorage.js")); express.use(require("./structure/mcp.js")); const port = process.env.PORT || 3551; -express.listen(port, console.log("Started listening on port", port)); +express.listen(port, console.log("LawinServer started listening on port", port)); +require("./structure/xmpp.js"); if (!fs.existsSync(path.join(process.env.LOCALAPPDATA, "LawinServer"))) fs.mkdirSync(path.join(process.env.LOCALAPPDATA, "LawinServer")); diff --git a/package-lock.json b/package-lock.json index 2a40460..14b3960 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,8 +1,602 @@ { "name": "lawinserver", "version": "1.0.0", - "lockfileVersion": 1, + "lockfileVersion": 2, "requires": true, + "packages": { + "": { + "name": "lawinserver", + "version": "1.0.0", + "license": "GPL-3.0", + "dependencies": { + "crypto": "^1.0.1", + "express": "^4.17.2", + "fs": "^0.0.1-security", + "ini": "^2.0.0", + "path": "^0.12.7", + "ws": "^8.5.0", + "xml-parser": "^1.2.1", + "xmlbuilder": "^15.1.1" + } + }, + "node_modules/accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dependencies": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "node_modules/body-parser": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.1.tgz", + "integrity": "sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA==", + "dependencies": { + "bytes": "3.1.1", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.9.6", + "raw-body": "2.4.2", + "type-is": "~1.6.18" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/bytes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz", + "integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "node_modules/crypto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz", + "integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==", + "deprecated": "This package is no longer supported. It's now a built-in Node module. If you've depended on crypto, you should switch to the one that's built-in." + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.2.tgz", + "integrity": "sha512-oxlxJxcQlYwqPWKVJJtvQiwHgosH/LrLSPA+H4UxpyvSS6jC5aH+5MoHFM+KABgTOt0APue4w66Ha8jCUo9QGg==", + "dependencies": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.4.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.9.6", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.17.2", + "serve-static": "1.14.2", + "setprototypeof": "1.2.0", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha1-invTcYa23d84E/I4WLV+yq9eQdQ=" + }, + "node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "dependencies": { + "mime-db": "1.51.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path": { + "version": "0.12.7", + "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", + "integrity": "sha1-1NwqUGxM4hl+tIHr/NWzbAFAsQ8=", + "dependencies": { + "process": "^0.11.1", + "util": "^0.10.3" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.9.6", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", + "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==", + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.2.tgz", + "integrity": "sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==", + "dependencies": { + "bytes": "3.1.1", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "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/send": { + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", + "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "1.8.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", + "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "dependencies": { + "inherits": "2.0.3" + } + }, + "node_modules/util/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ws": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "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/xml-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/xml-parser/-/xml-parser-1.2.1.tgz", + "integrity": "sha1-wx9MNPKXXbgq0BMiISBZJzYVb80=", + "dependencies": { + "debug": "^2.2.0" + } + }, + "node_modules/xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "engines": { + "node": ">=8.0" + } + } + }, "dependencies": { "accepts": { "version": "1.3.7", @@ -413,6 +1007,25 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "ws": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "requires": {} + }, + "xml-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/xml-parser/-/xml-parser-1.2.1.tgz", + "integrity": "sha1-wx9MNPKXXbgq0BMiISBZJzYVb80=", + "requires": { + "debug": "^2.2.0" + } + }, + "xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==" } } } diff --git a/package.json b/package.json index d2a6113..aef75f1 100644 --- a/package.json +++ b/package.json @@ -8,9 +8,11 @@ "express": "^4.17.2", "fs": "^0.0.1-security", "ini": "^2.0.0", - "path": "^0.12.7" + "path": "^0.12.7", + "ws": "^8.5.0", + "xml-parser": "^1.2.1", + "xmlbuilder": "^15.1.1" }, - "devDependencies": {}, "scripts": { "start": "node index.js", "test": "echo \"Error: no test specified\" && exit 1" diff --git a/responses/account.json b/responses/account.json new file mode 100644 index 0000000..93673cc --- /dev/null +++ b/responses/account.json @@ -0,0 +1,12 @@ +[ + { + "id": "SubtoLawin_123", + "displayName": "Subscribe to Lawin on YouTube!", + "externalAuths": {} + }, + { + "id": "Followlawin_123", + "displayName": "Follow @lawin_010 on twitter!", + "externalAuths": {} + } +] \ No newline at end of file diff --git a/responses/friendslist.json b/responses/friendslist.json index 65808d0..58063a1 100644 --- a/responses/friendslist.json +++ b/responses/friendslist.json @@ -1,58 +1,16 @@ [ { - "accountId": "SubtoLawin_LOL123", + "accountId": "SubtoLawin_123", "status": "ACCEPTED", "direction": "OUTBOUND", "created": "2000-05-11T15:53:53.072Z", "favorite": false }, { - "accountId": "Followlawin_LOL123", + "accountId": "Followlawin_123", "status": "ACCEPTED", "direction": "OUTBOUND", "created": "2000-04-08T12:32:42.069Z", "favorite": false - }, - { - "accountId": "NINJALOL_1238", - "status": "ACCEPTED", - "direction": "OUTBOUND", - "created": "2000-04-08T12:32:42.069Z", - "favorite": false - }, - { - "accountId": "TFUELOL_1238", - "status": "ACCEPTED", - "direction": "OUTBOUND", - "created": "2000-04-08T12:32:42.069Z", - "favorite": false - }, - { - "accountId": "ALIALOL_1238", - "status": "ACCEPTED", - "direction": "OUTBOUND", - "created": "2000-04-08T12:32:42.069Z", - "favorite": false - }, - { - "accountId": "DAKOTAZLOL_1238", - "status": "ACCEPTED", - "direction": "OUTBOUND", - "created": "2000-04-08T12:32:42.069Z", - "favorite": false - }, - { - "accountId": "SYPHERPKLOL_1238", - "status": "ACCEPTED", - "direction": "OUTBOUND", - "created": "2000-04-08T12:32:42.069Z", - "favorite": false - }, - { - "accountId": "NICKEH30LOLL_2897669", - "status": "PENDING", - "direction": "OUTBOUND", - "created": "2000-04-08T12:32:42.069Z", - "favorite": false } ] \ No newline at end of file diff --git a/responses/friendslist2.json b/responses/friendslist2.json index e40b664..e50d307 100644 --- a/responses/friendslist2.json +++ b/responses/friendslist2.json @@ -1,7 +1,7 @@ { "friends": [ { - "accountId": "SubtoLawin_LOL123", + "accountId": "SubtoLawin_123", "groups": [], "mutual": 0, "alias": "", @@ -10,52 +10,7 @@ "created": "2000-04-08T12:32:42.069Z" }, { - "accountId": "Followlawin_LOL123", - "groups": [], - "mutual": 0, - "alias": "", - "note": "", - "favorite": false, - "created": "2000-04-08T12:32:42.069Z" - }, - { - "accountId": "NINJALOL_1238", - "groups": [], - "mutual": 0, - "alias": "", - "note": "", - "favorite": false, - "created": "2000-04-08T12:32:42.069Z" - }, - { - "accountId": "TFUELOL_1238", - "groups": [], - "mutual": 0, - "alias": "", - "note": "", - "favorite": false, - "created": "2000-04-08T12:32:42.069Z" - }, - { - "accountId": "ALIALOL_1238", - "groups": [], - "mutual": 0, - "alias": "", - "note": "", - "favorite": false, - "created": "2000-04-08T12:32:42.069Z" - }, - { - "accountId": "DAKOTAZLOL_1238", - "groups": [], - "mutual": 0, - "alias": "", - "note": "", - "favorite": false, - "created": "2000-04-08T12:32:42.069Z" - }, - { - "accountId": "SYPHERPKLOL_1238", + "accountId": "Followlawin_123", "groups": [], "mutual": 0, "alias": "", @@ -65,12 +20,7 @@ } ], "incoming": [], - "outgoing": [ - { - "accountId": "NICKEH30LOLL_2897669", - "favorite": false - } - ], + "outgoing": [], "suggested": [], "blocklist": [], "settings": { diff --git a/structure/friends.js b/structure/friends.js index 06af54e..8eb2c0b 100644 --- a/structure/friends.js +++ b/structure/friends.js @@ -1,7 +1,10 @@ const Express = require("express"); const express = Express.Router(); +const fs = require("fs"); const friendslist = require("./../responses/friendslist.json"); const friendslist2 = require("./../responses/friendslist2.json"); +const functions = require("./functions.js"); +const memory = require("./../memory.json"); express.get("/friends/api/v1/*/settings", async (req, res) => { res.json({}) @@ -11,11 +14,99 @@ express.get("/friends/api/v1/*/blocklist", async (req, res) => { res.json([]) }) -express.get("/friends/api/public/friends/*", async (req, res) => { +express.get("/friends/api/public/friends/:accountId", async (req, res) => { + functions.GetVersionInfo(req, memory); + + if (!friendslist.find(i => i.accountId == req.params.accountId)) { + var FriendObject = { + "accountId": req.params.accountId, + "status": "ACCEPTED", + "direction": "OUTBOUND", + "created": new Date().toISOString(), + "favorite": false + }; + + friendslist.push(FriendObject) + friendslist2.friends.push({ + "accountId": FriendObject.accountId, + "groups": [], + "mutual": 0, + "alias": "", + "note": "", + "favorite": FriendObject.favorite, + "created": FriendObject.created + }) + + functions.sendXmppMessageToAll({ + "payload": FriendObject, + "type": "com.epicgames.friends.core.apiobjects.Friend", + "timestamp": FriendObject.created + }) + + functions.sendXmppMessageToAll({ + "type": "FRIENDSHIP_REQUEST", + "timestamp": FriendObject.created, + "from": FriendObject.accountId, + "status": FriendObject.status + }) + + fs.writeFileSync("./responses/friendslist.json", JSON.stringify(friendslist, null, 2)); + fs.writeFileSync("./responses/friendslist2.json", JSON.stringify(friendslist2, null, 2)); + } + + if (memory.season >= 7) { + var friends = JSON.parse(JSON.stringify(friendslist)) + friends.splice(friendslist.findIndex(i => i.accountId == req.params.accountId), 1) + return res.json(friends); + } + res.json(friendslist) }) -express.get("/friends/api/v1/*/summary", async (req, res) => { +express.get("/friends/api/v1/:accountId/summary", async (req, res) => { + if (!friendslist2.friends.find(i => i.accountId == req.params.accountId)) { + var FriendObject = { + "accountId": req.params.accountId, + "groups": [], + "mutual": 0, + "alias": "", + "note": "", + "favorite": false, + "created": new Date().toISOString() + }; + + friendslist2.friends.push(FriendObject) + friendslist.push({ + "accountId": FriendObject.accountId, + "status": "ACCEPTED", + "direction": "OUTBOUND", + "created": FriendObject.created, + "favorite": FriendObject.favorite + }) + + functions.sendXmppMessageToAll({ + "payload": { + "accountId": FriendObject.accountId, + "status": "ACCEPTED", + "direction": "OUTBOUND", + "created": FriendObject.created, + "favorite": FriendObject.favorite + }, + "type": "com.epicgames.friends.core.apiobjects.Friend", + "timestamp": FriendObject.created + }) + + functions.sendXmppMessageToAll({ + "type": "FRIENDSHIP_REQUEST", + "timestamp": FriendObject.created, + "from": FriendObject.accountId, + "status": "ACCEPTED" + }) + + fs.writeFileSync("./responses/friendslist.json", JSON.stringify(friendslist, null, 2)); + fs.writeFileSync("./responses/friendslist2.json", JSON.stringify(friendslist2, null, 2)); + } + res.json(friendslist2) }) diff --git a/structure/functions.js b/structure/functions.js index 26c7300..7f1d673 100644 --- a/structure/functions.js +++ b/structure/functions.js @@ -1,5 +1,6 @@ const crypto = require("crypto"); const memory = require("./../memory.json"); +const XMLBuilder = require("xmlbuilder"); function GetVersionInfo(req, memory) { if (req.headers["user-agent"]) @@ -234,10 +235,30 @@ function MakeID() { return FinishedID; } +function sendXmppMessageToAll(body) { + if (global.Clients) { + if (typeof body == "object") body = JSON.stringify(body); + + global.Clients.forEach(ClientData => { + ClientData.client.send(XMLBuilder.create("message") + .attribute("from", "xmpp-admin@prod.ol.epicgames.com") + .attribute("xmlns", "jabber:client") + .attribute("to", ClientData.jid) + .element("body", `${body}`).up().toString()); + }); + } +} + +function DecodeBase64(str) { + return Buffer.from(str, 'base64').toString() +} + module.exports = { GetVersionInfo, getItemShop, getTheater, getContentPages, - MakeID + MakeID, + sendXmppMessageToAll, + DecodeBase64 } \ No newline at end of file diff --git a/structure/user.js b/structure/user.js index 56a2f0d..f206e73 100644 --- a/structure/user.js +++ b/structure/user.js @@ -5,240 +5,65 @@ const path = require("path"); const iniparser = require("ini"); const config = iniparser.parse(fs.readFileSync(path.join(__dirname, "..", "Config", "config.ini")).toString()); const functions = require("./functions.js"); +const accounts = require("./../responses/account.json"); var Memory_CurrentAccountID = functions.MakeID().replace(/-/ig, ""); express.get("/account/api/public/account", async (req, res) => { var displayName = config.Config.displayName; + var response = []; + + if (displayName.includes("@")) displayName = displayName.split("@")[0]; if (config.Config.bUseConfigDisplayName == false) { - displayName = req.query.accountId; - } + if (typeof req.query.accountId == "string") { + displayName = req.query.accountId; + if (displayName.includes("@")) displayName = displayName.split("@")[0]; - res.json( - [ - { + if (!accounts.find(i => i.id.toLowerCase() == req.query.accountId.toLowerCase())) { + accounts.push({ + "id": req.query.accountId, + "displayName": displayName, + "externalAuths": {} + }) + } + + if (accounts.find(i => i.id.toLowerCase() == req.query.accountId.toLowerCase()).displayName != displayName) { + var index = accounts.findIndex(i => i.id.toLowerCase() == req.query.accountId.toLowerCase()); + accounts[index].displayName = displayName; + } + } + } else if (typeof req.query.accountId == "string") { + if (!accounts.find(i => i.id.toLowerCase() == req.query.accountId.toLowerCase())) { + accounts.push({ "id": req.query.accountId, "displayName": displayName, "externalAuths": {} - }, - { - "id": "SubtoLawin_LOL123", - "displayName": "Subscribe to Lawin on YouTube!", - "externalAuths": { - "xbl": { - "type": "xbl", - "externalAuthIdType": "xuid", - "accountId": "SubtoLawin_LOL123", - "externalDisplayName": "YouTube-Lawin", - "authIds": [{ - "id": "0", - "type": "xuid" - }] - }, - "psn": { - "type": "psn", - "externalAuthId": "0", - "externalAuthIdType": "psn_user_id", - "accountId": "SubtoLawin_LOL123", - "externalDisplayName": "YouTube-Lawin", - "authIds": [{ - "id": "0", - "type": "psn_user_id" - }] - } - } - }, - { - "id": "Followlawin_LOL123", - "displayName": "Follow @lawin_010 on twitter!", - "externalAuths": { - "xbl": { - "type": "xbl", - "externalAuthIdType": "xuid", - "accountId": "Followlawin_LOL123", - "externalDisplayName": "Twitter-lawin_010", - "authIds": [{ - "id": "0", - "type": "xuid" - }] - }, - "psn": { - "type": "psn", - "externalAuthId": "0", - "externalAuthIdType": "psn_user_id", - "accountId": "Followlawin_LOL123", - "externalDisplayName": "Twitter-lawin_010", - "authIds": [{ - "id": "0", - "type": "psn_user_id" - }] - } - } - }, - { - "id": "NINJALOL_1238", - "displayName": "Ninja", - "externalAuths": { - "xbl": { - "type": "xbl", - "externalAuthIdType": "xuid", - "accountId": "NINJALOL_1238", - "externalDisplayName": "Ninja", - "authIds": [{ - "id": "0", - "type": "xuid" - }] - }, - "psn": { - "type": "psn", - "externalAuthId": "0", - "externalAuthIdType": "psn_user_id", - "accountId": "NINJALOL_1238", - "externalDisplayName": "Ninja", - "authIds": [{ - "id": "0", - "type": "psn_user_id" - }] - } - } - }, - { - "id": "TFUELOL_1238", - "displayName": "Tfue", - "externalAuths": { - "xbl": { - "type": "xbl", - "externalAuthIdType": "xuid", - "accountId": "TFUELOL_1238", - "externalDisplayName": "Tfue", - "authIds": [{ - "id": "0", - "type": "xuid" - }] - }, - "psn": { - "type": "psn", - "externalAuthId": "0", - "externalAuthIdType": "psn_user_id", - "accountId": "TFUELOL_1238", - "externalDisplayName": "Tfue", - "authIds": [{ - "id": "0", - "type": "psn_user_id" - }] - } - } - }, - { - "id": "ALIALOL_1238", - "displayName": "Ali-A", - "externalAuths": { - "xbl": { - "type": "xbl", - "externalAuthIdType": "xuid", - "accountId": "ALIALOL_1238", - "externalDisplayName": "Ali-A", - "authIds": [{ - "id": "0", - "type": "xuid" - }] - }, - "psn": { - "type": "psn", - "externalAuthId": "0", - "externalAuthIdType": "psn_user_id", - "accountId": "ALIALOL_1238", - "externalDisplayName": "Ali-A", - "authIds": [{ - "id": "0", - "type": "psn_user_id" - }] - } - } - }, - { - "id": "DAKOTAZLOL_1238", - "displayName": "Dark", - "externalAuths": { - "xbl": { - "type": "xbl", - "externalAuthIdType": "xuid", - "accountId": "DAKOTAZLOL_1238", - "externalDisplayName": "Dark", - "authIds": [{ - "id": "0", - "type": "xuid" - }] - }, - "psn": { - "type": "psn", - "externalAuthId": "0", - "externalAuthIdType": "psn_user_id", - "accountId": "DAKOTAZLOL_1238", - "externalDisplayName": "Dark", - "authIds": [{ - "id": "0", - "type": "psn_user_id" - }] - } - } - }, - { - "id": "SYPHERPKLOL_1238", - "displayName": "SypherPK", - "externalAuths": { - "xbl": { - "type": "xbl", - "externalAuthIdType": "xuid", - "accountId": "SYPHERPKLOL_1238", - "externalDisplayName": "SypherPK", - "authIds": [{ - "id": "0", - "type": "xuid" - }] - }, - "psn": { - "type": "psn", - "externalAuthId": "0", - "externalAuthIdType": "psn_user_id", - "accountId": "SYPHERPKLOL_1238", - "externalDisplayName": "SypherPK", - "authIds": [{ - "id": "0", - "type": "psn_user_id" - }] - } - } - }, - { - "id": "NICKEH30LOLL_2897669", - "displayName": "Nick Eh 30", - "externalAuths": { - "xbl": { - "type": "xbl", - "externalAuthIdType": "xuid", - "accountId": "NICKEH30LOLL_2897669", - "externalDisplayName": "Nick Eh 30", - "authIds": [{ - "id": "0", - "type": "xuid" - }] - }, - "psn": { - "type": "psn", - "externalAuthId": "0", - "externalAuthIdType": "psn_user_id", - "accountId": "NICKEH30LOLL_2897669", - "externalDisplayName": "Nick Eh 30", - "authIds": [{ - "id": "0", - "type": "psn_user_id" - }] - } - } + }) + } + + if (accounts.find(i => i.id.toLowerCase() == req.query.accountId.toLowerCase()).displayName != displayName) { + var index = accounts.findIndex(i => i.id.toLowerCase() == req.query.accountId.toLowerCase()); + accounts[index].displayName = displayName; + } + } + + if (typeof req.query.accountId == "string") { + if (accounts.find(i => i.id.toLowerCase() == req.query.accountId.toLowerCase())) { + response.push(accounts.find(i => i.id.toLowerCase() == req.query.accountId.toLowerCase())) + } + } + + if (Array.isArray(req.query.accountId)) { + for (var x in req.query.accountId) { + if (accounts.find(i => i.id.toLowerCase() == req.query.accountId[x].toLowerCase())) { + response.push(accounts.find(i => i.id.toLowerCase() == req.query.accountId[x].toLowerCase())) } - ] - ) + } + } + + fs.writeFileSync("./responses/account.json", JSON.stringify(accounts, null, 2)); + + res.json(response) }) express.get("/account/api/public/account/:accountId", async (req, res) => { @@ -248,6 +73,8 @@ express.get("/account/api/public/account/:accountId", async (req, res) => { displayName = req.params.accountId; } + if (displayName.includes("@")) displayName = displayName.split("@")[0]; + res.json({ "id": req.params.accountId, "displayName": displayName, @@ -315,8 +142,12 @@ express.post("/account/api/oauth/token", async (req, res) => { if (config.Config.bUseConfigDisplayName == false) { Memory_CurrentAccountID = req.body.username || "LawinServer" displayName = req.body.username || "LawinServer" + + if (Memory_CurrentAccountID.includes("@")) Memory_CurrentAccountID = Memory_CurrentAccountID.split("@")[0]; } + if (displayName.includes("@")) displayName = displayName.split("@")[0]; + res.json({ "access_token": "lawinstokenlol", "expires_in": 28800, diff --git a/structure/xmpp.js b/structure/xmpp.js new file mode 100644 index 0000000..4608497 --- /dev/null +++ b/structure/xmpp.js @@ -0,0 +1,267 @@ +const WebSocket = require("ws").Server; +const XMLBuilder = require("xmlbuilder"); +const XMLParser = require("xml-parser"); + +const functions = require("./../structure/functions.js"); + +const port = 80; +const wss = new WebSocket({ port: port }, console.log("XMPP started listening on port", port)); + +global.Clients = []; + +wss.on('connection', async (ws) => { + var accountId = ""; + var jid = ""; + var id = ""; + var ID = functions.MakeID(); + var Authenticated = false; + + ws.on('message', async (message) => { + if (Buffer.isBuffer(message)) message = message.toString(); + const msg = XMLParser(message); + if (!msg.root) return Error(ws); + + switch (msg.root.name) { + case "open": + ws.send(XMLBuilder.create("open") + .attribute("xmlns", "urn:ietf:params:xml:ns:xmpp-framing") + .attribute("from", "prod.ol.epicgames.com") + .attribute("id", ID) + .attribute("version", "1.0") + .attribute("xml:lang", "en").toString()) + + if (Authenticated == true) { + ws.send(XMLBuilder.create("stream:features").attribute("xmlns:stream", "http://etherx.jabber.org/streams") + .element("ver").attribute("xmlns", "urn:xmpp:features:rosterver").up() + .element("starttls").attribute("xmlns", "urn:ietf:params:xml:ns:xmpp-tls").up() + .element("bind").attribute("xmlns", "urn:ietf:params:xml:ns:xmpp-bind").up() + .element("compression").attribute("xmlns", "http://jabber.org/features/compress") + .element("method", "zlib").up().up() + .element("session").attribute("xmlns", "urn:ietf:params:xml:ns:xmpp-session").up().toString()) + } else { + ws.send(XMLBuilder.create("stream:features").attribute("xmlns:stream", "http://etherx.jabber.org/streams") + .element("mechanisms").attribute("xmlns", "urn:ietf:params:xml:ns:xmpp-sasl") + .element("mechanism", "PLAIN").up().up() + .element("ver").attribute("xmlns", "urn:xmpp:features:rosterver").up() + .element("starttls").attribute("xmlns", "urn:ietf:params:xml:ns:xmpp-tls").up() + .element("compression").attribute("xmlns", "http://jabber.org/features/compress") + .element("method", "zlib").up().up() + .element("auth").attribute("xmlns", "http://jabber.org/features/iq-auth").up().toString()) + } + break; + + case "auth": + if (!msg.root.content) return Error(ws); + if (!functions.DecodeBase64(msg.root.content)) return Error(ws); + if (!functions.DecodeBase64(msg.root.content).includes("\u0000")) return Error(ws); + var decodedBase64 = functions.DecodeBase64(msg.root.content).split("\u0000"); + + if (global.Clients.find(i => i.accountId == decodedBase64[1])) return Error(ws); + + accountId = decodedBase64[1]; + + if (decodedBase64 && accountId && decodedBase64.length == 3) { + Authenticated = true; + console.log(`An xmpp client with the account id ${accountId} has logged in.`); + Success(ws); + } else { + return Error(ws); + } + break; + + case "iq": + switch (msg.root.attributes.id) { + case "_xmpp_bind1": + if (!msg.root.children.find(i => i.name == "bind")) return; + if (!msg.root.children.find(i => i.name == "bind").children.find(i => i.name == "resource")) return; + var resource = msg.root.children.find(i => i.name == "bind").children.find(i => i.name == "resource").content; + jid = `${accountId}@prod.ol.epicgames.com/${resource}`; + id = `${accountId}@prod.ol.epicgames.com`; + + ws.send(XMLBuilder.create("iq") + .attribute("to", jid) + .attribute("id", "_xmpp_bind1") + .attribute("xmlns", "jabber:client") + .attribute("type", "result") + .element("bind") + .attribute("xmlns", "urn:ietf:params:xml:ns:xmpp-bind") + .element("jid", jid).up().up().toString()) + break; + + case "_xmpp_session1": + if (!global.Clients.find(i => i.client == ws)) return Error(ws); + var xml = XMLBuilder.create("iq") + .attribute("to", jid) + .attribute("from", "prod.ol.epicgames.com") + .attribute("id", "_xmpp_session1") + .attribute("xmlns", "jabber:client") + .attribute("type", "result"); + + ws.send(xml.toString()); + getPresenceFromAll(ws); + break; + + default: + if (!global.Clients.find(i => i.client == ws)) return Error(ws); + var xml = XMLBuilder.create("iq") + .attribute("to", jid) + .attribute("from", "prod.ol.epicgames.com") + .attribute("id", msg.root.attributes.id) + .attribute("xmlns", "jabber:client") + .attribute("type", "result"); + + ws.send(xml.toString()); + } + break; + + case "message": + if (!global.Clients.find(i => i.client == ws)) return Error(ws); + if (!msg.root.children.find(i => i.name == "body")) return; + var body = msg.root.children.find(i => i.name == "body").content; + + if (msg.root.attributes.type) { + if (msg.root.attributes.type == "chat") { + if (!msg.root.attributes.to) return; + var receiver = global.Clients.find(i => i.id == msg.root.attributes.to); + var sender = global.Clients.find(i => i.client == ws); + if (!receiver || !sender) return; + if (receiver == sender) return; + + receiver.client.send(XMLBuilder.create("message") + .attribute("to", receiver.jid) + .attribute("from", sender.jid) + .attribute("xmlns", "jabber:client") + .attribute("type", "chat") + .element("body", body).up().toString()) + return; + } + } + + if (ifJSON(body)) { + var object = JSON.parse(body); + + if (object.hasOwnProperty("type")) { + if (typeof object.type == "string") { + switch (object.type.toLowerCase()) { + case "com.epicgames.party.invitation": + if (!msg.root.attributes.to) return; + var sender = global.Clients.find(i => i.client == ws); + var receiver = global.Clients.find(i => i.id == msg.root.attributes.to); + if (!receiver) return; + + receiver.client.send(XMLBuilder.create("message") + .attribute("from", sender.jid) + .attribute("id", msg.root.attributes.id) + .attribute("to", receiver.jid) + .attribute("xmlns", "jabber:client") + .element("body", body).up().toString()) + break; + + default: + ws.send(XMLBuilder.create("message") + .attribute("from", jid) + .attribute("id", msg.root.attributes.id) + .attribute("to", jid) + .attribute("xmlns", "jabber:client") + .element("body", body).up().toString()); + } + } + } + } + break; + + case "presence": + if (!global.Clients.find(i => i.client == ws)) return Error(ws); + if (!msg.root.children.find(i => i.name == "status")) return; + if (!ifJSON(msg.root.children.find(i => i.name == "status").content)) return; + var body = msg.root.children.find(i => i.name == "status").content; + var away = false; + if (msg.root.children.find(i => i.name == "show")) away = true; + + updatePresenceForAll(ws, body, away, false) + break; + } + + if (!global.Clients.find(i => i.client == ws)) { + if (accountId && jid && ID && id && Authenticated == true) { + global.Clients.push({ "client": ws, "accountId": accountId, "jid": jid, "id": id, "lastPresenceUpdate": { "away": false, "status": "{}" } }); + } + } + }) + + ws.on('close', () => RemoveClient(ws)) +}) + +function RemoveClient(ws) { + if (global.Clients.find(i => i.client == ws)) { + updatePresenceForAll(ws, "{}", false, true); + + console.log(`An xmpp client with the account id ${global.Clients.find(i => i.client == ws).accountId} has logged out.`); + + global.Clients.splice(global.Clients.findIndex(i => i.client == ws), 1); + } +} + +function Error(ws) { + ws.send(XMLBuilder.create("close").attribute("xmlns", "urn:ietf:params:xml:ns:xmpp-framing").toString()); + ws.close(); +} + +function Success(ws) { + ws.send(XMLBuilder.create("success").attribute("xmlns", "urn:ietf:params:xml:ns:xmpp-sasl").toString()); +} + +function updatePresenceForAll(ws, body, away, offline) { + if (global.Clients.find(i => i.client == ws)) { + var SenderData = global.Clients.find(i => i.client == ws); + var SenderIndex = global.Clients.findIndex(i => i.client == ws); + global.Clients[SenderIndex].lastPresenceUpdate.away = away; + global.Clients[SenderIndex].lastPresenceUpdate.status = body; + + global.Clients.forEach(ClientData => { + var xml = XMLBuilder.create("presence") + .attribute("to", ClientData.jid) + .attribute("xmlns", "jabber:client") + .attribute("from", SenderData.jid) + + if (offline == true) xml = xml.attribute("type", "unavailable"); + else xml = xml.attribute("type", "available") + + if (away == true) xml = xml.element("show", "away").up().element("status", body).up(); + else xml = xml.element("status", body).up(); + + ClientData.client.send(xml.toString()) + }) + } else { + return Error(ws); + } +} + +function getPresenceFromAll(ws) { + if (global.Clients.find(i => i.client == ws)) { + var SenderData = global.Clients.find(i => i.client == ws); + + global.Clients.forEach(ClientData => { + var xml = XMLBuilder.create("presence") + .attribute("to", SenderData.jid) + .attribute("xmlns", "jabber:client") + .attribute("from", ClientData.jid) + + if (ClientData.lastPresenceUpdate.away == true) xml = xml.attribute("type", "available").element("show", "away").up().element("status", ClientData.lastPresenceUpdate.status).up(); + else xml = xml.attribute("type", "available").element("status", ClientData.lastPresenceUpdate.status).up(); + + SenderData.client.send(xml.toString()) + }) + } else { + return Error(ws); + } +} + +function ifJSON(str) { + try { + JSON.parse(str) + } catch (err) { + return false; + } + return true; +} \ No newline at end of file