mirror of
https://github.com/ajayyy/SponsorBlock.git
synced 2025-12-07 12:07:11 +03:00
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "__MSG_fullName__",
|
"name": "__MSG_fullName__",
|
||||||
"short_name": "__MSG_Name__",
|
"short_name": "__MSG_Name__",
|
||||||
"version": "1.2.25",
|
"version": "1.2.26",
|
||||||
"default_locale": "en",
|
"default_locale": "en",
|
||||||
"description": "__MSG_Description__",
|
"description": "__MSG_Description__",
|
||||||
"content_scripts": [{
|
"content_scripts": [{
|
||||||
|
|||||||
@@ -515,7 +515,7 @@
|
|||||||
"message": "Manual Skip"
|
"message": "Manual Skip"
|
||||||
},
|
},
|
||||||
"showOverlay": {
|
"showOverlay": {
|
||||||
"message": "Show Overlay On Player"
|
"message": "Show In Seek Bar"
|
||||||
},
|
},
|
||||||
"enableTestingServer": {
|
"enableTestingServer": {
|
||||||
"message": "Enable Beta Testing Server"
|
"message": "Enable Beta Testing Server"
|
||||||
@@ -528,5 +528,8 @@
|
|||||||
},
|
},
|
||||||
"bracketNow": {
|
"bracketNow": {
|
||||||
"message": "(Now)"
|
"message": "(Now)"
|
||||||
|
},
|
||||||
|
"moreCategories": {
|
||||||
|
"message": "More Categories"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -338,6 +338,13 @@ input::-webkit-inner-spin-button {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sponsorTimeMessagesRow {
|
||||||
|
max-height: 300px;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.sponsorTimeEdit {
|
.sponsorTimeEdit {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export interface NoticeProps {
|
|||||||
fadeIn?: boolean,
|
fadeIn?: boolean,
|
||||||
|
|
||||||
// Callback for when this is closed
|
// Callback for when this is closed
|
||||||
closeListener?: () => void,
|
closeListener: () => void,
|
||||||
|
|
||||||
zIndex?: number
|
zIndex?: number
|
||||||
}
|
}
|
||||||
@@ -195,16 +195,10 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
|
|||||||
* @param silent If true, the close listener will not be called
|
* @param silent If true, the close listener will not be called
|
||||||
*/
|
*/
|
||||||
close(silent?: boolean) {
|
close(silent?: boolean) {
|
||||||
//TODO: Change to a listener in the renderer (not component)
|
|
||||||
let notice = document.getElementById("sponsorSkipNotice" + this.idSuffix);
|
|
||||||
if (notice != null) {
|
|
||||||
notice.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
//remove setInterval
|
//remove setInterval
|
||||||
if (this.countdownInterval !== null) clearInterval(this.countdownInterval);
|
if (this.countdownInterval !== null) clearInterval(this.countdownInterval);
|
||||||
|
|
||||||
if (this.props.closeListener && !silent) this.props.closeListener();
|
if (!silent) this.props.closeListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
changeNoticeTitle(title) {
|
changeNoticeTitle(title) {
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ export interface SkipNoticeProps {
|
|||||||
autoSkip: boolean;
|
autoSkip: boolean;
|
||||||
// Contains functions and variables from the content script needed by the skip notice
|
// Contains functions and variables from the content script needed by the skip notice
|
||||||
contentContainer: ContentContainer;
|
contentContainer: ContentContainer;
|
||||||
|
|
||||||
|
closeListener: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SkipNoticeState {
|
export interface SkipNoticeState {
|
||||||
@@ -112,7 +114,8 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
|
|||||||
fadeIn={true}
|
fadeIn={true}
|
||||||
timed={true}
|
timed={true}
|
||||||
maxCountdownTime={this.state.maxCountdownTime}
|
maxCountdownTime={this.state.maxCountdownTime}
|
||||||
ref={this.noticeRef}>
|
ref={this.noticeRef}
|
||||||
|
closeListener={this.props.closeListener}>
|
||||||
|
|
||||||
{(Config.config.audioNotificationOnSkip) && <audio ref={(source) => { this.audio = source; }}>
|
{(Config.config.audioNotificationOnSkip) && <audio ref={(source) => { this.audio = source; }}>
|
||||||
<source src={chrome.extension.getURL("icons/beep.ogg")} type="audio/ogg"></source>
|
<source src={chrome.extension.getURL("icons/beep.ogg")} type="audio/ogg"></source>
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
|
|||||||
className="sponsorTimeCategories"
|
className="sponsorTimeCategories"
|
||||||
defaultValue={sponsorTime.category}
|
defaultValue={sponsorTime.category}
|
||||||
ref={this.categoryOptionRef}
|
ref={this.categoryOptionRef}
|
||||||
onChange={this.saveEditTimes.bind(this)}>
|
onChange={this.categorySelectionChange.bind(this)}>
|
||||||
{this.getCategoryOptions()}
|
{this.getCategoryOptions()}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
@@ -190,13 +190,21 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
|
|||||||
getCategoryOptions() {
|
getCategoryOptions() {
|
||||||
let elements = [];
|
let elements = [];
|
||||||
|
|
||||||
//TODO: Remove this when testing server is not needed
|
for (const category of Config.config.categorySelections) {
|
||||||
let categoryList = Config.config.testingServer ? CompileConfig.categoryList : ["sponsor"];
|
|
||||||
for (const category of categoryList) {
|
|
||||||
elements.push(
|
elements.push(
|
||||||
<option value={category}
|
<option value={category.name}
|
||||||
key={category}>
|
key={category.name}>
|
||||||
{chrome.i18n.getMessage("category_" + category)}
|
{chrome.i18n.getMessage("category_" + category.name)}
|
||||||
|
</option>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elements.length < CompileConfig.categoryList.length) {
|
||||||
|
// Add show more button
|
||||||
|
elements.push(
|
||||||
|
<option value={"moreCategories"}
|
||||||
|
key={"moreCategories"}>
|
||||||
|
{chrome.i18n.getMessage("moreCategories")}
|
||||||
</option>
|
</option>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -204,6 +212,20 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
|
|||||||
return elements;
|
return elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
categorySelectionChange(event: React.ChangeEvent<HTMLSelectElement>) {
|
||||||
|
// See if show more categories was pressed
|
||||||
|
if (event.target.value === "moreCategories") {
|
||||||
|
// Open options page
|
||||||
|
chrome.runtime.sendMessage({"message": "openConfig"});
|
||||||
|
|
||||||
|
// Reset option to previous
|
||||||
|
event.target.value = this.props.contentContainer().sponsorTimesSubmitting[this.props.index].category;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.saveEditTimes();
|
||||||
|
}
|
||||||
|
|
||||||
setTimeToNow(index: number) {
|
setTimeToNow(index: number) {
|
||||||
let sponsorTime = this.props.contentContainer().sponsorTimesSubmitting[this.props.index];
|
let sponsorTime = this.props.contentContainer().sponsorTimesSubmitting[this.props.index];
|
||||||
|
|
||||||
@@ -259,7 +281,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
|
|||||||
let sponsorTimes = this.props.contentContainer().sponsorTimesSubmitting;
|
let sponsorTimes = this.props.contentContainer().sponsorTimesSubmitting;
|
||||||
let index = this.props.index;
|
let index = this.props.index;
|
||||||
|
|
||||||
let skipTime = sponsorTimes[index][0];
|
let skipTime = sponsorTimes[index].segment[0];
|
||||||
|
|
||||||
if (this.state.editing) {
|
if (this.state.editing) {
|
||||||
// Save edits before previewing
|
// Save edits before previewing
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ export interface SubmissionNoticeProps {
|
|||||||
contentContainer: ContentContainer;
|
contentContainer: ContentContainer;
|
||||||
|
|
||||||
callback: () => any;
|
callback: () => any;
|
||||||
|
|
||||||
|
closeListener: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SubmissionNoticeeState {
|
export interface SubmissionNoticeeState {
|
||||||
@@ -28,6 +30,8 @@ class SubmissionNoticeComponent extends React.Component<SubmissionNoticeProps, S
|
|||||||
noticeRef: React.MutableRefObject<NoticeComponent>;
|
noticeRef: React.MutableRefObject<NoticeComponent>;
|
||||||
timeEditRefs: React.RefObject<SponsorTimeEditComponent>[];
|
timeEditRefs: React.RefObject<SponsorTimeEditComponent>[];
|
||||||
|
|
||||||
|
videoObserver: MutationObserver;
|
||||||
|
|
||||||
constructor(props: SubmissionNoticeProps) {
|
constructor(props: SubmissionNoticeProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.noticeRef = React.createRef();
|
this.noticeRef = React.createRef();
|
||||||
@@ -45,6 +49,24 @@ class SubmissionNoticeComponent extends React.Component<SubmissionNoticeProps, S
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
// Catch and rerender when the video size changes
|
||||||
|
//TODO: Use ResizeObserver when it is supported in TypeScript
|
||||||
|
this.videoObserver = new MutationObserver(() => {
|
||||||
|
this.forceUpdate();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.videoObserver.observe(this.contentContainer().v, {
|
||||||
|
attributes: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
if (this.videoObserver) {
|
||||||
|
this.videoObserver.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<NoticeComponent noticeTitle={this.state.noticeTitle}
|
<NoticeComponent noticeTitle={this.state.noticeTitle}
|
||||||
@@ -57,8 +79,10 @@ class SubmissionNoticeComponent extends React.Component<SubmissionNoticeProps, S
|
|||||||
{this.getMessageBoxes()}
|
{this.getMessageBoxes()}
|
||||||
|
|
||||||
{/* Sponsor Time List */}
|
{/* Sponsor Time List */}
|
||||||
<tr id={"sponsorSkipNoticeMiddleRow" + this.state.idSuffix}>
|
<tr id={"sponsorSkipNoticeMiddleRow" + this.state.idSuffix}
|
||||||
<td>
|
className="sponsorTimeMessagesRow"
|
||||||
|
style={{maxHeight: (this.contentContainer().v.offsetHeight - 200) + "px"}}>
|
||||||
|
<td style={{width: "100%"}}>
|
||||||
{this.getSponsorTimeMessages()}
|
{this.getSponsorTimeMessages()}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -133,6 +157,8 @@ class SubmissionNoticeComponent extends React.Component<SubmissionNoticeProps, S
|
|||||||
this.noticeRef.current.close(true);
|
this.noticeRef.current.close(true);
|
||||||
|
|
||||||
this.contentContainer().resetSponsorSubmissionNotice();
|
this.contentContainer().resetSponsorSubmissionNotice();
|
||||||
|
|
||||||
|
this.props.closeListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
submit() {
|
submit() {
|
||||||
|
|||||||
451
src/content.ts
451
src/content.ts
@@ -593,239 +593,122 @@ function sponsorsLookup(id: string, channelIDPromise?) {
|
|||||||
//check database for sponsor times
|
//check database for sponsor times
|
||||||
//made true once a setTimeout has been created to try again after a server error
|
//made true once a setTimeout has been created to try again after a server error
|
||||||
let recheckStarted = false;
|
let recheckStarted = false;
|
||||||
if (Config.config.testingServer) {
|
// Create categories list
|
||||||
// Create categories list
|
let categories: string[] = [];
|
||||||
let categories: string[] = [];
|
for (const categorySelection of Config.config.categorySelections) {
|
||||||
for (const categorySelection of Config.config.categorySelections) {
|
categories.push(categorySelection.name);
|
||||||
categories.push(categorySelection.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
utils.asyncRequestToServer('GET', "/api/skipSegments", {
|
|
||||||
videoID: id,
|
|
||||||
categories
|
|
||||||
}).then(async (response: Response) => {
|
|
||||||
if (response.status === 200) {
|
|
||||||
let recievedSegments: SponsorTime[] = await response.json();
|
|
||||||
if (!recievedSegments.length) {
|
|
||||||
console.error("[SponsorBlock] Server returned malformed response: " + JSON.stringify(recievedSegments));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sponsorDataFound = true;
|
|
||||||
|
|
||||||
// Check if any old submissions should be kept
|
|
||||||
if (sponsorTimes !== null) {
|
|
||||||
for (let i = 0; i < sponsorTimes.length; i++) {
|
|
||||||
if (sponsorTimes[i].UUID === null) {
|
|
||||||
// This is a user submission, keep it
|
|
||||||
recievedSegments.push(sponsorTimes[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sponsorTimes = recievedSegments;
|
|
||||||
|
|
||||||
// Remove all submissions smaller than the minimum duration
|
|
||||||
if (Config.config.minDuration !== 0) {
|
|
||||||
let smallSegments: SponsorTime[] = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < sponsorTimes.length; i++) {
|
|
||||||
if (sponsorTimes[i].segment[1] - sponsorTimes[i].segment[0] >= Config.config.minDuration) {
|
|
||||||
smallSegments.push(sponsorTimes[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sponsorTimes = smallSegments;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!switchingVideos) {
|
|
||||||
// See if there are any starting sponsors
|
|
||||||
let startingSponsor: number = -1;
|
|
||||||
for (const time of sponsorTimes) {
|
|
||||||
if (time[0] <= video.currentTime && time.segment[0] > startingSponsor && time.segment[1] > video.currentTime) {
|
|
||||||
startingSponsor = time.segment[0];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!startingSponsor) {
|
|
||||||
for (const time of sponsorTimesSubmitting) {
|
|
||||||
if (time.segment[0] <= video.currentTime && time.segment[0] > startingSponsor && time.segment[1] > video.currentTime) {
|
|
||||||
startingSponsor = time.segment[0];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (startingSponsor !== -1) {
|
|
||||||
startSponsorSchedule(false, startingSponsor);
|
|
||||||
} else {
|
|
||||||
startSponsorSchedule();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset skip save
|
|
||||||
sponsorSkipped = [];
|
|
||||||
|
|
||||||
//update the preview bar
|
|
||||||
//leave the type blank for now until categories are added
|
|
||||||
if (lastPreviewBarUpdate == id || (lastPreviewBarUpdate == null && !isNaN(video.duration))) {
|
|
||||||
//set it now
|
|
||||||
//otherwise the listener can handle it
|
|
||||||
updatePreviewBar();
|
|
||||||
}
|
|
||||||
|
|
||||||
sponsorLookupRetries = 0;
|
|
||||||
} else if (response.status === 404) {
|
|
||||||
sponsorDataFound = false;
|
|
||||||
|
|
||||||
//check if this video was uploaded recently
|
|
||||||
//use the invidious api to get the time published
|
|
||||||
sendRequestToCustomServer('GET', "https://www.youtube.com/get_video_info?video_id=" + id, function(xmlhttp, error) {
|
|
||||||
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
|
|
||||||
let decodedData = decodeURIComponent(xmlhttp.responseText).match(/player_response=([^&]*)/)[1];
|
|
||||||
|
|
||||||
if (decodedData === undefined) {
|
|
||||||
console.error("[SB] Failed at getting video upload date info from YouTube.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let dateUploaded = JSON.parse(decodedData).microformat.playerMicroformatRenderer.uploadDate;
|
|
||||||
|
|
||||||
//if less than 3 days old
|
|
||||||
if (Date.now() - new Date(dateUploaded).getTime() < 259200000) {
|
|
||||||
//TODO lower when server becomes better
|
|
||||||
setTimeout(() => sponsorsLookup(id, channelIDPromise), 180000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
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, channelIDPromise), 10000);
|
|
||||||
|
|
||||||
sponsorLookupRetries++;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
utils.sendRequestToServer('GET', "/api/getVideoSponsorTimes?videoID=" + id, function(xmlhttp) {
|
|
||||||
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
|
|
||||||
sponsorDataFound = true;
|
|
||||||
|
|
||||||
let recievedSegments: number[][] = JSON.parse(xmlhttp.responseText).sponsorTimes;
|
|
||||||
let recievedUUIDs: string[] = JSON.parse(xmlhttp.responseText).UUIDs;
|
|
||||||
|
|
||||||
// Check if any old submissions should be kept
|
|
||||||
if (sponsorTimes !== null) {
|
|
||||||
for (let i = 0; i < sponsorTimes.length; i++) {
|
|
||||||
if (sponsorTimes[i].UUID === null) {
|
|
||||||
// This is a user submission, keep it
|
|
||||||
recievedSegments.push(sponsorTimes[i].segment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create formatted array
|
|
||||||
sponsorTimes = [];
|
|
||||||
for (let i = 0; i < recievedSegments.length; i++) {
|
|
||||||
sponsorTimes.push({
|
|
||||||
segment: recievedSegments[i],
|
|
||||||
UUID: recievedUUIDs[i],
|
|
||||||
// Force sponsor category for now
|
|
||||||
//TODO: Remove this
|
|
||||||
category: "sponsor"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove all submissions smaller than the minimum duration
|
|
||||||
if (Config.config.minDuration !== 0) {
|
|
||||||
let smallSegments: SponsorTime[] = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < sponsorTimes.length; i++) {
|
|
||||||
if (sponsorTimes[i].segment[1] - sponsorTimes[i].segment[0] >= Config.config.minDuration) {
|
|
||||||
smallSegments.push(sponsorTimes[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sponsorTimes = smallSegments;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!switchingVideos) {
|
|
||||||
// See if there are any starting sponsors
|
|
||||||
let startingSponsor: number = -1;
|
|
||||||
for (const time of sponsorTimes) {
|
|
||||||
if (time[0] <= video.currentTime && time.segment[0] > startingSponsor && time.segment[1] > video.currentTime) {
|
|
||||||
startingSponsor = time.segment[0];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!startingSponsor) {
|
|
||||||
for (const time of sponsorTimesSubmitting) {
|
|
||||||
if (time.segment[0] <= video.currentTime && time.segment[0] > startingSponsor && time.segment[1] > video.currentTime) {
|
|
||||||
startingSponsor = time.segment[0];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (startingSponsor !== -1) {
|
|
||||||
startSponsorSchedule(false, startingSponsor);
|
|
||||||
} else {
|
|
||||||
startSponsorSchedule();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset skip save
|
|
||||||
sponsorSkipped = [];
|
|
||||||
|
|
||||||
//update the preview bar
|
|
||||||
//leave the type blank for now until categories are added
|
|
||||||
if (lastPreviewBarUpdate == id || (lastPreviewBarUpdate == null && !isNaN(video.duration))) {
|
|
||||||
//set it now
|
|
||||||
//otherwise the listener can handle it
|
|
||||||
updatePreviewBar();
|
|
||||||
}
|
|
||||||
|
|
||||||
sponsorLookupRetries = 0;
|
|
||||||
} else if (xmlhttp.readyState == 4 && xmlhttp.status == 404) {
|
|
||||||
sponsorDataFound = false;
|
|
||||||
|
|
||||||
//check if this video was uploaded recently
|
|
||||||
//use the invidious api to get the time published
|
|
||||||
sendRequestToCustomServer('GET', "https://www.youtube.com/get_video_info?video_id=" + id, function(xmlhttp, error) {
|
|
||||||
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
|
|
||||||
let decodedData = decodeURIComponent(xmlhttp.responseText).match(/player_response=([^&]*)/)[1];
|
|
||||||
|
|
||||||
if (decodedData === undefined) {
|
|
||||||
console.error("[SB] Failed at getting video upload date info from YouTube.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let dateUploaded = JSON.parse(decodedData).microformat.playerMicroformatRenderer.uploadDate;
|
|
||||||
|
|
||||||
//if less than 3 days old
|
|
||||||
if (Date.now() - new Date(dateUploaded).getTime() < 259200000) {
|
|
||||||
//TODO lower when server becomes better
|
|
||||||
setTimeout(() => sponsorsLookup(id, channelIDPromise), 180000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
sponsorLookupRetries = 0;
|
|
||||||
} else if (xmlhttp.readyState == 4 && 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, channelIDPromise), 10000);
|
|
||||||
|
|
||||||
sponsorLookupRetries++;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
utils.asyncRequestToServer('GET', "/api/skipSegments", {
|
||||||
|
videoID: id,
|
||||||
|
categories
|
||||||
|
}).then(async (response: Response) => {
|
||||||
|
if (response.status === 200) {
|
||||||
|
let recievedSegments: SponsorTime[] = await response.json();
|
||||||
|
if (!recievedSegments.length) {
|
||||||
|
console.error("[SponsorBlock] Server returned malformed response: " + JSON.stringify(recievedSegments));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sponsorDataFound = true;
|
||||||
|
|
||||||
|
// Check if any old submissions should be kept
|
||||||
|
if (sponsorTimes !== null) {
|
||||||
|
for (let i = 0; i < sponsorTimes.length; i++) {
|
||||||
|
if (sponsorTimes[i].UUID === null) {
|
||||||
|
// This is a user submission, keep it
|
||||||
|
recievedSegments.push(sponsorTimes[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sponsorTimes = recievedSegments;
|
||||||
|
|
||||||
|
// Remove all submissions smaller than the minimum duration
|
||||||
|
if (Config.config.minDuration !== 0) {
|
||||||
|
let smallSegments: SponsorTime[] = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < sponsorTimes.length; i++) {
|
||||||
|
if (sponsorTimes[i].segment[1] - sponsorTimes[i].segment[0] >= Config.config.minDuration) {
|
||||||
|
smallSegments.push(sponsorTimes[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sponsorTimes = smallSegments;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!switchingVideos) {
|
||||||
|
// See if there are any starting sponsors
|
||||||
|
let startingSponsor: number = -1;
|
||||||
|
for (const time of sponsorTimes) {
|
||||||
|
if (time[0] <= video.currentTime && time.segment[0] > startingSponsor && time.segment[1] > video.currentTime) {
|
||||||
|
startingSponsor = time.segment[0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!startingSponsor) {
|
||||||
|
for (const time of sponsorTimesSubmitting) {
|
||||||
|
if (time.segment[0] <= video.currentTime && time.segment[0] > startingSponsor && time.segment[1] > video.currentTime) {
|
||||||
|
startingSponsor = time.segment[0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startingSponsor !== -1) {
|
||||||
|
startSponsorSchedule(false, startingSponsor);
|
||||||
|
} else {
|
||||||
|
startSponsorSchedule();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset skip save
|
||||||
|
sponsorSkipped = [];
|
||||||
|
|
||||||
|
//update the preview bar
|
||||||
|
//leave the type blank for now until categories are added
|
||||||
|
if (lastPreviewBarUpdate == id || (lastPreviewBarUpdate == null && !isNaN(video.duration))) {
|
||||||
|
//set it now
|
||||||
|
//otherwise the listener can handle it
|
||||||
|
updatePreviewBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
sponsorLookupRetries = 0;
|
||||||
|
} else if (response.status === 404) {
|
||||||
|
sponsorDataFound = false;
|
||||||
|
|
||||||
|
//check if this video was uploaded recently
|
||||||
|
//use the invidious api to get the time published
|
||||||
|
sendRequestToCustomServer('GET', "https://www.youtube.com/get_video_info?video_id=" + id, function(xmlhttp, error) {
|
||||||
|
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
|
||||||
|
let decodedData = decodeURIComponent(xmlhttp.responseText).match(/player_response=([^&]*)/)[1];
|
||||||
|
|
||||||
|
if (decodedData === undefined) {
|
||||||
|
console.error("[SB] Failed at getting video upload date info from YouTube.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let dateUploaded = JSON.parse(decodedData).microformat.playerMicroformatRenderer.uploadDate;
|
||||||
|
|
||||||
|
//if less than 3 days old
|
||||||
|
if (Date.now() - new Date(dateUploaded).getTime() < 259200000) {
|
||||||
|
//TODO lower when server becomes better
|
||||||
|
setTimeout(() => sponsorsLookup(id, channelIDPromise), 180000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
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, channelIDPromise), 10000);
|
||||||
|
|
||||||
|
sponsorLookupRetries++;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getYouTubeVideoID(url: string) {
|
function getYouTubeVideoID(url: string) {
|
||||||
@@ -1577,92 +1460,46 @@ async function sendSubmitMessage(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Config.config.testingServer) {
|
let response = await utils.asyncRequestToServer("POST", "/api/skipSegments", {
|
||||||
let response = await utils.asyncRequestToServer("POST", "/api/skipSegments", {
|
videoID: sponsorVideoID,
|
||||||
videoID: sponsorVideoID,
|
userID: Config.config.userID,
|
||||||
userID: Config.config.userID,
|
segments: sponsorTimesSubmitting
|
||||||
segments: sponsorTimesSubmitting
|
});
|
||||||
});
|
|
||||||
|
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
//hide loading message
|
//hide loading message
|
||||||
let submitButton = document.getElementById("submitButton");
|
let submitButton = document.getElementById("submitButton");
|
||||||
submitButton.style.animation = "rotate 1s";
|
submitButton.style.animation = "rotate 1s";
|
||||||
//finish this animation
|
//finish this animation
|
||||||
//when the animation is over, hide the button
|
//when the animation is over, hide the button
|
||||||
let animationEndListener = function() {
|
let animationEndListener = function() {
|
||||||
changeStartSponsorButton(true, false);
|
changeStartSponsorButton(true, false);
|
||||||
|
|
||||||
submitButton.style.animation = "none";
|
submitButton.style.animation = "none";
|
||||||
|
|
||||||
submitButton.removeEventListener("animationend", animationEndListener);
|
submitButton.removeEventListener("animationend", animationEndListener);
|
||||||
};
|
};
|
||||||
|
|
||||||
submitButton.addEventListener("animationend", animationEndListener);
|
submitButton.addEventListener("animationend", animationEndListener);
|
||||||
|
|
||||||
//clear the sponsor times
|
//clear the sponsor times
|
||||||
Config.config.sponsorTimes.delete(sponsorVideoID);
|
Config.config.sponsorTimes.delete(sponsorVideoID);
|
||||||
|
|
||||||
//add submissions to current sponsors list
|
//add submissions to current sponsors list
|
||||||
if (sponsorTimes === null) sponsorTimes = [];
|
if (sponsorTimes === null) sponsorTimes = [];
|
||||||
|
|
||||||
sponsorTimes = sponsorTimes.concat(sponsorTimesSubmitting);
|
sponsorTimes = sponsorTimes.concat(sponsorTimesSubmitting);
|
||||||
|
|
||||||
// Empty the submitting times
|
// Empty the submitting times
|
||||||
sponsorTimesSubmitting = [];
|
sponsorTimesSubmitting = [];
|
||||||
|
|
||||||
updatePreviewBar();
|
|
||||||
} else {
|
|
||||||
//show that the upload failed
|
|
||||||
document.getElementById("submitButton").style.animation = "unset";
|
|
||||||
(<HTMLImageElement> document.getElementById("submitImage")).src = chrome.extension.getURL("icons/PlayerUploadFailedIconSponsorBlocker256px.png");
|
|
||||||
|
|
||||||
alert(utils.getErrorMessage(response.status) + "\n\n" + (await response.text()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
updatePreviewBar();
|
||||||
} else {
|
} else {
|
||||||
chrome.runtime.sendMessage({
|
//show that the upload failed
|
||||||
message: "submitTimes",
|
document.getElementById("submitButton").style.animation = "unset";
|
||||||
videoID: sponsorVideoID
|
(<HTMLImageElement> document.getElementById("submitImage")).src = chrome.extension.getURL("icons/PlayerUploadFailedIconSponsorBlocker256px.png");
|
||||||
}, function(response) {
|
|
||||||
if (response != undefined) {
|
|
||||||
if (response.statusCode == 200) {
|
|
||||||
//hide loading message
|
|
||||||
let submitButton = document.getElementById("submitButton");
|
|
||||||
submitButton.style.animation = "rotate 1s";
|
|
||||||
//finish this animation
|
|
||||||
//when the animation is over, hide the button
|
|
||||||
let animationEndListener = function() {
|
|
||||||
changeStartSponsorButton(true, false);
|
|
||||||
|
|
||||||
submitButton.style.animation = "none";
|
alert(utils.getErrorMessage(response.status) + "\n\n" + (await response.text()));
|
||||||
|
|
||||||
submitButton.removeEventListener("animationend", animationEndListener);
|
|
||||||
};
|
|
||||||
|
|
||||||
submitButton.addEventListener("animationend", animationEndListener);
|
|
||||||
|
|
||||||
//clear the sponsor times
|
|
||||||
Config.config.sponsorTimes.delete(sponsorVideoID);
|
|
||||||
|
|
||||||
//add submissions to current sponsors list
|
|
||||||
if (sponsorTimes === null) sponsorTimes = [];
|
|
||||||
|
|
||||||
sponsorTimes = sponsorTimes.concat(sponsorTimesSubmitting);
|
|
||||||
|
|
||||||
// Empty the submitting times
|
|
||||||
sponsorTimesSubmitting = [];
|
|
||||||
|
|
||||||
updatePreviewBar();
|
|
||||||
} else {
|
|
||||||
//show that the upload failed
|
|
||||||
document.getElementById("submitButton").style.animation = "unset";
|
|
||||||
(<HTMLImageElement> document.getElementById("submitImage")).src = chrome.extension.getURL("icons/PlayerUploadFailedIconSponsorBlocker256px.png");
|
|
||||||
|
|
||||||
alert(utils.getErrorMessage(response.statusCode) + "\n\n" + response.responseText);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ class SkipNotice {
|
|||||||
// Contains functions and variables from the content script needed by the skip notice
|
// Contains functions and variables from the content script needed by the skip notice
|
||||||
contentContainer: () => any;
|
contentContainer: () => any;
|
||||||
|
|
||||||
|
noticeElement: HTMLDivElement;
|
||||||
|
|
||||||
constructor(UUID: string, autoSkip: boolean = false, contentContainer) {
|
constructor(UUID: string, autoSkip: boolean = false, contentContainer) {
|
||||||
this.UUID = UUID;
|
this.UUID = UUID;
|
||||||
this.autoSkip = autoSkip;
|
this.autoSkip = autoSkip;
|
||||||
@@ -35,16 +37,25 @@ class SkipNotice {
|
|||||||
//this is the suffix added at the end of every id
|
//this is the suffix added at the end of every id
|
||||||
let idSuffix = this.UUID + amountOfPreviousNotices;
|
let idSuffix = this.UUID + amountOfPreviousNotices;
|
||||||
|
|
||||||
let noticeElement = document.createElement("div");
|
this.noticeElement = document.createElement("div");
|
||||||
noticeElement.id = "sponsorSkipNoticeContainer" + idSuffix;
|
this.noticeElement.id = "sponsorSkipNoticeContainer" + idSuffix;
|
||||||
|
|
||||||
referenceNode.prepend(noticeElement);
|
referenceNode.prepend(this.noticeElement);
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<SkipNoticeComponent UUID={UUID} autoSkip={autoSkip} contentContainer={contentContainer} />,
|
<SkipNoticeComponent UUID={UUID}
|
||||||
noticeElement
|
autoSkip={autoSkip}
|
||||||
|
contentContainer={contentContainer}
|
||||||
|
closeListener={() => this.close()} />,
|
||||||
|
this.noticeElement
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
close() {
|
||||||
|
ReactDOM.unmountComponentAtNode(this.noticeElement);
|
||||||
|
|
||||||
|
this.noticeElement.remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SkipNotice;
|
export default SkipNotice;
|
||||||
@@ -11,6 +11,8 @@ class SubmissionNotice {
|
|||||||
|
|
||||||
noticeRef: React.MutableRefObject<SubmissionNoticeComponent>;
|
noticeRef: React.MutableRefObject<SubmissionNoticeComponent>;
|
||||||
|
|
||||||
|
noticeElement: HTMLDivElement;
|
||||||
|
|
||||||
constructor(contentContainer: () => any, callback: () => any) {
|
constructor(contentContainer: () => any, callback: () => any) {
|
||||||
this.noticeRef = React.createRef();
|
this.noticeRef = React.createRef();
|
||||||
|
|
||||||
@@ -34,23 +36,30 @@ class SubmissionNotice {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let noticeElement = document.createElement("div");
|
this.noticeElement = document.createElement("div");
|
||||||
noticeElement.id = "submissionNoticeContainer";
|
this.noticeElement.id = "submissionNoticeContainer";
|
||||||
|
|
||||||
referenceNode.prepend(noticeElement);
|
referenceNode.prepend(this.noticeElement);
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<SubmissionNoticeComponent
|
<SubmissionNoticeComponent
|
||||||
contentContainer={contentContainer}
|
contentContainer={contentContainer}
|
||||||
callback={callback}
|
callback={callback}
|
||||||
ref={this.noticeRef} />,
|
ref={this.noticeRef}
|
||||||
noticeElement
|
closeListener={() => this.close()} />,
|
||||||
|
this.noticeElement
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
update() {
|
update() {
|
||||||
this.noticeRef.current.forceUpdate();
|
this.noticeRef.current.forceUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
close() {
|
||||||
|
ReactDOM.unmountComponentAtNode(this.noticeElement);
|
||||||
|
|
||||||
|
this.noticeElement.remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SubmissionNotice;
|
export default SubmissionNotice;
|
||||||
Reference in New Issue
Block a user