From f9c71e300d1270501e006112af5cb6ed32836341 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Wed, 15 Nov 2023 23:15:21 -0500 Subject: [PATCH] added 3DS npfl service --- package-lock.json | 179 ++++++++++-------- package.json | 6 +- src/database.ts | 39 ++++ src/models/file.ts | 4 + src/server.ts | 2 + src/services/grpc/boss/list-files.ts | 4 + .../grpc/boss/update-file-metadata.ts | 4 + src/services/grpc/boss/upload-file.ts | 4 + src/services/npfl.ts | 114 +++++++++++ src/types/mongoose/file.ts | 4 + 10 files changed, 273 insertions(+), 87 deletions(-) create mode 100644 src/services/npfl.ts diff --git a/package-lock.json b/package-lock.json index b1e61d0..6b67227 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,8 +11,8 @@ "dependencies": { "@aws-sdk/client-s3": "^3.395.0", "@pretendonetwork/boss-crypto": "^1.0.0", - "@pretendonetwork/grpc": "^1.0.3", - "@typegoose/auto-increment": "^3.4.0", + "@pretendonetwork/grpc": "^1.0.4", + "@typegoose/auto-increment": "^3.6.1", "boss-js": "github:PretendoNetwork/boss-js", "cacache": "^18.0.0", "colors": "^1.4.0", @@ -32,7 +32,7 @@ "@types/node": "^20.5.0", "@typescript-eslint/eslint-plugin": "^6.4.0", "@typescript-eslint/parser": "^6.4.0", - "axios": "^0.27.2", + "axios": "^1.6.2", "eslint": "^8.47.0", "fs-extra": "^10.1.0", "tsc-alias": "^1.8.7", @@ -1048,6 +1048,15 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.1.tgz", + "integrity": "sha512-t7c5K033joZZMspnHg/gWPE4kandgc2OxE74aYOtGKfgB9VPuVJPix0H6fhmm2erj5PBJ21mqcx34lpIGtUCsQ==", + "optional": true, + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1157,9 +1166,9 @@ "integrity": "sha512-ybd3sB356v5Azxj99R62+7kytgAzfUYuXRJbdOznGL6infgCJ056TjTadN4V48m7t+3f6sPOUgo9YWUFNxlLLg==" }, "node_modules/@pretendonetwork/grpc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@pretendonetwork/grpc/-/grpc-1.0.3.tgz", - "integrity": "sha512-NlfzonmHqNRUDuc1nCON6u3f6II3KtSQgs7g5u4TEG8KKIIvBWKQT3mWVsRIkBEEpPdtad/dwASVzIR7lymKWw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@pretendonetwork/grpc/-/grpc-1.0.4.tgz", + "integrity": "sha512-r/OTdt5nhPVScxivbLbJxHHaFddgUe03zTSHzJgaY96NAxA9rM+3Up9JJcgv5traIF6ptKYVJck4kkR2PBOPgw==", "dependencies": { "long": "^5.2.1", "protobufjs": "^7.2.3" @@ -1811,18 +1820,18 @@ } }, "node_modules/@typegoose/auto-increment": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@typegoose/auto-increment/-/auto-increment-3.4.0.tgz", - "integrity": "sha512-f43J/dTnf4hQVEHNs9Vdwuf361GozCnXlDv37oaaWPjoKZsN1ZKhZqafj8OsYX1+HKJhUBnjKIGzS5PYRycfCg==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@typegoose/auto-increment/-/auto-increment-3.6.1.tgz", + "integrity": "sha512-WLSCc0TvVungjrOZSbCFlmTU14j4ob23i1/OI4JUKOILWn7AQFhAaDsCODB9ywcLdkXtZgWXJJsbtwtrfsdzpA==", "dependencies": { "loglevel": "^1.8.1", - "tslib": "^2.6.0" + "tslib": "^2.6.2" }, "engines": { "node": ">=14.17.0" }, "peerDependencies": { - "mongoose": "~7.4.0" + "mongoose": "~7.6.1" } }, "node_modules/@types/body-parser": { @@ -1964,9 +1973,9 @@ } }, "node_modules/@types/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog==" + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==" }, "node_modules/@types/whatwg-url": { "version": "8.2.2", @@ -2389,13 +2398,14 @@ "dev": true }, "node_modules/axios": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", + "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", "dev": true, "dependencies": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, "node_modules/balanced-match": { @@ -2490,9 +2500,9 @@ } }, "node_modules/bson": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/bson/-/bson-5.4.0.tgz", - "integrity": "sha512-WRZ5SQI5GfUuKnPTNmAYPiKIof3ORXAF4IRU5UcgmivNIon01rWQlw5RUH954dpu8yGL8T59YShVddIPaU/gFA==", + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/bson/-/bson-5.5.1.tgz", + "integrity": "sha512-ix0EwukN2EpC0SRWIj/7B5+A6uQMQy6KMREI9qQqvgpkV2frH63T0UDVd1SYedL6dNCmDBYB3QtXi4ISk9YT+g==", "engines": { "node": ">=14.20.1" } @@ -4114,11 +4124,11 @@ } }, "node_modules/mongodb": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.7.0.tgz", - "integrity": "sha512-zm82Bq33QbqtxDf58fLWBwTjARK3NSvKYjyz997KSy6hpat0prjeX/kxjbPVyZY60XYPDNETaHkHJI2UCzSLuw==", + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.9.0.tgz", + "integrity": "sha512-g+GCMHN1CoRUA+wb1Agv0TI4YTSiWr42B5ulkiAfLLHitGK1R+PkSAf3Lr5rPZwi/3F04LiaZEW0Kxro9Fi2TA==", "dependencies": { - "bson": "^5.4.0", + "bson": "^5.5.0", "mongodb-connection-string-url": "^2.6.0", "socks": "^2.7.1" }, @@ -4126,12 +4136,12 @@ "node": ">=14.20.1" }, "optionalDependencies": { - "saslprep": "^1.0.3" + "@mongodb-js/saslprep": "^1.1.0" }, "peerDependencies": { - "@aws-sdk/credential-providers": "^3.201.0", - "@mongodb-js/zstd": "^1.1.0", - "kerberos": "^2.0.1", + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.0.0", + "kerberos": "^1.0.0 || ^2.0.0", "mongodb-client-encryption": ">=2.3.0 <3", "snappy": "^7.2.2" }, @@ -4163,13 +4173,13 @@ } }, "node_modules/mongoose": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-7.4.3.tgz", - "integrity": "sha512-eok0lW6mZJHK2vVSWyJb9tUfPMUuRF3h7YC4pU2K2/YSZBlNDUwvKsHgftMOANbokP2Ry+4ylvzAdW4KjkRFjw==", + "version": "7.6.5", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-7.6.5.tgz", + "integrity": "sha512-ElHgGWVKQUawKBn0DXuHmSd3W5w5Kb8JUbDNQH30odhYCDKq9GCh+E1/SuN8jZGxrHgFyLrvYxLSpC36BpqS+w==", "dependencies": { - "bson": "^5.4.0", + "bson": "^5.5.0", "kareem": "2.5.1", - "mongodb": "5.7.0", + "mongodb": "5.9.0", "mpath": "0.9.0", "mquery": "5.0.0", "ms": "2.1.3", @@ -4547,6 +4557,12 @@ "node": ">= 0.10" } }, + "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==", + "dev": true + }, "node_modules/punycode": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", @@ -4704,18 +4720,6 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, - "node_modules/saslprep": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", - "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", - "optional": true, - "dependencies": { - "sparse-bitfield": "^3.0.3" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -6209,6 +6213,15 @@ } } }, + "@mongodb-js/saslprep": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.1.tgz", + "integrity": "sha512-t7c5K033joZZMspnHg/gWPE4kandgc2OxE74aYOtGKfgB9VPuVJPix0H6fhmm2erj5PBJ21mqcx34lpIGtUCsQ==", + "optional": true, + "requires": { + "sparse-bitfield": "^3.0.3" + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -6291,9 +6304,9 @@ "integrity": "sha512-ybd3sB356v5Azxj99R62+7kytgAzfUYuXRJbdOznGL6infgCJ056TjTadN4V48m7t+3f6sPOUgo9YWUFNxlLLg==" }, "@pretendonetwork/grpc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@pretendonetwork/grpc/-/grpc-1.0.3.tgz", - "integrity": "sha512-NlfzonmHqNRUDuc1nCON6u3f6II3KtSQgs7g5u4TEG8KKIIvBWKQT3mWVsRIkBEEpPdtad/dwASVzIR7lymKWw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@pretendonetwork/grpc/-/grpc-1.0.4.tgz", + "integrity": "sha512-r/OTdt5nhPVScxivbLbJxHHaFddgUe03zTSHzJgaY96NAxA9rM+3Up9JJcgv5traIF6ptKYVJck4kkR2PBOPgw==", "requires": { "long": "^5.2.1", "protobufjs": "^7.2.3" @@ -6828,12 +6841,12 @@ } }, "@typegoose/auto-increment": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@typegoose/auto-increment/-/auto-increment-3.4.0.tgz", - "integrity": "sha512-f43J/dTnf4hQVEHNs9Vdwuf361GozCnXlDv37oaaWPjoKZsN1ZKhZqafj8OsYX1+HKJhUBnjKIGzS5PYRycfCg==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@typegoose/auto-increment/-/auto-increment-3.6.1.tgz", + "integrity": "sha512-WLSCc0TvVungjrOZSbCFlmTU14j4ob23i1/OI4JUKOILWn7AQFhAaDsCODB9ywcLdkXtZgWXJJsbtwtrfsdzpA==", "requires": { "loglevel": "^1.8.1", - "tslib": "^2.6.0" + "tslib": "^2.6.2" } }, "@types/body-parser": { @@ -6975,9 +6988,9 @@ } }, "@types/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog==" + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==" }, "@types/whatwg-url": { "version": "8.2.2", @@ -7254,13 +7267,14 @@ "dev": true }, "axios": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", + "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", "dev": true, "requires": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, "balanced-match": { @@ -7340,9 +7354,9 @@ } }, "bson": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/bson/-/bson-5.4.0.tgz", - "integrity": "sha512-WRZ5SQI5GfUuKnPTNmAYPiKIof3ORXAF4IRU5UcgmivNIon01rWQlw5RUH954dpu8yGL8T59YShVddIPaU/gFA==" + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/bson/-/bson-5.5.1.tgz", + "integrity": "sha512-ix0EwukN2EpC0SRWIj/7B5+A6uQMQy6KMREI9qQqvgpkV2frH63T0UDVd1SYedL6dNCmDBYB3QtXi4ISk9YT+g==" }, "bytes": { "version": "3.1.2", @@ -8508,13 +8522,13 @@ "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" }, "mongodb": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.7.0.tgz", - "integrity": "sha512-zm82Bq33QbqtxDf58fLWBwTjARK3NSvKYjyz997KSy6hpat0prjeX/kxjbPVyZY60XYPDNETaHkHJI2UCzSLuw==", + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.9.0.tgz", + "integrity": "sha512-g+GCMHN1CoRUA+wb1Agv0TI4YTSiWr42B5ulkiAfLLHitGK1R+PkSAf3Lr5rPZwi/3F04LiaZEW0Kxro9Fi2TA==", "requires": { - "bson": "^5.4.0", + "@mongodb-js/saslprep": "^1.1.0", + "bson": "^5.5.0", "mongodb-connection-string-url": "^2.6.0", - "saslprep": "^1.0.3", "socks": "^2.7.1" } }, @@ -8528,13 +8542,13 @@ } }, "mongoose": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-7.4.3.tgz", - "integrity": "sha512-eok0lW6mZJHK2vVSWyJb9tUfPMUuRF3h7YC4pU2K2/YSZBlNDUwvKsHgftMOANbokP2Ry+4ylvzAdW4KjkRFjw==", + "version": "7.6.5", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-7.6.5.tgz", + "integrity": "sha512-ElHgGWVKQUawKBn0DXuHmSd3W5w5Kb8JUbDNQH30odhYCDKq9GCh+E1/SuN8jZGxrHgFyLrvYxLSpC36BpqS+w==", "requires": { - "bson": "^5.4.0", + "bson": "^5.5.0", "kareem": "2.5.1", - "mongodb": "5.7.0", + "mongodb": "5.9.0", "mpath": "0.9.0", "mquery": "5.0.0", "ms": "2.1.3", @@ -8808,6 +8822,12 @@ "ipaddr.js": "1.9.1" } }, + "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==", + "dev": true + }, "punycode": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", @@ -8903,15 +8923,6 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, - "saslprep": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", - "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", - "optional": true, - "requires": { - "sparse-bitfield": "^3.0.3" - } - }, "semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", diff --git a/package.json b/package.json index adb002c..88a45bf 100644 --- a/package.json +++ b/package.json @@ -15,8 +15,8 @@ "dependencies": { "@aws-sdk/client-s3": "^3.395.0", "@pretendonetwork/boss-crypto": "^1.0.0", - "@pretendonetwork/grpc": "^1.0.3", - "@typegoose/auto-increment": "^3.4.0", + "@pretendonetwork/grpc": "^1.0.4", + "@typegoose/auto-increment": "^3.6.1", "boss-js": "github:PretendoNetwork/boss-js", "cacache": "^18.0.0", "colors": "^1.4.0", @@ -36,7 +36,7 @@ "@types/node": "^20.5.0", "@typescript-eslint/eslint-plugin": "^6.4.0", "@typescript-eslint/parser": "^6.4.0", - "axios": "^0.27.2", + "axios": "^1.6.2", "eslint": "^8.47.0", "fs-extra": "^10.1.0", "tsc-alias": "^1.8.7", diff --git a/src/database.ts b/src/database.ts index 6dfc3b9..389dfdc 100644 --- a/src/database.ts +++ b/src/database.ts @@ -76,6 +76,45 @@ export function getTaskFiles(allowDeleted: boolean, bossAppID: string, taskID: s return File.find(filter); } +export function getTaskFilesWithAttributes(allowDeleted: boolean, bossAppID: string, taskID: string, country?: string, language?: string, attribute1?: string, attribute2?: string, attribute3?: string): Promise { + verifyConnected(); + + const filter: mongoose.FilterQuery = { + task_id: taskID.slice(0, 7), + boss_app_id: bossAppID + }; + + if (!allowDeleted) { + filter.deleted = false; + } + + if (country) { + filter.supported_countries = { + $in: [country] + }; + } + + if (language) { + filter.supported_languages = { + $in: [language] + }; + } + + if (attribute1) { + filter.attribute1 = attribute1; + } + + if (attribute2) { + filter.attribute2 = attribute2; + } + + if (attribute3) { + filter.attribute3 = attribute3; + } + + return File.find(filter); +} + export function getTaskFile(bossAppID: string, taskID: string, name: string): Promise { verifyConnected(); diff --git a/src/models/file.ts b/src/models/file.ts index 4da7bd2..1dccf10 100644 --- a/src/models/file.ts +++ b/src/models/file.ts @@ -12,6 +12,10 @@ const FileSchema = new mongoose.Schema({ boss_app_id: String, supported_countries: [String], supported_languages: [String], + password: String, + attribute1: String, + attribute2: String, + attribute3: String, creator_pid: Number, name: String, type: String, diff --git a/src/server.ts b/src/server.ts index 0c97684..ca3b85f 100644 --- a/src/server.ts +++ b/src/server.ts @@ -14,6 +14,7 @@ import authenticationMiddleware from '@/middleware/authentication'; import nppl from '@/services/nppl'; import npts from '@/services/npts'; import npdi from '@/services/npdi'; +import npfl from '@/services/npfl'; const app = express(); @@ -30,6 +31,7 @@ app.use(authenticationMiddleware); app.use(nppl); app.use(npts); app.use(npdi); +app.use(npfl); LOG_INFO('Creating 404 status handler'); app.use((_request, response) => { diff --git a/src/services/grpc/boss/list-files.ts b/src/services/grpc/boss/list-files.ts index 8ad1bcb..48fb609 100644 --- a/src/services/grpc/boss/list-files.ts +++ b/src/services/grpc/boss/list-files.ts @@ -45,6 +45,10 @@ export async function listFiles(request: ListFilesRequest): Promise, response) => { + for (const param in request.query) { + // * Beats me why the real server does this. + // * Just doing accurate emulation ¯\_(ツ)_/¯ + if (!ALLOWED_QUERY_PARMS.includes(param)) { + response.sendStatus(403); + return; + } + } + + const { appID, taskID } = request.params; + const country = request.query.c; + const language = request.query.l; + const attribute1 = request.query.a1; + const attribute2 = request.query.a2; + const attribute3 = request.query.a3; + + const files = await getTaskFilesWithAttributes(false, appID, taskID, country, language, attribute1, attribute2, attribute3); + + // * https://gist.github.com/DaniElectra/ada7ecc930a84432f2045f6fcabac84f#nintendo-boss-file-list-server-npfl + // * + // * File list has the following structure: + // * + // * - SHA1 hash of all following lines, including size line + // * - Size of whole file, include current line and hash line + // * - Size line is padded with spaces to 10 characters + // * - Size line has a trailing CRLF if no files found + // * - Files + // * + // * File lines have the following fields: + // * + // * - File name + // * - Unknown (password?) + // * - Attribute 1 + // * - Attribute 2 + // * - Attribute 3 + // * - File size (0 is allowed) + // * - Updated time (seconds) + // * + // * All fields of a file line are separated by a tab (\t) and are present even if no value. + // * All line breaks are CRLF (\r\n). + // * There is always a trailing CRLF, even if no files are returned (minimum 3 lines). + // * + // * Example: + // * + // * 9268c2ae0c210df07a417683e35dd67b42df19f4 + // * 132 + // * 007 anniversary 7 tj 5_50 0 1523520046 + // * 019 THANKYOU 19 tj 3_15 0 1557371320 + + let size = 0; + + size += 40 + 2; // * SHA1 hash of the remaining file + CRLF + size += 10 + 2; // * Size line is padded to 10 chars + CRLF + + let body = ''; + + for (const file of files) { + const params = [ + file.name, + file.password, // * Unsure if this is really what this is for. Team Kirby Clash Deluxe uses this for passwords though + file.attribute1, + file.attribute2, + file.attribute3, + file.size, + file.updated/1000n // * Expects time as seconds, not milliseconds + ]; + const line = `${params.join('\t')}\r\n`; + + body += line; + size += line.length; + } + + const sizeLine = `${size}`.padStart(10, ' '); + + body = `${sizeLine}\r\n${body}`; + + const hash = crypto.createHash('sha1').update(body).digest('hex'); + + body = `${hash}\r\n${body}`; + + response.setHeader('Content-Type', 'text/plain'); + response.send(body); +}); + +const router = express.Router(); + +router.use(subdomain('npfl.c.app', npfl)); + +export default router; \ No newline at end of file diff --git a/src/types/mongoose/file.ts b/src/types/mongoose/file.ts index a707156..043dfc4 100644 --- a/src/types/mongoose/file.ts +++ b/src/types/mongoose/file.ts @@ -7,6 +7,10 @@ export interface IFile { boss_app_id: string; supported_countries: string[]; supported_languages: string[]; + password: string; + attribute1: string; + attribute2: string; + attribute3: string; creator_pid: number; name: string; type: string;