Last active
February 10, 2019 13:56
-
-
Save bridgestew/989fb2ed7bc5b91f738fcd7628aa7f5c to your computer and use it in GitHub Desktop.
Notes-to-Twitter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// package.json shown below to double check nothing is missing | |
import fetch from 'node-fetch' | |
import dotenv from 'dotenv' | |
import Twitter from 'twitter' | |
import { AllHtmlEntities as Entities } from 'html-entities' | |
dotenv.config() | |
// URL of notes JSON feed | |
// output of file shown below | |
const NOTES_URL = 'https://www.bridgestew.com/notes.json' | |
// Configure Twitter API Client | |
// Have double checked values in .env for accuracy | |
const twitter = new Twitter({ | |
consumer_key: process.env.TWITTER_CONSUMER_KEY, | |
consumer_secret: process.env.TWITTER_CONSUMER_SECRET, | |
access_token_key: process.env.TWITTER_ACCESS_TOKEN_KEY, | |
access_token_secret: process.env.TWITTER_ACCESS_TOKEN_SECRET | |
}) | |
// Helper Function to return unknown errors | |
const handleError = err => ({ | |
statusCode: 422, | |
body: String(err) | |
}) | |
// Helper Function to return function status | |
const status = (code, msg) => { | |
console.log(msg) | |
return { | |
statusCode: code, | |
body: msg | |
} | |
} | |
// Check exisiting notes | |
const processNotes = async notes => { | |
if (!notes.length) { | |
return status(404, 'No notes found to process.') | |
} | |
// assume the last note is not yet syndicated | |
const latestNote = notes[0] | |
if (!latestNote.syndicate) { | |
return status( | |
400, | |
'Latest note has disabled syndication. No action taken.' | |
) | |
} | |
try { | |
// check twitter for any tweets containing note URL. | |
// if there are none, publish it. | |
const q = await twitter.get('search/tweets', { q: latestNote.url }) | |
if (q.statuses && q.statuses.length === 0) { | |
return publishNote(latestNote) | |
} else { | |
return status( | |
400, | |
'Latest note was already syndicated. No action taken.' | |
) | |
} | |
} catch (err) { | |
return handleError(err) | |
} | |
} | |
// Prepare the content string for tweet format | |
const prepareStatusText = note => { | |
const maxLength = 280 - 3 - 1 - 23 - 20 | |
const entities = new Entities() | |
// strip html tags and decode entities | |
let text = note.content.trim().replace(/<[^>]+>/g, '') | |
text = entities.decode(text) | |
// truncate note text if its too long for a tweet. | |
if (text.length > maxLength) { | |
text = text.substring(0, maxLength) + '...' | |
} | |
// include the note url at the end; | |
text = text + ' ' + note.url | |
return text | |
} | |
// Push a new note to Twitter | |
const publishNote = async note => { | |
try { | |
const statusText = prepareStatusText(note) | |
const tweet = await twitter.post('statuses/update', { | |
status: statusText | |
}) | |
if (tweet) { | |
return status( | |
200, | |
`Note ${note.date} successfully posted to Twitter.` | |
) | |
} else { | |
return status(422, 'Error posting to Twitter API.') | |
} | |
} catch (err) { | |
return handleError(err) | |
} | |
} | |
// Main Lambda Function Handler | |
exports.handler = async () => { | |
// Fetch the list of published notes to work on, | |
// then process them to check if an action is necessary | |
return fetch(NOTES_URL) | |
.then(response => response.json()) | |
.then(processNotes) | |
.catch(handleError) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[build] | |
publish = "_site" | |
command = "npm build trigger" | |
functions = "lambda" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[ | |
{ | |
"id": 1, | |
"date": "Fri Feb 08 2019 17:45:05 GMT-0500 (Eastern Standard Time)", | |
"url": "https://www.bridgestew.com/notes/2019-02-08-22-45/", | |
"content": "I've been trying to follow along with Max's code examples for how to get webmention sends working with Twitter. Still working out kinks.", | |
"syndicate": true | |
} | |
] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// The pertinent parts | |
{ | |
"scripts": { | |
"serve": "gulp watch & eleventy --serve", | |
"build": "npx eleventy", | |
"watch": "npx eleventy --watch", | |
"debug": "DEBUG=* npx eleventy", | |
"trigger": "eleventy & npm run build:lambda", | |
"build:lambda": "netlify-lambda build functions" | |
}, | |
"devDependencies": { | |
"@11ty/eleventy": "^0.7.1", | |
"@11ty/eleventy-plugin-rss": "^1.0.3", | |
"@11ty/eleventy-plugin-syntaxhighlight": "^2.0.0", | |
"acorn": "^6.0.7", | |
"eleventy-plugin-reading-time": "^0.0.1", | |
"luxon": "^1.9.0", | |
"markdown-it": "^8.4.1", | |
"markdown-it-abbr": "^1.0.4", | |
"markdown-it-anchor": "^5.0.2", | |
"markdown-it-attrs": "^2.3.2" | |
}, | |
"dependencies": { | |
"clean-css": "^4.2.1", | |
"dotenv": "^6.2.0", | |
"gulp": "^4.0.0", | |
"gulp-concat": "^2.6.1", | |
"gulp-sass": "^4.0.1", | |
"gulp-uglify": "^3.0.1", | |
"html-entities": "^1.2.1", | |
"html-minifier": "^3.5.21", | |
"netlify-lambda": "^1.3.3", | |
"node-fetch": "^2.3.0", | |
"sanitize-html": "^1.20.0", | |
"send-webmention": "^2.0.0", | |
"sitemap-generator": "^8.3.2", | |
"twitter": "^1.7.1", | |
"uglify-js": "^3.4.9" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
tried running your function in my local setup and it seems to work.
Could you try to expand the
handleError
function to:that should give you a more verbose output on Netlify's function console.