Last active
January 22, 2020 16:52
-
-
Save pirate/22438209f9ce5a7ece1813dac9014228 to your computer and use it in GitHub Desktop.
Read a block of code from stdin, submit it to carbon.sh, and output the resulting tweet url.
This file contains 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
#!/usr/bin/env node | |
/* | |
Submit code from stdin to carbon.now.sh and return a url to a new tweet containing a screenshot | |
carbon.now.sh authors: https://dawnlabs.io/ | |
carbonify author: Nick Sweeting <[email protected]> | |
MIT License 2017 | |
*/ | |
const puppeteer = require('puppeteer') | |
const USAGE = ` | |
Usage: | |
./carbonify.js < code_file.py | |
Output: | |
https://twitter.com/intent/tweet?text=pic.twitter.com/abcd1234.png | |
Dependencies: | |
yarn add GoogleChrome/puppeteer | |
To open a new tweet compose window: | |
open $(./carbonify.js < code_file.py) | |
To trigger from SublimeText, add a build variant: | |
{ | |
"cmd": | |
["open" "$(/path/to/carbonify.js < \"$file\")"], | |
"name": "Tweet carbon.now.sh screenshot", | |
"shell": true | |
} | |
` | |
function log(text) { | |
process.stderr.write(`${text}\n`) | |
} | |
// read stdin into variable | |
function readInput(buffer) { | |
return new Promise(function(resolve, reject) { | |
let code = ''; | |
buffer.on('data', (chunk) => { | |
code += `${chunk}\n` | |
}) | |
buffer.on('end', () => { | |
const empty_inputs = ['', ' ', '\n', '\n\n'] | |
if (empty_inputs.includes(code)) { | |
log('[!] No input was passed in!') | |
reject() | |
} else { | |
resolve(code) | |
} | |
}) | |
buffer.setEncoding('utf8') | |
buffer.resume() | |
}) | |
} | |
// screenshot code on carbon.now.sh and get new tweet url | |
function getCarbonTweetURL(code) { | |
return new Promise(async function(resolve, reject) { | |
const browser = await puppeteer.launch() // for testing use: {headless: false} | |
const page = await browser.newPage() | |
// load page and wait for tweet button to go from "Loading..." to "Tweet Image" | |
log('[1/4] Opening carbon.now.sh in headless chrome...') | |
await page.goto('https://carbon.now.sh') | |
await page.waitForFunction(() => { | |
const twitter_btn = '#toolbar > div.buttons > button:nth-child(1)' | |
const tweet_btn_elem = document.querySelectorAll(twitter_btn)[0] | |
return tweet_btn_elem.innerHTML.includes("Tweet Image") | |
}) | |
// clear example code out of code input field | |
const code_input = 'div.ReactCodeMirror div.CodeMirror-code > pre:nth-child(11)' | |
await page.click(code_input) | |
await page.keyboard.down('Meta') | |
await page.keyboard.down('a') | |
await page.keyboard.up('a') | |
await page.keyboard.up('Meta') | |
await page.keyboard.press('Backspace') | |
const lines = code.split('\n') | |
const len = lines.length | |
log(`[2/4] Inputting ${len} line code snippet...`) | |
if (len < 500) { | |
await page.keyboard.type(code) | |
} else { | |
// if file is large, do it line-by-line for performance reasons | |
lines.forEach(async (line, idx) => { | |
const mod = (num, amt) => ((num%amt)+amt)%amt | |
if (idx == 0 || !mod(idx+1, 25)) { | |
// every 25 lines, show progress | |
log(` ${idx+1}/${len} lines\n`) | |
} | |
await page.keyboard.type(`{line}\n`) | |
}) | |
log(` ${len}/${len} lines\n`) | |
} | |
// catch twitter popup and log url to console instead | |
log('[3/4] Uploading to Twitter...') | |
await page.evaluate(() => { | |
window.open = (url) => console.log(url) | |
}) | |
page.on('console', async (msg) => { | |
log('[4/4] Got tweet URL.') | |
const tweet_url = msg.text.replace('Built%20with%20%23Carbon%2C%20by%20%40dawn_labs%20', '') | |
await browser.close() | |
resolve(tweet_url) | |
}) | |
const tweet_button = '#toolbar > div.buttons > button:nth-child(1)' | |
await page.click(tweet_button) | |
}) | |
} | |
// if run from CLI instead of being imported | |
if (require.main === module) { | |
const node_version = Number(process.version.split('.')[0].slice(1)) | |
if (node_version < 8) { | |
log('[X] You need node version >= 8.0.0 to run this.') | |
process.exit(1) | |
} | |
if (process.argv.includes('--help') || process.argv.includes('-h')) { | |
log(USAGE) | |
} | |
(async () => { | |
const code = await readInput(process.stdin) | |
const picture_url = await getCarbonTweetURL(code) | |
console.log(picture_url) | |
})() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment