mirror of
https://github.com/ajayyy/SponsorBlockServer.git
synced 2025-12-26 17:38:28 +03:00
Merge branch 'master' of https://github.com/ajayyy/SponsorBlockServer into pr/mchangrh/293
This commit is contained in:
@@ -1,15 +1,15 @@
|
|||||||
# SponsorTimesDB
|
# SponsorTimesDB
|
||||||
|
|
||||||
[vipUsers](###vipUsers)
|
[vipUsers](#vipUsers)
|
||||||
[sponsorTimes](###sponsorTimes)
|
[sponsorTimes](#sponsorTimes)
|
||||||
[userNames](###userNames)
|
[userNames](#userNames)
|
||||||
[userNameLogs](###userNameLogs)
|
[userNameLogs](#userNameLogs)
|
||||||
[categoryVotes](###categoryVotes)
|
[categoryVotes](#categoryVotes)
|
||||||
[lockCategories](###lockCategories)
|
[lockCategories](#lockCategories)
|
||||||
[warnings](###warnings)
|
[warnings](#warnings)
|
||||||
[shadowBannedUsers](###shadowBannedUsers)
|
[shadowBannedUsers](#shadowBannedUsers)
|
||||||
[unlistedVideos](###unlistedVideos)
|
[unlistedVideos](#unlistedVideos)
|
||||||
[config](###config)
|
[config](#config)
|
||||||
|
|
||||||
### vipUsers
|
### vipUsers
|
||||||
| Name | Type | |
|
| Name | Type | |
|
||||||
@@ -142,10 +142,10 @@
|
|||||||
|
|
||||||
# Private
|
# Private
|
||||||
|
|
||||||
[vote](###vote)
|
[vote](#vote)
|
||||||
[categoryVotes](###categoryVotes)
|
[categoryVotes](#categoryVotes)
|
||||||
[sponsorTimes](###sponsorTimes)
|
[sponsorTimes](#sponsorTimes)
|
||||||
[config](###config)
|
[config](#config)
|
||||||
|
|
||||||
### vote
|
### vote
|
||||||
|
|
||||||
|
|||||||
215
package-lock.json
generated
215
package-lock.json
generated
@@ -17,7 +17,6 @@
|
|||||||
"express-promise-router": "^4.1.0",
|
"express-promise-router": "^4.1.0",
|
||||||
"express-rate-limit": "^5.1.3",
|
"express-rate-limit": "^5.1.3",
|
||||||
"http": "0.0.0",
|
"http": "0.0.0",
|
||||||
"iso8601-duration": "^1.2.0",
|
|
||||||
"node-fetch": "^2.6.0",
|
"node-fetch": "^2.6.0",
|
||||||
"pg": "^8.5.1",
|
"pg": "^8.5.1",
|
||||||
"redis": "^3.1.1",
|
"redis": "^3.1.1",
|
||||||
@@ -159,9 +158,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/eslintrc/node_modules/debug": {
|
"node_modules/@eslint/eslintrc/node_modules/debug": {
|
||||||
"version": "4.3.1",
|
"version": "4.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
|
||||||
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
|
"integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ms": "2.1.2"
|
"ms": "2.1.2"
|
||||||
@@ -221,9 +220,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@humanwhocodes/config-array/node_modules/debug": {
|
"node_modules/@humanwhocodes/config-array/node_modules/debug": {
|
||||||
"version": "4.3.1",
|
"version": "4.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
|
||||||
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
|
"integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ms": "2.1.2"
|
"ms": "2.1.2"
|
||||||
@@ -541,9 +540,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": {
|
"node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": {
|
||||||
"version": "4.3.1",
|
"version": "4.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
|
||||||
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
|
"integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ms": "2.1.2"
|
"ms": "2.1.2"
|
||||||
@@ -614,24 +613,6 @@
|
|||||||
"eslint": "*"
|
"eslint": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-utils": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"eslint-visitor-keys": "^2.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^10.0.0 || ^12.0.0 || >= 14.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/mysticatea"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"eslint": ">=5"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@typescript-eslint/parser": {
|
"node_modules/@typescript-eslint/parser": {
|
||||||
"version": "4.28.1",
|
"version": "4.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.1.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.1.tgz",
|
||||||
@@ -660,9 +641,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/parser/node_modules/debug": {
|
"node_modules/@typescript-eslint/parser/node_modules/debug": {
|
||||||
"version": "4.3.1",
|
"version": "4.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
|
||||||
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
|
"integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ms": "2.1.2"
|
"ms": "2.1.2"
|
||||||
@@ -740,9 +721,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/typescript-estree/node_modules/debug": {
|
"node_modules/@typescript-eslint/typescript-estree/node_modules/debug": {
|
||||||
"version": "4.3.1",
|
"version": "4.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
|
||||||
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
|
"integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ms": "2.1.2"
|
"ms": "2.1.2"
|
||||||
@@ -1861,27 +1842,21 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-utils": {
|
"node_modules/eslint-utils": {
|
||||||
"version": "2.1.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
|
||||||
"integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
|
"integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"eslint-visitor-keys": "^1.1.0"
|
"eslint-visitor-keys": "^2.0.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6"
|
"node": "^10.0.0 || ^12.0.0 || >= 14.0.0"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/mysticatea"
|
"url": "https://github.com/sponsors/mysticatea"
|
||||||
}
|
},
|
||||||
},
|
"peerDependencies": {
|
||||||
"node_modules/eslint-utils/node_modules/eslint-visitor-keys": {
|
"eslint": ">=5"
|
||||||
"version": "1.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
|
|
||||||
"integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-visitor-keys": {
|
"node_modules/eslint-visitor-keys": {
|
||||||
@@ -1926,9 +1901,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint/node_modules/debug": {
|
"node_modules/eslint/node_modules/debug": {
|
||||||
"version": "4.3.1",
|
"version": "4.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
|
||||||
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
|
"integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ms": "2.1.2"
|
"ms": "2.1.2"
|
||||||
@@ -1954,6 +1929,30 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/eslint/node_modules/eslint-utils": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"eslint-visitor-keys": "^1.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/mysticatea"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/eslint/node_modules/eslint-utils/node_modules/eslint-visitor-keys": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/eslint/node_modules/js-yaml": {
|
"node_modules/eslint/node_modules/js-yaml": {
|
||||||
"version": "3.14.1",
|
"version": "3.14.1",
|
||||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
||||||
@@ -2314,9 +2313,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/fastq": {
|
"node_modules/fastq": {
|
||||||
"version": "1.11.0",
|
"version": "1.11.1",
|
||||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.1.tgz",
|
||||||
"integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==",
|
"integrity": "sha512-HOnr8Mc60eNYl1gzwp6r5RoUyAn5/glBolUzP/Ez6IFVPMPirxn/9phgL6zhOtaTy7ISwPvQ+wT+hfcRZh/bzw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"reusify": "^1.0.4"
|
"reusify": "^1.0.4"
|
||||||
@@ -3018,11 +3017,6 @@
|
|||||||
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
|
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/iso8601-duration": {
|
|
||||||
"version": "1.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/iso8601-duration/-/iso8601-duration-1.2.0.tgz",
|
|
||||||
"integrity": "sha512-ErTBd++b17E8nmWII1K1uZtBgD1E8RjyvwmxlCjPHNqHMD7gmcMHOw0E8Ro/6+QT4PhHRSnnMo7bxa1vFPkwhg=="
|
|
||||||
},
|
|
||||||
"node_modules/js-tokens": {
|
"node_modules/js-tokens": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||||
@@ -4827,9 +4821,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/table/node_modules/ajv": {
|
"node_modules/table/node_modules/ajv": {
|
||||||
"version": "8.6.0",
|
"version": "8.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.1.tgz",
|
||||||
"integrity": "sha512-cnUG4NSBiM4YFBxgZIj/In3/6KX+rQ2l2YPRVcvAMQGWEPKuXoPIhxzwqh31jA3IPbI4qEOp/5ILI4ynioXsGQ==",
|
"integrity": "sha512-42VLtQUOLefAvKFAQIxIZDaThq6om/PrfP0CYk3/vn+y4BMNkKnbli8ON2QCiHov4KkzOSJ/xSoBJdayiiYvVQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fast-deep-equal": "^3.1.1",
|
"fast-deep-equal": "^3.1.1",
|
||||||
@@ -5666,9 +5660,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"debug": {
|
"debug": {
|
||||||
"version": "4.3.1",
|
"version": "4.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
|
||||||
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
|
"integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ms": "2.1.2"
|
"ms": "2.1.2"
|
||||||
@@ -5710,9 +5704,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"debug": {
|
"debug": {
|
||||||
"version": "4.3.1",
|
"version": "4.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
|
||||||
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
|
"integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ms": "2.1.2"
|
"ms": "2.1.2"
|
||||||
@@ -5998,9 +5992,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"debug": {
|
"debug": {
|
||||||
"version": "4.3.1",
|
"version": "4.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
|
||||||
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
|
"integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ms": "2.1.2"
|
"ms": "2.1.2"
|
||||||
@@ -6044,17 +6038,6 @@
|
|||||||
"@typescript-eslint/typescript-estree": "4.28.1",
|
"@typescript-eslint/typescript-estree": "4.28.1",
|
||||||
"eslint-scope": "^5.1.1",
|
"eslint-scope": "^5.1.1",
|
||||||
"eslint-utils": "^3.0.0"
|
"eslint-utils": "^3.0.0"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"eslint-utils": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"eslint-visitor-keys": "^2.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/parser": {
|
"@typescript-eslint/parser": {
|
||||||
@@ -6070,9 +6053,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"debug": {
|
"debug": {
|
||||||
"version": "4.3.1",
|
"version": "4.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
|
||||||
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
|
"integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ms": "2.1.2"
|
"ms": "2.1.2"
|
||||||
@@ -6118,9 +6101,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"debug": {
|
"debug": {
|
||||||
"version": "4.3.1",
|
"version": "4.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
|
||||||
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
|
"integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ms": "2.1.2"
|
"ms": "2.1.2"
|
||||||
@@ -7026,9 +7009,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"debug": {
|
"debug": {
|
||||||
"version": "4.3.1",
|
"version": "4.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
|
||||||
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
|
"integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ms": "2.1.2"
|
"ms": "2.1.2"
|
||||||
@@ -7040,6 +7023,23 @@
|
|||||||
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
|
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"eslint-utils": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"eslint-visitor-keys": "^1.1.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"eslint-visitor-keys": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"js-yaml": {
|
"js-yaml": {
|
||||||
"version": "3.14.1",
|
"version": "3.14.1",
|
||||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
||||||
@@ -7132,20 +7132,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"eslint-utils": {
|
"eslint-utils": {
|
||||||
"version": "2.1.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
|
||||||
"integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
|
"integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"eslint-visitor-keys": "^1.1.0"
|
"eslint-visitor-keys": "^2.0.0"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"eslint-visitor-keys": {
|
|
||||||
"version": "1.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
|
|
||||||
"integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
|
|
||||||
"dev": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"eslint-visitor-keys": {
|
"eslint-visitor-keys": {
|
||||||
@@ -7346,9 +7338,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"fastq": {
|
"fastq": {
|
||||||
"version": "1.11.0",
|
"version": "1.11.1",
|
||||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.1.tgz",
|
||||||
"integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==",
|
"integrity": "sha512-HOnr8Mc60eNYl1gzwp6r5RoUyAn5/glBolUzP/Ez6IFVPMPirxn/9phgL6zhOtaTy7ISwPvQ+wT+hfcRZh/bzw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"reusify": "^1.0.4"
|
"reusify": "^1.0.4"
|
||||||
@@ -7876,11 +7868,6 @@
|
|||||||
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
|
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"iso8601-duration": {
|
|
||||||
"version": "1.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/iso8601-duration/-/iso8601-duration-1.2.0.tgz",
|
|
||||||
"integrity": "sha512-ErTBd++b17E8nmWII1K1uZtBgD1E8RjyvwmxlCjPHNqHMD7gmcMHOw0E8Ro/6+QT4PhHRSnnMo7bxa1vFPkwhg=="
|
|
||||||
},
|
|
||||||
"js-tokens": {
|
"js-tokens": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||||
@@ -9280,9 +9267,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ajv": {
|
"ajv": {
|
||||||
"version": "8.6.0",
|
"version": "8.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.1.tgz",
|
||||||
"integrity": "sha512-cnUG4NSBiM4YFBxgZIj/In3/6KX+rQ2l2YPRVcvAMQGWEPKuXoPIhxzwqh31jA3IPbI4qEOp/5ILI4ynioXsGQ==",
|
"integrity": "sha512-42VLtQUOLefAvKFAQIxIZDaThq6om/PrfP0CYk3/vn+y4BMNkKnbli8ON2QCiHov4KkzOSJ/xSoBJdayiiYvVQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"fast-deep-equal": "^3.1.1",
|
"fast-deep-equal": "^3.1.1",
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
"express-promise-router": "^4.1.0",
|
"express-promise-router": "^4.1.0",
|
||||||
"express-rate-limit": "^5.1.3",
|
"express-rate-limit": "^5.1.3",
|
||||||
"http": "0.0.0",
|
"http": "0.0.0",
|
||||||
"iso8601-duration": "^1.2.0",
|
|
||||||
"node-fetch": "^2.6.0",
|
"node-fetch": "^2.6.0",
|
||||||
"pg": "^8.5.1",
|
"pg": "^8.5.1",
|
||||||
"redis": "^3.1.1",
|
"redis": "^3.1.1",
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { config } from '../config';
|
|||||||
import { db, privateDB } from '../databases/databases';
|
import { db, privateDB } from '../databases/databases';
|
||||||
import { skipSegmentsHashKey, skipSegmentsKey } from '../utils/redisKeys';
|
import { skipSegmentsHashKey, skipSegmentsKey } from '../utils/redisKeys';
|
||||||
import { SBRecord } from '../types/lib.model';
|
import { SBRecord } from '../types/lib.model';
|
||||||
import { Category, CategoryActionType, DBSegment, HashedIP, IPAddress, OverlappingSegmentGroup, Segment, SegmentCache, Service, VideoData, VideoID, VideoIDHash, Visibility, VotableObject } from "../types/segments.model";
|
import { Category, CategoryActionType, DBSegment, HashedIP, IPAddress, OverlappingSegmentGroup, Segment, SegmentCache, SegmentUUID, Service, VideoData, VideoID, VideoIDHash, Visibility, VotableObject } from "../types/segments.model";
|
||||||
import { getCategoryActionType } from '../utils/categoryInfo';
|
import { getCategoryActionType } from '../utils/categoryInfo';
|
||||||
import { getHash } from '../utils/getHash';
|
import { getHash } from '../utils/getHash';
|
||||||
import { getIP } from '../utils/getIP';
|
import { getIP } from '../utils/getIP';
|
||||||
@@ -14,7 +14,7 @@ import { getReputation } from '../utils/reputation';
|
|||||||
|
|
||||||
async function prepareCategorySegments(req: Request, videoID: VideoID, category: Category, segments: DBSegment[], cache: SegmentCache = {shadowHiddenSegmentIPs: {}}): Promise<Segment[]> {
|
async function prepareCategorySegments(req: Request, videoID: VideoID, category: Category, segments: DBSegment[], cache: SegmentCache = {shadowHiddenSegmentIPs: {}}): Promise<Segment[]> {
|
||||||
const shouldFilter: boolean[] = await Promise.all(segments.map(async (segment) => {
|
const shouldFilter: boolean[] = await Promise.all(segments.map(async (segment) => {
|
||||||
if (segment.votes < -1) {
|
if (segment.votes < -1 && !segment.required) {
|
||||||
return false; //too untrustworthy, just ignore it
|
return false; //too untrustworthy, just ignore it
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ async function prepareCategorySegments(req: Request, videoID: VideoID, category:
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getSegmentsByVideoID(req: Request, videoID: VideoID, categories: Category[], service: Service): Promise<Segment[]> {
|
async function getSegmentsByVideoID(req: Request, videoID: VideoID, categories: Category[], requiredSegments: SegmentUUID[], service: Service): Promise<Segment[]> {
|
||||||
const cache: SegmentCache = {shadowHiddenSegmentIPs: {}};
|
const cache: SegmentCache = {shadowHiddenSegmentIPs: {}};
|
||||||
const segments: Segment[] = [];
|
const segments: Segment[] = [];
|
||||||
|
|
||||||
@@ -61,6 +61,8 @@ async function getSegmentsByVideoID(req: Request, videoID: VideoID, categories:
|
|||||||
const segmentsByCategory: SBRecord<Category, DBSegment[]> = (await getSegmentsFromDBByVideoID(videoID, service))
|
const segmentsByCategory: SBRecord<Category, DBSegment[]> = (await getSegmentsFromDBByVideoID(videoID, service))
|
||||||
.filter((segment: DBSegment) => categories.includes(segment?.category))
|
.filter((segment: DBSegment) => categories.includes(segment?.category))
|
||||||
.reduce((acc: SBRecord<Category, DBSegment[]>, segment: DBSegment) => {
|
.reduce((acc: SBRecord<Category, DBSegment[]>, segment: DBSegment) => {
|
||||||
|
if (requiredSegments.includes(segment.UUID)) segment.required = true;
|
||||||
|
|
||||||
acc[segment.category] = acc[segment.category] || [];
|
acc[segment.category] = acc[segment.category] || [];
|
||||||
acc[segment.category].push(segment);
|
acc[segment.category].push(segment);
|
||||||
|
|
||||||
@@ -80,7 +82,7 @@ async function getSegmentsByVideoID(req: Request, videoID: VideoID, categories:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getSegmentsByHash(req: Request, hashedVideoIDPrefix: VideoIDHash, categories: Category[], service: Service): Promise<SBRecord<VideoID, VideoData>> {
|
async function getSegmentsByHash(req: Request, hashedVideoIDPrefix: VideoIDHash, categories: Category[], requiredSegments: SegmentUUID[], service: Service): Promise<SBRecord<VideoID, VideoData>> {
|
||||||
const cache: SegmentCache = {shadowHiddenSegmentIPs: {}};
|
const cache: SegmentCache = {shadowHiddenSegmentIPs: {}};
|
||||||
const segments: SBRecord<VideoID, VideoData> = {};
|
const segments: SBRecord<VideoID, VideoData> = {};
|
||||||
|
|
||||||
@@ -97,8 +99,9 @@ async function getSegmentsByHash(req: Request, hashedVideoIDPrefix: VideoIDHash,
|
|||||||
hash: segment.hashedVideoID,
|
hash: segment.hashedVideoID,
|
||||||
segmentPerCategory: {},
|
segmentPerCategory: {},
|
||||||
};
|
};
|
||||||
const videoCategories = acc[segment.videoID].segmentPerCategory;
|
if (requiredSegments.includes(segment.UUID)) segment.required = true;
|
||||||
|
|
||||||
|
const videoCategories = acc[segment.videoID].segmentPerCategory;
|
||||||
videoCategories[segment.category] = videoCategories[segment.category] || [];
|
videoCategories[segment.category] = videoCategories[segment.category] || [];
|
||||||
videoCategories[segment.category].push(segment);
|
videoCategories[segment.category].push(segment);
|
||||||
|
|
||||||
@@ -214,7 +217,7 @@ async function chooseSegments(segments: DBSegment[], max: number): Promise<DBSeg
|
|||||||
let cursor = -1; //-1 to make sure that, even if the 1st segment starts at 0, a new group is created
|
let cursor = -1; //-1 to make sure that, even if the 1st segment starts at 0, a new group is created
|
||||||
for (const segment of segments) {
|
for (const segment of segments) {
|
||||||
if (segment.startTime > cursor) {
|
if (segment.startTime > cursor) {
|
||||||
currentGroup = {segments: [], votes: 0, reputation: 0, locked: false};
|
currentGroup = {segments: [], votes: 0, reputation: 0, locked: false, required: false};
|
||||||
overlappingSegmentsGroups.push(currentGroup);
|
overlappingSegmentsGroups.push(currentGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,11 +236,18 @@ async function chooseSegments(segments: DBSegment[], max: number): Promise<DBSeg
|
|||||||
currentGroup.locked = true;
|
currentGroup.locked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (segment.required) {
|
||||||
|
currentGroup.required = true;
|
||||||
|
}
|
||||||
|
|
||||||
cursor = Math.max(cursor, segment.endTime);
|
cursor = Math.max(cursor, segment.endTime);
|
||||||
};
|
};
|
||||||
|
|
||||||
overlappingSegmentsGroups.forEach((group) => {
|
overlappingSegmentsGroups.forEach((group) => {
|
||||||
if (group.locked) {
|
if (group.required) {
|
||||||
|
// Required beats locked
|
||||||
|
group.segments = group.segments.filter((segment) => segment.required);
|
||||||
|
} else if (group.locked) {
|
||||||
group.segments = group.segments.filter((segment) => segment.locked);
|
group.segments = group.segments.filter((segment) => segment.locked);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,12 +287,24 @@ async function handleGetSegments(req: Request, res: Response): Promise<Segment[]
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const requiredSegments: SegmentUUID[] = req.query.requiredSegments
|
||||||
|
? JSON.parse(req.query.requiredSegments as string)
|
||||||
|
: req.query.requiredSegment
|
||||||
|
? Array.isArray(req.query.requiredSegment)
|
||||||
|
? req.query.requiredSegment
|
||||||
|
: [req.query.requiredSegment]
|
||||||
|
: [];
|
||||||
|
if (!Array.isArray(requiredSegments)) {
|
||||||
|
res.status(400).send("requiredSegments parameter does not match format requirements.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
let service: Service = req.query.service ?? req.body.service ?? Service.YouTube;
|
let service: Service = req.query.service ?? req.body.service ?? Service.YouTube;
|
||||||
if (!Object.values(Service).some((val) => val == service)) {
|
if (!Object.values(Service).some((val) => val == service)) {
|
||||||
service = Service.YouTube;
|
service = Service.YouTube;
|
||||||
}
|
}
|
||||||
|
|
||||||
const segments = await getSegmentsByVideoID(req, videoID, categories, service);
|
const segments = await getSegmentsByVideoID(req, videoID, categories, requiredSegments, service);
|
||||||
|
|
||||||
if (segments === null || segments === undefined) {
|
if (segments === null || segments === undefined) {
|
||||||
res.sendStatus(500);
|
res.sendStatus(500);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import {hashPrefixTester} from '../utils/hashPrefixTester';
|
import {hashPrefixTester} from '../utils/hashPrefixTester';
|
||||||
import {getSegmentsByHash} from './getSkipSegments';
|
import {getSegmentsByHash} from './getSkipSegments';
|
||||||
import {Request, Response} from 'express';
|
import {Request, Response} from 'express';
|
||||||
import { Category, Service, VideoIDHash } from '../types/segments.model';
|
import { Category, SegmentUUID, Service, VideoIDHash } from '../types/segments.model';
|
||||||
|
|
||||||
export async function getSkipSegmentsByHash(req: Request, res: Response) {
|
export async function getSkipSegmentsByHash(req: Request, res: Response) {
|
||||||
let hashPrefix = req.params.prefix as VideoIDHash;
|
let hashPrefix = req.params.prefix as VideoIDHash;
|
||||||
@@ -16,16 +16,33 @@ export async function getSkipSegmentsByHash(req: Request, res: Response) {
|
|||||||
categories = req.query.categories
|
categories = req.query.categories
|
||||||
? JSON.parse(req.query.categories as string)
|
? JSON.parse(req.query.categories as string)
|
||||||
: req.query.category
|
: req.query.category
|
||||||
? [req.query.category]
|
? Array.isArray(req.query.category)
|
||||||
: ["sponsor"];
|
? req.query.category
|
||||||
|
: [req.query.category]
|
||||||
|
: ['sponsor'];
|
||||||
if (!Array.isArray(categories)) {
|
if (!Array.isArray(categories)) {
|
||||||
return res.status(400).send("Categories parameter does not match format requirements.");
|
return res.status(400).send("Categories parameter does not match format requirements.");
|
||||||
}
|
}
|
||||||
}
|
} catch(error) {
|
||||||
catch(error) {
|
|
||||||
return res.status(400).send("Bad parameter: categories (invalid JSON)");
|
return res.status(400).send("Bad parameter: categories (invalid JSON)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let requiredSegments: SegmentUUID[] = [];
|
||||||
|
try {
|
||||||
|
requiredSegments = req.query.requiredSegments
|
||||||
|
? JSON.parse(req.query.requiredSegments as string)
|
||||||
|
: req.query.requiredSegment
|
||||||
|
? Array.isArray(req.query.requiredSegment)
|
||||||
|
? req.query.requiredSegment
|
||||||
|
: [req.query.requiredSegment]
|
||||||
|
: [];
|
||||||
|
if (!Array.isArray(requiredSegments)) {
|
||||||
|
return res.status(400).send("requiredSegments parameter does not match format requirements.");
|
||||||
|
}
|
||||||
|
} catch(error) {
|
||||||
|
return res.status(400).send("Bad parameter: requiredSegments (invalid JSON)");
|
||||||
|
}
|
||||||
|
|
||||||
let service: Service = req.query.service ?? req.body.service ?? Service.YouTube;
|
let service: Service = req.query.service ?? req.body.service ?? Service.YouTube;
|
||||||
if (!Object.values(Service).some((val) => val == service)) {
|
if (!Object.values(Service).some((val) => val == service)) {
|
||||||
service = Service.YouTube;
|
service = Service.YouTube;
|
||||||
@@ -35,7 +52,7 @@ export async function getSkipSegmentsByHash(req: Request, res: Response) {
|
|||||||
categories = categories.filter((item: any) => typeof item === "string");
|
categories = categories.filter((item: any) => typeof item === "string");
|
||||||
|
|
||||||
// Get all video id's that match hash prefix
|
// Get all video id's that match hash prefix
|
||||||
const segments = await getSegmentsByHash(req, hashPrefix, categories, service);
|
const segments = await getSegmentsByHash(req, hashPrefix, categories, requiredSegments, service);
|
||||||
|
|
||||||
if (!segments) return res.status(404).json([]);
|
if (!segments) return res.status(404).json([]);
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import {db, privateDB} from '../databases/databases';
|
|||||||
import {getMaxResThumbnail, YouTubeAPI} from '../utils/youtubeApi';
|
import {getMaxResThumbnail, YouTubeAPI} from '../utils/youtubeApi';
|
||||||
import {getSubmissionUUID} from '../utils/getSubmissionUUID';
|
import {getSubmissionUUID} from '../utils/getSubmissionUUID';
|
||||||
import fetch from 'node-fetch';
|
import fetch from 'node-fetch';
|
||||||
import isoDurations, { end } from 'iso8601-duration';
|
|
||||||
import {getHash} from '../utils/getHash';
|
import {getHash} from '../utils/getHash';
|
||||||
import {getIP} from '../utils/getIP';
|
import {getIP} from '../utils/getIP';
|
||||||
import {getFormattedTime} from '../utils/getFormattedTime';
|
import {getFormattedTime} from '../utils/getFormattedTime';
|
||||||
@@ -272,6 +271,34 @@ async function getYouTubeVideoInfo(videoID: VideoID, ignoreCache = false): Promi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function checkUserActiveWarning(userID: string): Promise<{ pass: boolean; errorMessage: string; }> {
|
||||||
|
const MILLISECONDS_IN_HOUR = 3600000;
|
||||||
|
const now = Date.now();
|
||||||
|
const warnings = await db.prepare('all',
|
||||||
|
`SELECT "reason"
|
||||||
|
FROM warnings
|
||||||
|
WHERE "userID" = ? AND "issueTime" > ? AND enabled = 1
|
||||||
|
ORDER BY "issueTime" DESC
|
||||||
|
LIMIT ?`,
|
||||||
|
[
|
||||||
|
userID,
|
||||||
|
Math.floor(now - (config.hoursAfterWarningExpires * MILLISECONDS_IN_HOUR)),
|
||||||
|
config.maxNumberOfActiveWarnings
|
||||||
|
],
|
||||||
|
) as {reason: string}[]
|
||||||
|
|
||||||
|
if (warnings?.length >= config.maxNumberOfActiveWarnings) {
|
||||||
|
const defaultMessage = 'Submission rejected due to a warning from a moderator. This means that we noticed you were making some common mistakes that are not malicious, and we just want to clarify the rules. Could you please send a message in Discord or Matrix so we can further help you?';
|
||||||
|
|
||||||
|
return {
|
||||||
|
pass: false,
|
||||||
|
errorMessage: warnings[0]?.reason?.length > 0 ? warnings[0].reason : defaultMessage
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {pass: true, errorMessage: ''};
|
||||||
|
}
|
||||||
|
|
||||||
function proxySubmission(req: Request) {
|
function proxySubmission(req: Request) {
|
||||||
fetch(config.proxySubmission + '/api/skipSegments?userID=' + req.query.userID + '&videoID=' + req.query.videoID, {
|
fetch(config.proxySubmission + '/api/skipSegments?userID=' + req.query.userID + '&videoID=' + req.query.videoID, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@@ -319,26 +346,18 @@ export async function postSkipSegments(req: Request, res: Response) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (invalidFields.length !== 0) {
|
if (invalidFields.length !== 0) {
|
||||||
// invalid request
|
// invalid request
|
||||||
const fields = invalidFields.reduce((p, c, i) => p + (i !== 0 ? ', ' : '') + c, '');
|
const fields = invalidFields.reduce((p, c, i) => p + (i !== 0 ? ', ' : '') + c, '');
|
||||||
res.status(400).send(`No valid ${fields} field(s) provided`);
|
res.status(400).send(`No valid ${fields} field(s) provided`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//hash the userID
|
//hash the userID
|
||||||
userID = getHash(userID);
|
userID = getHash(userID);
|
||||||
|
|
||||||
//hash the ip 5000 times so no one can get it from the database
|
const warningResult: {pass: boolean, errorMessage: string} = await checkUserActiveWarning(userID);
|
||||||
const hashedIP = getHash(getIP(req) + config.globalSalt);
|
if (!warningResult.pass) {
|
||||||
|
return res.status(403).send(warningResult.errorMessage);
|
||||||
const MILLISECONDS_IN_HOUR = 3600000;
|
|
||||||
const now = Date.now();
|
|
||||||
const warningsCount = (await db.prepare('get', `SELECT count(*) as count FROM warnings WHERE "userID" = ? AND "issueTime" > ? AND enabled = 1`,
|
|
||||||
[userID, Math.floor(now - (config.hoursAfterWarningExpires * MILLISECONDS_IN_HOUR))],
|
|
||||||
)).count;
|
|
||||||
|
|
||||||
if (warningsCount >= config.maxNumberOfActiveWarnings) {
|
|
||||||
return res.status(403).send('Submission rejected due to a warning from a moderator. This means that we noticed you were making some common mistakes that are not malicious, and we just want to clarify the rules. Could you please send a message in Discord or Matrix so we can further help you?');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let lockedCategoryList = (await db.prepare('all', 'SELECT category from "lockCategories" where "videoID" = ?', [videoID])).map((list: any) => {
|
let lockedCategoryList = (await db.prepare('all', 'SELECT category from "lockCategories" where "videoID" = ?', [videoID])).map((list: any) => {
|
||||||
@@ -350,9 +369,15 @@ export async function postSkipSegments(req: Request, res: Response) {
|
|||||||
|
|
||||||
const decreaseVotes = 0;
|
const decreaseVotes = 0;
|
||||||
|
|
||||||
const previousSubmissions = await db.prepare('all', `SELECT "videoDuration", "UUID" FROM "sponsorTimes" WHERE "videoID" = ? AND "service" = ? AND "hidden" = 0
|
const previousSubmissions = await db.prepare('all',
|
||||||
AND "shadowHidden" = 0 AND "votes" >= 0 AND "videoDuration" != 0`, [videoID, service]) as
|
`SELECT "videoDuration", "UUID"
|
||||||
{videoDuration: VideoDuration, UUID: SegmentUUID}[];
|
FROM "sponsorTimes"
|
||||||
|
WHERE "videoID" = ? AND "service" = ? AND
|
||||||
|
"hidden" = 0 AND "shadowHidden" = 0 AND
|
||||||
|
"votes" >= 0 AND "videoDuration" != 0`,
|
||||||
|
[videoID, service]
|
||||||
|
) as {videoDuration: VideoDuration, UUID: SegmentUUID}[];
|
||||||
|
|
||||||
// If the video's duration is changed, then the video should be unlocked and old submissions should be hidden
|
// If the video's duration is changed, then the video should be unlocked and old submissions should be hidden
|
||||||
const videoDurationChanged = (videoDuration: number) => videoDuration != 0 && previousSubmissions.length > 0 && !previousSubmissions.some((e) => Math.abs(videoDuration - e.videoDuration) < 2);
|
const videoDurationChanged = (videoDuration: number) => videoDuration != 0 && previousSubmissions.length > 0 && !previousSubmissions.some((e) => Math.abs(videoDuration - e.videoDuration) < 2);
|
||||||
|
|
||||||
@@ -452,6 +477,9 @@ export async function postSkipSegments(req: Request, res: Response) {
|
|||||||
const UUIDs = [];
|
const UUIDs = [];
|
||||||
const newSegments = [];
|
const newSegments = [];
|
||||||
|
|
||||||
|
//hash the ip 5000 times so no one can get it from the database
|
||||||
|
const hashedIP = getHash(getIP(req) + config.globalSalt);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
//get current time
|
//get current time
|
||||||
const timeSubmitted = Date.now();
|
const timeSubmitted = Date.now();
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ export interface DBSegment {
|
|||||||
userID: UserID;
|
userID: UserID;
|
||||||
votes: number;
|
votes: number;
|
||||||
locked: boolean;
|
locked: boolean;
|
||||||
|
required: boolean; // Requested specifically from the client
|
||||||
shadowHidden: Visibility;
|
shadowHidden: Visibility;
|
||||||
videoID: VideoID;
|
videoID: VideoID;
|
||||||
videoDuration: VideoDuration;
|
videoDuration: VideoDuration;
|
||||||
@@ -57,6 +58,7 @@ export interface OverlappingSegmentGroup {
|
|||||||
segments: DBSegment[],
|
segments: DBSegment[],
|
||||||
votes: number;
|
votes: number;
|
||||||
locked: boolean; // Contains a locked segment
|
locked: boolean; // Contains a locked segment
|
||||||
|
required: boolean; // Requested specifically from the client
|
||||||
reputation: number;
|
reputation: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ describe('getSkipSegments', () => {
|
|||||||
await db.prepare("run", query, ['locked', 20, 33, 2, 1, '1-uuid-locked-8', 'testman', 0, 50, 'intro', 'YouTube', 230, 0, 0, getHash('locked', 1)]);
|
await db.prepare("run", query, ['locked', 20, 33, 2, 1, '1-uuid-locked-8', 'testman', 0, 50, 'intro', 'YouTube', 230, 0, 0, getHash('locked', 1)]);
|
||||||
await db.prepare("run", query, ['locked', 20, 34, 100000, 0, '1-uuid-9', 'testman', 0, 50, 'intro', 'YouTube', 190, 0, 0, getHash('locked', 1)]);
|
await db.prepare("run", query, ['locked', 20, 34, 100000, 0, '1-uuid-9', 'testman', 0, 50, 'intro', 'YouTube', 190, 0, 0, getHash('locked', 1)]);
|
||||||
await db.prepare("run", query, ['onlyHiddenSegments', 20, 34, 100000, 0, 'onlyHiddenSegments', 'testman', 0, 50, 'sponsor', 'YouTube', 190, 1, 0, getHash('onlyHiddenSegments', 1)]);
|
await db.prepare("run", query, ['onlyHiddenSegments', 20, 34, 100000, 0, 'onlyHiddenSegments', 'testman', 0, 50, 'sponsor', 'YouTube', 190, 1, 0, getHash('onlyHiddenSegments', 1)]);
|
||||||
|
await db.prepare("run", query, ['requiredSegmentVid-raw', 60, 70, 2, 0, 'requiredSegmentVid-raw-1', 'testman', 0, 50, 'sponsor', 'YouTube', 0, 0, 0, getHash('requiredSegmentVid-raw', 1)]);
|
||||||
|
await db.prepare("run", query, ['requiredSegmentVid-raw', 60, 70, -2, 0, 'requiredSegmentVid-raw-2', 'testman', 0, 50, 'sponsor', 'YouTube', 0, 0, 0, getHash('requiredSegmentVid-raw', 1)]);
|
||||||
|
await db.prepare("run", query, ['requiredSegmentVid-raw', 80, 90, -2, 0, 'requiredSegmentVid-raw-3', 'testman', 0, 50, 'sponsor', 'YouTube', 0, 0, 0, getHash('requiredSegmentVid-raw', 1)]);
|
||||||
|
await db.prepare("run", query, ['requiredSegmentVid-raw', 80, 90, 2, 0, 'requiredSegmentVid-raw-4', 'testman', 0, 50, 'sponsor', 'YouTube', 0, 0, 0, getHash('requiredSegmentVid-raw', 1)]);
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -309,4 +313,34 @@ describe('getSkipSegments', () => {
|
|||||||
})
|
})
|
||||||
.catch(err => ("Couldn't call endpoint"));
|
.catch(err => ("Couldn't call endpoint"));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Should be able to get specific segments with requiredSegments', (done: Done) => {
|
||||||
|
fetch(getbaseURL() + '/api/skipSegments?videoID=requiredSegmentVid-raw&requiredSegments=["requiredSegmentVid-raw-2","requiredSegmentVid-raw-3"]')
|
||||||
|
.then(async res => {
|
||||||
|
if (res.status !== 200) done("non 200 status code, was " + res.status);
|
||||||
|
else {
|
||||||
|
const body = await res.json();
|
||||||
|
if (body.length !== 2) done("expected 2 segments, got " + body.length);
|
||||||
|
else if (body[0].UUID !== 'requiredSegmentVid-raw-2'
|
||||||
|
|| body[1].UUID !== 'requiredSegmentVid-raw-3') done("Did not recieve the correct segments\n" + JSON.stringify(body, null, 2));
|
||||||
|
else done();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => done("Couldn't call endpoint"));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to get specific segments with repeating requiredSegment', (done: Done) => {
|
||||||
|
fetch(getbaseURL() + '/api/skipSegments?videoID=requiredSegmentVid-raw&requiredSegment=requiredSegmentVid-raw-2&requiredSegment=requiredSegmentVid-raw-3')
|
||||||
|
.then(async res => {
|
||||||
|
if (res.status !== 200) done("non 200 status code, was " + res.status);
|
||||||
|
else {
|
||||||
|
const body = await res.json();
|
||||||
|
if (body.length !== 2) done("expected 2 segments, got " + body.length);
|
||||||
|
else if (body[0].UUID !== 'requiredSegmentVid-raw-2'
|
||||||
|
|| body[1].UUID !== 'requiredSegmentVid-raw-3') done("Did not recieve the correct segments\n" + JSON.stringify(body, null, 2));
|
||||||
|
else done();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => done("Couldn't call endpoint"));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -21,6 +21,10 @@ describe('getSegmentsByHash', () => {
|
|||||||
await db.prepare("run", query, ['onlyHidden', 60, 70, 2, 'onlyHidden', 'testman', 0, 50, 'sponsor', 'YouTube', 1, 0, 'f3a199e1af001d716cdc6599360e2b062c2d2b3fa2885f6d9d2fd741166cbbd3']);
|
await db.prepare("run", query, ['onlyHidden', 60, 70, 2, 'onlyHidden', 'testman', 0, 50, 'sponsor', 'YouTube', 1, 0, 'f3a199e1af001d716cdc6599360e2b062c2d2b3fa2885f6d9d2fd741166cbbd3']);
|
||||||
await db.prepare("run", query, ['highlightVid', 60, 60, 2, 'highlightVid-1', 'testman', 0, 50, 'highlight', 'YouTube', 0, 0, getHash('highlightVid', 1)]);
|
await db.prepare("run", query, ['highlightVid', 60, 60, 2, 'highlightVid-1', 'testman', 0, 50, 'highlight', 'YouTube', 0, 0, getHash('highlightVid', 1)]);
|
||||||
await db.prepare("run", query, ['highlightVid', 70, 70, 2, 'highlightVid-2', 'testman', 0, 50, 'highlight', 'YouTube', 0, 0, getHash('highlightVid', 1)]);
|
await db.prepare("run", query, ['highlightVid', 70, 70, 2, 'highlightVid-2', 'testman', 0, 50, 'highlight', 'YouTube', 0, 0, getHash('highlightVid', 1)]);
|
||||||
|
await db.prepare("run", query, ['requiredSegmentVid', 60, 70, 2, 'requiredSegmentVid-1', 'testman', 0, 50, 'sponsor', 'YouTube', 0, 0, 'd51822c3f681e07aef15a8855f52ad12db9eb9cf059e65b16b64c43359557f61']);
|
||||||
|
await db.prepare("run", query, ['requiredSegmentVid', 60, 70, -2, 'requiredSegmentVid-2', 'testman', 0, 50, 'sponsor', 'YouTube', 0, 0, 'd51822c3f681e07aef15a8855f52ad12db9eb9cf059e65b16b64c43359557f61']);
|
||||||
|
await db.prepare("run", query, ['requiredSegmentVid', 80, 90, -2, 'requiredSegmentVid-3', 'testman', 0, 50, 'sponsor', 'YouTube', 0, 0, 'd51822c3f681e07aef15a8855f52ad12db9eb9cf059e65b16b64c43359557f61']);
|
||||||
|
await db.prepare("run", query, ['requiredSegmentVid', 80, 90, 2, 'requiredSegmentVid-4', 'testman', 0, 50, 'sponsor', 'YouTube', 0, 0, 'd51822c3f681e07aef15a8855f52ad12db9eb9cf059e65b16b64c43359557f61']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should be able to get a 200', (done: Done) => {
|
it('Should be able to get a 200', (done: Done) => {
|
||||||
@@ -219,4 +223,67 @@ describe('getSegmentsByHash', () => {
|
|||||||
})
|
})
|
||||||
.catch(err => done('(post) ' + err));
|
.catch(err => done('(post) ' + err));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Should be able to get multiple categories with repeating parameters', (done: Done) => {
|
||||||
|
fetch(getbaseURL() + "/api/skipSegments/fdaff4?&category=sponsor&category=intro")
|
||||||
|
.then(async res => {
|
||||||
|
if (res.status !== 200) done("Status code was: " + res.status);
|
||||||
|
else {
|
||||||
|
const body = await res.json();
|
||||||
|
if (body.length !== 1) done("expected 1 video, got " + body.length);
|
||||||
|
|
||||||
|
const data = body[0].segments;
|
||||||
|
if (data.length === 2) {
|
||||||
|
let success = true;
|
||||||
|
for (const segment of data) {
|
||||||
|
if ((segment.segment[0] !== 1 || segment.segment[1] !== 10
|
||||||
|
|| segment.category !== "sponsor" || segment.UUID !== "getSegmentsByHash-0-0") &&
|
||||||
|
(segment.segment[0] !== 20 || segment.segment[1] !== 30
|
||||||
|
|| segment.category !== "intro" || segment.UUID !== "getSegmentsByHash-0-1")) {
|
||||||
|
success = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success) done();
|
||||||
|
else done("Received incorrect body: " + JSON.stringify(body));
|
||||||
|
} else {
|
||||||
|
done("Received incorrect body: " + JSON.stringify(body));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => ("Couldn't call endpoint"));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to get specific segments with requiredSegments', (done: Done) => {
|
||||||
|
fetch(getbaseURL() + '/api/skipSegments/d518?requiredSegments=["requiredSegmentVid-2","requiredSegmentVid-3"]')
|
||||||
|
.then(async res => {
|
||||||
|
if (res.status !== 200) done("non 200 status code, was " + res.status);
|
||||||
|
else {
|
||||||
|
const body = await res.json();
|
||||||
|
if (body.length !== 1) done("expected 1 video, got " + body.length);
|
||||||
|
else if (body[0].segments.length !== 2) done("expected 2 segments for video, got " + body[0].segments.length);
|
||||||
|
else if (body[0].segments[0].UUID !== 'requiredSegmentVid-2'
|
||||||
|
|| body[0].segments[1].UUID !== 'requiredSegmentVid-3') done("Did not recieve the correct segments\n" + JSON.stringify(body, null, 2));
|
||||||
|
else done();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => done("Couldn't call endpoint"));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to get specific segments with repeating requiredSegment', (done: Done) => {
|
||||||
|
fetch(getbaseURL() + '/api/skipSegments/d518?requiredSegment=requiredSegmentVid-2&requiredSegment=requiredSegmentVid-3')
|
||||||
|
.then(async res => {
|
||||||
|
if (res.status !== 200) done("non 200 status code, was " + res.status);
|
||||||
|
else {
|
||||||
|
const body = await res.json();
|
||||||
|
if (body.length !== 1) done("expected 1 video, got " + body.length);
|
||||||
|
else if (body[0].segments.length !== 2) done("expected 2 segments for video, got " + body[0].segments.length);
|
||||||
|
else if (body[0].segments[0].UUID !== 'requiredSegmentVid-2'
|
||||||
|
|| body[0].segments[1].UUID !== 'requiredSegmentVid-3') done("Did not recieve the correct segments\n" + JSON.stringify(body, null, 2));
|
||||||
|
else done();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => done("Couldn't call endpoint"));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -23,22 +23,31 @@ describe('postSkipSegments', () => {
|
|||||||
const warnUser01Hash = getHash("warn-user01");
|
const warnUser01Hash = getHash("warn-user01");
|
||||||
const warnUser02Hash = getHash("warn-user02");
|
const warnUser02Hash = getHash("warn-user02");
|
||||||
const warnUser03Hash = getHash("warn-user03");
|
const warnUser03Hash = getHash("warn-user03");
|
||||||
|
const warnUser04Hash = getHash("warn-user04");
|
||||||
|
const reason01 = 'Reason01';
|
||||||
|
const reason02 = '';
|
||||||
|
const reason03 = 'Reason03';
|
||||||
|
const reason04 = '';
|
||||||
const MILLISECONDS_IN_HOUR = 3600000;
|
const MILLISECONDS_IN_HOUR = 3600000;
|
||||||
const warningExpireTime = MILLISECONDS_IN_HOUR * config.hoursAfterWarningExpires;
|
const warningExpireTime = MILLISECONDS_IN_HOUR * config.hoursAfterWarningExpires;
|
||||||
|
|
||||||
const insertWarningQuery = 'INSERT INTO warnings ("userID", "issueTime", "issuerUserID", "enabled") VALUES(?, ?, ?, ?)';
|
const insertWarningQuery = 'INSERT INTO warnings ("userID", "issueTime", "issuerUserID", "enabled", "reason") VALUES(?, ?, ?, ?, ?)';
|
||||||
db.prepare("run", insertWarningQuery, [warnUser01Hash, now, warnVip01Hash, 1]);
|
db.prepare("run", insertWarningQuery, [warnUser01Hash, now, warnVip01Hash, 1, reason01]);
|
||||||
db.prepare("run", insertWarningQuery, [warnUser01Hash, (now - 1000), warnVip01Hash, 1]);
|
db.prepare("run", insertWarningQuery, [warnUser01Hash, (now - 1000), warnVip01Hash, 1, reason01]);
|
||||||
db.prepare("run", insertWarningQuery, [warnUser01Hash, (now - 2000), warnVip01Hash, 1]);
|
db.prepare("run", insertWarningQuery, [warnUser01Hash, (now - 2000), warnVip01Hash, 1, reason01]);
|
||||||
db.prepare("run", insertWarningQuery, [warnUser01Hash, (now - 3601000), warnVip01Hash, 1]);
|
db.prepare("run", insertWarningQuery, [warnUser01Hash, (now - 3601000), warnVip01Hash, 1, reason01]);
|
||||||
db.prepare("run", insertWarningQuery, [warnUser02Hash, now, warnVip01Hash, 1]);
|
db.prepare("run", insertWarningQuery, [warnUser02Hash, now, warnVip01Hash, 1, reason02]);
|
||||||
db.prepare("run", insertWarningQuery, [warnUser02Hash, now, warnVip01Hash, 1]);
|
db.prepare("run", insertWarningQuery, [warnUser02Hash, now, warnVip01Hash, 1, reason02]);
|
||||||
db.prepare("run", insertWarningQuery, [warnUser02Hash, (now - (warningExpireTime + 1000)), warnVip01Hash, 1]);
|
db.prepare("run", insertWarningQuery, [warnUser02Hash, (now - (warningExpireTime + 1000)), warnVip01Hash, 1, reason02]);
|
||||||
db.prepare("run", insertWarningQuery, [warnUser02Hash, (now - (warningExpireTime + 2000)), warnVip01Hash, 1]);
|
db.prepare("run", insertWarningQuery, [warnUser02Hash, (now - (warningExpireTime + 2000)), warnVip01Hash, 1, reason02]);
|
||||||
db.prepare("run", insertWarningQuery, [warnUser03Hash, now, warnVip01Hash, 0]);
|
db.prepare("run", insertWarningQuery, [warnUser03Hash, now, warnVip01Hash, 0, reason03]);
|
||||||
db.prepare("run", insertWarningQuery, [warnUser03Hash, (now - 1000), warnVip01Hash, 0]);
|
db.prepare("run", insertWarningQuery, [warnUser03Hash, (now - 1000), warnVip01Hash, 0, reason03]);
|
||||||
db.prepare("run", insertWarningQuery, [warnUser03Hash, (now - 2000), warnVip01Hash, 1]);
|
db.prepare("run", insertWarningQuery, [warnUser03Hash, (now - 2000), warnVip01Hash, 1, reason03]);
|
||||||
db.prepare("run", insertWarningQuery, [warnUser03Hash, (now - 3601000), warnVip01Hash, 1]);
|
db.prepare("run", insertWarningQuery, [warnUser03Hash, (now - 3601000), warnVip01Hash, 1, reason03]);
|
||||||
|
db.prepare("run", insertWarningQuery, [warnUser04Hash, now, warnVip01Hash, 0, reason04]);
|
||||||
|
db.prepare("run", insertWarningQuery, [warnUser04Hash, (now - 1000), warnVip01Hash, 0, reason04]);
|
||||||
|
db.prepare("run", insertWarningQuery, [warnUser04Hash, (now - 2000), warnVip01Hash, 1, reason04]);
|
||||||
|
db.prepare("run", insertWarningQuery, [warnUser04Hash, (now - 3601000), warnVip01Hash, 1, reason04]);
|
||||||
|
|
||||||
const insertVipUserQuery = 'INSERT INTO "vipUsers" ("userID") VALUES (?)';
|
const insertVipUserQuery = 'INSERT INTO "vipUsers" ("userID") VALUES (?)';
|
||||||
db.prepare("run", insertVipUserQuery, [getHash("VIPUserSubmission")]);
|
db.prepare("run", insertVipUserQuery, [getHash("VIPUserSubmission")]);
|
||||||
@@ -601,7 +610,7 @@ describe('postSkipSegments', () => {
|
|||||||
.catch(err => done("Couldn't call endpoint"));
|
.catch(err => done("Couldn't call endpoint"));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should be rejected if user has to many active warnings', (done: Done) => {
|
it('Should be rejected with custom message if user has to many active warnings', (done: Done) => {
|
||||||
fetch(getbaseURL()
|
fetch(getbaseURL()
|
||||||
+ "/api/postVideoSponsorTimes", {
|
+ "/api/postVideoSponsorTimes", {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@@ -619,7 +628,12 @@ describe('postSkipSegments', () => {
|
|||||||
})
|
})
|
||||||
.then(async res => {
|
.then(async res => {
|
||||||
if (res.status === 403) {
|
if (res.status === 403) {
|
||||||
done(); // success
|
const errorMessage = await res.text();
|
||||||
|
if (errorMessage === 'Reason01') {
|
||||||
|
done(); // success
|
||||||
|
} else {
|
||||||
|
done("Status code was 403 but message was: " + errorMessage);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
done("Status code was " + res.status);
|
done("Status code was " + res.status);
|
||||||
}
|
}
|
||||||
@@ -693,6 +707,37 @@ describe('postSkipSegments', () => {
|
|||||||
.catch(err => done(true));
|
.catch(err => done(true));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Should be rejected with default message if user has to many active warnings', (done: Done) => {
|
||||||
|
fetch(getbaseURL()
|
||||||
|
+ "/api/postVideoSponsorTimes", {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
userID: "warn-user01",
|
||||||
|
videoID: "dQw4w9WgXcF",
|
||||||
|
segments: [{
|
||||||
|
segment: [0, 10],
|
||||||
|
category: "sponsor",
|
||||||
|
}],
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.then(async res => {
|
||||||
|
if (res.status === 403) {
|
||||||
|
const errorMessage = await res.text();
|
||||||
|
if (errorMessage !== '') {
|
||||||
|
done(); // success
|
||||||
|
} else {
|
||||||
|
done("Status code was 403 but message was: " + errorMessage);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
done("Status code was " + res.status);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => done(err));
|
||||||
|
});
|
||||||
|
|
||||||
it('Should return 400 for missing params (JSON method) 1', (done: Done) => {
|
it('Should return 400 for missing params (JSON method) 1', (done: Done) => {
|
||||||
fetch(getbaseURL()
|
fetch(getbaseURL()
|
||||||
+ "/api/postVideoSponsorTimes", {
|
+ "/api/postVideoSponsorTimes", {
|
||||||
|
|||||||
Reference in New Issue
Block a user