From c4622c7931bb81e5748c50b1ee66be82af15e5ec Mon Sep 17 00:00:00 2001 From: CesarMendivil Date: Sat, 28 Feb 2026 17:46:55 -0700 Subject: [PATCH] Add Facebook Live creation functionality and new settings fields --- src/views/Edit/Sources/Network.js | 2 +- src/views/Publication/Services/Facebook.js | 89 +++++++++++++++++++++- 2 files changed, 88 insertions(+), 3 deletions(-) diff --git a/src/views/Edit/Sources/Network.js b/src/views/Edit/Sources/Network.js index cade667..283a3c7 100644 --- a/src/views/Edit/Sources/Network.js +++ b/src/views/Edit/Sources/Network.js @@ -38,7 +38,7 @@ const useStyles = makeStyles((theme) => ({ height: '56px', minWidth: '56px', color: 'rgba(255,255,255,0.5)', - borderColor: 'rgba(255,255,255,0.23)', + borderColor: 'rgba(128,128,128,0.35)', '&:hover': { borderColor: '#FF0000', color: '#FF0000', diff --git a/src/views/Publication/Services/Facebook.js b/src/views/Publication/Services/Facebook.js index cf7cfcf..a6fb4b0 100644 --- a/src/views/Publication/Services/Facebook.js +++ b/src/views/Publication/Services/Facebook.js @@ -45,6 +45,12 @@ function init(settings) { stream_key_backup: '', rtmp_primary: true, rtmp_backup: false, + // new fields + page_id: '', + page_access_token: '', + title: '', + description: '', + create_live: false, ...settings, }; @@ -55,9 +61,9 @@ function Service(props) { const settings = init(props.settings); const handleChange = (what) => (event) => { - const value = event.target.value; + const value = event && event.target ? event.target.value : event; - if (['rtmp_primary', 'rtmp_backup'].includes(what)) { + if (['rtmp_primary', 'rtmp_backup', 'create_live'].includes(what)) { settings[what] = !settings[what]; } else { settings[what] = value; @@ -96,6 +102,62 @@ function Service(props) { return outputs; }; + // Creates a Facebook live video via Graph API and fills the primary stream key + const createFacebookLive = async () => { + if (!settings.page_id || !settings.page_access_token) { + window.alert('Please provide Page ID and Page Access Token to create a Facebook Live.'); + return; + } + + try { + const url = `https://graph.facebook.com/${encodeURIComponent(settings.page_id)}/live_videos`; + const form = new URLSearchParams(); + if (settings.title) form.append('title', settings.title); + if (settings.description) form.append('description', settings.description); + form.append('access_token', settings.page_access_token); + + const resp = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + body: form.toString(), + }); + + if (!resp.ok) { + const text = await resp.text(); + throw new Error('Facebook API error: ' + text); + } + + const data = await resp.json(); + + // Facebook returns a stream_url or stream_url/secure_stream_url — extract key + let stream = ''; + if (data.stream_url) stream = data.stream_url; + else if (data.secure_stream_url) stream = data.secure_stream_url; + + if (stream.length === 0) { + window.alert('Facebook did not return a stream URL.'); + return; + } + + // stream like rtmps://live-api-s.facebook.com:443/rtmp/STREAM_KEY + const parts = stream.split('/'); + const key = parts[parts.length - 1] || ''; + + settings.stream_key_primary = key; + settings.create_live = true; + + const outputs = createOutput(settings); + props.onChange(outputs, settings); + + window.alert('Facebook Live creado y stream key rellenada.'); + } catch (err) { + console.error(err); + window.alert('Error creando Facebook Live: ' + err.message); + } + }; + return ( {settings.rtmp_primary === true && ( @@ -107,6 +169,11 @@ function Service(props) { value={settings.stream_key_primary} onChange={handleChange('stream_key_primary')} /> + + {/* Button to create FB Live and populate stream key */} + + Create + )} {settings.rtmp_primary === true && ( @@ -134,9 +201,27 @@ function Service(props) { )} + + {/* New fields for page id, token, title and description */} + + Facebook Page ID} value={settings.page_id} onChange={handleChange('page_id')} /> + + + Page Access Token} value={settings.page_access_token} onChange={handleChange('page_access_token')} /> + + + + Title} value={settings.title} onChange={handleChange('title')} /> + + + Description} value={settings.description} onChange={handleChange('description')} /> + + Enable primary stream} checked={settings.rtmp_primary} onChange={handleChange('rtmp_primary')} /> Enable backup stream} checked={settings.rtmp_backup} onChange={handleChange('rtmp_backup')} /> + {/* Optionally mark that we created the live via API */} + Create live via API} checked={settings.create_live} onChange={handleChange('create_live')} /> );