add alt text support for Twitter images (#372)

* add alt text support for Twitter images

* move constant declarations up

* Use UNSAFE_cWRP

* remove duplicate TODO (whoops)
main
Brian Dennis 7 years ago committed by Michael Fix
parent 3e2624727b
commit d885b63b3a

@ -38,8 +38,8 @@ class Carbon extends PureComponent {
ro.observe(this.exportContainerNode) ro.observe(this.exportContainerNode)
} }
componentWillReceiveProps(newProps) { // TODO use getDerivedStateFromProps
// TODO use getDerivedStateFromProps() on React@16.3 UNSAFE_componentWillReceiveProps(newProps) {
this.handleLanguageChange(newProps.children, { customProps: newProps }) this.handleLanguageChange(newProps.children, { customProps: newProps })
} }

@ -153,7 +153,7 @@ class Editor extends React.Component {
upload() { upload() {
this.setState({ uploading: true }) this.setState({ uploading: true })
this.getCarbonImage({ format: 'png' }) this.getCarbonImage({ format: 'png' })
.then(this.props.tweet) .then(this.props.tweet.bind(null, this.state.code || DEFAULT_CODE))
// eslint-disable-next-line // eslint-disable-next-line
.catch(console.error) .catch(console.error)
.then(() => this.setState({ uploading: false })) .then(() => this.setState({ uploading: false }))

@ -45,8 +45,8 @@ export default class extends React.Component {
this.onDragEnd = this.onDragEnd.bind(this) this.onDragEnd = this.onDragEnd.bind(this)
} }
componentWillReceiveProps(nextProps) { // TODO use getDerivedStateFromProps
// TODO use getDerivedStateFromProps() on React@16.3 UNSAFE_componentWillReceiveProps(nextProps) {
if (this.state.crop && this.props.aspectRatio !== nextProps.aspectRatio) { if (this.state.crop && this.props.aspectRatio !== nextProps.aspectRatio) {
// update crop for editor container aspect-ratio change // update crop for editor container aspect-ratio change
this.setState({ this.setState({

@ -1,24 +1,40 @@
const Twitter = require('twitter') const Twitter = require('twit')
const morph = require('morphmorph') const morph = require('morphmorph')
const RATE_LIMIT_CODE = 420 const RATE_LIMIT_CODE = 420
const MAX_ALT_TEXT_LENGTH = 420
const client = new Twitter({ const client = new Twitter({
consumer_key: process.env.TWITTER_CONSUMER_KEY, consumer_key: process.env.TWITTER_CONSUMER_KEY,
consumer_secret: process.env.TWITTER_CONSUMER_SECRET, consumer_secret: process.env.TWITTER_CONSUMER_SECRET,
access_token_key: process.env.TWITTER_ACCESS_TOKEN_KEY, access_token: process.env.TWITTER_ACCESS_TOKEN_KEY,
access_token_secret: process.env.TWITTER_ACCESS_TOKEN_SECRET access_token_secret: process.env.TWITTER_ACCESS_TOKEN_SECRET
}) })
const extractMediaId = morph.get('data.media_id_string')
const extractImageUrl = morph.get('data.entities.media.0.display_url')
const extractErrorCode = morph.get('0.code')
const uploadImage = data => client.post('media/upload', { media_data: data }) const uploadImage = data => client.post('media/upload', { media_data: data })
const uploadTweet = (media = {}) => const uploadMetadata = (altText, twitterRes = {}) => {
client.post('statuses/update', { if (!altText)
status: `Carbon Copy #${media.media_id_string.slice(0, 8)}`, return twitterRes
media_ids: media.media_id_string
})
const extractImageUrl = morph.get('entities.media.0.display_url') const formattedAltText = altText.length > MAX_ALT_TEXT_LENGTH
const extractErrorCode = morph.get('0.code') ? `${altText.slice(0, MAX_ALT_TEXT_LENGTH - 3)}...`
: altText
return client
.post('media/metadata/create', {
media_id: extractMediaId(twitterRes),
alt_text: { text: formattedAltText }
})
.then(() => twitterRes)
}
const uploadTweet = (twitterRes = {}) => client.post('statuses/update', {
status: `Carbon Copy #${extractMediaId(twitterRes).slice(0, 8)}`,
media_ids: extractMediaId(twitterRes)
})
const respondSuccess = (res, url) => res.json({ url }) const respondSuccess = (res, url) => res.json({ url })
const respondFail = (res, err) => { const respondFail = (res, err) => {
@ -35,11 +51,12 @@ const respondFail = (res, err) => {
} }
module.exports = (req, res) => { module.exports = (req, res) => {
if (!req.body.data) { if (!req.body.imageData) {
return res.status(400).send() return res.status(400).send()
} }
return uploadImage(req.body.data) return uploadImage(req.body.imageData)
.then(uploadMetadata.bind(null, req.body.altText))
.then(uploadTweet) .then(uploadTweet)
.then(extractImageUrl) .then(extractImageUrl)
.then(respondSuccess.bind(null, res)) .then(respondSuccess.bind(null, res))

@ -14,11 +14,14 @@ const gistClient = axios.create({
} }
}) })
async function tweet(encodedImage) { async function tweet(content, encodedImage) {
const processedData = encodedImage.split(',')[1] const processedData = encodedImage.split(',')[1]
return axios return axios
.post(`${DOMAIN}/twitter`, { data: processedData }) .post(`${DOMAIN}/twitter`, {
imageData: processedData,
altText: content
})
.then(res => res.data.url) .then(res => res.data.url)
.then(url => encodeURIComponent(`Built with #Carbon, by @dawn_labs ${url}`)) .then(url => encodeURIComponent(`Built with #Carbon, by @dawn_labs ${url}`))
.then(uri => `https://twitter.com/intent/tweet?text=${uri}`) .then(uri => `https://twitter.com/intent/tweet?text=${uri}`)

@ -55,7 +55,7 @@
"react-syntax-highlight": "^15.3.1", "react-syntax-highlight": "^15.3.1",
"resize-observer-polyfill": "^1.5.0", "resize-observer-polyfill": "^1.5.0",
"tohash": "^1.0.2", "tohash": "^1.0.2",
"twitter": "^1.7.1", "twit": "^2.2.9",
"unsplash-js": "^4.8.0" "unsplash-js": "^4.8.0"
}, },
"devDependencies": { "devDependencies": {

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save