Skip to content

Commit

Permalink
Merge pull request #308 from th-ch/sponsorblock-plugin
Browse files Browse the repository at this point in the history
Add Sponsorblock plugin
  • Loading branch information
th-ch committed Jun 4, 2021
2 parents cda07c9 + 4a60aa9 commit 3485d26
Show file tree
Hide file tree
Showing 9 changed files with 189 additions and 26 deletions.
14 changes: 13 additions & 1 deletion config/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,19 @@ const defaultConfig = {
volumeDown: "Shift+PageDown"
},
savedVolume: undefined //plugin save volume between session here
}
},
sponsorblock: {
enabled: false,
apiURL: "https://sponsor.ajay.app",
categories: [
"sponsor",
"intro",
"outro",
"interaction",
"selfpromo",
"music_offtopic",
],
},
},
};

Expand Down
1 change: 0 additions & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,5 @@ module.exports = {
globals: {
__APP__: undefined, // A different app will be launched in each test environment
},
testEnvironment: "./tests/environment",
testTimeout: 30000, // 30s
};
33 changes: 9 additions & 24 deletions plugins/disable-autoplay/front.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,10 @@
let videoElement = null;

const observer = new MutationObserver((mutations, observer) => {
if (!videoElement) {
videoElement = document.querySelector("video");
}

if (videoElement) {
videoElement.ontimeupdate = () => {
if (videoElement.currentTime === 0 && videoElement.duration !== NaN) {
// auto-confirm-when-paused plugin can interfere here if not disabled!
videoElement.pause();
}
};
}
});

function observeVideoElement() {
observer.observe(document, {
childList: true,
subtree: true,
const { ontimeupdate } = require("../../providers/video-element");

module.exports = () => {
ontimeupdate((videoElement) => {
if (videoElement.currentTime === 0 && videoElement.duration !== NaN) {
// auto-confirm-when-paused plugin can interfere here if not disabled!
videoElement.pause();
}
});
}

module.exports = observeVideoElement;
};
51 changes: 51 additions & 0 deletions plugins/sponsorblock/back.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
const fetch = require("node-fetch");

const defaultConfig = require("../../config/defaults");
const registerCallback = require("../../providers/song-info");
const { sortSegments } = require("./segments");

let videoID;

module.exports = (win, options) => {
const { apiURL, categories } = {
...defaultConfig.plugins.sponsorblock,
...options,
};

registerCallback(async (info) => {
const newURL = info.url || win.webContents.getURL();
const newVideoID = new URL(newURL).searchParams.get("v");

if (videoID !== newVideoID) {
videoID = newVideoID;
const segments = await fetchSegments(apiURL, categories);
win.webContents.send("sponsorblock-skip", segments);
}
});
};

const fetchSegments = async (apiURL, categories) => {
const sponsorBlockURL = `${apiURL}/api/skipSegments?videoID=${videoID}&categories=${JSON.stringify(
categories
)}`;
try {
const resp = await fetch(sponsorBlockURL, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
redirect: "follow",
});
if (resp.status !== 200) {
return [];
}
const segments = await resp.json();
const sortedSegments = sortSegments(
segments.map((submission) => submission.segment)
);

return sortedSegments;
} catch {
return [];
}
};
27 changes: 27 additions & 0 deletions plugins/sponsorblock/front.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const { ipcRenderer } = require("electron");

const is = require("electron-is");

const { ontimeupdate } = require("../../providers/video-element");

let currentSegments = [];

module.exports = () => {
ipcRenderer.on("sponsorblock-skip", (_, segments) => {
currentSegments = segments;
});

ontimeupdate((videoElement) => {
currentSegments.forEach((segment) => {
if (
videoElement.currentTime >= segment[0] &&
videoElement.currentTime <= segment[1]
) {
videoElement.currentTime = segment[1];
if (is.dev()) {
console.log("SponsorBlock: skipping segment", segment);
}
}
});
});
};
29 changes: 29 additions & 0 deletions plugins/sponsorblock/segments.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Segments are an array [ [start, end], … ]
module.exports.sortSegments = (segments) => {
segments.sort((segment1, segment2) =>
segment1[0] === segment2[0]
? segment1[1] - segment2[1]
: segment1[0] - segment2[0]
);

const compiledSegments = [];
let currentSegment;

segments.forEach((segment) => {
if (!currentSegment) {
currentSegment = segment;
return;
}

if (currentSegment[1] < segment[0]) {
compiledSegments.push(currentSegment);
currentSegment = segment;
return;
}

currentSegment[1] = Math.max(currentSegment[1], segment[1]);
});
compiledSegments.push(currentSegment);

return compiledSegments;
};
34 changes: 34 additions & 0 deletions plugins/sponsorblock/tests/segments.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
const { sortSegments } = require("../segments");

test("Segment sorting", () => {
expect(
sortSegments([
[0, 3],
[7, 8],
[5, 6],
])
).toEqual([
[0, 3],
[5, 6],
[7, 8],
]);

expect(
sortSegments([
[0, 5],
[6, 8],
[4, 6],
])
).toEqual([[0, 8]]);

expect(
sortSegments([
[0, 6],
[7, 8],
[4, 6],
])
).toEqual([
[0, 6],
[7, 8],
]);
});
22 changes: 22 additions & 0 deletions providers/video-element.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
let videoElement = null;

module.exports.ontimeupdate = (cb) => {
const observer = new MutationObserver((mutations, observer) => {
if (!videoElement) {
videoElement = document.querySelector("video");
if (videoElement) {
observer.disconnect();
videoElement.ontimeupdate = () => cb(videoElement);
}
}
});

if (!videoElement) {
observer.observe(document, {
childList: true,
subtree: true,
});
} else {
videoElement.ontimeupdate = () => cb(videoElement);
}
};
4 changes: 4 additions & 0 deletions tests/index.test.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/**
* @jest-environment ./tests/environment
*/

describe("YouTube Music App", () => {
const app = global.__APP__;

Expand Down

0 comments on commit 3485d26

Please sign in to comment.