mirror of
https://github.com/th-ch/youtube-music.git
synced 2026-01-13 19:31:46 +00:00
convert plugins
This commit is contained in:
@ -1,4 +1,11 @@
|
||||
import { createPluginBuilder } from '../utils/builder';
|
||||
import is from 'electron-is';
|
||||
|
||||
import { createPlugin } from '@/utils';
|
||||
|
||||
import { sortSegments } from './segments';
|
||||
|
||||
import type { GetPlayerResponse } from '@/types/get-player-response';
|
||||
import type { Segment, SkipSegment } from './types';
|
||||
|
||||
export type SponsorBlockPluginConfig = {
|
||||
enabled: boolean;
|
||||
@ -6,7 +13,9 @@ export type SponsorBlockPluginConfig = {
|
||||
categories: ('sponsor' | 'intro' | 'outro' | 'interaction' | 'selfpromo' | 'music_offtopic')[];
|
||||
};
|
||||
|
||||
const builder = createPluginBuilder('sponsorblock', {
|
||||
let currentSegments: Segment[] = [];
|
||||
|
||||
export default createPlugin({
|
||||
name: 'SponsorBlock',
|
||||
restartNeeded: true,
|
||||
config: {
|
||||
@ -21,12 +30,83 @@ const builder = createPluginBuilder('sponsorblock', {
|
||||
'music_offtopic',
|
||||
],
|
||||
} as SponsorBlockPluginConfig,
|
||||
});
|
||||
async backend({ getConfig, ipc }) {
|
||||
const fetchSegments = async (apiURL: string, categories: string[], videoId: string) => {
|
||||
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 [];
|
||||
}
|
||||
|
||||
export default builder;
|
||||
const segments = await resp.json() as SkipSegment[];
|
||||
return sortSegments(
|
||||
segments.map((submission) => submission.segment),
|
||||
);
|
||||
} catch (error) {
|
||||
if (is.dev()) {
|
||||
console.log('error on sponsorblock request:', error);
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface PluginBuilderList {
|
||||
[builder.id]: typeof builder;
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
const config = await getConfig();
|
||||
|
||||
const { apiURL, categories } = config;
|
||||
|
||||
ipc.on('video-src-changed', async (data: GetPlayerResponse) => {
|
||||
const segments = await fetchSegments(apiURL, categories, data?.videoDetails?.videoId);
|
||||
ipc.send('sponsorblock-skip', segments);
|
||||
});
|
||||
},
|
||||
renderer: {
|
||||
timeUpdateListener: (e: Event) => {
|
||||
if (e.target instanceof HTMLVideoElement) {
|
||||
const target = e.target;
|
||||
|
||||
for (const segment of currentSegments) {
|
||||
if (
|
||||
target.currentTime >= segment[0]
|
||||
&& target.currentTime < segment[1]
|
||||
) {
|
||||
target.currentTime = segment[1];
|
||||
if (window.electronIs.dev()) {
|
||||
console.log('SponsorBlock: skipping segment', segment);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
resetSegments: () => currentSegments = [],
|
||||
start({ ipc }) {
|
||||
ipc.on('sponsorblock-skip', (segments: Segment[]) => {
|
||||
currentSegments = segments;
|
||||
});
|
||||
},
|
||||
onPlayerApiReady() {
|
||||
const video = document.querySelector<HTMLVideoElement>('video');
|
||||
if (!video) return;
|
||||
|
||||
video.addEventListener('timeupdate', this.timeUpdateListener);
|
||||
// Reset segments on song end
|
||||
video.addEventListener('emptied', this.resetSegments);
|
||||
},
|
||||
stop() {
|
||||
const video = document.querySelector<HTMLVideoElement>('video');
|
||||
if (!video) return;
|
||||
|
||||
video.removeEventListener('timeupdate', this.timeUpdateListener);
|
||||
video.removeEventListener('emptied', this.resetSegments);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,51 +0,0 @@
|
||||
import is from 'electron-is';
|
||||
|
||||
import { sortSegments } from './segments';
|
||||
|
||||
import { SkipSegment } from './types';
|
||||
|
||||
import builder from './index';
|
||||
|
||||
import type { GetPlayerResponse } from '../../types/get-player-response';
|
||||
|
||||
const fetchSegments = async (apiURL: string, categories: string[], videoId: string) => {
|
||||
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() as SkipSegment[];
|
||||
return sortSegments(
|
||||
segments.map((submission) => submission.segment),
|
||||
);
|
||||
} catch (error) {
|
||||
if (is.dev()) {
|
||||
console.log('error on sponsorblock request:', error);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
export default builder.createMain(({ getConfig, on, send }) => ({
|
||||
async onLoad() {
|
||||
const config = await getConfig();
|
||||
|
||||
const { apiURL, categories } = config;
|
||||
|
||||
on('video-src-changed', async (_, data: GetPlayerResponse) => {
|
||||
const segments = await fetchSegments(apiURL, categories, data?.videoDetails?.videoId);
|
||||
send('sponsorblock-skip', segments);
|
||||
});
|
||||
}
|
||||
}));
|
||||
@ -1,49 +0,0 @@
|
||||
import { Segment } from './types';
|
||||
import builder from './index';
|
||||
|
||||
export default builder.createRenderer(({ on }) => {
|
||||
let currentSegments: Segment[] = [];
|
||||
|
||||
const timeUpdateListener = (e: Event) => {
|
||||
if (e.target instanceof HTMLVideoElement) {
|
||||
const target = e.target;
|
||||
|
||||
for (const segment of currentSegments) {
|
||||
if (
|
||||
target.currentTime >= segment[0]
|
||||
&& target.currentTime < segment[1]
|
||||
) {
|
||||
target.currentTime = segment[1];
|
||||
if (window.electronIs.dev()) {
|
||||
console.log('SponsorBlock: skipping segment', segment);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const resetSegments = () => currentSegments = [];
|
||||
|
||||
return ({
|
||||
onLoad() {
|
||||
on('sponsorblock-skip', (_, segments: Segment[]) => {
|
||||
currentSegments = segments;
|
||||
});
|
||||
},
|
||||
onPlayerApiReady() {
|
||||
const video = document.querySelector<HTMLVideoElement>('video');
|
||||
if (!video) return;
|
||||
|
||||
video.addEventListener('timeupdate', timeUpdateListener);
|
||||
// Reset segments on song end
|
||||
video.addEventListener('emptied', resetSegments);
|
||||
},
|
||||
onUnload() {
|
||||
const video = document.querySelector<HTMLVideoElement>('video');
|
||||
if (!video) return;
|
||||
|
||||
video.removeEventListener('timeupdate', timeUpdateListener);
|
||||
video.removeEventListener('emptied', resetSegments);
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user