My Firebase web project has been working for several months now. But on Sunday June 3, 2018, my application stopped sending tweets with media (images) attached. Before this, it was working for months. I have not changed the failing code before the 3rd and I have even reverted to code that worked before but the app still fails.
SDK versions:
I am using the most up to date versions of Firebase tools (3.18.6), and cloud functions (1.0.3). Along with twit (2.2.10) a javascript library for twitter api.
Do note my project was also working on older versions of the above including pre v1.0 cloud functions. Also note, I am still able to send regular text tweets just not ones with any media (image,gif,mp4).
How to reproduce:
For simplicity, I will link to the code in a tutorial which I originally used when starting the project.
Setup a twitter account and retrieve all the necessary tokens as outlined in the tutorial. Then simply call the cloud function below and it will attempt to tweet the NASA image of the day.
The function is able to upload the picture to the twitter server and the response I get is expected:
{ media_id: 1004461244487643100,
media_id_string: '1004461244487643136',
media_key: '5_1004461244487643136',
size: 92917,
expires_after_secs: 86400,
image: { image_type: 'image/jpeg', w: 960, h: 1318 } }
However, once it attempts to post the tweet with the media attached, I receive an error
code 324: ‘Unsupported raw media category’
which doesn’t exist in Twitter’s docs: https://developer.twitter.com/en/docs/basics/response-codes.html
Now, Code 324 does exist but in Twitter’s docs there is a different description:
“The validation of media ids failed”
Which I have yet to receive. So my media id is valid, so something else is wrong. No where on the internet can I find someone with this exact error.
Link to tutorial code:
Javascript code that reproduces the issue:
**index.js
'use strict';
const functions = require('firebase-functions');
const request = require('request');
const path = require('path');
const os = require('os');
const fs = require('fs');
const tmpDir = os.tmpdir(); // Ref to the temporary dir on worker machine
const Twit = require('twit');
const T = new Twit({
consumer_key: 'your twitter key'
,consumer_secret: 'your twitter secret'
,access_token: 'your twitter token'
,access_token_secret: 'your twitter token secret'
});
exports.http_testMediaTweet = functions.https.onRequest((req, res) => {
function getPhoto() {
const parameters = {
url: 'https://api.nasa.gov/planetary/apod',
qs: {
api_key: 'DEMO_KEY'
},
encoding: 'binary'
};
request.get(parameters, (err, response, body) => {
if (err) {console.log('err: ' + err)}
body = JSON.parse(body);
var f = path.join(tmpDir, 'nasa.jpg');
saveFile(body, f);
});
}
function saveFile(body, fileName) {
const file = fs.createWriteStream(fileName);
request(body).pipe(file).on('close', err => {
if (err) {
console.log(err)
} else {
console.log('Media saved! '+body.title)
const descriptionText = body.title
uploadMedia(descriptionText, fileName);
}
})
}
function uploadMedia(descriptionText, fileName) {
const filePath = path.join(__dirname, `../${fileName}`)
console.log(`uploadMedia: file PATH ${fileName}`)
T.postMediaChunked({
file_path: fileName
}, (err, data, respone) => {
if (err) {
console.log(err)
} else {
console.log(data)
const params = {
status: descriptionText,
media_ids: data.media_id_string
}
postStatus(params);
}
})
}
function postStatus(params) {
T.post('statuses/update', params, (err, data, respone) => {
if (err) {
console.log(err)
res.status(500).send('Error: ' + err);
} else {
console.log('Status posted!')
res.status(200).send('success');
}
})
}
// Do thing
getPhoto();
});
I’ve tried everything I can think of and consulted the docs for Twitter and the js library but I seem to be doing everything right. Hopefully someone can shed some light on this, thanks.