/** * Description: In Firebot Events, add this file to "Run Custom Script" * in an event triggered by "Stream Started". * This script will: * - fetch stream description, title and thumbnail from the OpenGraph meta tags * - create a session with Bluesky * - upload the thumbnail as a blob to Bluesky * - create the app.bsky.actor.status record that enables the live badge */ /** * Firebot-specific code block below. * You will have to change this if you are using a different bot. */ exports.run = (runRequest) => { const logger = runRequest.modules.logger; const { BSKY_HANDLE, APP_PASSWORD, PDS_HOST, TWITCH_USERNAME, DURATION, } = runRequest.parameters; goLive( BSKY_HANDLE, APP_PASSWORD, PDS_HOST, TWITCH_USERNAME, DURATION, logger, ); }; exports.getScriptManifest = function () { return { name: "Go Live on Bluesky", description: "Creates the app.bsky.actor.status record via API that enables the live badge on Bluesky.", author: "timtinkers.online", version: "1.1.0", website: "https://tangled.org/timtinkers.online/", startupOnly: false, firebotVersion: "5", }; }; exports.getDefaultParameters = function getDefaultParameters() { return new Promise((resolve, reject) => { resolve({ BSKY_HANDLE: { "type": "string", "description": "Your full Bluesky handle", "default": "alice.bsky.social", }, APP_PASSWORD: { "type": "string", "description": "App-password created at https://bsky.app/settings/app-passwords.\nNEVER share your app password with anyone else, it gives full API access to your account!", "default": "xxxx-xxxx-xxxx-xxxx", }, PDS_HOST: { "type": "string", "description": "URL of your host Personal Data Server, do not change if you don't know what that is!", "default": "https://bsky.social", }, TWITCH_USERNAME: { "type": "string", "description": "Your Twitch username, that will be linked in the badge", "default": "twitchdev", }, DURATION: { "type": "number", "description": "Duration in minutes you expect to be live for, maximum 240 minutes", "default": 240, }, }); }); }; /** * Extracts OpenGraph data from the HTML document of the Twitch URL */ async function extractOpenGraphData(url, logger) { try { logger.info(`Fetching OpenGraph data from: ${url}`); const response = await fetch(url, { // Setting a user agent so Twitch doesn't spend time loading JS headers: { "User-Agent": "facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)", }, }); if (!response.ok) { logger.error( `Failed to fetch Twitch page: ${response.status} ${response.statusText}`, ); throw new Error(`HTTP ${response.status}: ${response.statusText}`); } const html = await response.text(); const getMetaContent = (property) => { // Try property/name first, then content const regex1 = new RegExp( `