mirror of
https://github.com/ajayyy/SponsorBlockServer.git
synced 2024-11-10 09:07:47 +01:00
commit
1fe68c66c5
32 changed files with 1427 additions and 216 deletions
|
@ -4,6 +4,8 @@ COPY package.json .
|
||||||
RUN npm install
|
RUN npm install
|
||||||
COPY index.js .
|
COPY index.js .
|
||||||
COPY src src
|
COPY src src
|
||||||
|
RUN mkdir databases
|
||||||
|
COPY databases/*.sql databases/
|
||||||
COPY entrypoint.sh .
|
COPY entrypoint.sh .
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
CMD ./entrypoint.sh
|
CMD ./entrypoint.sh
|
8
databases/_upgrade_private_1.sql
Normal file
8
databases/_upgrade_private_1.sql
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
/* for testing the db upgrade, don't remove because it looks empty */
|
||||||
|
|
||||||
|
/* Add version to config */
|
||||||
|
INSERT INTO config (key, value) VALUES("version", 1);
|
||||||
|
|
||||||
|
COMMIT;
|
13
databases/_upgrade_sponsorTimes_2.sql
Normal file
13
databases/_upgrade_sponsorTimes_2.sql
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
/* Add new table: noSegments */
|
||||||
|
CREATE TABLE "noSegments" (
|
||||||
|
"videoID" TEXT NOT NULL,
|
||||||
|
"userID" TEXT NOT NULL,
|
||||||
|
"category" TEXT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
/* Add version to config */
|
||||||
|
UPDATE config SET value = 2 WHERE key = 'version';
|
||||||
|
|
||||||
|
COMMIT;
|
13
databases/_upgrade_sponsorTimes_3.sql
Normal file
13
databases/_upgrade_sponsorTimes_3.sql
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
/* hash upgrade test sha256('vid') = '1ff838dc6ca9680d88455341118157d59a055fe6d0e3870f9c002847bebe4663'
|
||||||
|
/* Add hash field */
|
||||||
|
ALTER TABLE sponsorTimes ADD hashedVideoID TEXT NOT NULL default "";
|
||||||
|
UPDATE sponsorTimes SET hashedVideoID = sha256(videoID);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS sponsorTimes_hashedVideoID on sponsorTimes(hashedVideoID);
|
||||||
|
|
||||||
|
/* Bump version in config */
|
||||||
|
UPDATE config SET value = 3 WHERE key = "version";
|
||||||
|
|
||||||
|
COMMIT;
|
240
package-lock.json
generated
240
package-lock.json
generated
|
@ -68,6 +68,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
||||||
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
|
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
|
||||||
},
|
},
|
||||||
|
"asap": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/asap/-/asap-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-sqRdpf36ILBJb8N2jMJ8EvqRan0="
|
||||||
|
},
|
||||||
"asn1": {
|
"asn1": {
|
||||||
"version": "0.2.4",
|
"version": "0.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
|
||||||
|
@ -96,12 +101,39 @@
|
||||||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz",
|
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz",
|
||||||
"integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug=="
|
"integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug=="
|
||||||
},
|
},
|
||||||
|
"babel-runtime": {
|
||||||
|
"version": "6.26.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
|
||||||
|
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
|
||||||
|
"requires": {
|
||||||
|
"core-js": "^2.4.0",
|
||||||
|
"regenerator-runtime": "^0.11.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"balanced-match": {
|
"balanced-match": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"barrage": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/barrage/-/barrage-1.1.0.tgz",
|
||||||
|
"integrity": "sha1-b1OEdlxGP3cYAS8WDczwM/xvw5Q=",
|
||||||
|
"requires": {
|
||||||
|
"promise": "^6.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"promise": {
|
||||||
|
"version": "6.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/promise/-/promise-6.1.0.tgz",
|
||||||
|
"integrity": "sha1-LOcp9rlLRcJoka0GAsXJDgTG7vY=",
|
||||||
|
"requires": {
|
||||||
|
"asap": "~1.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"base64url": {
|
"base64url": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/base64url/-/base64url-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/base64url/-/base64url-1.0.6.tgz",
|
||||||
|
@ -128,6 +160,11 @@
|
||||||
"tar": "^4.4.10"
|
"tar": "^4.4.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"bignumber.js": {
|
||||||
|
"version": "9.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz",
|
||||||
|
"integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A=="
|
||||||
|
},
|
||||||
"binary-extensions": {
|
"binary-extensions": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz",
|
||||||
|
@ -269,6 +306,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
|
||||||
"integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
|
"integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
|
||||||
},
|
},
|
||||||
|
"buffer-from": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
|
||||||
|
},
|
||||||
"bytes": {
|
"bytes": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
|
||||||
|
@ -471,6 +513,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
||||||
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
|
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
|
||||||
},
|
},
|
||||||
|
"core-js": {
|
||||||
|
"version": "2.6.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz",
|
||||||
|
"integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg=="
|
||||||
|
},
|
||||||
"core-util-is": {
|
"core-util-is": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||||
|
@ -559,6 +606,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
|
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
|
||||||
},
|
},
|
||||||
|
"denque": {
|
||||||
|
"version": "1.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz",
|
||||||
|
"integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ=="
|
||||||
|
},
|
||||||
"depd": {
|
"depd": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||||
|
@ -877,6 +929,11 @@
|
||||||
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
|
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"get-port": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz",
|
||||||
|
"integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw="
|
||||||
|
},
|
||||||
"get-stdin": {
|
"get-stdin": {
|
||||||
"version": "4.0.1",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
|
||||||
|
@ -1744,6 +1801,56 @@
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||||
},
|
},
|
||||||
|
"mysql": {
|
||||||
|
"version": "2.18.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz",
|
||||||
|
"integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==",
|
||||||
|
"requires": {
|
||||||
|
"bignumber.js": "9.0.0",
|
||||||
|
"readable-stream": "2.3.7",
|
||||||
|
"safe-buffer": "5.1.2",
|
||||||
|
"sqlstring": "2.3.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"isarray": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
|
||||||
|
},
|
||||||
|
"process-nextick-args": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
|
||||||
|
},
|
||||||
|
"readable-stream": {
|
||||||
|
"version": "2.3.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
|
||||||
|
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
|
||||||
|
"requires": {
|
||||||
|
"core-util-is": "~1.0.0",
|
||||||
|
"inherits": "~2.0.3",
|
||||||
|
"isarray": "~1.0.0",
|
||||||
|
"process-nextick-args": "~2.0.0",
|
||||||
|
"safe-buffer": "~5.1.1",
|
||||||
|
"string_decoder": "~1.1.1",
|
||||||
|
"util-deprecate": "~1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"safe-buffer": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||||
|
},
|
||||||
|
"string_decoder": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||||
|
"requires": {
|
||||||
|
"safe-buffer": "~5.1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"negotiator": {
|
"negotiator": {
|
||||||
"version": "0.6.2",
|
"version": "0.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
|
||||||
|
@ -2005,6 +2112,21 @@
|
||||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
|
||||||
"integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
|
"integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
|
||||||
},
|
},
|
||||||
|
"promise": {
|
||||||
|
"version": "7.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
|
||||||
|
"integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
|
||||||
|
"requires": {
|
||||||
|
"asap": "~2.0.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"asap": {
|
||||||
|
"version": "2.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
|
||||||
|
"integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"proxy-addr": {
|
"proxy-addr": {
|
||||||
"version": "2.0.6",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
|
||||||
|
@ -2089,6 +2211,40 @@
|
||||||
"picomatch": "^2.0.4"
|
"picomatch": "^2.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"redis": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/redis/-/redis-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-PNhLCrjU6vKVuMOyFu7oSP296mwBkcE6lrAjruBYG5LgdSqtRBoVQIylrMyVZD/lkF24RSNNatzvYag6HRBHjQ==",
|
||||||
|
"requires": {
|
||||||
|
"denque": "^1.4.1",
|
||||||
|
"redis-commands": "^1.5.0",
|
||||||
|
"redis-errors": "^1.2.0",
|
||||||
|
"redis-parser": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"redis-commands": {
|
||||||
|
"version": "1.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.6.0.tgz",
|
||||||
|
"integrity": "sha512-2jnZ0IkjZxvguITjFTrGiLyzQZcTvaw8DAaCXxZq/dsHXz7KfMQ3OUJy7Tz9vnRtZRVz6VRCPDvruvU8Ts44wQ=="
|
||||||
|
},
|
||||||
|
"redis-errors": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
|
||||||
|
"integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60="
|
||||||
|
},
|
||||||
|
"redis-parser": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz",
|
||||||
|
"integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=",
|
||||||
|
"requires": {
|
||||||
|
"redis-errors": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"regenerator-runtime": {
|
||||||
|
"version": "0.11.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
|
||||||
|
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
|
||||||
|
},
|
||||||
"registry-auth-token": {
|
"registry-auth-token": {
|
||||||
"version": "3.4.0",
|
"version": "3.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz",
|
||||||
|
@ -2277,6 +2433,11 @@
|
||||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
|
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"sqlstring": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz",
|
||||||
|
"integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A="
|
||||||
|
},
|
||||||
"sshpk": {
|
"sshpk": {
|
||||||
"version": "1.16.1",
|
"version": "1.16.1",
|
||||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
|
||||||
|
@ -2414,6 +2575,75 @@
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
|
||||||
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
|
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
|
||||||
},
|
},
|
||||||
|
"sync-mysql": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/sync-mysql/-/sync-mysql-3.0.1.tgz",
|
||||||
|
"integrity": "sha1-B6ArGSk04EzZDtU+lvCfgbFM68g=",
|
||||||
|
"requires": {
|
||||||
|
"babel-runtime": "^6.18.0",
|
||||||
|
"concat-stream": "^1.6.0",
|
||||||
|
"sync-rpc": "^1.1.1",
|
||||||
|
"then-mysql": "^1.1.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"concat-stream": {
|
||||||
|
"version": "1.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
|
||||||
|
"integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
|
||||||
|
"requires": {
|
||||||
|
"buffer-from": "^1.0.0",
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"readable-stream": "^2.2.2",
|
||||||
|
"typedarray": "^0.0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"isarray": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
|
||||||
|
},
|
||||||
|
"process-nextick-args": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
|
||||||
|
},
|
||||||
|
"readable-stream": {
|
||||||
|
"version": "2.3.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
|
||||||
|
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
|
||||||
|
"requires": {
|
||||||
|
"core-util-is": "~1.0.0",
|
||||||
|
"inherits": "~2.0.3",
|
||||||
|
"isarray": "~1.0.0",
|
||||||
|
"process-nextick-args": "~2.0.0",
|
||||||
|
"safe-buffer": "~5.1.1",
|
||||||
|
"string_decoder": "~1.1.1",
|
||||||
|
"util-deprecate": "~1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"safe-buffer": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||||
|
},
|
||||||
|
"string_decoder": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||||
|
"requires": {
|
||||||
|
"safe-buffer": "~5.1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sync-rpc": {
|
||||||
|
"version": "1.3.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/sync-rpc/-/sync-rpc-1.3.6.tgz",
|
||||||
|
"integrity": "sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw==",
|
||||||
|
"requires": {
|
||||||
|
"get-port": "^3.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"tar": {
|
"tar": {
|
||||||
"version": "4.4.13",
|
"version": "4.4.13",
|
||||||
"resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz",
|
"resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz",
|
||||||
|
@ -2437,6 +2667,16 @@
|
||||||
"execa": "^0.7.0"
|
"execa": "^0.7.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"then-mysql": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/then-mysql/-/then-mysql-1.1.1.tgz",
|
||||||
|
"integrity": "sha1-p1Q2zGXyvm37t3+HIg6YKuDjYR0=",
|
||||||
|
"requires": {
|
||||||
|
"barrage": "^1.1.0",
|
||||||
|
"mysql": "^2.10.0",
|
||||||
|
"promise": "^7.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"timed-out": {
|
"timed-out": {
|
||||||
"version": "4.0.1",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz",
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"http": "0.0.0",
|
"http": "0.0.0",
|
||||||
"iso8601-duration": "^1.2.0",
|
"iso8601-duration": "^1.2.0",
|
||||||
|
"redis": "^3.0.2",
|
||||||
"sync-mysql": "^3.0.1",
|
"sync-mysql": "^3.0.1",
|
||||||
"uuid": "^3.3.2",
|
"uuid": "^3.3.2",
|
||||||
"youtube-api": "^2.0.10",
|
"youtube-api": "^2.0.10",
|
||||||
|
|
14
src/app.js
14
src/app.js
|
@ -2,6 +2,7 @@ var express = require('express');
|
||||||
// Create a service (the app object is just a callback).
|
// Create a service (the app object is just a callback).
|
||||||
var app = express();
|
var app = express();
|
||||||
var config = require('./config.js');
|
var config = require('./config.js');
|
||||||
|
var redis = require('./utils/redis.js');
|
||||||
|
|
||||||
// Middleware
|
// Middleware
|
||||||
var corsMiddleware = require('./middleware/cors.js');
|
var corsMiddleware = require('./middleware/cors.js');
|
||||||
|
@ -11,6 +12,7 @@ const userCounter = require('./middleware/userCounter.js');
|
||||||
// Routes
|
// Routes
|
||||||
var getSkipSegments = require('./routes/getSkipSegments.js').endpoint;
|
var getSkipSegments = require('./routes/getSkipSegments.js').endpoint;
|
||||||
var postSkipSegments = require('./routes/postSkipSegments.js');
|
var postSkipSegments = require('./routes/postSkipSegments.js');
|
||||||
|
var getSkipSegmentsByHash = require('./routes/getSkipSegmentsByHash.js');
|
||||||
var voteOnSponsorTime = require('./routes/voteOnSponsorTime.js');
|
var voteOnSponsorTime = require('./routes/voteOnSponsorTime.js');
|
||||||
var viewedVideoSponsorTime = require('./routes/viewedVideoSponsorTime.js');
|
var viewedVideoSponsorTime = require('./routes/viewedVideoSponsorTime.js');
|
||||||
var setUsername = require('./routes/setUsername.js');
|
var setUsername = require('./routes/setUsername.js');
|
||||||
|
@ -22,6 +24,8 @@ var getViewsForUser = require('./routes/getViewsForUser.js');
|
||||||
var getTopUsers = require('./routes/getTopUsers.js');
|
var getTopUsers = require('./routes/getTopUsers.js');
|
||||||
var getTotalStats = require('./routes/getTotalStats.js');
|
var getTotalStats = require('./routes/getTotalStats.js');
|
||||||
var getDaysSavedFormatted = require('./routes/getDaysSavedFormatted.js');
|
var getDaysSavedFormatted = require('./routes/getDaysSavedFormatted.js');
|
||||||
|
var postNoSegments = require('./routes/postNoSegments.js');
|
||||||
|
var getIsUserVIP = require('./routes/getIsUserVIP.js');
|
||||||
|
|
||||||
// Old Routes
|
// Old Routes
|
||||||
var oldGetVideoSponsorTimes = require('./routes/oldGetVideoSponsorTimes.js');
|
var oldGetVideoSponsorTimes = require('./routes/oldGetVideoSponsorTimes.js');
|
||||||
|
@ -51,6 +55,9 @@ app.post('/api/postVideoSponsorTimes', oldSubmitSponsorTimes);
|
||||||
app.get('/api/skipSegments', getSkipSegments);
|
app.get('/api/skipSegments', getSkipSegments);
|
||||||
app.post('/api/skipSegments', postSkipSegments);
|
app.post('/api/skipSegments', postSkipSegments);
|
||||||
|
|
||||||
|
// add the privacy protecting skip segments functions
|
||||||
|
app.get('/api/skipSegments/:prefix', getSkipSegmentsByHash);
|
||||||
|
|
||||||
//voting endpoint
|
//voting endpoint
|
||||||
app.get('/api/voteOnSponsorTime', voteOnSponsorTime.endpoint);
|
app.get('/api/voteOnSponsorTime', voteOnSponsorTime.endpoint);
|
||||||
app.post('/api/voteOnSponsorTime', voteOnSponsorTime.endpoint);
|
app.post('/api/voteOnSponsorTime', voteOnSponsorTime.endpoint);
|
||||||
|
@ -89,6 +96,13 @@ app.get('/api/getTotalStats', getTotalStats);
|
||||||
//send out a formatted time saved total
|
//send out a formatted time saved total
|
||||||
app.get('/api/getDaysSavedFormatted', getDaysSavedFormatted);
|
app.get('/api/getDaysSavedFormatted', getDaysSavedFormatted);
|
||||||
|
|
||||||
|
//submit video containing no segments
|
||||||
|
app.post('/api/noSegments', postNoSegments);
|
||||||
|
|
||||||
|
//get if user is a vip
|
||||||
|
app.get('/api/isUserVIP', getIsUserVIP);
|
||||||
|
|
||||||
|
|
||||||
app.get('/database.db', function (req, res) {
|
app.get('/database.db', function (req, res) {
|
||||||
res.sendFile("./databases/sponsorTimes.db", { root: "./" });
|
res.sendFile("./databases/sponsorTimes.db", { root: "./" });
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
var fs = require('fs');
|
const fs = require('fs');
|
||||||
var config = undefined;
|
let config = {};
|
||||||
|
|
||||||
// Check to see if launched in test mode
|
// Check to see if launched in test mode
|
||||||
if (process.env.npm_lifecycle_script === 'node test.js') {
|
if (process.env.npm_lifecycle_script === 'node test.js') {
|
||||||
|
@ -9,4 +9,27 @@ if (process.env.npm_lifecycle_script === 'node test.js') {
|
||||||
config = JSON.parse(fs.readFileSync('config.json'));
|
config = JSON.parse(fs.readFileSync('config.json'));
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = config;
|
addDefaults(config, {
|
||||||
|
"port": 80,
|
||||||
|
"behindProxy": "X-Forwarded-For",
|
||||||
|
"db": "./databases/sponsorTimes.db",
|
||||||
|
"privateDB": "./databases/private.db",
|
||||||
|
"createDatabaseIfNotExist": true,
|
||||||
|
"schemaFolder": "./databases",
|
||||||
|
"dbSchema": "./databases/_sponsorTimes.db.sql",
|
||||||
|
"privateDBSchema": "./databases/_private.db.sql",
|
||||||
|
"readOnly": false,
|
||||||
|
"webhooks": [],
|
||||||
|
"categoryList": ["sponsor", "intro", "outro", "interaction", "selfpromo", "music_offtopic"]
|
||||||
|
})
|
||||||
|
|
||||||
|
module.exports = config;
|
||||||
|
|
||||||
|
// Add defaults
|
||||||
|
function addDefaults(config, defaults) {
|
||||||
|
for (const key in defaults) {
|
||||||
|
if(!config.hasOwnProperty(key)) {
|
||||||
|
config[key] = defaults[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
|
@ -1,5 +1,4 @@
|
||||||
var MysqlInterface = require('sync-mysql');
|
var MysqlInterface = require('sync-mysql');
|
||||||
var config = require('../config.js');
|
|
||||||
const logger = require('../utils/logger.js');
|
const logger = require('../utils/logger.js');
|
||||||
|
|
||||||
class Mysql {
|
class Mysql {
|
||||||
|
|
|
@ -3,7 +3,9 @@ var Sqlite3 = require('better-sqlite3');
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
var Sqlite = require('./Sqlite.js')
|
var Sqlite = require('./Sqlite.js')
|
||||||
var Mysql = require('./Mysql.js')
|
var Mysql = require('./Mysql.js');
|
||||||
|
const logger = require('../utils/logger.js');
|
||||||
|
const getHash = require('../utils/getHash.js');
|
||||||
|
|
||||||
let options = {
|
let options = {
|
||||||
readonly: config.readOnly,
|
readonly: config.readOnly,
|
||||||
|
@ -33,6 +35,10 @@ if (config.mysql) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!config.readOnly) {
|
if (!config.readOnly) {
|
||||||
|
db.function("sha256", (string) => {
|
||||||
|
return getHash(string, 1);
|
||||||
|
});
|
||||||
|
|
||||||
// Upgrade database if required
|
// Upgrade database if required
|
||||||
ugradeDB(db, "sponsorTimes");
|
ugradeDB(db, "sponsorTimes");
|
||||||
ugradeDB(privateDB, "private")
|
ugradeDB(privateDB, "private")
|
||||||
|
@ -60,12 +66,16 @@ if (config.mysql) {
|
||||||
let versionCodeInfo = db.prepare("SELECT value FROM config WHERE key = ?").get("version");
|
let versionCodeInfo = db.prepare("SELECT value FROM config WHERE key = ?").get("version");
|
||||||
let versionCode = versionCodeInfo ? versionCodeInfo.value : 0;
|
let versionCode = versionCodeInfo ? versionCodeInfo.value : 0;
|
||||||
|
|
||||||
let path = config.schemaFolder + "/_upgrade_" + prefix + "_" + (versionCode + 1) + ".sql";
|
let path = config.schemaFolder + "/_upgrade_" + prefix + "_" + (parseInt(versionCode) + 1) + ".sql";
|
||||||
|
logger.debug('db update: trying ' + path);
|
||||||
while (fs.existsSync(path)) {
|
while (fs.existsSync(path)) {
|
||||||
|
logger.debug('db update: updating ' + path);
|
||||||
db.exec(fs.readFileSync(path).toString());
|
db.exec(fs.readFileSync(path).toString());
|
||||||
|
|
||||||
versionCode = db.prepare("SELECT value FROM config WHERE key = ?").get("version").value;
|
versionCode = db.prepare("SELECT value FROM config WHERE key = ?").get("version").value;
|
||||||
path = config.schemaFolder + "/_upgrade_" + prefix + "_" + (versionCode + 1) + ".sql";
|
path = config.schemaFolder + "/_upgrade_" + prefix + "_" + (parseInt(versionCode) + 1) + ".sql";
|
||||||
|
logger.debug('db update: trying ' + path);
|
||||||
}
|
}
|
||||||
|
logger.debug('db update: no file ' + path);
|
||||||
}
|
}
|
||||||
}
|
}
|
31
src/routes/getIsUserVIP.js
Normal file
31
src/routes/getIsUserVIP.js
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
var db = require('../databases/databases.js').db;
|
||||||
|
|
||||||
|
var getHash = require('../utils/getHash.js');
|
||||||
|
const logger = require('../utils/logger.js');
|
||||||
|
const isUserVIP = require('../utils/isUserVIP.js');
|
||||||
|
|
||||||
|
module.exports = (req, res) => {
|
||||||
|
let userID = req.query.userID;
|
||||||
|
|
||||||
|
if (userID == undefined) {
|
||||||
|
//invalid request
|
||||||
|
res.sendStatus(400);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//hash the userID
|
||||||
|
userID = getHash(userID);
|
||||||
|
|
||||||
|
try {
|
||||||
|
let vipState = isUserVIP(userID);
|
||||||
|
res.status(200).json({
|
||||||
|
hashedUserID: userID,
|
||||||
|
vip: vipState
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
logger.error(err);
|
||||||
|
res.sendStatus(500);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,3 @@
|
||||||
var fs = require('fs');
|
|
||||||
var config = require('../config.js');
|
var config = require('../config.js');
|
||||||
|
|
||||||
var databases = require('../databases/databases.js');
|
var databases = require('../databases/databases.js');
|
||||||
|
@ -9,45 +8,101 @@ var logger = require('../utils/logger.js');
|
||||||
var getHash = require('../utils/getHash.js');
|
var getHash = require('../utils/getHash.js');
|
||||||
var getIP = require('../utils/getIP.js');
|
var getIP = require('../utils/getIP.js');
|
||||||
|
|
||||||
|
function cleanGetSegments(req, videoID, categories) {
|
||||||
|
let userHashedIP, shadowHiddenSegments;
|
||||||
|
|
||||||
|
let segments = [];
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (const category of categories) {
|
||||||
|
const categorySegments = db
|
||||||
|
.prepare(
|
||||||
|
'all',
|
||||||
|
'SELECT startTime, endTime, votes, UUID, shadowHidden FROM sponsorTimes WHERE videoID = ? and category = ? ORDER BY startTime',
|
||||||
|
[videoID, category]
|
||||||
|
)
|
||||||
|
.filter(segment => {
|
||||||
|
if (segment.votes < -1) {
|
||||||
|
return false; //too untrustworthy, just ignore it
|
||||||
|
}
|
||||||
|
|
||||||
|
//check if shadowHidden
|
||||||
|
//this means it is hidden to everyone but the original ip that submitted it
|
||||||
|
if (segment.shadowHidden != 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shadowHiddenSegments === undefined) {
|
||||||
|
shadowHiddenSegments = privateDB.prepare('all', 'SELECT hashedIP FROM sponsorTimes WHERE videoID = ?', [videoID]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//if this isn't their ip, don't send it to them
|
||||||
|
return shadowHiddenSegments.some(shadowHiddenSegment => {
|
||||||
|
if (userHashedIP === undefined) {
|
||||||
|
//hash the IP only if it's strictly necessary
|
||||||
|
userHashedIP = getHash(getIP(req) + config.globalSalt);
|
||||||
|
}
|
||||||
|
return shadowHiddenSegment.hashedIP === userHashedIP;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
chooseSegments(categorySegments).forEach(chosenSegment => {
|
||||||
|
segments.push({
|
||||||
|
category,
|
||||||
|
segment: [chosenSegment.startTime, chosenSegment.endTime],
|
||||||
|
UUID: chosenSegment.UUID,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return segments;
|
||||||
|
} catch (err) {
|
||||||
|
if (err) {
|
||||||
|
logger.error(err);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//gets a weighted random choice from the choices array based on their `votes` property.
|
//gets a weighted random choice from the choices array based on their `votes` property.
|
||||||
//amountOfChoices specifies the maximum amount of choices to return, 1 or more.
|
//amountOfChoices specifies the maximum amount of choices to return, 1 or more.
|
||||||
//choices are unique
|
//choices are unique
|
||||||
function getWeightedRandomChoice(choices, amountOfChoices) {
|
function getWeightedRandomChoice(choices, amountOfChoices) {
|
||||||
//trivial case: no need to go through the whole process
|
//trivial case: no need to go through the whole process
|
||||||
if (amountOfChoices >= choices.length) {
|
if (amountOfChoices >= choices.length) {
|
||||||
return choices;
|
return choices;
|
||||||
}
|
|
||||||
|
|
||||||
//assign a weight to each choice
|
|
||||||
let totalWeight = 0;
|
|
||||||
choices = choices.map(choice => {
|
|
||||||
//The 3 makes -2 the minimum votes before being ignored completely
|
|
||||||
//https://www.desmos.com/calculator/c1duhfrmts
|
|
||||||
//this can be changed if this system increases in popularity.
|
|
||||||
const weight = Math.exp((choice.votes + 3), 0.85);
|
|
||||||
totalWeight += weight;
|
|
||||||
|
|
||||||
return { ...choice, weight };
|
|
||||||
});
|
|
||||||
|
|
||||||
//iterate and find amountOfChoices choices
|
|
||||||
const chosen = [];
|
|
||||||
while (amountOfChoices-- > 0) {
|
|
||||||
//weighted random draw of one element of choices
|
|
||||||
const randomNumber = Math.random() * totalWeight;
|
|
||||||
let stackWeight = choices[0].weight;
|
|
||||||
let i = 0;
|
|
||||||
while (stackWeight < randomNumber) {
|
|
||||||
stackWeight += choices[++i].weight;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//add it to the chosen ones and remove it from the choices before the next iteration
|
//assign a weight to each choice
|
||||||
chosen.push(choices[i]);
|
let totalWeight = 0;
|
||||||
totalWeight -= choices[i].weight;
|
choices = choices.map(choice => {
|
||||||
choices.splice(i, 1);
|
//The 3 makes -2 the minimum votes before being ignored completely
|
||||||
}
|
//https://www.desmos.com/calculator/c1duhfrmts
|
||||||
|
//this can be changed if this system increases in popularity.
|
||||||
|
const weight = Math.exp((choice.votes + 3), 0.85);
|
||||||
|
totalWeight += weight;
|
||||||
|
|
||||||
return chosen;
|
return { ...choice, weight };
|
||||||
|
});
|
||||||
|
|
||||||
|
//iterate and find amountOfChoices choices
|
||||||
|
const chosen = [];
|
||||||
|
while (amountOfChoices-- > 0) {
|
||||||
|
//weighted random draw of one element of choices
|
||||||
|
const randomNumber = Math.random() * totalWeight;
|
||||||
|
let stackWeight = choices[0].weight;
|
||||||
|
let i = 0;
|
||||||
|
while (stackWeight < randomNumber) {
|
||||||
|
stackWeight += choices[++i].weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
//add it to the chosen ones and remove it from the choices before the next iteration
|
||||||
|
chosen.push(choices[i]);
|
||||||
|
totalWeight -= choices[i].weight;
|
||||||
|
choices.splice(i, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return chosen;
|
||||||
}
|
}
|
||||||
|
|
||||||
//This function will find segments that are contained inside of eachother, called similar segments
|
//This function will find segments that are contained inside of eachother, called similar segments
|
||||||
|
@ -55,34 +110,34 @@ function getWeightedRandomChoice(choices, amountOfChoices) {
|
||||||
//This allows new less voted items to still sometimes appear to give them a chance at getting votes.
|
//This allows new less voted items to still sometimes appear to give them a chance at getting votes.
|
||||||
//Segments with less than -1 votes are already ignored before this function is called
|
//Segments with less than -1 votes are already ignored before this function is called
|
||||||
function chooseSegments(segments) {
|
function chooseSegments(segments) {
|
||||||
//Create groups of segments that are similar to eachother
|
//Create groups of segments that are similar to eachother
|
||||||
//Segments must be sorted by their startTime so that we can build groups chronologically:
|
//Segments must be sorted by their startTime so that we can build groups chronologically:
|
||||||
//1. As long as the segments' startTime fall inside the currentGroup, we keep adding them to that group
|
//1. As long as the segments' startTime fall inside the currentGroup, we keep adding them to that group
|
||||||
//2. If a segment starts after the end of the currentGroup (> cursor), no other segment will ever fall
|
//2. If a segment starts after the end of the currentGroup (> cursor), no other segment will ever fall
|
||||||
// inside that group (because they're sorted) so we can create a new one
|
// inside that group (because they're sorted) so we can create a new one
|
||||||
const similarSegmentsGroups = [];
|
const similarSegmentsGroups = [];
|
||||||
let currentGroup;
|
let currentGroup;
|
||||||
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
|
||||||
segments.forEach(segment => {
|
segments.forEach(segment => {
|
||||||
if (segment.startTime > cursor) {
|
if (segment.startTime > cursor) {
|
||||||
currentGroup = { segments: [], votes: 0 };
|
currentGroup = { segments: [], votes: 0 };
|
||||||
similarSegmentsGroups.push(currentGroup);
|
similarSegmentsGroups.push(currentGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentGroup.segments.push(segment);
|
currentGroup.segments.push(segment);
|
||||||
//only if it is a positive vote, otherwise it is probably just a sponsor time with slightly wrong time
|
//only if it is a positive vote, otherwise it is probably just a sponsor time with slightly wrong time
|
||||||
if (segment.votes > 0) {
|
if (segment.votes > 0) {
|
||||||
currentGroup.votes += segment.votes;
|
currentGroup.votes += segment.votes;
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor = Math.max(cursor, segment.endTime);
|
cursor = Math.max(cursor, segment.endTime);
|
||||||
});
|
});
|
||||||
|
|
||||||
//if there are too many groups, find the best 8
|
//if there are too many groups, find the best 8
|
||||||
return getWeightedRandomChoice(similarSegmentsGroups, 8).map(
|
return getWeightedRandomChoice(similarSegmentsGroups, 8).map(
|
||||||
//randomly choose 1 good segment per group and return them
|
//randomly choose 1 good segment per group and return them
|
||||||
group => getWeightedRandomChoice(group.segments, 1)[0]
|
group => getWeightedRandomChoice(group.segments, 1)[0]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -96,91 +151,39 @@ function chooseSegments(segments) {
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
function handleGetSegments(req, res) {
|
function handleGetSegments(req, res) {
|
||||||
const videoID = req.query.videoID;
|
const videoID = req.query.videoID;
|
||||||
// Default to sponsor
|
// Default to sponsor
|
||||||
// If using params instead of JSON, only one category can be pulled
|
// If using params instead of JSON, only one category can be pulled
|
||||||
const categories = req.query.categories
|
const categories = req.query.categories
|
||||||
? JSON.parse(req.query.categories)
|
? JSON.parse(req.query.categories)
|
||||||
: req.query.category
|
: req.query.category
|
||||||
? [req.query.category]
|
? [req.query.category]
|
||||||
: ['sponsor'];
|
: ['sponsor'];
|
||||||
|
|
||||||
/**
|
let segments = cleanGetSegments(req, videoID, categories);
|
||||||
* @type {Array<{
|
|
||||||
* segment: number[],
|
|
||||||
* category: string,
|
|
||||||
* UUID: string
|
|
||||||
* }>
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
const segments = [];
|
|
||||||
|
|
||||||
let userHashedIP, shadowHiddenSegments;
|
if (segments === null || segments === undefined) {
|
||||||
|
res.sendStatus(500);
|
||||||
try {
|
return false;
|
||||||
for (const category of categories) {
|
|
||||||
const categorySegments = db
|
|
||||||
.prepare(
|
|
||||||
'all',
|
|
||||||
'SELECT startTime, endTime, votes, UUID, shadowHidden FROM sponsorTimes WHERE videoID = ? and category = ? ORDER BY startTime',
|
|
||||||
[videoID, category]
|
|
||||||
)
|
|
||||||
.filter(segment => {
|
|
||||||
if (segment.votes < -1) {
|
|
||||||
return false; //too untrustworthy, just ignore it
|
|
||||||
}
|
|
||||||
|
|
||||||
//check if shadowHidden
|
|
||||||
//this means it is hidden to everyone but the original ip that submitted it
|
|
||||||
if (segment.shadowHidden != 1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shadowHiddenSegments === undefined) {
|
|
||||||
shadowHiddenSegments = privateDB.prepare('all', 'SELECT hashedIP FROM sponsorTimes WHERE videoID = ?', [videoID]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//if this isn't their ip, don't send it to them
|
|
||||||
return shadowHiddenSegments.some(shadowHiddenSegment => {
|
|
||||||
if (userHashedIP === undefined) {
|
|
||||||
//hash the IP only if it's strictly necessary
|
|
||||||
userHashedIP = getHash(getIP(req) + config.globalSalt);
|
|
||||||
}
|
|
||||||
return shadowHiddenSegment.hashedIP === userHashedIP;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
chooseSegments(categorySegments).forEach(chosenSegment => {
|
|
||||||
segments.push({
|
|
||||||
category,
|
|
||||||
segment: [chosenSegment.startTime, chosenSegment.endTime],
|
|
||||||
UUID: chosenSegment.UUID,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (segments.length == 0) {
|
if (segments.length == 0) {
|
||||||
res.sendStatus(404);
|
res.sendStatus(404);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return segments;
|
return segments;
|
||||||
} catch (error) {
|
|
||||||
logger.error(error);
|
|
||||||
res.sendStatus(500);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
handleGetSegments,
|
handleGetSegments,
|
||||||
endpoint: function (req, res) {
|
cleanGetSegments,
|
||||||
let segments = handleGetSegments(req, res);
|
endpoint: function (req, res) {
|
||||||
|
let segments = handleGetSegments(req, res);
|
||||||
|
|
||||||
if (segments) {
|
if (segments) {
|
||||||
//send result
|
//send result
|
||||||
res.send(segments);
|
res.send(segments);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
37
src/routes/getSkipSegmentsByHash.js
Normal file
37
src/routes/getSkipSegmentsByHash.js
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
const hashPrefixTester = require('../utils/hashPrefixTester.js');
|
||||||
|
const getSegments = require('./getSkipSegments.js').cleanGetSegments;
|
||||||
|
|
||||||
|
const databases = require('../databases/databases.js');
|
||||||
|
const logger = require('../utils/logger.js');
|
||||||
|
const db = databases.db;
|
||||||
|
|
||||||
|
module.exports = async function (req, res) {
|
||||||
|
let hashPrefix = req.params.prefix;
|
||||||
|
if (!hashPrefixTester(req.params.prefix)) {
|
||||||
|
res.status(400).send("Hash prefix does not match format requirements."); // Exit early on faulty prefix
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const categories = req.query.categories
|
||||||
|
? JSON.parse(req.query.categories)
|
||||||
|
: req.query.category
|
||||||
|
? [req.query.category]
|
||||||
|
: ['sponsor'];
|
||||||
|
|
||||||
|
// Get all video id's that match hash prefix
|
||||||
|
const videoIds = db.prepare('all', 'SELECT DISTINCT videoId, hashedVideoID from sponsorTimes WHERE hashedVideoID LIKE ?', [hashPrefix+'%']);
|
||||||
|
if (videoIds.length === 0) {
|
||||||
|
res.sendStatus(404);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let segments = videoIds.map((video) => {
|
||||||
|
return {
|
||||||
|
videoID: video.videoID,
|
||||||
|
hash: video.hashedVideoID,
|
||||||
|
segments: getSegments(req, video.videoID, categories)
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
res.status(200).json(segments);
|
||||||
|
}
|
74
src/routes/postNoSegments.js
Normal file
74
src/routes/postNoSegments.js
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
const db = require('../databases/databases.js').db;
|
||||||
|
const getHash = require('../utils/getHash.js');
|
||||||
|
const isUserVIP = require('../utils/isUserVIP.js');
|
||||||
|
const logger = require('../utils/logger.js');
|
||||||
|
|
||||||
|
module.exports = (req, res) => {
|
||||||
|
// Collect user input data
|
||||||
|
let videoID = req.body.videoID;
|
||||||
|
let userID = req.body.userID;
|
||||||
|
let categories = req.body.categories;
|
||||||
|
|
||||||
|
// Check input data is valid
|
||||||
|
if (!videoID
|
||||||
|
|| !userID
|
||||||
|
|| !categories
|
||||||
|
|| !Array.isArray(categories)
|
||||||
|
|| categories.length === 0
|
||||||
|
) {
|
||||||
|
res.status(400).json({
|
||||||
|
message: 'Bad Format'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if user is VIP
|
||||||
|
userID = getHash(userID);
|
||||||
|
let userIsVIP = isUserVIP(userID);
|
||||||
|
|
||||||
|
if (!userIsVIP) {
|
||||||
|
res.status(403).json({
|
||||||
|
message: 'Must be a VIP to mark videos.'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get existing no segment markers
|
||||||
|
let noSegmentList = db.prepare('all', 'SELECT category from noSegments where videoID = ?', [videoID]);
|
||||||
|
if (!noSegmentList || noSegmentList.length === 0) {
|
||||||
|
noSegmentList = [];
|
||||||
|
} else {
|
||||||
|
noSegmentList = noSegmentList.map((obj) => {
|
||||||
|
return obj.category;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// get user categories not already submitted that match accepted format
|
||||||
|
let categoriesToMark = categories.filter((category) => {
|
||||||
|
return !!category.match(/^[_a-zA-Z]+$/);
|
||||||
|
}).filter((category) => {
|
||||||
|
return noSegmentList.indexOf(category) === -1;
|
||||||
|
});
|
||||||
|
|
||||||
|
// remove any duplicates
|
||||||
|
categoriesToMark = categoriesToMark.filter((category, index) => {
|
||||||
|
return categoriesToMark.indexOf(category) === index;
|
||||||
|
});
|
||||||
|
|
||||||
|
// create database entry
|
||||||
|
categoriesToMark.forEach((category) => {
|
||||||
|
try {
|
||||||
|
db.prepare('run', "INSERT INTO noSegments (videoID, userID, category) VALUES(?, ?, ?)", [videoID, userID, category]);
|
||||||
|
} catch (err) {
|
||||||
|
logger.error("Error submitting 'noSegment' marker for category '" + category + "' for video '" + videoID + "'");
|
||||||
|
logger.error(err);
|
||||||
|
res.status(500).json({
|
||||||
|
message: "Internal Server Error: Could not write marker to the database."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
submitted: categoriesToMark
|
||||||
|
});
|
||||||
|
};
|
|
@ -49,10 +49,7 @@ function sendWebhooks(userID, videoID, UUID, segmentInfo) {
|
||||||
if (config.youtubeAPIKey !== null) {
|
if (config.youtubeAPIKey !== null) {
|
||||||
let userSubmissionCountRow = db.prepare('get', "SELECT count(*) as submissionCount FROM sponsorTimes WHERE userID = ?", [userID]);
|
let userSubmissionCountRow = db.prepare('get', "SELECT count(*) as submissionCount FROM sponsorTimes WHERE userID = ?", [userID]);
|
||||||
|
|
||||||
YouTubeAPI.videos.list({
|
YouTubeAPI.listVideos(videoID, "snippet", (err, data) => {
|
||||||
part: "snippet",
|
|
||||||
id: videoID
|
|
||||||
}, function (err, data) {
|
|
||||||
if (err || data.items.length === 0) {
|
if (err || data.items.length === 0) {
|
||||||
err && logger.error(err);
|
err && logger.error(err);
|
||||||
return;
|
return;
|
||||||
|
@ -156,10 +153,7 @@ async function autoModerateSubmission(submission) {
|
||||||
// Get the video information from the youtube API
|
// Get the video information from the youtube API
|
||||||
if (config.youtubeAPIKey !== null) {
|
if (config.youtubeAPIKey !== null) {
|
||||||
let {err, data} = await new Promise((resolve, reject) => {
|
let {err, data} = await new Promise((resolve, reject) => {
|
||||||
YouTubeAPI.videos.list({
|
YouTubeAPI.listVideos(submission.videoID, "contentDetails,snippet", (err, data) => resolve({err, data}));
|
||||||
part: "contentDetails,snippet",
|
|
||||||
id: submission.videoID
|
|
||||||
}, (err, data) => resolve({err, data}));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -224,7 +218,6 @@ async function autoModerateSubmission(submission) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
logger.debug("Skipped YouTube API");
|
logger.debug("Skipped YouTube API");
|
||||||
|
|
||||||
|
@ -238,9 +231,9 @@ function proxySubmission(req) {
|
||||||
request.post(config.proxySubmission + '/api/skipSegments?userID='+req.query.userID+'&videoID='+req.query.videoID, {json: req.body}, (err, result) => {
|
request.post(config.proxySubmission + '/api/skipSegments?userID='+req.query.userID+'&videoID='+req.query.videoID, {json: req.body}, (err, result) => {
|
||||||
if (config.mode === 'development') {
|
if (config.mode === 'development') {
|
||||||
if (!err) {
|
if (!err) {
|
||||||
logger.error('Proxy Submission: ' + result.statusCode + ' ('+result.body+')');
|
logger.debug('Proxy Submission: ' + result.statusCode + ' ('+result.body+')');
|
||||||
} else {
|
} else {
|
||||||
logger.debug("Proxy Submission: Failed to make call");
|
logger.error("Proxy Submission: Failed to make call");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -277,6 +270,8 @@ module.exports = async function postSkipSegments(req, res) {
|
||||||
//hash the ip 5000 times so no one can get it from the database
|
//hash the ip 5000 times so no one can get it from the database
|
||||||
let hashedIP = getHash(getIP(req) + config.globalSalt);
|
let hashedIP = getHash(getIP(req) + config.globalSalt);
|
||||||
|
|
||||||
|
let noSegmentList = db.prepare('all', 'SELECT category from noSegments where videoID = ?', [videoID]).map((list) => { return list.category });
|
||||||
|
|
||||||
//check if this user is on the vip list
|
//check if this user is on the vip list
|
||||||
let isVIP = db.prepare("get", "SELECT count(*) as userCount FROM vipUsers WHERE userID = ?", [userID]).userCount > 0;
|
let isVIP = db.prepare("get", "SELECT count(*) as userCount FROM vipUsers WHERE userID = ?", [userID]).userCount > 0;
|
||||||
|
|
||||||
|
@ -295,6 +290,18 @@ module.exports = async function postSkipSegments(req, res) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reject segemnt if it's in the no segments list
|
||||||
|
if (noSegmentList.indexOf(segments[i].category) !== -1) {
|
||||||
|
// TODO: Do something about the fradulent submission
|
||||||
|
logger.warn("Caught a no-segment submission. userID: '" + userID + "', videoID: '" + videoID + "', category: '" + segments[i].category + "'");
|
||||||
|
res.status(403).send(
|
||||||
|
"Request rejected by auto moderator: This video has been reported as not containing any segments with the category '"
|
||||||
|
+ segments[i].category + "'. If you believe this is incorrect, contact someone on Discord."
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
let startTime = parseFloat(segments[i].segment[0]);
|
let startTime = parseFloat(segments[i].segment[0]);
|
||||||
let endTime = parseFloat(segments[i].segment[1]);
|
let endTime = parseFloat(segments[i].segment[1]);
|
||||||
|
|
||||||
|
@ -394,11 +401,13 @@ module.exports = async function postSkipSegments(req, res) {
|
||||||
segmentInfo.segment[1] + segmentInfo.category + userID, 1);
|
segmentInfo.segment[1] + segmentInfo.category + userID, 1);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
db.prepare('run', "INSERT INTO sponsorTimes " +
|
db.prepare('run', "INSERT INTO sponsorTimes " +
|
||||||
"(videoID, startTime, endTime, votes, UUID, userID, timeSubmitted, views, category, shadowHidden)" +
|
"(videoID, startTime, endTime, votes, UUID, userID, timeSubmitted, views, category, shadowHidden, hashedVideoID)" +
|
||||||
"VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", [videoID, segmentInfo.segment[0],
|
"VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", [
|
||||||
segmentInfo.segment[1], startingVotes, UUID, userID, timeSubmitted, 0, segmentInfo.category, shadowBanned]);
|
videoID, segmentInfo.segment[0], segmentInfo.segment[1], startingVotes, UUID, userID, timeSubmitted, 0, segmentInfo.category, shadowBanned, getHash(videoID, 1)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
//add to private db as well
|
//add to private db as well
|
||||||
privateDB.prepare('run', "INSERT INTO sponsorTimes VALUES(?, ?, ?)", [videoID, hashedIP, timeSubmitted]);
|
privateDB.prepare('run', "INSERT INTO sponsorTimes VALUES(?, ?, ?)", [videoID, hashedIP, timeSubmitted]);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
var fs = require('fs');
|
|
||||||
var config = require('../config.js');
|
var config = require('../config.js');
|
||||||
|
|
||||||
var getHash = require('../utils/getHash.js');
|
var getHash = require('../utils/getHash.js');
|
||||||
var getIP = require('../utils/getIP.js');
|
var getIP = require('../utils/getIP.js');
|
||||||
var getFormattedTime = require('../utils/getFormattedTime.js');
|
var getFormattedTime = require('../utils/getFormattedTime.js');
|
||||||
var isUserTrustworthy = require('../utils/isUserTrustworthy.js');
|
var isUserTrustworthy = require('../utils/isUserTrustworthy.js');
|
||||||
const {getVoteAuthor, getVoteAuthorRaw, dispatchEvent} = require('../utils/webhookUtils.js');
|
const { getVoteAuthor, getVoteAuthorRaw, dispatchEvent } = require('../utils/webhookUtils.js');
|
||||||
|
|
||||||
var databases = require('../databases/databases.js');
|
var databases = require('../databases/databases.js');
|
||||||
var db = databases.db;
|
var db = databases.db;
|
||||||
|
@ -49,10 +48,7 @@ function sendWebhooks(voteData) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.youtubeAPIKey !== null) {
|
if (config.youtubeAPIKey !== null) {
|
||||||
YouTubeAPI.videos.list({
|
YouTubeAPI.listVideos(submissionInfoRow.videoID, "snippet", (err, data) => {
|
||||||
part: "snippet",
|
|
||||||
id: submissionInfoRow.videoID
|
|
||||||
}, function (err, data) {
|
|
||||||
if (err || data.items.length === 0) {
|
if (err || data.items.length === 0) {
|
||||||
err && logger.error(err);
|
err && logger.error(err);
|
||||||
return;
|
return;
|
||||||
|
@ -375,8 +371,6 @@ async function voteOnSponsorTime(req, res) {
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
voteOnSponsorTime,
|
voteOnSponsorTime,
|
||||||
endpoint: function (req, res) {
|
endpoint: voteOnSponsorTime
|
||||||
voteOnSponsorTime(req, res);
|
};
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
10
src/utils/hashPrefixTester.js
Normal file
10
src/utils/hashPrefixTester.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
const config = require('../config.js');
|
||||||
|
|
||||||
|
const minimumPrefix = config.minimumPrefix || '3';
|
||||||
|
const maximumPrefix = config.maximumPrefix || '32'; // Half the hash.
|
||||||
|
|
||||||
|
const prefixChecker = new RegExp('^[\\da-f]{' + minimumPrefix + ',' + maximumPrefix + '}$', 'i');
|
||||||
|
|
||||||
|
module.exports = (prefix) => {
|
||||||
|
return prefixChecker.test(prefix);
|
||||||
|
};
|
8
src/utils/isUserVIP.js
Normal file
8
src/utils/isUserVIP.js
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
const databases = require('../databases/databases.js');
|
||||||
|
const db = databases.db;
|
||||||
|
|
||||||
|
module.exports = (userID) => {
|
||||||
|
return db.prepare('get', "SELECT count(*) as userCount FROM vipUsers WHERE userID = ?", [userID]).userCount > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ if (config.mode === 'development') {
|
||||||
settings.INFO = true;
|
settings.INFO = true;
|
||||||
settings.DEBUG = true;
|
settings.DEBUG = true;
|
||||||
} else if (config.mode === 'test') {
|
} else if (config.mode === 'test') {
|
||||||
settings.WARN = false;
|
settings.WARN = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function log(level, string) {
|
function log(level, string) {
|
||||||
|
|
18
src/utils/redis.js
Normal file
18
src/utils/redis.js
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
const config = require('../config.js');
|
||||||
|
const logger = require('./logger.js');
|
||||||
|
|
||||||
|
if (config.redis) {
|
||||||
|
const redis = require('redis');
|
||||||
|
logger.info('Connected to redis');
|
||||||
|
const client = redis.createClient(config.redis);
|
||||||
|
module.exports = client;
|
||||||
|
} else {
|
||||||
|
module.exports = {
|
||||||
|
get: (key, callback) => {
|
||||||
|
callback(false);
|
||||||
|
},
|
||||||
|
set: (key, value, callback) => {
|
||||||
|
callback(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -2,6 +2,8 @@ var config = require('../config.js');
|
||||||
|
|
||||||
// YouTube API
|
// YouTube API
|
||||||
const YouTubeAPI = require("youtube-api");
|
const YouTubeAPI = require("youtube-api");
|
||||||
|
const redis = require('./redis.js');
|
||||||
|
const logger = require('./logger.js');
|
||||||
|
|
||||||
var exportObject;
|
var exportObject;
|
||||||
// If in test mode, return a mocked youtube object
|
// If in test mode, return a mocked youtube object
|
||||||
|
@ -14,6 +16,41 @@ if (config.mode === "test") {
|
||||||
key: config.youtubeAPIKey
|
key: config.youtubeAPIKey
|
||||||
});
|
});
|
||||||
exportObject = YouTubeAPI;
|
exportObject = YouTubeAPI;
|
||||||
|
|
||||||
|
// YouTubeAPI.videos.list wrapper with cacheing
|
||||||
|
exportObject.listVideos = (videoID, part, callback) => {
|
||||||
|
let redisKey = "youtube.video." + videoID + "." + part;
|
||||||
|
redis.get(redisKey, (getErr, result) => {
|
||||||
|
if (getErr || !result) {
|
||||||
|
logger.debug("redis: no cache for video information: " + videoID);
|
||||||
|
YouTubeAPI.videos.list({
|
||||||
|
part,
|
||||||
|
id: videoID
|
||||||
|
}, (ytErr, data) => {
|
||||||
|
if (!ytErr) {
|
||||||
|
// Only set cache if data returned
|
||||||
|
if (data.items.length > 0) {
|
||||||
|
redis.set(redisKey, JSON.stringify(data), (setErr) => {
|
||||||
|
if(setErr) {
|
||||||
|
logger.warn(setErr);
|
||||||
|
} else {
|
||||||
|
logger.debug("redis: video information cache set for: " + videoID);
|
||||||
|
}
|
||||||
|
callback(false, data); // don't fail
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
callback(false, data); // don't fail
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
callback(ytErr, data)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
logger.debug("redis: fetched video information from cache: " + videoID);
|
||||||
|
callback(getErr, JSON.parse(result));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = exportObject;
|
module.exports = exportObject;
|
7
test.js
7
test.js
|
@ -9,6 +9,7 @@ if (fs.existsSync(config.privateDB)) fs.unlinkSync(config.privateDB);
|
||||||
|
|
||||||
var createServer = require('./src/app.js');
|
var createServer = require('./src/app.js');
|
||||||
var createMockServer = require('./test/mocks.js');
|
var createMockServer = require('./test/mocks.js');
|
||||||
|
const logger = require('./src/utils/logger.js');
|
||||||
|
|
||||||
// Instantiate a Mocha instance.
|
// Instantiate a Mocha instance.
|
||||||
var mocha = new Mocha();
|
var mocha = new Mocha();
|
||||||
|
@ -27,11 +28,11 @@ fs.readdirSync(testDir).filter(function(file) {
|
||||||
});
|
});
|
||||||
|
|
||||||
var mockServer = createMockServer(() => {
|
var mockServer = createMockServer(() => {
|
||||||
console.log("Started mock HTTP Server");
|
logger.info("Started mock HTTP Server");
|
||||||
var server = createServer(() => {
|
var server = createServer(() => {
|
||||||
console.log("Started main HTTP server");
|
logger.info("Started main HTTP server");
|
||||||
// Run the tests.
|
// Run the tests.
|
||||||
mocha.run(function(failures) {
|
mocha.run((failures) => {
|
||||||
mockServer.close();
|
mockServer.close();
|
||||||
server.close();
|
server.close();
|
||||||
process.exitCode = failures ? 1 : 0; // exit with non-zero status if there were failures
|
process.exitCode = failures ? 1 : 0; // exit with non-zero status if there were failures
|
||||||
|
|
12
test/cases/dbUpgrade.js
Normal file
12
test/cases/dbUpgrade.js
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
const databases = require('../../src/databases/databases.js');
|
||||||
|
const db = databases.db;
|
||||||
|
const privateDB = databases.privateDB;
|
||||||
|
|
||||||
|
describe('dbUpgrade', () => {
|
||||||
|
it('Should update the database version when starting the application', (done) => {
|
||||||
|
let dbVersion = db.prepare('get', 'SELECT key, value FROM config where key = ?', ['version']).value;
|
||||||
|
let privateVersion = privateDB.prepare('get', 'SELECT key, value FROM config where key = ?', ['version']).value;
|
||||||
|
if (dbVersion >= 1 && privateVersion >= 1) done();
|
||||||
|
else done('Versions are not at least 1. db is ' + dbVersion + ', private is ' + privateVersion);
|
||||||
|
});
|
||||||
|
});
|
|
@ -13,6 +13,10 @@ describe('getHash', () => {
|
||||||
assert.equal(getHash("test"), "2f327ef967ade1ebf4319163f7debbda9cc17bb0c8c834b00b30ca1cf1c256ee");
|
assert.equal(getHash("test"), "2f327ef967ade1ebf4319163f7debbda9cc17bb0c8c834b00b30ca1cf1c256ee");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it ('Should be able to output the same has the DB upgrade script will output', () => {
|
||||||
|
assert.equal(getHash("vid", 1), "1ff838dc6ca9680d88455341118157d59a055fe6d0e3870f9c002847bebe4663");
|
||||||
|
});
|
||||||
|
|
||||||
it ('Should take a variable number of passes', () => {
|
it ('Should take a variable number of passes', () => {
|
||||||
assert.equal(getHash("test", 1), "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08");
|
assert.equal(getHash("test", 1), "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08");
|
||||||
assert.equal(getHash("test", 2), "7b3d979ca8330a94fa7e9e1b466d8b99e0bcdea1ec90596c0dcc8d7ef6b4300c");
|
assert.equal(getHash("test", 2), "7b3d979ca8330a94fa7e9e1b466d8b99e0bcdea1ec90596c0dcc8d7ef6b4300c");
|
||||||
|
|
57
test/cases/getIsUserVIP.js
Normal file
57
test/cases/getIsUserVIP.js
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
var request = require('request');
|
||||||
|
var utils = require('../utils.js');
|
||||||
|
var db = require('../../src/databases/databases.js').db;
|
||||||
|
var getHash = require('../../src/utils/getHash.js');
|
||||||
|
|
||||||
|
describe('getIsUserVIP', () => {
|
||||||
|
before(() => {
|
||||||
|
db.exec("INSERT INTO vipUsers (userID) VALUES ('" + getHash("supertestman") + "')");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to get a 200', (done) => {
|
||||||
|
request.get(utils.getbaseURL()
|
||||||
|
+ "/api/isUserVIP?userID=supertestman", null,
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done("couldn't call endpoint");
|
||||||
|
else if (res.statusCode !== 200) done("non 200: " + res.statusCode);
|
||||||
|
else done(); // pass
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('Should get a 400 if no userID', (done) => {
|
||||||
|
request.get(utils.getbaseURL()
|
||||||
|
+ "/api/isUserVIP", null,
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done("couldn't call endpoint");
|
||||||
|
else if (res.statusCode !== 400) done("non 400: " + res.statusCode);
|
||||||
|
else done(); // pass
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should say a VIP is a VIP', (done) => {
|
||||||
|
request.get(utils.getbaseURL()
|
||||||
|
+ "/api/isUserVIP?userID=supertestman", null,
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done("couldn't call endpoint");
|
||||||
|
else if (res.statusCode !== 200) done("non 200: " + res.statusCode);
|
||||||
|
else {
|
||||||
|
if (JSON.parse(body).vip === true) done(); // pass
|
||||||
|
else done("Result was non-vip when should have been vip");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should say a normal user is not a VIP', (done) => {
|
||||||
|
request.get(utils.getbaseURL()
|
||||||
|
+ "/api/isUserVIP?userID=regulartestman", null,
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done("couldn't call endpoint");
|
||||||
|
else if (res.statusCode !== 200) done("non 200: " + res.statusCode);
|
||||||
|
else {
|
||||||
|
if (JSON.parse(body).vip === false) done(); // pass
|
||||||
|
else done("Result was vip when should have been non-vip");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -5,8 +5,8 @@ var getHash = require('../../src/utils/getHash.js');
|
||||||
|
|
||||||
describe('getSavedTimeForUser', () => {
|
describe('getSavedTimeForUser', () => {
|
||||||
before(() => {
|
before(() => {
|
||||||
let startOfQuery = "INSERT INTO sponsorTimes (videoID, startTime, endTime, votes, UUID, userID, timeSubmitted, views, category, shadowHidden) VALUES";
|
let startOfQuery = "INSERT INTO sponsorTimes (videoID, startTime, endTime, votes, UUID, userID, timeSubmitted, views, category, shadowHidden, hashedVideoID) VALUES";
|
||||||
db.exec(startOfQuery + "('getSavedTimeForUser', 1, 11, 2, 'abc1239999', '" + getHash("testman") + "', 0, 50, 'sponsor', 0)");
|
db.exec(startOfQuery + "('getSavedTimeForUser', 1, 11, 2, 'abc1239999', '" + getHash("testman") + "', 0, 50, 'sponsor', 0, '" + getHash('getSavedTimeForUser', 0) + "')");
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should be able to get a 200', (done) => {
|
it('Should be able to get a 200', (done) => {
|
||||||
|
|
189
test/cases/getSegmentsByHash.js
Normal file
189
test/cases/getSegmentsByHash.js
Normal file
|
@ -0,0 +1,189 @@
|
||||||
|
var request = require('request');
|
||||||
|
var db = require('../../src/databases/databases.js').db;
|
||||||
|
var utils = require('../utils.js');
|
||||||
|
var getHash = require('../../src/utils/getHash.js');
|
||||||
|
|
||||||
|
describe('getSegmentsByHash', () => {
|
||||||
|
before(() => {
|
||||||
|
let startOfQuery = "INSERT INTO sponsorTimes (videoID, startTime, endTime, votes, UUID, userID, timeSubmitted, views, category, shadowHidden, hashedVideoID) VALUES";
|
||||||
|
db.exec(startOfQuery + "('getSegmentsByHash-0', 1, 10, 2, 'getSegmentsByHash-0-0', 'testman', 0, 50, 'sponsor', 0, '" + getHash('getSegmentsByHash-0', 1) + "')"); // hash = fdaff4dee1043451faa7398324fb63d8618ebcd11bddfe0491c488db12c6c910
|
||||||
|
db.exec(startOfQuery + "('getSegmentsByHash-0', 20, 30, 2, 'getSegmentsByHash-0-1', 'testman', 100, 150, 'intro', 0, '" + getHash('getSegmentsByHash-0', 1) + "')"); // hash = fdaff4dee1043451faa7398324fb63d8618ebcd11bddfe0491c488db12c6c910
|
||||||
|
db.exec(startOfQuery + "('getSegmentsByHash-noMatchHash', 40, 50, 2, 'getSegmentsByHash-noMatchHash', 'testman', 0, 50, 'sponsor', 0, 'fdaffnoMatchHash')"); // hash = fdaff4dee1043451faa7398324fb63d8618ebcd11bddfe0491c488db12c6c910
|
||||||
|
db.exec(startOfQuery + "('getSegmentsByHash-1', 60, 70, 2, 'getSegmentsByHash-1', 'testman', 0, 50, 'sponsor', 0, '" + getHash('getSegmentsByHash-1', 1) + "')"); // hash = 3272fa85ee0927f6073ef6f07ad5f3146047c1abba794cfa364d65ab9921692b
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to get a 200', (done) => {
|
||||||
|
request.get(utils.getbaseURL()
|
||||||
|
+ '/api/skipSegments/3272f?categories=["sponsor", "intro"]', null,
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done("Couldn't call endpoint");
|
||||||
|
else if (res.statusCode !== 200) done("non 200 status code, was " + res.statusCode);
|
||||||
|
else {
|
||||||
|
done();
|
||||||
|
} // pass
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to get a 200 with empty segments for video but no matching categories', (done) => {
|
||||||
|
request.get(utils.getbaseURL()
|
||||||
|
+ '/api/skipSegments/3272f?categories=["shilling"]', null,
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done("Couldn't call endpoint");
|
||||||
|
else if (res.statusCode !== 200) done("non 200 status code, was " + res.statusCode);
|
||||||
|
else {
|
||||||
|
if (JSON.parse(body) && JSON.parse(body).length > 0 && JSON.parse(body)[0].segments.length === 0) {
|
||||||
|
done(); // pass
|
||||||
|
} else {
|
||||||
|
done("response had segments");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to get a 404 if no videos', (done) => {
|
||||||
|
request.get(utils.getbaseURL()
|
||||||
|
+ '/api/skipSegments/11111?categories=["shilling"]', null,
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done("Couldn't call endpoint");
|
||||||
|
else if (res.statusCode !== 404) done("non 404 status code, was " + res.statusCode);
|
||||||
|
else {
|
||||||
|
done(); // pass
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return 400 prefix too short', (done) => {
|
||||||
|
request.get(utils.getbaseURL()
|
||||||
|
+ '/api/skipSegments/11?categories=["shilling"]', null,
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done("Couldn't call endpoint");
|
||||||
|
else if (res.statusCode !== 400) done("non 400 status code, was " + res.statusCode);
|
||||||
|
else {
|
||||||
|
done(); // pass
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return 400 prefix too long', (done) => {
|
||||||
|
let prefix = new Array(50).join('1');
|
||||||
|
if (prefix.length <= 32) { // default value, config can change this
|
||||||
|
done('failed to generate a long enough string for the test ' + prefix.length);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
request.get(utils.getbaseURL()
|
||||||
|
+ '/api/skipSegments/'+prefix+'?categories=["shilling"]', null,
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done("Couldn't call endpoint");
|
||||||
|
else if (res.statusCode !== 400) done("non 400 status code, was " + res.statusCode);
|
||||||
|
else {
|
||||||
|
done(); // pass
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should not return 400 prefix in range', (done) => {
|
||||||
|
request.get(utils.getbaseURL()
|
||||||
|
+ '/api/skipSegments/11111?categories=["shilling"]', null,
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done("Couldn't call endpoint");
|
||||||
|
else if (res.statusCode === 400) done("prefix length 5 gave 400 " + res.statusCode);
|
||||||
|
else {
|
||||||
|
done(); // pass
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return 404 for no hash', (done) => {
|
||||||
|
request.get(utils.getbaseURL()
|
||||||
|
+ '/api/skipSegments/?categories=["shilling"]', null,
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done("Couldn't call endpoint");
|
||||||
|
else if (res.statusCode !== 404) done("expected 404, got " + res.statusCode);
|
||||||
|
else {
|
||||||
|
done(); // pass
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return 500 for bad format categories', (done) => { // should probably be 400
|
||||||
|
request.get(utils.getbaseURL()
|
||||||
|
+ '/api/skipSegments/?categories=shilling', null,
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done("Couldn't call endpoint");
|
||||||
|
else if (res.statusCode !== 500) done("expected 500 got " + res.statusCode);
|
||||||
|
else {
|
||||||
|
done(); // pass
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to get multiple videos', (done) => {
|
||||||
|
request.get(utils.getbaseURL()
|
||||||
|
+ '/api/skipSegments/fdaf?categories=["sponsor","intro"]', null,
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done("Couldn't call endpoint");
|
||||||
|
else if (res.statusCode !== 200) done("non 200 status code, was " + res.statusCode);
|
||||||
|
else {
|
||||||
|
body = JSON.parse(body);
|
||||||
|
if (body.length !== 2) done("expected 2 video, got " + body.length);
|
||||||
|
else if (body[0].segments.length !== 2) done("expected 2 segments for first video, got " + body[0].segments.length);
|
||||||
|
else if (body[1].segments.length !== 1) done("expected 1 segment for second video, got " + body[1].segments.length);
|
||||||
|
else done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to get 200 for no categories (default sponsor)', (done) => {
|
||||||
|
request.get(utils.getbaseURL()
|
||||||
|
+ '/api/skipSegments/fdaf', null,
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done("Couldn't call endpoint");
|
||||||
|
else if (res.statusCode !== 200) done("non 200 status code, was " + res.statusCode);
|
||||||
|
else {
|
||||||
|
body = JSON.parse(body);
|
||||||
|
if (body.length !== 2) done("expected 2 videos, got " + body.length);
|
||||||
|
else if (body[0].segments.length !== 1) done("expected 1 segments for first video, got " + body[0].segments.length);
|
||||||
|
else if (body[1].segments.length !== 1) done("expected 1 segments for second video, got " + body[1].segments.length);
|
||||||
|
else if (body[0].segments[0].category !== 'sponsor' || body[1].segments[0].category !== 'sponsor') done("both segments are not sponsor");
|
||||||
|
else done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to post a segment and get it using endpoint', (done) => {
|
||||||
|
let testID = 'abc123goodVideo';
|
||||||
|
request.post(utils.getbaseURL()
|
||||||
|
+ "/api/postVideoSponsorTimes", {
|
||||||
|
json: {
|
||||||
|
userID: "test",
|
||||||
|
videoID: testID,
|
||||||
|
segments: [{
|
||||||
|
segment: [13, 17],
|
||||||
|
category: "sponsor"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done('(post) ' + err);
|
||||||
|
else if (res.statusCode === 200) {
|
||||||
|
request.get(utils.getbaseURL()
|
||||||
|
+ '/api/skipSegments/'+getHash(testID, 1).substring(0,3), null,
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done("(get) Couldn't call endpoint");
|
||||||
|
else if (res.statusCode !== 200) done("(get) non 200 status code, was " + res.statusCode);
|
||||||
|
else {
|
||||||
|
body = JSON.parse(body);
|
||||||
|
if (body.length !== 1) done("(get) expected 1 video, got " + body.length);
|
||||||
|
else if (body[0].segments.length !== 1) done("(get) expected 1 segments for first video, got " + body[0].segments.length);
|
||||||
|
else if (body[0].segments[0].category !== 'sponsor') done("(get) segment should be sponsor, was "+body[0].segments[0].category);
|
||||||
|
else done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
done("(post) non 200 status code, was " + res.statusCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,31 +1,19 @@
|
||||||
var request = require('request');
|
var request = require('request');
|
||||||
var db = require('../../src/databases/databases.js').db;
|
var db = require('../../src/databases/databases.js').db;
|
||||||
var utils = require('../utils.js');
|
var utils = require('../utils.js');
|
||||||
|
var getHash = require('../../src/utils/getHash.js');
|
||||||
|
|
||||||
/*
|
|
||||||
*CREATE TABLE IF NOT EXISTS "sponsorTimes" (
|
|
||||||
"videoID" TEXT NOT NULL,
|
|
||||||
"startTime" REAL NOT NULL,
|
|
||||||
"endTime" REAL NOT NULL,
|
|
||||||
"votes" INTEGER NOT NULL,
|
|
||||||
"UUID" TEXT NOT NULL UNIQUE,
|
|
||||||
"userID" TEXT NOT NULL,
|
|
||||||
"timeSubmitted" INTEGER NOT NULL,
|
|
||||||
"views" INTEGER NOT NULL,
|
|
||||||
"shadowHidden" INTEGER NOT NULL
|
|
||||||
);
|
|
||||||
*/
|
|
||||||
|
|
||||||
describe('getSkipSegments', () => {
|
describe('getSkipSegments', () => {
|
||||||
before(() => {
|
before(() => {
|
||||||
let startOfQuery = "INSERT INTO sponsorTimes (videoID, startTime, endTime, votes, UUID, userID, timeSubmitted, views, category, shadowHidden) VALUES";
|
let startOfQuery = "INSERT INTO sponsorTimes (videoID, startTime, endTime, votes, UUID, userID, timeSubmitted, views, category, shadowHidden, hashedVideoID) VALUES";
|
||||||
db.exec(startOfQuery + "('testtesttest', 1, 11, 2, '1-uuid-0', 'testman', 0, 50, 'sponsor', 0)");
|
db.exec(startOfQuery + "('testtesttest', 1, 11, 2, '1-uuid-0', 'testman', 0, 50, 'sponsor', 0, '" + getHash('testtesttest', 0) + "')");
|
||||||
db.exec(startOfQuery + "('testtesttest', 20, 33, 2, '1-uuid-2', 'testman', 0, 50, 'intro', 0)");
|
db.exec(startOfQuery + "('testtesttest', 20, 33, 2, '1-uuid-2', 'testman', 0, 50, 'intro', 0, '" + getHash('testtesttest', 0) + "')");
|
||||||
db.exec(startOfQuery + "('testtesttest,test', 1, 11, 2, '1-uuid-1', 'testman', 0, 50, 'sponsor', 0)");
|
db.exec(startOfQuery + "('testtesttest,test', 1, 11, 2, '1-uuid-1', 'testman', 0, 50, 'sponsor', 0, '" + getHash('testtesttest,test', 0) + "')");
|
||||||
db.exec(startOfQuery + "('test3', 1, 11, 2, '1-uuid-4', 'testman', 0, 50, 'sponsor', 0)");
|
db.exec(startOfQuery + "('test3', 1, 11, 2, '1-uuid-4', 'testman', 0, 50, 'sponsor', 0, '" + getHash('test3', 0) + "')");
|
||||||
db.exec(startOfQuery + "('test3', 7, 22, -3, '1-uuid-5', 'testman', 0, 50, 'sponsor', 0)");
|
db.exec(startOfQuery + "('test3', 7, 22, -3, '1-uuid-5', 'testman', 0, 50, 'sponsor', 0, '" + getHash('test3', 0) + "')");
|
||||||
db.exec(startOfQuery + "('multiple', 1, 11, 2, '1-uuid-6', 'testman', 0, 50, 'intro', 0)");
|
db.exec(startOfQuery + "('multiple', 1, 11, 2, '1-uuid-6', 'testman', 0, 50, 'intro', 0, '" + getHash('multiple', 0) + "')");
|
||||||
db.exec(startOfQuery + "('multiple', 20, 33, 2, '1-uuid-7', 'testman', 0, 50, 'intro', 0)");
|
db.exec(startOfQuery + "('multiple', 20, 33, 2, '1-uuid-7', 'testman', 0, 50, 'intro', 0, '" + getHash('multiple', 0) + "')");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
408
test/cases/noSegmentRecords.js
Normal file
408
test/cases/noSegmentRecords.js
Normal file
|
@ -0,0 +1,408 @@
|
||||||
|
var request = require('request');
|
||||||
|
|
||||||
|
var utils = require('../utils.js');
|
||||||
|
const getHash = require('../../src/utils/getHash.js');
|
||||||
|
|
||||||
|
var databases = require('../../src/databases/databases.js');
|
||||||
|
const logger = require('../../src/utils/logger.js');
|
||||||
|
var db = databases.db;
|
||||||
|
|
||||||
|
describe('noSegmentRecords', () => {
|
||||||
|
before(() => {
|
||||||
|
db.exec("INSERT INTO vipUsers (userID) VALUES ('" + getHash("VIPUser-noSegments") + "')");
|
||||||
|
|
||||||
|
db.exec("INSERT INTO noSegments (userID, videoID, category) VALUES ('" + getHash("VIPUser-noSegments") + "', 'no-segments-video-id', 'sponsor')");
|
||||||
|
db.exec("INSERT INTO noSegments (userID, videoID, category) VALUES ('" + getHash("VIPUser-noSegments") + "', 'no-segments-video-id', 'intro')");
|
||||||
|
|
||||||
|
db.exec("INSERT INTO noSegments (userID, videoID, category) VALUES ('" + getHash("VIPUser-noSegments") + "', 'no-segments-video-id-1', 'sponsor')");
|
||||||
|
db.exec("INSERT INTO noSegments (userID, videoID, category) VALUES ('" + getHash("VIPUser-noSegments") + "', 'no-segments-video-id-1', 'intro')");
|
||||||
|
db.exec("INSERT INTO noSegments (userID, videoID, category) VALUES ('" + getHash("VIPUser-noSegments") + "', 'noSubmitVideo', 'sponsor')");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should update the database version when starting the application', (done) => {
|
||||||
|
let version = db.prepare('get', 'SELECT key, value FROM config where key = ?', ['version']).value;
|
||||||
|
if (version > 1) done();
|
||||||
|
else done('Version isn\'t greater than 1. Version is ' + version);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to submit categories not in video (http response)', (done) => {
|
||||||
|
let json = {
|
||||||
|
videoID: 'no-segments-video-id',
|
||||||
|
userID: 'VIPUser-noSegments',
|
||||||
|
categories: [
|
||||||
|
'outro',
|
||||||
|
'shilling',
|
||||||
|
'shilling',
|
||||||
|
'shil ling',
|
||||||
|
'',
|
||||||
|
'intro'
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
let expected = {
|
||||||
|
submitted: [
|
||||||
|
'outro',
|
||||||
|
'shilling'
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
request.post(utils.getbaseURL()
|
||||||
|
+ "/api/noSegments", {json},
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done(err);
|
||||||
|
else if (res.statusCode === 200) {
|
||||||
|
if (JSON.stringify(body) === JSON.stringify(expected)) {
|
||||||
|
done();
|
||||||
|
} else {
|
||||||
|
done("Incorrect response: expected " + JSON.stringify(expected) + " got " + JSON.stringify(body));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log(body);
|
||||||
|
done("Status code was " + res.statusCode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to submit categories not in video (sql check)', (done) => {
|
||||||
|
let json = {
|
||||||
|
videoID: 'no-segments-video-id-1',
|
||||||
|
userID: 'VIPUser-noSegments',
|
||||||
|
categories: [
|
||||||
|
'outro',
|
||||||
|
'shilling',
|
||||||
|
'shilling',
|
||||||
|
'shil ling',
|
||||||
|
'',
|
||||||
|
'intro'
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
request.post(utils.getbaseURL()
|
||||||
|
+ "/api/noSegments", {json},
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done(err);
|
||||||
|
else if (res.statusCode === 200) {
|
||||||
|
let result = db.prepare('all', 'SELECT * FROM noSegments WHERE videoID = ?', ['no-segments-video-id-1']);
|
||||||
|
if (result.length !== 4) {
|
||||||
|
console.log(result);
|
||||||
|
done("Expected 4 entrys in db, got " + result.length);
|
||||||
|
} else {
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log(body);
|
||||||
|
done("Status code was " + res.statusCode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to submit categories with _ in the category', (done) => {
|
||||||
|
let json = {
|
||||||
|
videoID: 'underscore',
|
||||||
|
userID: 'VIPUser-noSegments',
|
||||||
|
categories: [
|
||||||
|
'word_word',
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
request.post(utils.getbaseURL()
|
||||||
|
+ "/api/noSegments", {json},
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done(err);
|
||||||
|
else if (res.statusCode === 200) {
|
||||||
|
let result = db.prepare('all', 'SELECT * FROM noSegments WHERE videoID = ?', ['underscore']);
|
||||||
|
if (result.length !== 1) {
|
||||||
|
console.log(result);
|
||||||
|
done("Expected 1 entrys in db, got " + result.length);
|
||||||
|
} else {
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log(body);
|
||||||
|
done("Status code was " + res.statusCode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to submit categories with upper and lower case in the category', (done) => {
|
||||||
|
let json = {
|
||||||
|
videoID: 'bothCases',
|
||||||
|
userID: 'VIPUser-noSegments',
|
||||||
|
categories: [
|
||||||
|
'wordWord',
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
request.post(utils.getbaseURL()
|
||||||
|
+ "/api/noSegments", {json},
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done(err);
|
||||||
|
else if (res.statusCode === 200) {
|
||||||
|
let result = db.prepare('all', 'SELECT * FROM noSegments WHERE videoID = ?', ['bothCases']);
|
||||||
|
if (result.length !== 1) {
|
||||||
|
console.log(result);
|
||||||
|
done("Expected 1 entrys in db, got " + result.length);
|
||||||
|
} else {
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log(body);
|
||||||
|
done("Status code was " + res.statusCode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should not be able to submit categories with $ in the category', (done) => {
|
||||||
|
let json = {
|
||||||
|
videoID: 'specialChar',
|
||||||
|
userID: 'VIPUser-noSegments',
|
||||||
|
categories: [
|
||||||
|
'word&word',
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
request.post(utils.getbaseURL()
|
||||||
|
+ "/api/noSegments", {json},
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done(err);
|
||||||
|
else if (res.statusCode === 200) {
|
||||||
|
let result = db.prepare('all', 'SELECT * FROM noSegments WHERE videoID = ?', ['specialChar']);
|
||||||
|
if (result.length !== 0) {
|
||||||
|
console.log(result);
|
||||||
|
done("Expected 0 entrys in db, got " + result.length);
|
||||||
|
} else {
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log(body);
|
||||||
|
done("Status code was " + res.statusCode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return 400 for missing params', (done) => {
|
||||||
|
request.post(utils.getbaseURL()
|
||||||
|
+ "/api/noSegments", {json: {}},
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done(err);
|
||||||
|
else if (res.statusCode === 400) {
|
||||||
|
done()
|
||||||
|
} else {
|
||||||
|
done("Status code was " + res.statusCode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return 400 for no categories', (done) => {
|
||||||
|
let json = {
|
||||||
|
videoID: 'test',
|
||||||
|
userID: 'test',
|
||||||
|
categories: []
|
||||||
|
};
|
||||||
|
|
||||||
|
request.post(utils.getbaseURL()
|
||||||
|
+ "/api/noSegments", {json},
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done(err);
|
||||||
|
else if (res.statusCode === 400) {
|
||||||
|
done()
|
||||||
|
} else {
|
||||||
|
done("Status code was " + res.statusCode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return 400 for no userID', (done) => {
|
||||||
|
let json = {
|
||||||
|
videoID: 'test',
|
||||||
|
userID: null,
|
||||||
|
categories: ['sponsor']
|
||||||
|
};
|
||||||
|
|
||||||
|
request.post(utils.getbaseURL()
|
||||||
|
+ "/api/noSegments", {json},
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done(err);
|
||||||
|
else if (res.statusCode === 400) {
|
||||||
|
done()
|
||||||
|
} else {
|
||||||
|
done("Status code was " + res.statusCode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return 400 for no videoID', (done) => {
|
||||||
|
let json = {
|
||||||
|
videoID: null,
|
||||||
|
userID: 'test',
|
||||||
|
categories: ['sponsor']
|
||||||
|
};
|
||||||
|
|
||||||
|
request.post(utils.getbaseURL()
|
||||||
|
+ "/api/noSegments", {json},
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done(err);
|
||||||
|
else if (res.statusCode === 400) {
|
||||||
|
done()
|
||||||
|
} else {
|
||||||
|
done("Status code was " + res.statusCode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return 400 object categories)', (done) => {
|
||||||
|
let json = {
|
||||||
|
videoID: 'test',
|
||||||
|
userID: 'test',
|
||||||
|
categories: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
request.post(utils.getbaseURL()
|
||||||
|
+ "/api/noSegments", {json},
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done(err);
|
||||||
|
else if (res.statusCode === 400) {
|
||||||
|
done()
|
||||||
|
} else {
|
||||||
|
done("Status code was " + res.statusCode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return 400 bad format categories', (done) => {
|
||||||
|
let json = {
|
||||||
|
videoID: 'test',
|
||||||
|
userID: 'test',
|
||||||
|
categories: 'sponsor'
|
||||||
|
};
|
||||||
|
|
||||||
|
request.post(utils.getbaseURL()
|
||||||
|
+ "/api/noSegments", {json},
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done(err);
|
||||||
|
else if (res.statusCode === 400) {
|
||||||
|
done()
|
||||||
|
} else {
|
||||||
|
done("Status code was " + res.statusCode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return 403 if user is not VIP', (done) => {
|
||||||
|
let json = {
|
||||||
|
videoID: 'test',
|
||||||
|
userID: 'test',
|
||||||
|
categories: [
|
||||||
|
'sponsor'
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
request.post(utils.getbaseURL()
|
||||||
|
+ "/api/noSegments", {json},
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done(err);
|
||||||
|
else if (res.statusCode === 403) {
|
||||||
|
done();
|
||||||
|
} else {
|
||||||
|
done("Status code was " + res.statusCode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Submission tests in this file do not check database records, only status codes.
|
||||||
|
* To test the submission code properly see ./test/cases/postSkipSegments.js
|
||||||
|
*/
|
||||||
|
|
||||||
|
it('Should not be able to submit a segment to a video with a no-segment record (single submission)', (done) => {
|
||||||
|
request.post(utils.getbaseURL()
|
||||||
|
+ "/api/postVideoSponsorTimes", {
|
||||||
|
json: {
|
||||||
|
userID: "testman42",
|
||||||
|
videoID: "noSubmitVideo",
|
||||||
|
segments: [{
|
||||||
|
segment: [20, 40],
|
||||||
|
category: "sponsor"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done(err);
|
||||||
|
else if (res.statusCode === 403) {
|
||||||
|
done()
|
||||||
|
} else {
|
||||||
|
done("Status code was " + res.statusCode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should not be able to submit segments to a video where any of the submissions with a no-segment record', (done) => {
|
||||||
|
request.post(utils.getbaseURL()
|
||||||
|
+ "/api/postVideoSponsorTimes", {
|
||||||
|
json: {
|
||||||
|
userID: "testman42",
|
||||||
|
videoID: "noSubmitVideo",
|
||||||
|
segments: [{
|
||||||
|
segment: [20, 40],
|
||||||
|
category: "sponsor"
|
||||||
|
},{
|
||||||
|
segment: [50, 60],
|
||||||
|
category: "intro"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done(err);
|
||||||
|
else if (res.statusCode === 403) {
|
||||||
|
done()
|
||||||
|
} else {
|
||||||
|
done("Status code was " + res.statusCode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('Should be able to submit a segment to a video with a different no-segment record', (done) => {
|
||||||
|
request.post(utils.getbaseURL()
|
||||||
|
+ "/api/postVideoSponsorTimes", {
|
||||||
|
json: {
|
||||||
|
userID: "testman42",
|
||||||
|
videoID: "noSubmitVideo",
|
||||||
|
segments: [{
|
||||||
|
segment: [20, 40],
|
||||||
|
category: "intro"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done(err);
|
||||||
|
else if (res.statusCode === 200) {
|
||||||
|
done()
|
||||||
|
} else {
|
||||||
|
done("Status code was " + res.statusCode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to submit a segment to a video with no no-segment records', (done) => {
|
||||||
|
request.post(utils.getbaseURL()
|
||||||
|
+ "/api/postVideoSponsorTimes", {
|
||||||
|
json: {
|
||||||
|
userID: "testman42",
|
||||||
|
videoID: "normalVideo",
|
||||||
|
segments: [{
|
||||||
|
segment: [20, 40],
|
||||||
|
category: "intro"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(err, res, body) => {
|
||||||
|
if (err) done(err);
|
||||||
|
else if (res.statusCode === 200) {
|
||||||
|
done()
|
||||||
|
} else {
|
||||||
|
done("Status code was " + res.statusCode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,6 +1,7 @@
|
||||||
var request = require('request');
|
var request = require('request');
|
||||||
var db = require('../../src/databases/databases.js').db;
|
var db = require('../../src/databases/databases.js').db;
|
||||||
var utils = require('../utils.js');
|
var utils = require('../utils.js');
|
||||||
|
var getHash = require('../../src/utils/getHash.js');
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -19,9 +20,9 @@ var utils = require('../utils.js');
|
||||||
|
|
||||||
describe('getVideoSponsorTime (Old get method)', () => {
|
describe('getVideoSponsorTime (Old get method)', () => {
|
||||||
before(() => {
|
before(() => {
|
||||||
let startOfQuery = "INSERT INTO sponsorTimes (videoID, startTime, endTime, votes, UUID, userID, timeSubmitted, views, category, shadowHidden) VALUES";
|
let startOfQuery = "INSERT INTO sponsorTimes (videoID, startTime, endTime, votes, UUID, userID, timeSubmitted, views, category, shadowHidden, hashedVideoID) VALUES";
|
||||||
db.exec(startOfQuery + "('old-testtesttest', 1, 11, 2, 'uuid-0', 'testman', 0, 50, 'sponsor', 0)");
|
db.exec(startOfQuery + "('old-testtesttest', 1, 11, 2, 'uuid-0', 'testman', 0, 50, 'sponsor', 0, '" + getHash('old-testtesttest', 1) + "')");
|
||||||
db.exec(startOfQuery + "('old-testtesttest,test', 1, 11, 2, 'uuid-1', 'testman', 0, 50, 'sponsor', 0)");
|
db.exec(startOfQuery + "('old-testtesttest,test', 1, 11, 2, 'uuid-1', 'testman', 0, 50, 'sponsor', 0, '" + getHash('old-testtesttest,test', 1) + "')");
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should be able to get a time', (done) => {
|
it('Should be able to get a time', (done) => {
|
||||||
|
|
|
@ -5,25 +5,26 @@ const getHash = require('../../src/utils/getHash.js');
|
||||||
|
|
||||||
describe('voteOnSponsorTime', () => {
|
describe('voteOnSponsorTime', () => {
|
||||||
before(() => {
|
before(() => {
|
||||||
let startOfQuery = "INSERT INTO sponsorTimes (videoID, startTime, endTime, votes, UUID, userID, timeSubmitted, views, category, shadowHidden) VALUES";
|
let startOfQuery = "INSERT INTO sponsorTimes (videoID, startTime, endTime, votes, UUID, userID, timeSubmitted, views, category, shadowHidden, hashedVideoID) VALUES";
|
||||||
db.exec(startOfQuery + "('vote-testtesttest', 1, 11, 2, 'vote-uuid-0', 'testman', 0, 50, 'sponsor', 0)");
|
|
||||||
db.exec(startOfQuery + "('vote-testtesttest2', 1, 11, 2, 'vote-uuid-1', 'testman', 0, 50, 'sponsor', 0)");
|
db.exec(startOfQuery + "('vote-testtesttest', 1, 11, 2, 'vote-uuid-0', 'testman', 0, 50, 'sponsor', 0, '" + getHash('vote-testtesttest', 1) + "')");
|
||||||
db.exec(startOfQuery + "('vote-testtesttest2', 1, 11, 10, 'vote-uuid-1.5', 'testman', 0, 50, 'outro', 0)");
|
db.exec(startOfQuery + "('vote-testtesttest2', 1, 11, 2, 'vote-uuid-1', 'testman', 0, 50, 'sponsor', 0, '" + getHash('vote-testtesttest2', 1) + "')");
|
||||||
db.exec(startOfQuery + "('vote-testtesttest2', 1, 11, 10, 'vote-uuid-1.6', 'testman', 0, 50, 'interaction', 0)");
|
db.exec(startOfQuery + "('vote-testtesttest2', 1, 11, 10, 'vote-uuid-1.5', 'testman', 0, 50, 'outro', 0, '" + getHash('vote-testtesttest2', 1) + "')");
|
||||||
db.exec(startOfQuery + "('vote-testtesttest3', 20, 33, 10, 'vote-uuid-2', 'testman', 0, 50, 'intro', 0)");
|
db.exec(startOfQuery + "('vote-testtesttest2', 1, 11, 10, 'vote-uuid-1.6', 'testman', 0, 50, 'interaction', 0, '" + getHash('vote-testtesttest2', 1) + "')");
|
||||||
db.exec(startOfQuery + "('vote-testtesttest,test', 1, 11, 100, 'vote-uuid-3', 'testman', 0, 50, 'sponsor', 0)");
|
db.exec(startOfQuery + "('vote-testtesttest3', 20, 33, 10, 'vote-uuid-2', 'testman', 0, 50, 'intro', 0, '" + getHash('vote-testtesttest3', 1) + "')");
|
||||||
db.exec(startOfQuery + "('vote-test3', 1, 11, 2, 'vote-uuid-4', 'testman', 0, 50, 'sponsor', 0)");
|
db.exec(startOfQuery + "('vote-testtesttest,test', 1, 11, 100, 'vote-uuid-3', 'testman', 0, 50, 'sponsor', 0, '" + getHash('vote-testtesttest,test', 1) + "')");
|
||||||
db.exec(startOfQuery + "('vote-test3', 7, 22, -3, 'vote-uuid-5', 'testman', 0, 50, 'intro', 0)");
|
db.exec(startOfQuery + "('vote-test3', 1, 11, 2, 'vote-uuid-4', 'testman', 0, 50, 'sponsor', 0, '" + getHash('vote-test3', 1) + "')");
|
||||||
db.exec(startOfQuery + "('vote-multiple', 1, 11, 2, 'vote-uuid-6', 'testman', 0, 50, 'intro', 0)");
|
db.exec(startOfQuery + "('vote-test3', 7, 22, -3, 'vote-uuid-5', 'testman', 0, 50, 'intro', 0, '" + getHash('vote-test3', 1) + "')");
|
||||||
db.exec(startOfQuery + "('vote-multiple', 20, 33, 2, 'vote-uuid-7', 'testman', 0, 50, 'intro', 0)");
|
db.exec(startOfQuery + "('vote-multiple', 1, 11, 2, 'vote-uuid-6', 'testman', 0, 50, 'intro', 0, '" + getHash('vote-multiple', 1) + "')");
|
||||||
db.exec(startOfQuery + "('voter-submitter', 1, 11, 2, 'vote-uuid-8', '" + getHash("randomID") + "', 0, 50, 'sponsor', 0)");
|
db.exec(startOfQuery + "('vote-multiple', 20, 33, 2, 'vote-uuid-7', 'testman', 0, 50, 'intro', 0, '" + getHash('vote-multiple', 1) + "')");
|
||||||
db.exec(startOfQuery + "('voter-submitter2', 1, 11, 2, 'vote-uuid-9', '" + getHash("randomID2") + "', 0, 50, 'sponsor', 0)");
|
db.exec(startOfQuery + "('voter-submitter', 1, 11, 2, 'vote-uuid-8', '" + getHash("randomID") + "', 0, 50, 'sponsor', 0, '" + getHash('voter-submitter', 1) + "')");
|
||||||
db.exec(startOfQuery + "('voter-submitter2', 1, 11, 2, 'vote-uuid-10', '" + getHash("randomID3") + "', 0, 50, 'sponsor', 0)");
|
db.exec(startOfQuery + "('voter-submitter2', 1, 11, 2, 'vote-uuid-9', '" + getHash("randomID2") + "', 0, 50, 'sponsor', 0, '" + getHash('voter-submitter2', 1) + "')");
|
||||||
db.exec(startOfQuery + "('voter-submitter2', 1, 11, 2, 'vote-uuid-11', '" + getHash("randomID4") + "', 0, 50, 'sponsor', 0)");
|
db.exec(startOfQuery + "('voter-submitter2', 1, 11, 2, 'vote-uuid-10', '" + getHash("randomID3") + "', 0, 50, 'sponsor', 0, '" + getHash('voter-submitter2', 1) + "')");
|
||||||
db.exec(startOfQuery + "('own-submission-video', 1, 11, 500, 'own-submission-uuid', '"+ getHash('own-submission-id') +"', 0, 50, 'sponsor', 0)");
|
db.exec(startOfQuery + "('voter-submitter2', 1, 11, 2, 'vote-uuid-11', '" + getHash("randomID4") + "', 0, 50, 'sponsor', 0, '" + getHash('voter-submitter2', 1) + "')");
|
||||||
db.exec(startOfQuery + "('not-own-submission-video', 1, 11, 500, 'not-own-submission-uuid', '"+ getHash('somebody-else-id') +"', 0, 50, 'sponsor', 0)");
|
db.exec(startOfQuery + "('own-submission-video', 1, 11, 500, 'own-submission-uuid', '"+ getHash('own-submission-id') +"', 0, 50, 'sponsor', 0, '" + getHash('own-submission-video', 1) + "')");
|
||||||
db.exec(startOfQuery + "('incorrect-category', 1, 11, 500, 'incorrect-category', '"+ getHash('somebody-else-id') +"', 0, 50, 'sponsor', 0)");
|
db.exec(startOfQuery + "('not-own-submission-video', 1, 11, 500, 'not-own-submission-uuid', '"+ getHash('somebody-else-id') +"', 0, 50, 'sponsor', 0, '" + getHash('not-own-submission-video', 1) + "')");
|
||||||
db.exec(startOfQuery + "('incorrect-category-change', 1, 11, 500, 'incorrect-category-change', '"+ getHash('somebody-else-id') +"', 0, 50, 'sponsor', 0)");
|
db.exec(startOfQuery + "('incorrect-category', 1, 11, 500, 'incorrect-category', '"+ getHash('somebody-else-id') +"', 0, 50, 'sponsor', 0, '" + getHash('incorrect-category', 1) + "')");
|
||||||
|
db.exec(startOfQuery + "('incorrect-category-change', 1, 11, 500, 'incorrect-category-change', '"+ getHash('somebody-else-id') +"', 0, 50, 'sponsor', 0, '" + getHash('incorrect-category-change', 1) + "')");
|
||||||
|
|
||||||
db.exec("INSERT INTO vipUsers (userID) VALUES ('" + getHash("VIPUser") + "')");
|
db.exec("INSERT INTO vipUsers (userID) VALUES ('" + getHash("VIPUser") + "')");
|
||||||
privateDB.exec("INSERT INTO shadowBannedUsers (userID) VALUES ('" + getHash("randomID4") + "')");
|
privateDB.exec("INSERT INTO shadowBannedUsers (userID) VALUES ('" + getHash("randomID4") + "')");
|
||||||
|
|
|
@ -8,6 +8,12 @@ YouTubeAPI.videos.list({
|
||||||
// https://developers.google.com/youtube/v3/docs/videos
|
// https://developers.google.com/youtube/v3/docs/videos
|
||||||
|
|
||||||
const YouTubeAPI = {
|
const YouTubeAPI = {
|
||||||
|
listVideos: (id, part, callback) => {
|
||||||
|
YouTubeAPI.videos.list({
|
||||||
|
part: part,
|
||||||
|
id: id
|
||||||
|
}, callback);
|
||||||
|
},
|
||||||
videos: {
|
videos: {
|
||||||
list: (obj, callback) => {
|
list: (obj, callback) => {
|
||||||
if (obj.id === "knownWrongID") {
|
if (obj.id === "knownWrongID") {
|
||||||
|
|
Loading…
Reference in a new issue