Skip to content

Instantly share code, notes, and snippets.

@dphov
Forked from isaacs/gist.js
Created December 13, 2016 16:56
Show Gist options
  • Save dphov/49559f4fdd23e45149f3e33c73025023 to your computer and use it in GitHub Desktop.
Save dphov/49559f4fdd23e45149f3e33c73025023 to your computer and use it in GitHub Desktop.
var args = process.argv.slice(2)
var path = require('path')
var fs = require('fs')
var private = false
var description = ''
var opener = require('opener')
var copy = process.platform === 'darwin'
var open = false
var help = false
var stdin = true
var type = 'txt'
var files = []
var doMain = true
var ini = require('ini')
var child_process = require('child_process')
var execFile = child_process.execFile
var spawn = child_process.spawn
var home = require('osenv').home()
var authFile = home + '/.gist-login'
var https = require('https')
var read = require('read')
for (var a = 0; a < args.length; a++) {
switch (args[a]) {
case '-c': case '--copy':
copy = true && process.platform === 'darwin'
break
case '--no-copy':
copy = false
break
case '-p': case '--private':
private = true
break
case '--no-private':
private = false
break
case '-t': case '--type':
type = args[++a]
break
case '-d': case '--description':
description = args[++a]
break
case '-o': case '--open':
open = true
break
case '--no-open':
open = false
break
case '-v': case '--version':
version()
doMain = false
break
case '-h': case '--help':
help()
doMain = false
break
default:
files.push(args[a])
break
}
}
if (files.length !== 0 && files.indexOf('-') === -1)
stdin = false
if (doMain) main()
function help() {
console.log([
'Usage: gist [options] [filename, ...]',
'Filename \'-\' forces gist to read from stdin.',
'gist will read from stdin by default if no files specified',
' -p, --[no-]private Make the gist private',
' -t, --type [EXTENSION] Set syntax highlighting of the Gist by file extension',
' (Only applies to stdin data, filenames use extension)',
' -d, --description DESCRIPTION Set description of the new gist',
' -o, --[no-]open Open gist in browser',
' -c, --[no-]copy Save url to clipboard (osx only)',
' -v, --version Print version',
' -h, --help Display this screen'
].join('\n'))
}
function version() {
console.log(require('./package.json').version)
}
function main() {
console.error('main start')
getAuth(function(er, auth) {
console.error('auth', er, auth)
if (er)
throw er
getData(files, function(er, data) {
// console.error('file data', data)
if (er)
throw er
var body = new Buffer(JSON.stringify({
description: description,
public: !private,
files: data
}))
console.error('body', body.toString())
var opt = {
method: 'POST',
host: 'api.github.com',
port: 443,
path: '/gists',
headers: {
host: 'api.github.com',
authorization: 'token ' + auth.token,
'content-length': body.length,
'content-type': 'application/json'
}
}
console.error('making request', opt)
var req = https.request(opt)
req.on('response', function (res) {
var result = ''
res.setEncoding('utf8')
res.on('data', function(c) {
result += c
})
res.on('end', function() {
result = JSON.parse(result)
var id = result.id
var user = auth.user
var url = 'https://gist.github.com/' + user + '/' + id
if (open)
opener(url)
if (copy)
copyUrl(url)
process.on('exit', function() {
console.log(url)
})
})
saveAuth(auth, function (er, result) {
if (er)
throw er
})
})
req.end(body)
})
})
}
function copyUrl(url) {
spawn('pbcopy', []).stdin.end(url)
}
function getAuth(cb) {
getAuthFromFile(authFile, function(er, auth) {
console.error('getAuthFromFile', er, auth)
if (er)
getAuthFromGit(function (er, auth) {
console.error('getAuthFromGit', er, auth)
if (er)
getAuthFromCli(function (er, auth) {
console.error('getAuthFromCli', er, auth)
done(er, auth)
})
else
done(er, auth)
})
else
done(er, auth)
})
function done(er, auth) {
if (er)
return cb(er)
auth.user = auth.user.trim()
auth.token = auth.token.trim()
cb(er, auth)
}
}
function getAuthFromCli(cb) {
// can't read a file from stdin if we're reading login!
stdin = false
if (files.indexOf('-') !== -1) {
console.error('warning: ignoring stdin because you need to auth')
files = files.filter(function(f) { return f !== '-' })
}
var data = {}
read({ prompt: 'github.com username: ' }, function(er, user) {
if (er)
return cb(er)
data.user = user.trim()
read({ prompt: 'github.com password: ', silent: true }, function(er, password) {
if (er)
return cb(er)
password = password.trim()
// curl -u isaacs \
// -d '{"scopes":["gist"],"note":"gist cli access"}' \
// https://api.github.com/authorizations
var body = new Buffer(JSON.stringify({
scopes: [ 'gist' ],
note: 'gist cli access'
}))
var req = https.request({
method: 'POST',
host: 'api.github.com',
headers: {
'content-type': 'application/json',
'content-length': body.length,
authorization: 'Basic ' +
new Buffer(data.user + ':' + password).toString('base64')
},
path: '/authorizations'
})
var result = ''
req.on('response', function(res) {
res.on('error', cb)
res.setEncoding('utf8')
res.on('data', function(c) {
result += c
})
res.on('end', function() {
result = JSON.parse(result)
data.token = result.token
// just to make sure we don't waste this...
if (files.length === 0)
saveAuth(data, function(er) {
cb(er, data)
})
else
cb(null, data)
})
})
req.on('error', cb)
req.write(body)
req.end()
})
})
}
function getAuthFromFile(authFile, cb) {
// try to load from our file
fs.readFile(authFile, 'utf8', function(er, data) {
if (er)
return cb(er)
data = ini.parse(data)
if (!data.gist || !data.gist.user || !data.gist.token)
return cb(new Error('no login data in '+authFile))
return cb(null, data.gist)
})
}
function getAuthFromGit(cb) {
var data = {}
getConfFromGit('gist.user', function(er, user) {
if (er)
return cb(er)
data.user = user
getConfFromGit('gist.token', function(er, token) {
if (er)
return cb(er)
data.token = token
cb(null, data)
})
})
}
function getConfFromGit(key, cb) {
console.error('getConfFromGit', 'git', ['config', '--get', key].join(' '))
var env = { env: process.env }
execFile('git', ['config', '--get', key], env, function (er, stdout, stderr) {
console.error('back from git config', er, stdout, stderr)
if (er || !stdout)
console.error(stderr)
return cb(er, stdout)
})
}
function saveAuth(data, cb) {
var d = { gist: {
user: data.user,
token: data.token
}}
fs.writeFile(authFile, ini.stringify(d), cb)
}
function getData(files, cb) {
var data = {}
if (stdin && files.indexOf('-') === -1) {
files.push('-')
}
var c = files.length
var errState = null
var didStdin = false
files.forEach(function (f) {
if (f === '-') {
if (!didStdin) {
didStdin = true
var stdinData = ''
process.stdin.setEncoding('utf8')
process.stdin.on('data', function(chunk) {
stdinData += chunk
})
process.stdin.on('error', function(er) {
next(er)
})
process.stdin.on('end', function() {
data['gistfile.txt'] = { content: stdinData }
next()
})
}
} else {
fs.readFile(f, 'utf8', function(er, fileData) {
if (er)
next(er)
else {
data[f.replace(/\\|\//g, '-')] = { content: fileData }
next()
}
})
}
})
function next(er) {
if (errState)
return
else if (er)
return cb(errState = er)
else if (--c === 0)
cb(null, data)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment