mirror of
https://github.com/th-ch/youtube-music.git
synced 2026-01-15 12:21:47 +00:00
feat: migration to TypeScript FINAL
Co-authored-by: Su-Yong <simssy2205@gmail.com>
This commit is contained in:
@ -1,26 +1,31 @@
|
||||
const { ipcMain } = require('electron');
|
||||
const is = require('electron-is');
|
||||
import { BrowserWindow, ipcMain } from 'electron';
|
||||
import is from 'electron-is';
|
||||
|
||||
const { sortSegments } = require('./segments');
|
||||
import { sortSegments } from './segments';
|
||||
|
||||
const defaultConfig = require('../../config/defaults');
|
||||
import { SkipSegment } from './types';
|
||||
|
||||
let videoID;
|
||||
import defaultConfig from '../../config/defaults';
|
||||
import { GetPlayerResponse } from '../../types/get-player-response';
|
||||
|
||||
module.exports = (win, options) => {
|
||||
import type { ConfigType } from '../../config/dynamic';
|
||||
|
||||
let videoID: string;
|
||||
|
||||
export default (win: BrowserWindow, options: ConfigType<'sponsorblock'>) => {
|
||||
const { apiURL, categories } = {
|
||||
...defaultConfig.plugins.sponsorblock,
|
||||
...options,
|
||||
};
|
||||
|
||||
ipcMain.on('video-src-changed', async (_, data) => {
|
||||
videoID = JSON.parse(data)?.videoDetails?.videoId;
|
||||
ipcMain.on('video-src-changed', async (_, data: string) => {
|
||||
videoID = (JSON.parse(data) as GetPlayerResponse)?.videoDetails?.videoId;
|
||||
const segments = await fetchSegments(apiURL, categories);
|
||||
win.webContents.send('sponsorblock-skip', segments);
|
||||
});
|
||||
};
|
||||
|
||||
const fetchSegments = async (apiURL, categories) => {
|
||||
const fetchSegments = async (apiURL: string, categories: string[]) => {
|
||||
const sponsorBlockURL = `${apiURL}/api/skipSegments?videoID=${videoID}&categories=${JSON.stringify(
|
||||
categories,
|
||||
)}`;
|
||||
@ -36,7 +41,7 @@ const fetchSegments = async (apiURL, categories) => {
|
||||
return [];
|
||||
}
|
||||
|
||||
const segments = await resp.json();
|
||||
const segments = await resp.json() as SkipSegment[];
|
||||
return sortSegments(
|
||||
segments.map((submission) => submission.segment),
|
||||
);
|
||||
@ -1,30 +0,0 @@
|
||||
const { ipcRenderer } = require('electron');
|
||||
const is = require('electron-is');
|
||||
|
||||
let currentSegments = [];
|
||||
|
||||
module.exports = () => {
|
||||
ipcRenderer.on('sponsorblock-skip', (_, segments) => {
|
||||
currentSegments = segments;
|
||||
});
|
||||
|
||||
document.addEventListener('apiLoaded', () => {
|
||||
const video = document.querySelector('video');
|
||||
|
||||
video.addEventListener('timeupdate', (e) => {
|
||||
for (const segment of currentSegments) {
|
||||
if (
|
||||
e.target.currentTime >= segment[0]
|
||||
&& e.target.currentTime < segment[1]
|
||||
) {
|
||||
e.target.currentTime = segment[1];
|
||||
if (is.dev()) {
|
||||
console.log('SponsorBlock: skipping segment', segment);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
// Reset segments on song end
|
||||
video.addEventListener('emptied', () => currentSegments = []);
|
||||
}, { once: true, passive: true });
|
||||
};
|
||||
35
plugins/sponsorblock/front.ts
Normal file
35
plugins/sponsorblock/front.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { ipcRenderer } from 'electron';
|
||||
import is from 'electron-is';
|
||||
|
||||
import { Segment } from './types';
|
||||
|
||||
let currentSegments: Segment[] = [];
|
||||
|
||||
export default () => {
|
||||
ipcRenderer.on('sponsorblock-skip', (_, segments: Segment[]) => {
|
||||
currentSegments = segments;
|
||||
});
|
||||
|
||||
document.addEventListener('apiLoaded', () => {
|
||||
const video = document.querySelector('video') as HTMLVideoElement | undefined;
|
||||
if (!video) return;
|
||||
|
||||
video.addEventListener('timeupdate', (e) => {
|
||||
const target = e.target as HTMLVideoElement;
|
||||
|
||||
for (const segment of currentSegments) {
|
||||
if (
|
||||
target.currentTime >= segment[0]
|
||||
&& target.currentTime < segment[1]
|
||||
) {
|
||||
target.currentTime = segment[1];
|
||||
if (is.dev()) {
|
||||
console.log('SponsorBlock: skipping segment', segment);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
// Reset segments on song end
|
||||
video.addEventListener('emptied', () => currentSegments = []);
|
||||
}, { once: true, passive: true });
|
||||
};
|
||||
@ -1,13 +1,15 @@
|
||||
// Segments are an array [ [start, end], … ]
|
||||
module.exports.sortSegments = (segments) => {
|
||||
import { Segment } from './types';
|
||||
|
||||
export const sortSegments = (segments: Segment[]) => {
|
||||
segments.sort((segment1, segment2) =>
|
||||
segment1[0] === segment2[0]
|
||||
? segment1[1] - segment2[1]
|
||||
: segment1[0] - segment2[0],
|
||||
);
|
||||
|
||||
const compiledSegments = [];
|
||||
let currentSegment;
|
||||
const compiledSegments: Segment[] = [];
|
||||
let currentSegment: Segment | undefined;
|
||||
|
||||
for (const segment of segments) {
|
||||
if (!currentSegment) {
|
||||
@ -24,7 +26,9 @@ module.exports.sortSegments = (segments) => {
|
||||
currentSegment[1] = Math.max(currentSegment[1], segment[1]);
|
||||
}
|
||||
|
||||
compiledSegments.push(currentSegment);
|
||||
if (currentSegment) {
|
||||
compiledSegments.push(currentSegment);
|
||||
}
|
||||
|
||||
return compiledSegments;
|
||||
};
|
||||
12
plugins/sponsorblock/types.ts
Normal file
12
plugins/sponsorblock/types.ts
Normal file
@ -0,0 +1,12 @@
|
||||
export type Segment = [number, number];
|
||||
|
||||
export interface SkipSegment { // Array of this object
|
||||
segment: Segment; //[0, 15.23] start and end time in seconds
|
||||
UUID: string,
|
||||
category: string, // [1]
|
||||
videoDuration: number // Duration of video when submission occurred (to be used to determine when a submission is out of date). 0 when unknown. +- 1 second
|
||||
actionType: string, // [3]
|
||||
locked: number, // if submission is locked
|
||||
votes: number, // Votes on segment
|
||||
description: string, // title for chapters, empty string for other segments
|
||||
}
|
||||
Reference in New Issue
Block a user