Skip to content
41 changes: 16 additions & 25 deletions src/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ import "content-scripts-register-polyfill";
import { sendRealRequestToCustomServer, setupBackgroundRequestProxy } from "../maze-utils/src/background-request-proxy";
import { setupTabUpdates } from "../maze-utils/src/tab-updates";
import { generateUserID } from "../maze-utils/src/setup";
function serializeOrStringify(e: unknown): string {
if (e instanceof Error) return e.stack || e.message || String(e);
try {
if (typeof e === "object") return JSON.stringify(e as unknown as Record<string, unknown>);
} catch (err) {
return String(err);
}
return String(e);
}

import Utils from "./utils";

Expand Down Expand Up @@ -217,33 +226,15 @@ async function submitVote(type: number, UUID: string, category: string, videoID:

try {
const response = await asyncRequestToServer("POST", "/api/voteOnSponsorTime?UUID=" + UUID + "&videoID=" + videoID + "&userID=" + userID + typeSection);

if (response.ok) {
return {
successType: 1,
responseText: await response.text()
};
} else if (response.status == 405) {
//duplicate vote
return {
successType: 0,
statusCode: response.status,
responseText: await response.text()
};
} else {
//error while connect
return {
successType: -1,
statusCode: response.status,
responseText: await response.text()
};
}
return {
status: response.status,
ok: response.ok,
responseText: await response.text(),
};
} catch (e) {
console.error(e);
console.error("Error while voting:", e);
return {
successType: -1,
statusCode: -1,
responseText: ""
error: serializeOrStringify(e),
};
}
}
Expand Down
14 changes: 9 additions & 5 deletions src/components/CategoryPillComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import { downvoteButtonColor, SkipNoticeAction } from "../utils/noticeUtils";
import { VoteResponse } from "../messageTypes";
import { AnimationUtils } from "../../maze-utils/src/animationUtils";
import { Tooltip } from "../render/Tooltip";
import { getErrorMessage } from "../../maze-utils/src/formating";

import { formatJSErrorMessage, getLongErrorMessage } from "../utils/errorFormat";
import { logRequest } from "../utils/requestLogging";
export interface CategoryPillProps {
vote: (type: number, UUID: SegmentUUID, category?: Category) => Promise<VoteResponse>;
showTextByDefault: boolean;
Expand Down Expand Up @@ -127,15 +127,19 @@ class CategoryPillComponent extends React.Component<CategoryPillProps, CategoryP
const response = await this.props.vote(type, this.state.segment.UUID);
await stopAnimation();

if (response.successType == 1 || (response.successType == -1 && response.statusCode == 429)) {
if ("error" in response) {
console.error("[SB] Caught error while attempting to vote on a FV label", response.error);
alert(formatJSErrorMessage(response.error));
} else if (response.ok || response.status === 429) {
this.setState({
open: false,
show: type === 1
});

this.closeTooltip();
} else if (response.statusCode !== 403) {
alert(getErrorMessage(response.statusCode, response.responseText));
} else if (response.status !== 403) {
logRequest({headers: null, ...response}, "SB", "vote on FV label");
alert(getLongErrorMessage(response.status, response.responseText));
}
}
}
Expand Down
13 changes: 9 additions & 4 deletions src/components/ChapterVoteComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import { downvoteButtonColor, SkipNoticeAction } from "../utils/noticeUtils";
import { VoteResponse } from "../messageTypes";
import { AnimationUtils } from "../../maze-utils/src/animationUtils";
import { Tooltip } from "../render/Tooltip";
import { getErrorMessage } from "../../maze-utils/src/formating";
import { formatJSErrorMessage, getLongErrorMessage } from "../utils/errorFormat";
import { logRequest } from "../utils/requestLogging";

export interface ChapterVoteProps {
vote: (type: number, UUID: SegmentUUID, category?: Category) => Promise<VoteResponse>;
Expand Down Expand Up @@ -119,12 +120,16 @@ class ChapterVoteComponent extends React.Component<ChapterVoteProps, ChapterVote
const response = await this.props.vote(type, this.state.segment.UUID);
await stopAnimation();

if (response.successType == 1 || (response.successType == -1 && response.statusCode == 429)) {
if ("error" in response){
console.error("[SB] Caught error while attempting to vote on a chapter", response.error);
alert(formatJSErrorMessage(response.error));
} else if (response.ok || response.status == 429) {
this.setState({
show: type === 1
});
} else if (response.statusCode !== 403) {
alert(getErrorMessage(response.statusCode, response.responseText));
} else if (response.status !== 403) {
logRequest({headers: null, ...response}, "SB", "vote on chapter");
alert(getLongErrorMessage(response.status, response.responseText));
}
}
}
Expand Down
4 changes: 0 additions & 4 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ interface SBConfig {
hideDeleteButtonPlayerControls: boolean;
hideUploadButtonPlayerControls: boolean;
hideSkipButtonPlayerControls: boolean;
hideDiscordLaunches: number;
hideDiscordLink: boolean;
invidiousInstances: string[];
supportInvidious: boolean;
serverAddress: string;
Expand Down Expand Up @@ -305,8 +303,6 @@ const syncDefaults = {
hideDeleteButtonPlayerControls: false,
hideUploadButtonPlayerControls: false,
hideSkipButtonPlayerControls: false,
hideDiscordLaunches: 0,
hideDiscordLink: false,
invidiousInstances: [],
supportInvidious: false,
serverAddress: CompileConfig.serverAddress,
Expand Down
28 changes: 21 additions & 7 deletions src/content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { ChapterVote } from "./render/ChapterVote";
import { openWarningDialog } from "./utils/warnings";
import { extensionUserAgent, isFirefoxOrSafari, waitFor } from "../maze-utils/src";
import { getErrorMessage, getFormattedTime } from "../maze-utils/src/formating";
import { formatJSErrorMessage, getLongErrorMessage } from "./utils/errorFormat";
import { getChannelIDInfo, getVideo, getIsAdPlaying, getIsLivePremiere, setIsAdPlaying, checkVideoIDChange, getVideoID, getYouTubeVideoID, setupVideoModule, checkIfNewVideoID, isOnInvidious, isOnMobileYouTube, isOnYouTubeMusic, isOnYTTV, getLastNonInlineVideoID, triggerVideoIDChange, triggerVideoElementChange, getIsInline, getCurrentTime, setCurrentTime, getVideoDuration, verifyCurrentTime, waitForVideo } from "../maze-utils/src/video";
import { Keybind, StorageChangesObject, isSafari, keybindEquals, keybindToString } from "../maze-utils/src/config";
import { findValidElement } from "../maze-utils/src/dom"
Expand Down Expand Up @@ -1720,7 +1721,13 @@ function sendTelemetryAndCount(skippingSegments: SponsorTime[], secondsSkipped:
counted = true;
}

if (fullSkip) asyncRequestToServer("POST", "/api/viewedVideoSponsorTime?UUID=" + segment.UUID + "&videoID=" + getVideoID());
if (fullSkip) asyncRequestToServer("POST", "/api/viewedVideoSponsorTime?UUID=" + segment.UUID + "&videoID=" + getVideoID())
.then(r => {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { logRequest } = require("./utils/requestLogging");
if (!r.ok) logRequest(r, "SB", "segment skip log");
})
.catch(e => console.warn("[SB] Caught error while attempting to log segment skip", e));
}
}
}
Expand Down Expand Up @@ -2287,14 +2294,17 @@ async function vote(type: number, UUID: SegmentUUID, category?: Category, skipNo
if (response != undefined) {
//see if it was a success or failure
if (skipNotice != null) {
if (response.successType == 1 || (response.successType == -1 && response.statusCode == 429)) {
if ("error" in response) {
skipNotice.setNoticeInfoMessage.bind(skipNotice)(formatJSErrorMessage(response.error as unknown as Error));
skipNotice.resetVoteButtonInfo.bind(skipNotice)();
} else if (response.ok || response.status === 429) {
//success (treat rate limits as a success)
skipNotice.afterVote.bind(skipNotice)(utils.getSponsorTimeFromUUID(sponsorTimes, UUID), type, category);
} else if (response.successType == -1) {
if (response.statusCode === 403 && response.responseText.startsWith("Vote rejected due to a tip from a moderator.")) {
} else {
if (response.status === 403 && response.responseText.startsWith("Vote rejected due to a tip from a moderator.")) {
openWarningDialog(skipNoticeContentContainer);
} else {
skipNotice.setNoticeInfoMessage.bind(skipNotice)(getErrorMessage(response.statusCode, response.responseText))
skipNotice.setNoticeInfoMessage.bind(skipNotice)(getLongErrorMessage(response.status, response.responseText));
}

skipNotice.resetVoteButtonInfo.bind(skipNotice)();
Expand Down Expand Up @@ -2334,8 +2344,12 @@ async function voteAsync(type: number, UUID: SegmentUUID, category?: Category):
category: category,
videoID: getVideoID()
}, (response) => {
if (response.successType === 1) {
// Change the sponsor locally
if (!response || "error" in response) {
resolve(response);
return;
}

if (response.ok || response.status === 429) {
const segment = utils.getSponsorTimeFromUUID(sponsorTimes, UUID);
if (segment) {
if (type === 0) {
Expand Down
13 changes: 7 additions & 6 deletions src/messageTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export type Message = BaseMessage & (DefaultMessage | BoolValueMessage | IsInfoF

export interface IsInfoFoundMessageResponse {
found: boolean;
status: number;
status: number | string | Error;
sponsorTimes: SponsorTime[];
time: number;
onMobileYouTube: boolean;
Expand Down Expand Up @@ -120,12 +120,13 @@ export type MessageResponse =
| LogResponse
| LoopedChapterResponse;

export interface VoteResponse {
successType: number;
statusCode: number;
export type VoteResponse = {
status: number;
ok: boolean;
responseText: string;
}

} | {
error: Error | string;
};
interface ImportSegmentsResponse {
importedSegments: SponsorTime[];
}
Expand Down
6 changes: 0 additions & 6 deletions src/popup/PopupComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,6 @@ export const PopupComponent = () => {
titleFormatting={titleFormatting}
/>
</a>
<a href="https://discord.gg/SponsorBlock" target="_blank" rel="noreferrer">
<FormattedText
text="Discord"
titleFormatting={titleFormatting}
/>
</a>
<a href="https://matrix.to/#/#edittogether:matrix.org" target="_blank" rel="noreferrer">
<FormattedText
text="Matrix"
Expand Down
11 changes: 7 additions & 4 deletions src/popup/SegmentListComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ 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 { getFormattedTime } from "../../maze-utils/src/formating";
import { formatJSErrorMessage, getLongErrorMessage } from "../utils/errorFormat";
import { AnimationUtils } from "../../maze-utils/src/animationUtils";
import { asyncRequestToServer } from "../utils/requests";
import { Message, MessageResponse, VoteResponse } from "../messageTypes";
Expand Down Expand Up @@ -303,11 +304,13 @@ async function vote(props: {

if (response != undefined) {
// See if it was a success or failure
if (response.successType == 1 || (response.successType == -1 && response.statusCode == 429)) {
if ("error" in response) {
props.setVoteMessage(formatJSErrorMessage(response.error));
} 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 {
props.setVoteMessage(getLongErrorMessage(response.status, response.responseText));
}
setTimeout(() => props.setVoteMessage(null), 1500);
}
Expand Down
4 changes: 2 additions & 2 deletions src/submission/SubmissionComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@
const upvotedThumbnail = unsubmitted.thumbnails.find((t) => t.selected);
if (upvotedThumbnail) {
const upvotedThumbnailIndex = thumbnails.findIndex((t) => (t.type === ThumbnailType.Original && upvotedThumbnail.original)
|| (t.type === ThumbnailType.SpecifiedTime && !upvotedThumbnail.original && t.timestamp === (upvotedThumbnail as any).timestamp));

Check warning on line 161 in src/submission/SubmissionComponent.tsx

View workflow job for this annotation

GitHub Actions / Create artifacts

Unexpected any. Specify a different type

Check warning on line 161 in src/submission/SubmissionComponent.tsx

View workflow job for this annotation

GitHub Actions / Create artifacts

Unexpected any. Specify a different type
if (upvotedThumbnailIndex !== -1) {
setUpvotedThumbnailIndex(upvotedThumbnailIndex);
}
Expand Down Expand Up @@ -236,7 +236,7 @@
titles: []
};

const existingSubmission = unsubmitted.thumbnails.findIndex((s) => !s.original && (s as any).timestamp === (t as any).timestamp);

Check warning on line 239 in src/submission/SubmissionComponent.tsx

View workflow job for this annotation

GitHub Actions / Create artifacts

Unexpected any. Specify a different type

Check warning on line 239 in src/submission/SubmissionComponent.tsx

View workflow job for this annotation

GitHub Actions / Create artifacts

Unexpected any. Specify a different type

Check warning on line 239 in src/submission/SubmissionComponent.tsx

View workflow job for this annotation

GitHub Actions / Create artifacts

Unexpected any. Specify a different type

Check warning on line 239 in src/submission/SubmissionComponent.tsx

View workflow job for this annotation

GitHub Actions / Create artifacts

Unexpected any. Specify a different type
if (existingSubmission === -1) {
unsubmitted.thumbnails.unshift(t);

Expand All @@ -251,7 +251,7 @@

if (existingSubmission !== -1) {
const extraUnsubmitted = extraThumbnails.findIndex((s) => s.type === ThumbnailType.SpecifiedTime
&& s.timestamp === (t as any).timestamp);

Check warning on line 254 in src/submission/SubmissionComponent.tsx

View workflow job for this annotation

GitHub Actions / Create artifacts

Unexpected any. Specify a different type

Check warning on line 254 in src/submission/SubmissionComponent.tsx

View workflow job for this annotation

GitHub Actions / Create artifacts

Unexpected any. Specify a different type

if (extraUnsubmitted !== -1) {
selectedIndex = defaultThumbnails.length + extraUnsubmitted;
Expand Down Expand Up @@ -399,7 +399,7 @@
<a className="cbNoticeButton"
href={`https://chat.sponsor.ajay.app/#${objectToURI("", {
displayName: getChatDisplayName(chatDisplayName),
customDescription: `${chrome.i18n.getMessage("chatboxDescription")}\n\nhttps://discord.gg/SponsorBlock\nhttps://matrix.to/#/#edittogether:matrix.org`,
customDescription: `${chrome.i18n.getMessage("chatboxDescription")}\n\nhttps://matrix.to/#/#edittogether:matrix.org`,
bigDescription: true
}, false)}`}
target="_blank"
Expand Down Expand Up @@ -453,7 +453,7 @@
if (unsubmittedThumbnails) {
thumbnailsResult = unsubmittedThumbnails
.filter((t) => thumbnails.every((s) => !t.original && (s.type !== ThumbnailType.SpecifiedTime
|| s.timestamp !== (t as any).timestamp)))

Check warning on line 456 in src/submission/SubmissionComponent.tsx

View workflow job for this annotation

GitHub Actions / Create artifacts

Unexpected any. Specify a different type

Check warning on line 456 in src/submission/SubmissionComponent.tsx

View workflow job for this annotation

GitHub Actions / Create artifacts

Unexpected any. Specify a different type
.map((t) => ({
type: ThumbnailType.SpecifiedTime,
timestamp: (t as CustomThumbnailResult).timestamp,
Expand Down Expand Up @@ -583,7 +583,7 @@
name: chrome.i18n.getMessage("questionButton"),
listener: () => window.open(`https://chat.sponsor.ajay.app/#${objectToURI("", {
displayName: getChatDisplayName(name),
customDescription: `${chrome.i18n.getMessage("chatboxDescription")}\n\nhttps://discord.gg/SponsorBlock\nhttps://matrix.to/#/#sponsor:ajay.app?via=matrix.org`,
customDescription: `${chrome.i18n.getMessage("chatboxDescription")}\n\nhttps://matrix.to/#/#sponsor:ajay.app?via=matrix.org`,
bigDescription: true
}, false)}`)
}],
Expand Down
2 changes: 1 addition & 1 deletion src/submission/autoWarning.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ function showAutoWarningIfRequiredInternal(title: string, element: HTMLElement):

window.open(`https://chat.sponsor.ajay.app/#${objectToURI("", {
displayName: getChatDisplayName(name),
customDescription: `${chrome.i18n.getMessage("chatboxDescription")}\n\nhttps://discord.gg/SponsorBlock\nhttps://matrix.to/#/#edittogether:matrix.org?via=matrix.org`,
customDescription: `${chrome.i18n.getMessage("chatboxDescription")}\n\nhttps://matrix.to/#/#edittogether:matrix.org?via=matrix.org`,
bigDescription: true
}, false)}`);
}
Expand Down
2 changes: 2 additions & 0 deletions src/thumbnails/thumbnailRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,7 @@ export function getThumbnailImageSelector(brandingLocation: BrandingLocation): s
case BrandingLocation.Endcards:
return ".ytp-ce-covering-image";
case BrandingLocation.Autoplay:
case BrandingLocation.EndAutonav:
return "div.ytp-autonav-endscreen-upnext-thumbnail";
case BrandingLocation.EndRecommendations:
return "div.ytp-videowall-still-image";
Expand Down Expand Up @@ -551,6 +552,7 @@ function getThumbnailBox(image: HTMLElement, brandingLocation: BrandingLocation)
return image;
}
case BrandingLocation.Autoplay:
case BrandingLocation.EndAutonav:
case BrandingLocation.UpNextPreview:
return image;
default:
Expand Down
12 changes: 5 additions & 7 deletions src/titles/titleFormatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,19 @@ if (LOAD_CLD) {
*/

export async function formatTitle(title: string, isCustom: boolean, videoID: VideoID | null): Promise<string> {
const shouldOnlyFormatCustom = !Config.config!.formatOriginalTitles && Config.config!.formatCustomTitles;
return formatTitleInternal(title, isCustom, await getTitleFormatting(videoID), await shouldCleanEmojis(videoID), shouldOnlyFormatCustom);
return formatTitleInternal(title, isCustom, await getTitleFormatting(videoID), await shouldCleanEmojis(videoID), Config.config!.formatCustomTitles, Config.config!.formatOriginalTitles);
}

export async function formatTitleDefaultSettings(title: string, isCustom: boolean): Promise<string> {
const shouldOnlyFormatCustom = !Config.config!.formatOriginalTitles && Config.config!.formatCustomTitles;
return await formatTitleInternal(title, isCustom, Config.config!.titleFormatting, Config.config!.shouldCleanEmojis, shouldOnlyFormatCustom);
return await formatTitleInternal(title, isCustom, Config.config!.titleFormatting, Config.config!.shouldCleanEmojis, Config.config!.formatCustomTitles, Config.config!.formatOriginalTitles);
}

export async function formatTitleInternal(title: string, isCustom: boolean, titleFormatting: TitleFormatting, shouldCleanEmojis: boolean, onlyFormatCustomTitles = false): Promise<string> {
export async function formatTitleInternal(title: string, isCustom: boolean, titleFormatting: TitleFormatting, shouldCleanEmojis: boolean, formatCustomTitles = true, formatOriginalTitles = true): Promise<string> {
if (shouldCleanEmojis) {
title = cleanFancyText(cleanEmojis(title));
}

if (onlyFormatCustomTitles && !isCustom) {
if ((!formatCustomTitles && isCustom) || (!formatOriginalTitles && !isCustom)) {
titleFormatting = TitleFormatting.Disable;
}

Expand Down Expand Up @@ -645,7 +643,7 @@ export function cleanFancyText(title: string): string {
// Allow emoji variation selectors on either side of the replacement character
// Supports emojis such as 🅱️
title = title.replace(new RegExp(`[\u{fe00}-\u{fe0f}\u{e0100}-\u{e01ef}]?${replacement[0]}[\u{fe00}-\u{fe0f}\u{e0100}-\u{e01ef}]?`
, "ug"), replacement[1].toUpperCase());
, "ug"), replacement[1]);
}

return title.trim();
Expand Down
15 changes: 15 additions & 0 deletions src/utils/errorFormat.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export function formatJSErrorMessage(e: unknown): string {
try {
if (e instanceof Error) return e.message || String(e);
if (typeof e === "object") return JSON.stringify(e);
} catch (err) {
return String(err);
}
return String(e);
}

export function getLongErrorMessage(status: number, responseText?: string): string {
let base = `Error ${status}`;
if (responseText) base += `: ${responseText}`;
return base;
}
18 changes: 18 additions & 0 deletions src/utils/requestLogging.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export function serializeOrStringify(e: unknown): string {
if (e instanceof Error) return e.stack || e.message || String(e);
try {
if (typeof e === "object") return JSON.stringify(e);
} catch (err) {
return String(err);
}
return String(e);
}

export function logRequest(response: { status: number; ok: boolean; responseText?: string; headers?: Record<string, string> | null }, prefix = "SB", action = "request"): void {
try {
// eslint-disable-next-line no-console
console.warn(`[${prefix}] Non-OK ${action}: status=${response.status} ok=${response.ok}`, response.responseText);
} catch (_err) {
void _err;
}
}
Loading
Loading