dmig / Yandex Music & Radio MediaApi Support

// ==UserScript==
// @name Yandex Music & Radio MediaApi Support
// @description A better implementation of MediaSession browser API connection. Allows to use OS media player controls. This fork contains several fixes to the original script from Syleront.
// @version 0.2.1
// @author Syleront, dmig
// @include https://music.yandex.ru/*
// @include https://radio.yandex.ru/*
// @run-at document-idle
// @license MIT
// @copyright 2021, dmig
// ==/UserScript==

(() => {
    const { navigator, externalAPI } = unsafeWindow;

    if (!("mediaSession" in navigator && externalAPI)) return;

    const {
        EVENT_TRACK, EVENT_SOURCE_INFO,
        getCurrentTrack, getSourceInfo,
        togglePause, prev, next
    } = externalAPI;
    // All available avatar sizes, let the browser choose one
    const sizeList = ['30x30', '50x50', '80x80', '100x100', '200x200', '300x300', '400x400'];

    externalAPI.on(EVENT_TRACK, () => {
        const current = getCurrentTrack();
        if (current === null) return;

        const { title, artists, cover } = current;
        const artist = artists.map((e) => e.title).join(", ");
        const album = current.album.title;
        const artwork = sizeList.map(s => {return {src: 'https://' + cover.replace('%%', s), sizes: s}});

        // Use album name if artist is empty (for podcasts)
        navigator.mediaSession.metadata = new MediaMetadata({ title, artist: artist || album, album, artwork });
    });

    // handle station type change properly
    externalAPI.on(EVENT_SOURCE_INFO, () => {
        const current = getSourceInfo();
        if (current === null) return;

        if (current.type == 'radio') {
            // radio changes tracks only to the next
            navigator.mediaSession.setActionHandler("previoustrack", null);
        } else {
            navigator.mediaSession.setActionHandler("previoustrack", prev);
        }
    });

    navigator.mediaSession.setActionHandler("play", togglePause);
    navigator.mediaSession.setActionHandler("pause", togglePause);
    navigator.mediaSession.setActionHandler("nexttrack", next);
})();