added 3DS npfl service

This commit is contained in:
Jonathan Barrow 2023-11-15 23:15:21 -05:00
parent c98fc03ccf
commit f9c71e300d
No known key found for this signature in database
GPG Key ID: E86E9FE9049C741F
10 changed files with 273 additions and 87 deletions

179
package-lock.json generated
View File

@ -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",

View File

@ -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",

View File

@ -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<HydratedFileDocument[]> {
verifyConnected();
const filter: mongoose.FilterQuery<IFile> = {
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<HydratedFileDocument | null> {
verifyConnected();

View File

@ -12,6 +12,10 @@ const FileSchema = new mongoose.Schema<IFile, FileModel, IFileMethods>({
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,

View File

@ -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) => {

View File

@ -45,6 +45,10 @@ export async function listFiles(request: ListFilesRequest): Promise<ListFilesRes
bossAppId: file.boss_app_id,
supportedCountries: file.supported_countries,
supportedLanguages: file.supported_languages,
password: file.password,
attribute1: file.attribute1,
attribute2: file.attribute2,
attribute3: file.attribute3,
creatorPid: file.creator_pid,
name: file.name,
type: file.type,

View File

@ -45,6 +45,10 @@ export async function updateFileMetadata(request: UpdateFileMetadataRequest, con
file.boss_app_id = updateData.bossAppId;
file.supported_countries = updateData.supportedCountries;
file.supported_languages = updateData.supportedLanguages;
file.password = updateData.password;
file.attribute1 = updateData.attribute1;
file.attribute2 = updateData.attribute2;
file.attribute3 = updateData.attribute3;
file.name = updateData.name;
file.type = updateData.type;
file.notify_on_new = updateData.notifyOnNew;

View File

@ -160,6 +160,10 @@ export async function uploadFile(request: UploadFileRequest, context: CallContex
bossAppId: file.boss_app_id,
supportedCountries: file.supported_countries,
supportedLanguages: file.supported_languages,
password: file.password,
attribute1: file.attribute1,
attribute2: file.attribute2,
attribute3: file.attribute3,
creatorPid: file.creator_pid,
name: file.name,
type: file.type,

114
src/services/npfl.ts Normal file
View File

@ -0,0 +1,114 @@
import crypto from 'node:crypto';
import express from 'express';
import subdomain from 'express-subdomain';
import { getTaskFilesWithAttributes } from '@/database';
const ALLOWED_QUERY_PARMS = [
'c', 'l',
'a1', 'a2', 'a3',
'ap', 'tm'
];
const npfl = express.Router();
npfl.get('/p01/filelist/:appID/:taskID', async (request: express.Request<{
appID: string;
taskID: string;
}, any, any, {
c?: string;
l?: string;
a1?: string;
a2?: string;
a3?: string;
ap?: string;
tm?: string;
}>, 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;

View File

@ -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;