Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added fallback server option #1572

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions config.json.example
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
{
"serverAddress": "https://sponsor.ajay.app",
"testingServerAddress": "https://sponsor.ajay.app/test",
"fallbackServerAddress": "",
"serverAddressComment": "This specifies the default SponsorBlock server to connect to",
"fallbackAddressComment": "This specifies the server SponsorBlock will attempt to connect to if the primary one fails.",
"categoryList": ["sponsor", "selfpromo", "exclusive_access", "interaction", "poi_highlight", "intro", "outro", "preview", "filler", "chapter", "music_offtopic"],
"categorySupport": {
"sponsor": ["skip", "mute", "full"],
Expand Down
6 changes: 6 additions & 0 deletions public/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,12 @@
"customServerAddressDescription": {
"message": "The address SponsorBlock uses to make calls to the server.\nUnless you have your own server instance, this should not be changed."
},
"fallbackServerAddress": {
"message": "SponsorBlock Fallback Server Address"
},
"fallbackServerAddressDescription": {
"message": "The address SponsorBlock uses to make calls to the server if the main server is down."
},
"save": {
"message": "Save"
},
Expand Down
20 changes: 20 additions & 0 deletions public/options/options.html
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,26 @@ <h2>__MSG_exportOptions__</h2>
</div>
</div>
</div>

<div data-type="text-change" data-sync="fallbackServerAddress" data-dependent-on="testingServer" data-dependent-on-inverted="true">
<label class="optionLabel inline">
<span class="optionLabel">__MSG_fallbackServerAddress__:</span>

<input class="option-text-box" type="text" style="margin-right:10px">
</label>

<div class="small-description">__MSG_fallbackServerAddressDescription__</div>

<div class="next-line">
<div class="option-button text-change-set inline">
__MSG_save__
</div>

<div class="option-button text-change-reset inline">
__MSG_reset__
</div>
</div>
</div>

</div>

Expand Down
11 changes: 7 additions & 4 deletions src/components/SponsorTimeEditComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -696,11 +696,10 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
this.saveEditTimes();
}

async fetchSuggestions(description: string): Promise<void> {
async fetchSuggestions(description: string, fallbackServer = false): Promise<void> {
if (this.props.contentContainer().channelIDInfo.status !== ChannelIDStatus.Found) return;

this.fetchingSuggestions = true;
const result = await utils.asyncRequestToServer("GET", "/api/chapterNames", {
const result = await utils.asyncRequestToServer("GET", "/api/chapterNames", fallbackServer, {
description,
channelID: this.props.contentContainer().channelIDInfo.id
});
Expand All @@ -713,7 +712,11 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
label: n.description
}))
});
} catch (e) {} //eslint-disable-line no-empty
} catch (e) {
if (!fallbackServer) {
this.fetchSuggestions(description, true);
}
}
}

this.fetchingSuggestions = false;
Expand Down
2 changes: 2 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ interface SBConfig {
invidiousInstances: string[];
supportInvidious: boolean;
serverAddress: string;
fallbackServerAddress: string;
minDuration: number;
skipNoticeDuration: number;
audioNotificationOnSkip: boolean;
Expand Down Expand Up @@ -181,6 +182,7 @@ const Config: SBObject = {
invidiousInstances: ["invidious.snopyta.org"], // leave as default
supportInvidious: false,
serverAddress: CompileConfig.serverAddress,
fallbackServerAddress: CompileConfig.fallbackServerAddress,
minDuration: 0,
skipNoticeDuration: 4,
audioNotificationOnSkip: false,
Expand Down
24 changes: 16 additions & 8 deletions src/content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ let isAdPlaying = false;
let lastResponseStatus: number;
let retryCount = 0;

// flips between true/false on server request failure
let fallbackServer = false;

// Contains all of the functions and variables needed by the skip notice
const skipNoticeContentContainer: ContentContainer = () => ({
vote,
Expand Down Expand Up @@ -1008,9 +1011,8 @@ async function sponsorsLookup(keepOldSubmissions = true) {
const extraRequestData: Record<string, unknown> = {};
const hashParams = getHashParams();
if (hashParams.requiredSegment) extraRequestData.requiredSegment = hashParams.requiredSegment;

const hashPrefix = (await utils.getHash(sponsorVideoID, 1)).slice(0, 4) as VideoID & HashedValue;
const response = await utils.asyncRequestToServer('GET', "/api/skipSegments/" + hashPrefix, {
const response = await utils.asyncRequestToServer('GET', "/api/skipSegments/" + hashPrefix, fallbackServer, {
categories,
actionTypes: getEnabledActionTypes(showChapterMessage),
userAgent: `${chrome.runtime.id}`,
Expand All @@ -1019,7 +1021,6 @@ async function sponsorsLookup(keepOldSubmissions = true) {

// store last response status
lastResponseStatus = response?.status;

if (response?.ok) {
let recievedSegments: SponsorTime[] = JSON.parse(response.responseText)
?.filter((video) => video.videoID === sponsorVideoID)
Expand Down Expand Up @@ -1170,7 +1171,7 @@ function getEnabledActionTypes(forceFullVideo = false): ActionType[] {

async function lockedCategoriesLookup(): Promise<void> {
const hashPrefix = (await utils.getHash(sponsorVideoID, 1)).slice(0, 4);
const response = await utils.asyncRequestToServer("GET", "/api/lockCategories/" + hashPrefix);
const response = await utils.asyncRequestToServer("GET", "/api/lockCategories/" + hashPrefix, fallbackServer);

if (response.ok) {
try {
Expand All @@ -1192,9 +1193,16 @@ function retryFetch(errorCode: number): void {
return;
}

fallbackServer = retryCount % 2 === 0
retryCount++;

const delay = errorCode === 404 ? (30000 + Math.random() * 30000) : (2000 + Math.random() * 10000);
let delay: number;
switch (errorCode) {
case 404:
delay = (30000 + Math.random() * 30000);
break;
default:
delay = retryCount <= 2 ? 0 : (2000 + Math.random() * 10000);
}
retryFetchTimeout = setTimeout(() => {
if (sponsorVideoID && sponsorTimes?.length === 0
|| sponsorTimes.every((segment) => segment.source !== SponsorSourceType.Server)) {
Expand Down Expand Up @@ -1630,7 +1638,7 @@ function sendTelemetryAndCount(skippingSegments: SponsorTime[], secondsSkipped:
counted = true;
}

if (fullSkip) utils.asyncRequestToServer("POST", "/api/viewedVideoSponsorTime?UUID=" + segment.UUID);
if (fullSkip) utils.asyncRequestToServer("POST", "/api/viewedVideoSponsorTime?UUID=" + segment.UUID, false);
}
}
}
Expand Down Expand Up @@ -2236,7 +2244,7 @@ async function sendSubmitMessage() {
}
}

const response = await utils.asyncRequestToServer("POST", "/api/skipSegments", {
const response = await utils.asyncRequestToServer("POST", "/api/skipSegments", false, {
videoID: sponsorVideoID,
userID: Config.config.userID,
segments: sponsorTimesSubmitting,
Expand Down
9 changes: 5 additions & 4 deletions src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,8 @@ async function init() {
textChangeSetButton.addEventListener("click", async () => {
// See if anything extra must be done
switch (option) {
case "serverAddress": {
case "serverAddress":
case "fallbackServerAddress": {
const result = validateServerAddress(textChangeInput.value);

if (result !== null) {
Expand Down Expand Up @@ -531,8 +532,8 @@ function activatePrivateTextChange(element: HTMLElement) {
switch (option) {
case "userID":
if (Config.config[option]) {
utils.asyncRequestToServer("GET", "/api/userInfo", {
publicUserID: utils.getHash(Config.config[option]),
utils.asyncRequestToServer("GET", "/api/userInfo", false, {
userID: Config.config[option],
values: ["warnings", "banned"]
}).then((result) => {
const userInfo = JSON.parse(result.responseText);
Expand Down Expand Up @@ -672,4 +673,4 @@ function copyDebugOutputToClipboard() {

function isIncognitoAllowed(): Promise<boolean> {
return new Promise((resolve) => chrome.extension.isAllowedIncognitoAccess(resolve));
}
}
2 changes: 1 addition & 1 deletion src/popup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
const values = ["userName", "viewCount", "minutesSaved", "vip", "permissions"];
if (!Config.config.payments.freeAccess && !noRefreshFetchingChaptersAllowed()) values.push("freeChaptersAccess");

utils.asyncRequestToServer("GET", "/api/userInfo", {
utils.asyncRequestToServer("GET", "/api/userInfo", false,{
publicUserID: await utils.getHash(Config.config.userID),
values
}).then((res) => {
Expand Down
13 changes: 9 additions & 4 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,6 @@ export default class Utils {
return selection;
}
}
return { name: "None", option: 0} as CategorySelection;
}

/**
Expand Down Expand Up @@ -365,11 +364,17 @@ export default class Utils {
*
* @param type The request type. "GET", "POST", etc.
* @param address The address to add to the SponsorBlock server address
* @param fallback Use the fallback server URL if true.
* @param callback
*/
async asyncRequestToServer(type: string, address: string, data = {}): Promise<FetchResponse> {
const serverAddress = Config.config.testingServer ? CompileConfig.testingServerAddress : Config.config.serverAddress;

async asyncRequestToServer(type: string, address: string, fallback = false, data = {}): Promise<FetchResponse> {
let serverAddress = Config.config.serverAddress;
if (Config.config.testingServer){
serverAddress = CompileConfig.testingServerAddress;
} else if (fallback && Config.config.fallbackServerAddress) {
serverAddress = Config.config.fallbackServerAddress;
}

return await (this.asyncRequestToCustomServer(type, serverAddress + address, data));
}

Expand Down
14 changes: 7 additions & 7 deletions src/utils/licenseKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as CompileConfig from "../../config.json";
const utils = new Utils();

export async function checkLicenseKey(licenseKey: string): Promise<boolean> {
const result = await utils.asyncRequestToServer("GET", "/api/verifyToken", {
const result = await utils.asyncRequestToServer("GET", "/api/verifyToken", false,{
licenseKey
});

Expand All @@ -15,7 +15,7 @@ export async function checkLicenseKey(licenseKey: string): Promise<boolean> {
Config.config.showChapterInfoMessage = false;
Config.config.payments.lastCheck = Date.now();
Config.forceSyncUpdate("payments");

return true;
}
} catch (e) { } //eslint-disable-line no-empty
Expand Down Expand Up @@ -43,17 +43,17 @@ export async function fetchingChaptersAllowed(): Promise<boolean> {
return licensePromise;
}
}

if (Config.config.payments.chaptersAllowed) return true;

if (Config.config.payments.lastCheck === 0 && Date.now() - Config.config.payments.lastFreeCheck > 2 * 24 * 60 * 60 * 1000) {
Config.config.payments.lastFreeCheck = Date.now();
Config.forceSyncUpdate("payments");

// Check for free access if no license key, and it is the first time
const result = await utils.asyncRequestToServer("GET", "/api/userInfo", {
const result = await utils.asyncRequestToServer("GET", "/api/userInfo", false,{
value: "freeChaptersAccess",
publicUserID: await utils.getHash(Config.config.userID)
userID: Config.config.userID
});

try {
Expand All @@ -66,12 +66,12 @@ export async function fetchingChaptersAllowed(): Promise<boolean> {
Config.config.payments.chaptersAllowed = true;
Config.config.showChapterInfoMessage = false;
Config.forceSyncUpdate("payments");

return true;
}
}
} catch (e) { } //eslint-disable-line no-empty
}

return false;
}
}
8 changes: 4 additions & 4 deletions src/utils/warnings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ export interface ChatConfig {
}

export async function openWarningDialog(contentContainer: ContentContainer): Promise<void> {
const userInfo = await utils.asyncRequestToServer("GET", "/api/userInfo", {
publicUserID: await utils.getHash(Config.config.userID),
const userInfo = await utils.asyncRequestToServer("GET", "/api/userInfo", false, {
userID: Config.config.userID,
values: ["warningReason"]
});

Expand Down Expand Up @@ -42,7 +42,7 @@ export async function openWarningDialog(contentContainer: ContentContainer): Pro
{
name: chrome.i18n.getMessage("warningConfirmButton"),
listener: async () => {
const result = await utils.asyncRequestToServer("POST", "/api/warnUser", {
const result = await utils.asyncRequestToServer("POST", "/api/warnUser", false, {
userID: Config.config.userID,
enabled: false
});
Expand All @@ -63,4 +63,4 @@ export async function openWarningDialog(contentContainer: ContentContainer): Pro

export function openChat(config: ChatConfig): void {
window.open("https://chat.sponsor.ajay.app/#" + GenericUtils.objectToURI("", config, false));
}
}