Merge pull request #459 from Joe-Dowd/hash-prefix

Added hash prefix implementation (server code not yet merged)
This commit is contained in:
Ajay Ramachandran 2020-09-16 13:53:53 -04:00 committed by GitHub
commit b4e1cb0cfd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 121 additions and 21 deletions

5
package-lock.json generated
View file

@ -10494,6 +10494,11 @@
"traverse": "0.4.x" "traverse": "0.4.x"
} }
}, },
"js-sha256": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz",
"integrity": "sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA=="
},
"js-tokens": { "js-tokens": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",

View file

@ -11,6 +11,7 @@
"babel-loader": "^8.0.6", "babel-loader": "^8.0.6",
"babel-preset-env": "^1.7.0", "babel-preset-env": "^1.7.0",
"concurrently": "^5.1.0", "concurrently": "^5.1.0",
"js-sha256": "^0.9.0",
"react": "^16.12.0", "react": "^16.12.0",
"react-dom": "^16.12.0" "react-dom": "^16.12.0"
}, },

View file

@ -202,6 +202,18 @@
"whatViewTracking": { "whatViewTracking": {
"message": "This feature tracks which segments you have skipped to let users know how much their submission has helped others and used as a metric along with upvotes to ensure that spam doesn't get into the database. The extension sends a message to the server each time you skip a segment. Hopefully most people don't change this setting so that the view numbers are accurate. :)" "message": "This feature tracks which segments you have skipped to let users know how much their submission has helped others and used as a metric along with upvotes to ensure that spam doesn't get into the database. The extension sends a message to the server each time you skip a segment. Hopefully most people don't change this setting so that the view numbers are accurate. :)"
}, },
"enableQueryByHashPrefix": {
"message": "Query By Hash Prefix"
},
"whatQueryByHashPrefix": {
"message": "Instead of requesting segments from the server using the videoID, the first 4 characters of the hash of the videoID are sent. This server will send back data for all videos with similar hashes."
},
"enableRefetchWhenNotFound": {
"message": "Refetch Segments On New Videos"
},
"whatRefetchWhenNotFound": {
"message": "If the video is new, and there are no segments found, it will keep refetching every few minutes while you watch."
},
"showNotice": { "showNotice": {
"message": "Show Notice Again" "message": "Show Notice Again"
}, },

View file

@ -305,6 +305,40 @@
<br/> <br/>
<br/> <br/>
<div option-type="toggle" sync-option="hashPrefix">
<label class="switch-container" label-name="__MSG_enableQueryByHashPrefix__">
<label class="switch">
<input type="checkbox" checked>
<span class="slider round"></span>
</label>
</label>
<br/>
<br/>
<div class="small-description">__MSG_whatQueryByHashPrefix__</div>
</div>
<br/>
<br/>
<div option-type="toggle" sync-option="refetchWhenNotFound">
<label class="switch-container" label-name="__MSG_enableRefetchWhenNotFound__">
<label class="switch">
<input type="checkbox" checked>
<span class="slider round"></span>
</label>
</label>
<br/>
<br/>
<div class="small-description">__MSG_whatRefetchWhenNotFound__</div>
</div>
<br/>
<br/>
<div option-type="toggle" sync-option="checkForUnlistedVideos"> <div option-type="toggle" sync-option="checkForUnlistedVideos">
<label class="switch-container" label-name="__MSG_unlistedCheck__"> <label class="switch-container" label-name="__MSG_unlistedCheck__">
<label class="switch"> <label class="switch">

View file

@ -6,7 +6,6 @@ const utils = new Utils();
interface SBConfig { interface SBConfig {
userID: string, userID: string,
// sponsorTimes: SBMap<string, SponsorTime[]>,
segmentTimes: SBMap<string, SponsorTime[]>, segmentTimes: SBMap<string, SponsorTime[]>,
defaultCategory: string, defaultCategory: string,
whitelistedChannels: string[], whitelistedChannels: string[],
@ -35,6 +34,8 @@ interface SBConfig {
audioNotificationOnSkip, audioNotificationOnSkip,
checkForUnlistedVideos: boolean, checkForUnlistedVideos: boolean,
testingServer: boolean, testingServer: boolean,
hashPrefix: boolean,
refetchWhenNotFound: boolean,
// What categories should be skipped // What categories should be skipped
categorySelections: CategorySelection[], categorySelections: CategorySelection[],
@ -166,6 +167,8 @@ var Config: SBObject = {
audioNotificationOnSkip: false, audioNotificationOnSkip: false,
checkForUnlistedVideos: false, checkForUnlistedVideos: false,
testingServer: false, testingServer: false,
hashPrefix: false,
refetchWhenNotFound: true,
categorySelections: [{ categorySelections: [{
name: "sponsor", name: "sponsor",

View file

@ -618,12 +618,36 @@ function sponsorsLookup(id: string) {
categories.push(categorySelection.name); categories.push(categorySelection.name);
} }
utils.asyncRequestToServer('GET', "/api/skipSegments", { // Check for hashPrefix setting
let getRequest;
if (Config.config.hashPrefix) {
getRequest = utils.asyncRequestToServer('GET', "/api/skipSegments/" + utils.getHash(id, 1).substr(0,4), {
categories
});
} else {
getRequest = utils.asyncRequestToServer('GET', "/api/skipSegments", {
videoID: id, videoID: id,
categories categories
}).then(async (response: FetchResponse) => { });
}
getRequest.then(async (response: FetchResponse) => {
if (response?.ok) { if (response?.ok) {
let recievedSegments: SponsorTime[] = JSON.parse(response.responseText); let result = JSON.parse(response.responseText);
if (Config.config.hashPrefix) {
result = result.filter((video) => video.videoID === id);
if (result.length > 0) {
result = result[0].segments;
if (result.length === 0) { // return if no segments found
retryFetch(id);
return;
}
} else { // return if no video found
retryFetch(id);
return;
}
}
let recievedSegments: SponsorTime[] = result;
if (!recievedSegments.length) { if (!recievedSegments.length) {
console.error("[SponsorBlock] Server returned malformed response: " + JSON.stringify(recievedSegments)); console.error("[SponsorBlock] Server returned malformed response: " + JSON.stringify(recievedSegments));
return; return;
@ -667,6 +691,22 @@ function sponsorsLookup(id: string) {
sponsorLookupRetries = 0; sponsorLookupRetries = 0;
} else if (response?.status === 404) { } else if (response?.status === 404) {
retryFetch(id);
} else if (sponsorLookupRetries < 90 && !recheckStarted) {
recheckStarted = true;
//TODO lower when server becomes better (back to 1 second)
//some error occurred, try again in a second
setTimeout(() => sponsorsLookup(id), 10000 + Math.random() * 30000);
sponsorLookupRetries++;
}
});
}
function retryFetch(id: string): void {
if (!Config.config.refetchWhenNotFound) return;
sponsorDataFound = false; sponsorDataFound = false;
//check if this video was uploaded recently //check if this video was uploaded recently
@ -676,21 +716,11 @@ function sponsorsLookup(id: string) {
//if less than 3 days old //if less than 3 days old
if (Date.now() - new Date(dateUploaded).getTime() < 259200000) { if (Date.now() - new Date(dateUploaded).getTime() < 259200000) {
//TODO lower when server becomes better //TODO lower when server becomes better
setTimeout(() => sponsorsLookup(id), 180000); setTimeout(() => sponsorsLookup(id), 120000);
} }
}); });
sponsorLookupRetries = 0; sponsorLookupRetries = 0;
} else if (sponsorLookupRetries < 90 && !recheckStarted) {
recheckStarted = true;
//TODO lower when server becomes better (back to 1 second)
//some error occurred, try again in a second
setTimeout(() => sponsorsLookup(id), 10000);
sponsorLookupRetries++;
}
});
} }
/** /**

View file

@ -1,5 +1,6 @@
import Config from "./config"; import Config from "./config";
import { CategorySelection, SponsorTime, FetchResponse } from "./types"; import { CategorySelection, SponsorTime, FetchResponse } from "./types";
import { sha256 } from 'js-sha256';
import * as CompileConfig from "../config.json"; import * as CompileConfig from "../config.json";
@ -378,6 +379,20 @@ class Utils {
isFirefox(): boolean { isFirefox(): boolean {
return typeof(browser) !== "undefined"; return typeof(browser) !== "undefined";
} }
getHash(value: string, times=5000): string {
if (times <= 0) return "";
for (let i = 0; i < times; i++) {
let hash = sha256.create();
hash.update(value);
hash.hex();
value = hash.toString();
}
return value;
}
} }
export default Utils; export default Utils;