Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
925ef98
Plugin that tries to skip live versions of songs
amontariol Nov 18, 2025
bee0523
Update src/plugins/skip-live-songs/index.ts
amontariol Nov 19, 2025
7ab5bf3
Update src/plugins/skip-live-songs/index.ts
amontariol Nov 19, 2025
63776bf
Update src/plugins/skip-live-songs/index.ts
amontariol Nov 19, 2025
4e6256e
Update src/plugins/skip-live-songs/index.ts
amontariol Nov 19, 2025
e1f559e
Update src/plugins/skip-live-songs/index.ts
amontariol Nov 19, 2025
f63bb72
Update src/plugins/skip-live-songs/patterns.ts
amontariol Nov 19, 2025
43992d7
Update src/plugins/skip-live-songs/patterns.ts
amontariol Nov 19, 2025
10c4584
Update src/plugins/skip-live-songs/patterns.ts
amontariol Nov 19, 2025
c60d715
Update src/plugins/skip-live-songs/patterns.ts
amontariol Nov 19, 2025
0f9c16e
Update src/plugins/skip-live-songs/patterns.ts
amontariol Nov 19, 2025
70e6ce1
Update src/plugins/skip-live-songs/index.ts
amontariol Nov 19, 2025
e2c07fe
Update src/plugins/skip-live-songs/index.ts
amontariol Nov 19, 2025
41f8334
Update src/plugins/skip-live-songs/patterns.ts
amontariol Nov 19, 2025
473c942
Update src/plugins/skip-live-songs/index.ts
amontariol Nov 19, 2025
548c536
Update src/plugins/skip-live-songs/index.ts
amontariol Nov 19, 2025
dd350d4
Update src/plugins/skip-live-songs/patterns.ts
amontariol Nov 19, 2025
16df9f3
Update src/plugins/skip-live-songs/patterns.ts
amontariol Nov 19, 2025
0000964
Update src/plugins/skip-live-songs/patterns.ts
amontariol Nov 19, 2025
445448b
Update src/plugins/skip-live-songs/patterns.ts
amontariol Nov 19, 2025
36c3d09
Update src/plugins/skip-live-songs/patterns.ts
amontariol Nov 19, 2025
2f02ace
Apply suggestions from code review
amontariol Nov 19, 2025
5e58654
Update src/plugins/skip-live-songs/index.ts
amontariol Nov 19, 2025
d6c4f78
Update src/plugins/skip-live-songs/index.ts
amontariol Nov 19, 2025
e6a9339
Update src/plugins/skip-live-songs/index.ts
amontariol Nov 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/i18n/resources/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,10 @@
"description": "Automatically skip silences sections in songs",
"name": "Skip Silences"
},
"skip-live-songs": {
"description": "Automatically tries to skip renditions of songs",
"name": "Skip Live Songs"
},
"sponsorblock": {
"description": "Automatically Skips non-music parts like intro/outro or parts of music videos where the song isn't playing",
"name": "SponsorBlock"
Expand Down
90 changes: 90 additions & 0 deletions src/plugins/skip-live-songs/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { t } from '@/i18n';
import { createPlugin } from '@/utils';

import type { SongInfo } from '@/providers/song-info';
import { nonStudioPatterns } from './patterns';

import type { SongInfo } from '@/providers/song-info';
Comment on lines +4 to +7
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [eslint] <importPlugin/no-duplicates> reported by reviewdog 🐶
'/home/runner/work/pear-desktop/pear-desktop/src/providers/song-info.ts' imported multiple times.

Suggested change
import type { SongInfo } from '@/providers/song-info';
import { nonStudioPatterns } from './patterns';
import type { SongInfo } from '@/providers/song-info';
import type { SongInfo } from '@/providers/song-info';
import { nonStudioPatterns } from './patterns';

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [eslint] <importPlugin/no-duplicates> reported by reviewdog 🐶
'/home/runner/work/pear-desktop/pear-desktop/src/providers/song-info.ts' imported multiple times.


export default createPlugin({
name: () => t('plugins.skip-live-songs.name'),
description: () => t('plugins.skip-live-songs.description'),
restartNeeded: false,
config: {
enabled: false,
},
renderer: {
lastSkippedVideoId: '',

_skipLiveHandler: undefined as unknown as
| ((songInfo: SongInfo) => void)
| undefined,

start({ ipc }) {
console.debug('[Skip Live Songs] Renderer started');

const SELECTORS = [
'yt-icon-button.next-button',
'.next-button',
'button[aria-label*="Next"]',
'button[aria-label*="next"]',
'#player-bar-next-button',
'ytmusic-player-bar .next-button',
'.player-bar .next-button',
];

const handler = (songInfo: SongInfo) => {
const titleToCheck = songInfo.alternativeTitle || songInfo.title;
if (!titleToCheck) return;

// Skip if we've already attempted this video id
if (songInfo.videoId === this.lastSkippedVideoId) return;

const isNonStudio = nonStudioPatterns.some((pattern) =>
pattern.test(titleToCheck),
);

if (!isNonStudio) return; // studio version — nothing to do

// Mark as attempted so we don't loop repeatedly
this.lastSkippedVideoId = songInfo.videoId;
console.info(
`[Skip Live Songs] Skipping non-studio song: "${titleToCheck}" (id: ${songInfo.videoId})`,
);

let clicked = false;
for (const sel of SELECTORS) {
const button = document.querySelector<HTMLElement>(sel);
if (button) {
button.click();
console.debug(
`[Skip Live Songs] Clicked next button using selector: ${sel}`,
);
clicked = true;
break;
}
}

if (!clicked) {
console.warn(
'[Skip Live Songs] Could not find next button with any configured selector',
);
}
};

this._skipLiveHandler = handler;
ipc.on('peard:update-song-info', handler);
},

// Unregister the ipc handler on plugin stop to avoid duplicate listeners on hot reload
stop({ ipc }) {
if (this._skipLiveHandler) {
ipc.removeAllListeners('peard:update-song-info');
this._skipLiveHandler = undefined;
console.debug(
'[Skip Live Songs] Renderer stopped and listeners removed',
);
}
},
},
});
34 changes: 34 additions & 0 deletions src/plugins/skip-live-songs/patterns.ts
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* Patterns to detect non-studio recordings
*
* Add or modify patterns here to customize what gets skipped.
* All patterns are not case-sensitive.
*/

export const nonStudioPatterns = [
// "Live" in specific contexts (not as part of song title)
/[\(\[]live[\)\]]/i, // "(Live)" or "[Live]" in parentheses/brackets
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [eslint] <no-useless-escape> reported by reviewdog 🐶
Unnecessary escape character: (.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [eslint] <no-useless-escape> reported by reviewdog 🐶
Unnecessary escape character: [.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [eslint] <no-useless-escape> reported by reviewdog 🐶
Unnecessary escape character: ).

/live\s+(at|from|in|on|with|@)/i, // "Live at", "Live from", "Live in", etc.
/live\s+with\b/i, // "Live with" (e.g. "Live with the SFSO")
/-\s*live\s*$/i, // "- Live" at the end of title
/:\s*live\s*$/i, // ": Live" at the end of title
// Concert/Performance indicators
/\b(concert|festival|tour)\b/i, // Concert, Festival, Tour
/\(.*?(concert|live performance|live recording).*?(19|20)\d{2}\)/i, // (Live 1985), (Concert 2024)
// Recording types
/\b(acoustic|unplugged|rehearsal|demo)\b/i, // Acoustic, Unplugged, Rehearsal, Demo
// Venues
/\b(arena|stadium|center|centre|hall)\b/i, // Arena, Stadium, Center, Hall
/\bmadison\s+square\s+garden\b/i, // Madison Square Garden
/day\s+on\s+the\s+green/i, // Day on the Green
// Famous venues/festivals
/\b(wembley|glastonbury|woodstock|coachella)\b/i, // Wembley, Glastonbury, Woodstock, Coachella
// Dates and locations
/\b(january|february|march|april|may|june|july|august|september|october|november|december)\s+\d+/i, // "September 22", "August 31"
/\b\d{1,2}[/-]\d{1,2}[/-]\d{2,4}\b/, // Date formats: 09/22/2024, 9-22-24
/\b[A-Z][a-z]+,\s*[A-Z]{2}\b/, // Locations: "Oakland, CA", "London, UK"
/\b[A-Z][a-z]+\s+City\b/i, // Cities: "Mexico City", "New York City"
/\b(tokyo|paris|berlin|sydney)\b/i, // More cities
/\b(bbc|radio|session)\b/i, // Radio sessions
];

Loading