Skip to content

Instantly share code, notes, and snippets.

@mikesparr
Created September 28, 2025 00:37
Show Gist options
  • Save mikesparr/9a570b47950cdc71caef325fd70db4fd to your computer and use it in GitHub Desktop.
Save mikesparr/9a570b47950cdc71caef325fd70db4fd to your computer and use it in GitHub Desktop.
Test script publishing posts to a Facebook page
import express from "express";
import fetch from "node-fetch";
const app = express();
app.use(express.json());
// Load environment variables
const {
FB_PAGE_ID,
FB_ACCESS_TOKEN,
PORT = 8080
} = process.env;
// Endpoint to receive messages
app.post("/publish", async (req, res) => {
try {
const message = req.body.message || "System generated message";
// Build the Graph API URL
const url = `https://graph.facebook.com/${FB_PAGE_ID}/feed`;
// Send request to Facebook
const response = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
message,
access_token: FB_ACCESS_TOKEN
})
});
const data = await response.json();
if (!response.ok) {
console.error("Error posting to Facebook:", data);
return res.status(500).json({ error: data });
}
res.json({ success: true, postId: data.id });
} catch (err) {
console.error("Unexpected error:", err);
res.status(500).json({ error: "Internal server error" });
}
});
// Endpoint to receive messages with photos
app.post("/publish-photos", async (req, res) => {
try {
const message = req.body.message || "System generated message";
const photoUrls = req.body.urls;
if (!Array.isArray(photoUrls) || photoUrls.length === 0) {
return res.status(400).json({ error: "Missing 'urls' array of photo URLs" });
}
const uploadUrl = `https://graph.facebook.com/${FB_PAGE_ID}/photos`;
// Step 1: Upload all photos unpublished
const mediaFbids = [];
for (const photoUrl of photoUrls) {
const params = new URLSearchParams();
params.append("url", photoUrl);
params.append("published", "false");
params.append("access_token", FB_ACCESS_TOKEN);
const response = await fetch(uploadUrl, {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: params.toString()
});
const data = await response.json();
if (!response.ok) {
console.error("Error uploading photo:", data);
return res.status(500).json({ error: data });
}
mediaFbids.push(data.id);
}
// Step 2: Publish post with attached media
const feedUrl = `https://graph.facebook.com/${FB_PAGE_ID}/feed`;
const params = new URLSearchParams();
params.append("message", message);
params.append("access_token", FB_ACCESS_TOKEN);
mediaFbids.forEach((id, index) => {
params.append(`attached_media[${index}]`, JSON.stringify({ media_fbid: id }));
});
const postResponse = await fetch(feedUrl, {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: params.toString()
});
const postData = await postResponse.json();
if (!postResponse.ok) {
console.error("Error creating multi-photo post:", postData);
return res.status(500).json({ error: postData });
}
res.json({ success: true, postId: postData.id, photos: mediaFbids });
} catch (err) {
console.error("Unexpected error:", err);
res.status(500).json({ error: "Internal server error" });
}
});
app.listen(PORT, () => {
console.log(`Service listening on port ${PORT}`);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment