iBicha / playlet

The unofficial, privacy driven, YouTube client for Roku
GNU Affero General Public License v3.0
308 stars 11 forks source link

[Script] cast to Playlet using TamperMonkey #132

Closed iBicha closed 7 months ago

iBicha commented 1 year ago
// ==UserScript==
// @name         Cast to Playlet
// @namespace    http://playlet.org
// @version      1.0
// @description  Cast video to Playlet
// @author       Brahim Hadriche
// @match        https://*.youtube.com/watch*
// @grant        GM_xmlhttpRequest
// @grant        GM_registerMenuCommand
// @grant        GM_getValue
// @grant        GM_setValue

// ==/UserScript==

(function() {
    'use strict';

    function cast() {
        const videoInfo = parseYouTubeUrl(window.location.href);
        if (!videoInfo.videoId) {
            return;
        }
        castVideo(videoInfo);
    }

    function queue() {
        const videoInfo = parseYouTubeUrl(window.location.href);
        if (!videoInfo.videoId) {
            return;
        }
        queueVideo(videoInfo);
    }
    GM_registerMenuCommand('Cast Video', cast);
    GM_registerMenuCommand('Queue Video', queue);
})();

function parseYouTubeUrl(url) {
    const urlSearchParams = new URLSearchParams(new URL(url).search);

    function getTimestamp() {
        const timestamp = urlSearchParams.get("t");
        if (timestamp) {
            return timestamp.endsWith("s") ? timestamp.slice(0, -1) : timestamp;
        }
    }

    // Share/Short url
    const YoutubeUrls = [
        "https://youtu.be/",
        "http://youtu.be/",
        "https://www.youtu.be/",
        "http://www.youtu.be/",
        "https://youtube.com/shorts/",
        "http://youtube.com/shorts/",
        "https://www.youtube.com/shorts/",
        "http://www.youtube.com/shorts/",
    ];
    for (var i in YoutubeUrls) {
        let youtubeUrl = YoutubeUrls[i];
        if (url.startsWith(youtubeUrl)) {
            let videoId = url.replace(youtubeUrl, "");
            if (videoId.includes("?")) {
                videoId = videoId.substring(0, videoId.indexOf("?"));
            }
            const result = {
                videoId,
            };

            const timestamp = getTimestamp();
            if (timestamp) {
                result.timestamp = timestamp;
            }
            return result;
        }
    }

    // regular url
    const result = {
        videoId: urlSearchParams.get("v"),
    };

    const timestamp = getTimestamp();
    if (timestamp) {
        result.timestamp = timestamp;
    }

    return result;
}

function castVideo(videoInfo) {
    const payload = {
        videoId: videoInfo.videoId,
    };
    if (videoInfo.timestamp) {
        payload.timestamp = videoInfo.timestamp;
    }

    postData('/api/queue/play', payload);
}

function queueVideo(videoInfo) {
    const payload = {
        videoId: videoInfo.videoId,
    };

    postData('/api/queue', payload);
}

function postData(endpoint, payload) {
    const ip = getRokuIp();
    GM_xmlhttpRequest({
        method: 'POST',
        url: `http://${ip}:8888${endpoint}`,
        headers: {
            'Content-Type': 'application/json',
        },
        data: JSON.stringify(payload),
        onload: function(response) {
            if (response.status === 200) {
                console.log('Response from the API:', response.responseText);
            } else {
                console.error('Error:', response.status, response.statusText);
            }
        },
        onerror: function(error) {
            console.error('Error:', error);
        }
    });
}

function getRokuIp() {
    let url = GM_getValue("roku_ip")
    if(!url) {
        url = prompt("Enter IP Address of Roku device (without http:// or port)")
        GM_setValue("roku_ip", url)
    }
    return url;
}
aerickson commented 9 months ago

Very handy! Works great for me.

Changing // @match https://www.youtube.com/watch* to // @match https://*.youtube.com/watch* allowed this to work in Firefox Android with Violentmonkey (it goes to m.youtube.com).

iBicha commented 9 months ago

Very handy! Works great for me.

Changing // @match https://www.youtube.com/watch* to // @match https://*.youtube.com/watch* allowed this to work in Firefox Android with Violentmonkey (it goes to m.youtube.com).

That's a good idea, I've updated the script! Thanks