mirror of
https://github.com/th-ch/youtube-music.git
synced 2026-01-10 10:11:46 +00:00
feat: Support disabling scrobbling for non-music content (#1665)
Co-authored-by: JellyBrick <shlee1503@naver.com>
This commit is contained in:
@ -147,7 +147,7 @@ winget install th-ch.YouTubeMusic
|
||||
> (see [this post](https://github.com/th-ch/youtube-music/issues/410#issuecomment-952060709) if you have problem
|
||||
accessing the menu after enabling this plugin and hide-menu option)
|
||||
|
||||
- [**Last.fm**](https://www.last.fm/): Scrobbles support
|
||||
- **Scrobbler**: Adds scrobbling support for [Last.fm](https://www.last.fm/) and [ListenBrainz](https://listenbrainz.org/)
|
||||
|
||||
- **Lumia Stream**: Adds [Lumia Stream](https://lumiastream.com/) support
|
||||
|
||||
|
||||
@ -32,6 +32,7 @@ export interface DefaultConfig {
|
||||
proxy: string;
|
||||
startingPage: string;
|
||||
overrideUserAgent: boolean;
|
||||
usePodcastParticipantAsArtist: boolean;
|
||||
themes: string[];
|
||||
};
|
||||
plugins: Record<string, unknown>;
|
||||
@ -66,6 +67,7 @@ const defaultConfig: DefaultConfig = {
|
||||
proxy: '',
|
||||
startingPage: '',
|
||||
overrideUserAgent: false,
|
||||
usePodcastParticipantAsArtist: false,
|
||||
themes: [],
|
||||
},
|
||||
'plugins': {},
|
||||
|
||||
@ -572,6 +572,7 @@
|
||||
"scrobbler": {
|
||||
"description": "Add scrobbling support (etc. last.fm, Listenbrainz)",
|
||||
"menu": {
|
||||
"scrobble-other-media": "Scrobble other media",
|
||||
"lastfm": {
|
||||
"api-settings": "Last.fm API Settings"
|
||||
},
|
||||
|
||||
@ -6,6 +6,12 @@ import { backend } from './main';
|
||||
|
||||
export interface ScrobblerPluginConfig {
|
||||
enabled: boolean,
|
||||
/**
|
||||
* Attempt to scrobble other video types (e.g. Podcasts, normal YouTube videos)
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
scrobble_other_media: boolean,
|
||||
scrobblers: {
|
||||
lastfm: {
|
||||
/**
|
||||
@ -64,6 +70,7 @@ export interface ScrobblerPluginConfig {
|
||||
|
||||
export const defaultConfig: ScrobblerPluginConfig = {
|
||||
enabled: false,
|
||||
scrobble_other_media: true,
|
||||
scrobblers: {
|
||||
lastfm: {
|
||||
enabled: false,
|
||||
|
||||
@ -51,6 +51,11 @@ export const backend = createBackend<{
|
||||
clearTimeout(scrobbleTimer);
|
||||
if (!songInfo.isPaused) {
|
||||
const configNonnull = this.config!;
|
||||
// Scrobblers normally have no trouble working with official music videos
|
||||
if (!configNonnull.scrobble_other_media && (songInfo.mediaType !== 'AUDIO' && songInfo.mediaType !== 'ORIGINAL_MUSIC_VIDEO')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Scrobble when the song is halfway through, or has passed the 4-minute mark
|
||||
const scrobbleTime = Math.min(Math.ceil(songInfo.songDuration / 2), 4 * 60);
|
||||
if (scrobbleTime > (songInfo.elapsedSeconds ?? 0)) {
|
||||
|
||||
@ -79,6 +79,15 @@ export const onMenu = async ({
|
||||
const config = await getConfig();
|
||||
|
||||
return [
|
||||
{
|
||||
label: t('plugins.scrobbler.menu.scrobble-other-media'),
|
||||
type: 'checkbox',
|
||||
checked: Boolean(config.scrobble_other_media),
|
||||
click(item) {
|
||||
config.scrobble_other_media = item.checked;
|
||||
setConfig(config);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Last.fm',
|
||||
submenu: [
|
||||
|
||||
@ -164,12 +164,6 @@ export default (api: YoutubePlayer) => {
|
||||
data.videoDetails.elapsedSeconds = 0;
|
||||
data.videoDetails.isPaused = false;
|
||||
|
||||
// HACK: This is a workaround for "podcast" type video. GREAT JOB GOOGLE.
|
||||
if (data.playabilityStatus.transportControlsConfig) {
|
||||
data.videoDetails.author =
|
||||
data.microformat.microformatDataRenderer.pageOwnerDetails.name;
|
||||
}
|
||||
|
||||
window.ipcRenderer.send('ytmd:video-src-changed', data);
|
||||
}
|
||||
};
|
||||
|
||||
@ -7,6 +7,26 @@ import config from '@/config';
|
||||
|
||||
import type { GetPlayerResponse } from '@/types/get-player-response';
|
||||
|
||||
enum MediaType {
|
||||
/**
|
||||
* Audio uploaded by the original artist
|
||||
*/
|
||||
Audio = 'AUDIO',
|
||||
/**
|
||||
* Official music video uploaded by the original artist
|
||||
*/
|
||||
OriginalMusicVideo = 'ORIGINAL_MUSIC_VIDEO',
|
||||
/**
|
||||
* Normal YouTube video uploaded by a user
|
||||
*/
|
||||
UserGeneratedContent = 'USER_GENERATED_CONTENT',
|
||||
/**
|
||||
* Podcast episode
|
||||
*/
|
||||
PodcastEpisode = 'PODCAST_EPISODE',
|
||||
OtherVideo = 'OTHER_VIDEO',
|
||||
}
|
||||
|
||||
export interface SongInfo {
|
||||
title: string;
|
||||
artist: string;
|
||||
@ -21,6 +41,7 @@ export interface SongInfo {
|
||||
album?: string | null;
|
||||
videoId: string;
|
||||
playlistId?: string;
|
||||
mediaType: MediaType;
|
||||
}
|
||||
|
||||
// Grab the native image using the src
|
||||
@ -61,6 +82,7 @@ const handleData = async (
|
||||
album: undefined,
|
||||
videoId: '',
|
||||
playlistId: '',
|
||||
mediaType: MediaType.Audio,
|
||||
} satisfies SongInfo;
|
||||
|
||||
const microformat = data.microformat?.microformatDataRenderer;
|
||||
@ -84,6 +106,28 @@ const handleData = async (
|
||||
songInfo.videoId = videoDetails.videoId;
|
||||
songInfo.album = data?.videoDetails?.album; // Will be undefined if video exist
|
||||
|
||||
switch (videoDetails?.musicVideoType) {
|
||||
case 'MUSIC_VIDEO_TYPE_ATV':
|
||||
songInfo.mediaType = MediaType.Audio;
|
||||
break;
|
||||
case 'MUSIC_VIDEO_TYPE_OMV':
|
||||
songInfo.mediaType = MediaType.OriginalMusicVideo;
|
||||
break;
|
||||
case 'MUSIC_VIDEO_TYPE_UGC':
|
||||
songInfo.mediaType = MediaType.UserGeneratedContent;
|
||||
break;
|
||||
case 'MUSIC_VIDEO_TYPE_PODCAST_EPISODE':
|
||||
songInfo.mediaType = MediaType.PodcastEpisode;
|
||||
// HACK: Podcast's participant is not the artist
|
||||
if (!config.get('options.usePodcastParticipantAsArtist')) {
|
||||
songInfo.artist = cleanupName(data.microformat.microformatDataRenderer.pageOwnerDetails.name);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
songInfo.mediaType = MediaType.OtherVideo;
|
||||
break;
|
||||
}
|
||||
|
||||
const thumbnails = videoDetails.thumbnail?.thumbnails;
|
||||
songInfo.imageSrc = thumbnails.at(-1)?.url.split('?')[0];
|
||||
if (songInfo.imageSrc) songInfo.image = await getImage(songInfo.imageSrc);
|
||||
|
||||
Reference in New Issue
Block a user