Skip to content

Instantly share code, notes, and snippets.

@mackenly
Last active November 2, 2022 19:56
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mackenly/3d289416d345dfc121437a2e1c85477f to your computer and use it in GitHub Desktop.
Save mackenly/3d289416d345dfc121437a2e1c85477f to your computer and use it in GitHub Desktop.
Ghost to Ayrshare (social channel distribution) Integration
/*
* Name: Ghost-Ayrshare Integration
* Desc: CloudFlare Worker To Consume Ghost Webhooks and Share On Social With Ayrshare
* Created by: Mackenly Jones (mackenly.com)
* Date: 10/26/2021
* Updated: 11/2/2022
* Requres: Ghost CMS, CloudFlare Worker, and Ayrshare Account
* Variables: Store your Ayrshare API key as API_KEY and referal code as REF_CODE into your Worker's enviormental variables
*
* The referal code is just a basic way to make sure requests are from you.
* You should create an integration in Ghost with a post.published webhook that sends a request to your Worker.
* The URL should look like this:
* https://worker-name.username.workers.dev/api/post/referal=yourrefcode
*/
// Create event listener to handle responses and requests
addEventListener('fetch', (event) => {
event.respondWith(handleRequest(event.request).catch((err) => new Response(err.stack, { status: 500 })));
});
/* Function to get the response from Ayrshare */
async function gatherResponse(response) {
// Find out what content type the request wants
const { headers } = response;
const contentType = headers.get('content-type') || '';
// Return json is it wants json, text if anything else
if (contentType.includes('application/json')) {
return JSON.stringify(await response.json());
} else {
return await response.text();
}
}
/**
* Handle the request, if it's to the API check if it's a post and HTTPS
* If it's not to the API return a fun error.
* @param {Request} request
* @returns {Promise<Response>}
*/
async function handleRequest(request) {
const { pathname } = new URL(request.url);
// Check to see if the user is using https, if not throw 403.4
if (!request.url.startsWith('https://')) {
return new Response('Error 403.4: SSL Required', { status: 403.4 });
}
// Check to see if user is sending request to /api/post
if (pathname.startsWith('/api/post')) {
// Do things if the user is using the POST method
if (request.method === 'POST') {
// Extract the request body as json
const body = await request.json();
// Get the referal code from the URL and validate it as acceptable
const { searchParams } = new URL(request.url);
let referal_key = searchParams.get('referal');
if (referal_key !== REF_CODE) {
// If the referal code doesn't match throw error 401
return new Response('Error 401: Unauthorized', { status: 401 });
}
/**
* Visit the Ayrshare docs for more info:
* https://docs.ayrshare.com/
*/
// Set the API endpoint
const endpoint = 'https://app.ayrshare.com/api/post';
// Build the text that the posts will contain
let postText =
body.post.current.title + ' \u2063\n\u2063\n' + body.post.current.excerpt + ' \u2063\n' + body.post.current.url;
// For Twitter if postText is longer than 280 characters, trim it down to 280 characters
if (postText.length > 280) {
postText = trimText(body.post.current.title, body.post.current.excerpt, body.post.current.url, 280);
} else {
postText = postText;
}
// Build the request body
function trimText(title, excerpt, link, length) {
let trimmedString = excerpt + ' \u2063\n' + link;
if (trimmedString.length > length - 4) {
return trimText(title, trimmedString.substr(0, excerpt.split(' ').slice(0, -1).join(' ').length), link, length);
} else {
return (
trimmedString.split(' ', trimmedString.split(' ').length - 1).join(' ') +
'...\u2063\n' +
trimmedString.split(' ')[trimmedString.split(' ').length - 1]
);
}
}
// Create the meta data used by Ayrshare
const body_data = {
post: postText,
platforms: ['twitter', 'facebook', 'linkedin', 'fbg'],
};
// Create the request
const init = {
body: JSON.stringify(body_data),
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${API_KEY}`,
},
};
// Use fetch to send the request
const response = await fetch(endpoint, init);
// Wait for the response from Ayrshare
const results = await gatherResponse(response);
// Return Ayrshare's reponse to the client for debugging
return new Response(results, init);
} else if (request.method === 'GET' || request.method !== 'POST') {
// If the user isn't using POST throw error 405
return new Response('Error 405: Method Not Allowed', { status: 405 });
}
} else {
// If the request doesn't meet any of the conditions respond error 418
return new Response("Error 418: I'm a teapot", { status: 418 });
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment