You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
carbon/lib/api.js

167 lines
3.9 KiB
JavaScript

import axios from 'axios'
import debounce from 'lodash.debounce'
import omitBy from 'lodash.omitby'
import ms from 'ms'
import { fileToDataURL } from './util'
import firebase from './client'
import { DEFAULT_CODE, DEFAULT_SETTINGS } from './constants'
export const client = axios.create({
baseURL: `${process.env.API_URL || ''}/api`,
headers: {
Accept: 'application/json'
}
})
function tweet(content, encodedImage) {
const processedData = encodedImage.split(',')[1]
return client
.post('/twitter', {
imageData: processedData,
altText: content
})
.then(res => res.data.url)
.then(url => encodeURIComponent(`Created with @carbon_app ${url}`))
.then(uri => `https://twitter.com/intent/tweet?text=${uri}`)
.then(openTwitterUrl)
.catch(checkIfRateLimited)
}
const RATE_LIMIT_CODE = 420
function checkIfRateLimited(err) {
if (err.response.status === RATE_LIMIT_CODE) {
alert(
"Oh no! Looks like to many people are trying to tweet right now and we've been rate limited. Try again soon or save and upload manually!"
)
return
}
throw err
}
function image(state) {
return client.post('/image', { state }).then(res => res.data)
}
function openTwitterUrl(twitterUrl) {
const width = 575
const height = 400
const left = (window.outerWidth - width) / 2
const top = (window.outerHeight - height) / 2
const opts = `status=1,width=${width},height=${height},top=${top},left=${left}`
window.open(twitterUrl, 'twitter', opts)
}
const downloadThumbnailImage = img => {
return client
.get(img.url.replace('http://', 'https://'), { responseType: 'blob' })
.then(res => res.data)
.then(fileToDataURL)
.then(dataURL => Object.assign(img, { dataURL }))
}
const unsplash = {
download(id) {
return client.get(`/unsplash/download/${id}`).then(res => res.data)
},
async random() {
const imageUrls = await client.get('/unsplash/random')
return Promise.all(imageUrls.data.map(downloadThumbnailImage))
}
}
function getSnippet(uid = '', { host } = {}) {
return client
.get(`/snippets/${uid}`, host ? { baseURL: `https://${host}/api` } : undefined)
.then(res => res.data)
.catch(e => {
console.error(e)
return null
})
}
function listSnippets(page) {
// IDEA: move into axios interceptor
return firebase
.auth()
.currentUser.getIdToken()
.then(authorization =>
client
.get(`/snippets`, {
params: {
page
},
headers: {
authorization
}
})
.then(res => res.data)
.catch(e => {
console.error(e)
throw e
})
)
}
function isNotDefaultSetting(v, k) {
return v === DEFAULT_SETTINGS[k] || !Object.prototype.hasOwnProperty.call(DEFAULT_SETTINGS, k)
}
function updateSnippet(uid, state) {
const sanitized = omitBy(state, isNotDefaultSetting)
const data = {
...sanitized,
code: state.code != null ? state.code : DEFAULT_CODE
}
if (uid) {
return client
.patch(`/snippets/${uid}`, data)
.then(res => res.data)
.catch(e => {
console.error(e)
return null
})
}
return client
.post(`/snippets`, data)
.then(res => res.data)
.catch(e => {
console.error(e)
return null
})
}
function deleteSnippet(uid) {
return client
.delete(`/snippets/${uid}`)
.then(res => res.data)
.catch(e => {
console.error(e)
return null
})
}
const createSnippet = debounce(data => updateSnippet(null, data), ms('5s'), {
leading: true,
trailing: false
})
export default {
snippet: {
get: getSnippet,
list: listSnippets,
update: debounce(updateSnippet, ms('1s'), { leading: true, trailing: true }),
create: createSnippet,
delete: id => deleteSnippet(id)
},
tweet: debounce(tweet, ms('5s'), { leading: true, trailing: false }),
image: debounce(image, ms('5s'), { leading: true, trailing: false }),
unsplash,
downloadThumbnailImage
}