Node.js: inviare tweet con immagine allegata

Node.js ci permette di inviare tweet con immagini allegate usando una procedura molto semplice.

Installiamo i moduli necessari:


npm install express --save
npm install body-parser --save
npm install twitter --save
npm install formidable --save

Creiamo la seguente classe di utility:


const Twitter = require('twitter');
const credentials = {
    consumer_key: 'key',
    consumer_secret: 'secret',
    access_token_key: 'key',
    access_token_secret: 'secret'
};

class Share {
    static tweet(message, data) {
        let client = new Twitter(credentials);
        return new Promise(function(resolve, reject) {
            client.post('media/upload', {media: data}).then(function(media) {
                let status = {
                    status: message,
                    media_ids: media.media_id_string
                };
                client.post('statuses/update', status).then(function(tweet) {
                    resolve(tweet);
                }).catch(function(err) {
                   reject(err);
                });
            }).catch(function(err) {
               reject(err);
            });
        });
    }

}

module.exports = Share;

Quindi creiamo la seguente route in Express per l’invio del tweet con l’immagine allegata:


const path = require('path');
const ABSPATH = path.dirname(process.mainModule.filename);
const formidable = require('formidable');
const fs = require('fs');
const Share = require(ABSPATH + '/classes/Share');
const bodyParser = require('body-parser');
const express = require('express');
const port = process.env.PORT || 3000;
const app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use('/uploads', express.static(path.join(__dirname, '/uploads')));

app.post('/tweet', function(req, res) {
    // Aggiungere validazione: 
    // 1) Immagine non superiore ai 5Mb
    // 2) Testo non superiore ai 140 caratteri

    let form = new formidable.IncomingForm();
        form.multiples = false;
        form.uploadDir = ABSPATH + '/uploads';

        form.on('file', function(field, file) {
          fs.rename(file.path, path.join(form.uploadDir, file.name));
        });

        form.parse(req, function(err, fields, files) {
            let message = fields.message;
            let data = fs.readFileSync(ABSPATH + '/uploads/' + files.image.name);
            Share.tweet(message, data).then(function(tweet) {
                // Successo
            }).catch(function(err) {
                // Errore
            });
        });
});


app.listen(port);