mirror of
https://github.com/ajayyy/SponsorBlock.git
synced 2025-12-20 14:38:28 +03:00
Improve error handling
- pass errors from background threads back to clients - log all HTTP request errors and display them to the user where possible
This commit is contained in:
@@ -17,6 +17,7 @@ export enum LoadingStatus {
|
||||
SegmentsFound,
|
||||
NoSegmentsFound,
|
||||
ConnectionError,
|
||||
JSError,
|
||||
StillLoading,
|
||||
NoVideo
|
||||
}
|
||||
@@ -24,6 +25,7 @@ export enum LoadingStatus {
|
||||
export interface LoadingData {
|
||||
status: LoadingStatus;
|
||||
code?: number;
|
||||
error?: Error | string;
|
||||
}
|
||||
|
||||
let loadRetryCount = 0;
|
||||
@@ -302,7 +304,9 @@ function getVideoStatusText(status: LoadingData): string {
|
||||
case LoadingStatus.NoSegmentsFound:
|
||||
return chrome.i18n.getMessage("sponsor404");
|
||||
case LoadingStatus.ConnectionError:
|
||||
return chrome.i18n.getMessage("connectionError") + status.code;
|
||||
return `${chrome.i18n.getMessage("connectionError")} ${chrome.i18n.getMessage("errorCode").replace("{code}", `${status.code}`)}`;
|
||||
case LoadingStatus.JSError:
|
||||
return `${chrome.i18n.getMessage("connectionError")} ${status.error}`;
|
||||
case LoadingStatus.StillLoading:
|
||||
return chrome.i18n.getMessage("segmentsStillLoading");
|
||||
case LoadingStatus.NoVideo:
|
||||
@@ -350,6 +354,11 @@ function segmentsLoaded(response: IsInfoFoundMessageResponse, props: SegmentsLoa
|
||||
props.setStatus({
|
||||
status: LoadingStatus.SegmentsFound
|
||||
});
|
||||
} else if (typeof response.status !== "number") {
|
||||
props.setStatus({
|
||||
status: LoadingStatus.JSError,
|
||||
error: response.status,
|
||||
})
|
||||
} else if (response.status === 404 || response.status === 200) {
|
||||
props.setStatus({
|
||||
status: LoadingStatus.NoSegmentsFound
|
||||
@@ -457,4 +466,4 @@ window.addEventListener("message", async (e): Promise<void> => {
|
||||
style.textContent = e.data.css;
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,7 +3,7 @@ import { ActionType, SegmentUUID, SponsorHideType, SponsorTime, VideoID } from "
|
||||
import Config from "../config";
|
||||
import { waitFor } from "../../maze-utils/src";
|
||||
import { shortCategoryName } from "../utils/categoryUtils";
|
||||
import { getErrorMessage, getFormattedTime } from "../../maze-utils/src/formating";
|
||||
import { formatJSErrorMessage, getFormattedTime, getShortErrorMessage } from "../../maze-utils/src/formating";
|
||||
import { AnimationUtils } from "../../maze-utils/src/animationUtils";
|
||||
import { asyncRequestToServer } from "../utils/requests";
|
||||
import { Message, MessageResponse, VoteResponse } from "../messageTypes";
|
||||
@@ -11,6 +11,7 @@ import { LoadingStatus } from "./PopupComponent";
|
||||
import GenericNotice from "../render/GenericNotice";
|
||||
import { exportTimes } from "../utils/exporter";
|
||||
import { copyToClipboardPopup } from "./popupUtils";
|
||||
import { logRequest } from "../../maze-utils/src/background-request-proxy";
|
||||
|
||||
interface SegmentListComponentProps {
|
||||
videoID: VideoID;
|
||||
@@ -192,20 +193,26 @@ function SegmentListItem({ segment, videoID, currentTime, isVip, startingLooped,
|
||||
onClick={async (e) => {
|
||||
const stopAnimation = AnimationUtils.applyLoadingAnimation(e.currentTarget, 0.3);
|
||||
|
||||
if (segment.UUID.length > 60) {
|
||||
copyToClipboardPopup(segment.UUID, sendMessage);
|
||||
} else {
|
||||
const segmentIDData = await asyncRequestToServer("GET", "/api/segmentID", {
|
||||
UUID: segment.UUID,
|
||||
videoID: videoID
|
||||
});
|
||||
|
||||
if (segmentIDData.ok && segmentIDData.responseText) {
|
||||
copyToClipboardPopup(segmentIDData.responseText, sendMessage);
|
||||
try {
|
||||
if (segment.UUID.length > 60) {
|
||||
copyToClipboardPopup(segment.UUID, sendMessage);
|
||||
} else {
|
||||
const segmentIDData = await asyncRequestToServer("GET", "/api/segmentID", {
|
||||
UUID: segment.UUID,
|
||||
videoID: videoID
|
||||
});
|
||||
if (segmentIDData.ok && segmentIDData.responseText) {
|
||||
copyToClipboardPopup(segmentIDData.responseText, sendMessage);
|
||||
} else {
|
||||
logRequest(segmentIDData, "SB", "segment UUID resolution");
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("[SB] Caught error while attempting to resolve and copy segment UUID", e);
|
||||
} finally {
|
||||
stopAnimation();
|
||||
}
|
||||
|
||||
stopAnimation();
|
||||
}}/>
|
||||
{
|
||||
segment.actionType === ActionType.Chapter &&
|
||||
@@ -298,14 +305,24 @@ async function vote(props: {
|
||||
}) as VoteResponse;
|
||||
|
||||
if (response != undefined) {
|
||||
let messageDuration = 1_500;
|
||||
// See if it was a success or failure
|
||||
if (response.successType == 1 || (response.successType == -1 && response.statusCode == 429)) {
|
||||
if ("error" in response) {
|
||||
// JS error
|
||||
console.error("[SB] Caught error while attempting to submit a vote", response.error);
|
||||
props.setVoteMessage(formatJSErrorMessage(response.error));
|
||||
messageDuration = 10_000;
|
||||
}
|
||||
else if (response.ok || response.status === 429) {
|
||||
// Success (treat rate limits as a success)
|
||||
props.setVoteMessage(chrome.i18n.getMessage("voted"));
|
||||
} else if (response.successType == -1) {
|
||||
props.setVoteMessage(getErrorMessage(response.statusCode, response.responseText));
|
||||
} else {
|
||||
// Error
|
||||
logRequest({headers: null, ...response}, "SB", "vote on segment");
|
||||
props.setVoteMessage(getShortErrorMessage(response.status, response.responseText));
|
||||
messageDuration = 10_000;
|
||||
}
|
||||
setTimeout(() => props.setVoteMessage(null), 1500);
|
||||
setTimeout(() => props.setVoteMessage(null), messageDuration);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -433,4 +450,4 @@ function ImportSegments(props: ImportSegmentsProps) {
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import * as React from "react";
|
||||
import { getHash } from "../../maze-utils/src/hash";
|
||||
import { getErrorMessage } from "../../maze-utils/src/formating";
|
||||
import { formatJSErrorMessage, getShortErrorMessage } from "../../maze-utils/src/formating";
|
||||
import Config from "../config";
|
||||
import { asyncRequestToServer } from "../utils/requests";
|
||||
import PencilIcon from "../svg-icons/pencilIcon";
|
||||
import ClipboardIcon from "../svg-icons/clipboardIcon";
|
||||
import CheckIcon from "../svg-icons/checkIcon";
|
||||
import { showDonationLink } from "../utils/configUtils";
|
||||
import { FetchResponse, logRequest } from "../../maze-utils/src/background-request-proxy";
|
||||
|
||||
export const YourWorkComponent = () => {
|
||||
const [isSettingUsername, setIsSettingUsername] = React.useState(false);
|
||||
@@ -21,10 +22,16 @@ export const YourWorkComponent = () => {
|
||||
React.useEffect(() => {
|
||||
(async () => {
|
||||
const values = ["userName", "viewCount", "minutesSaved", "vip", "permissions", "segmentCount"];
|
||||
const result = await asyncRequestToServer("GET", "/api/userInfo", {
|
||||
publicUserID: await getHash(Config.config!.userID!),
|
||||
values
|
||||
});
|
||||
let result: FetchResponse;
|
||||
try {
|
||||
result = await asyncRequestToServer("GET", "/api/userInfo", {
|
||||
publicUserID: await getHash(Config.config!.userID!),
|
||||
values
|
||||
});
|
||||
} catch (e) {
|
||||
console.error("[SB] Caught error while fetching user info", e);
|
||||
return
|
||||
}
|
||||
|
||||
if (result.ok) {
|
||||
const userInfo = JSON.parse(result.responseText);
|
||||
@@ -38,6 +45,8 @@ export const YourWorkComponent = () => {
|
||||
|
||||
setShowDonateMessage(Config.config.showDonationLink && Config.config.donateClicked <= 0 && Config.config.showPopupDonationCount < 5
|
||||
&& viewCount < 50000 && !Config.config.isVip && Config.config.skipCount > 10 && showDonationLink());
|
||||
} else {
|
||||
logRequest(result, "SB", "user info");
|
||||
}
|
||||
})();
|
||||
}, []);
|
||||
@@ -94,10 +103,12 @@ export const YourWorkComponent = () => {
|
||||
setUsername(newUsername);
|
||||
setIsSettingUsername(!isSettingUsername);
|
||||
} else {
|
||||
setUsernameSubmissionStatus(getErrorMessage(result.status, result.responseText));
|
||||
logRequest(result, "SB", "username change");
|
||||
setUsernameSubmissionStatus(getShortErrorMessage(result.status, result.responseText));
|
||||
}
|
||||
}).catch((e) => {
|
||||
setUsernameSubmissionStatus(`${chrome.i18n.getMessage("Error")}: ${e}`);
|
||||
console.error("[SB] Caught error while requesting a username change", e)
|
||||
setUsernameSubmissionStatus(formatJSErrorMessage(e));
|
||||
});
|
||||
}
|
||||
}}>
|
||||
@@ -205,4 +216,4 @@ function getFormattedHours(minutes) {
|
||||
const days = Math.floor(minutes / 1440) % 365;
|
||||
const hours = Math.floor(minutes / 60) % 24;
|
||||
return (years > 0 ? years + chrome.i18n.getMessage("yearAbbreviation") + " " : "") + (days > 0 ? days + chrome.i18n.getMessage("dayAbbreviation") + " " : "") + (hours > 0 ? hours + chrome.i18n.getMessage("hourAbbreviation") + " " : "") + (minutes % 60).toFixed(1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user