feat: Support disabling scrobbling for non-music content (#1665)

Co-authored-by: JellyBrick <shlee1503@naver.com>
This commit is contained in:
Alex
2024-01-31 03:41:55 -05:00
committed by GitHub
parent f2f15bc3cc
commit e3ad804dc4
8 changed files with 69 additions and 7 deletions

View File

@ -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

View File

@ -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': {},

View File

@ -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"
},

View File

@ -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,

View File

@ -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)) {

View File

@ -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: [

View File

@ -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);
}
};

View File

@ -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);