UNPKG

@jaybirdgroup/data-hub-connector-twitter

Version:

Connector to interact with Twitter API in scope of Data Hub.

261 lines (205 loc) 7.31 kB
/** * Twitter bot re-posts latest post from random competitor Facebook page. * * @module twitter-bot */ 'use strict'; const Twit = require('twit'); const TwitterApi = require('node-twitter-api'); const _merge = require('lodash/merge'); const fs = require('fs'); const request = require('request').defaults({ encoding: null }); const path = require('path'); /** * Class representing a Twitter bot re-posts latest post from random competitor Facebook page */ class Twitter { /** * Init class and apply defaults. * @param {Object} config - Bot configurations and Twitter keys. */ constructor(config) { // default params this.defaults = { consumerKey: '', consumerSecret: '', accessToken: '', accessTokenSecret: '', appOnlyAuth: false }; // TODO: check for missing parameters this.config = _merge({}, this.defaults, config); this.twitter = new Twit({ consumer_key: this.config.consumerKey, consumer_secret: this.config.consumerSecret, access_token: this.config.accessToken, access_token_secret: this.config.accessTokenSecret, app_only_auth: this.config.appOnlyAuth, timeout_ms: 60 * 1000 // optional HTTP request timeout to apply to all requests. }); } /** * Method to be called after post is published or error occurred. * @callback publishPostCallback * @param {Array} errs - Array with JS Errors objects or empty. * @param {Array} publishedPosts - Array with results or empty. */ /** * Publish post to one or several destination Facebook pages * @param {Object} publishData - Post data to be sent * @param {string} publishData.url - Post url * @param {?string} publishData.title - Title of the store * @param {?string} publishData.content - Message * @param {publishPostCallback} next - [Callback function]{@link module:twitter-bot~publishPostCallback}. */ publishPost (publishData, next) { // publishData example: // { // url: normalizedPost.videoSource, // title: normalizedPost.title, // content: normalizedPost.message // } const localname = `tempmedia-${Date.now()}`; const PATH = path.join( __dirname, `${localname}` ); // get the media from remote storage request.get(publishData.url, (error, response, body) => { if (error) { return next(error); } // save media to disk temporarily, we // delete the media after uploading it fs.writeFile(PATH, body, (error) => { if (error) { return next(error); } // step ONE this.twitter.postMediaChunked({ file_path: PATH }, (error, data, response) => { if (error) { return next(error); } const mediaIdStr = data.media_id_string; const meta_params = { media_id: mediaIdStr }; // step TWO this.twitter.post('media/metadata/create', meta_params, (error, data, response) => { if (error) { return next(error); } const params = { status: publishData.content, media_ids: [mediaIdStr] }; // step THREE this.twitter.post('statuses/update', params, (error, tweet, response) => { fs.unlinkSync(PATH); // Deletes media from /tmp folder return next(error, tweet); }); // end '/statuses/update' }); // end '/media/metadata/create' }); // end T.postMedisChunked }); //end fs.writeFile }); // end request.get } /** * Check for a Twitter error. * @param {Object} res - A response from a Twitter API. * @returns {?Error} - An Error object or null. */ _error (res) { if (!res || res.error) { let errorMessage = 'unknown error occurred'; if (res.error && typeof res.error === 'string') { errorMessage = res.error; } else if (res.error) { errorMessage = JSON.stringify(res.error); } return new Error(errorMessage); } return null; } /** * Method to be called after get login url or error occurred. * @callback getLoginUrlCallback * @param {?Error} err - An Error object or null. * @param {Object} loginInfo - An object with login information * @param {string} loginInfo.loginUrl - A login url * @param {string} loginInfo.requestToken - A request token * @param {string} loginInfo.requestTokenSecret - A request token secret */ /** * Get url for login * @param {string} returnUrl - A return url to be redirected to after twitter login * @param {string} accessType - A permission * @param {getLoginUrlCallback} next - [Callback function]{@link module:twitter-bot~getLoginUrlCallback}. * @return {Promise} */ getLoginUrl(returnUrl, accessType, next) { const twitterApi = new TwitterApi({ consumerKey: this.config.consumerKey, consumerSecret: this.config.consumerSecret, callback: returnUrl, x_auth_access_type: accessType }); return new Promise((resolve, reject) => { twitterApi.getRequestToken((err, requestToken, requestTokenSecret) => { if (err) { if (next) { next(err); } return reject(err); } const loginUrl = twitterApi.getAuthUrl(requestToken); const results = { loginUrl, requestToken, requestTokenSecret }; if (next) { next(null, results); } resolve(results); }); }); } /** * Method to be called after get access token or error occurred. * @callback getAccessTokenCallback * @param {?Error} err - An Error object or null. * @param {Object} accessTokenInfo - An object with access token information * @param {string} accessTokenInfo.accessToken - An access token * @param {string} accessTokenInfo.accessTokenSecret - An access token secret */ /** * Get access token to make api calls * @param {string} oauthVerifier - Oauth verifier received after login on twitter side * @param {string} requestToken - A request token * @param {string} requestTokenSecret - A request token secret * @param {getAccessTokenCallback} next - [Callback function]{@link module:twitter-bot~getAccessTokenCallback}. * @return {Promise} */ getAccessToken(oauthVerifier, requestToken, requestTokenSecret, next) { const twitterApi = new TwitterApi({ consumerKey: this.config.consumerKey, consumerSecret: this.config.consumerSecret }); return new Promise((resolve, reject) => { twitterApi.getAccessToken(requestToken, requestTokenSecret, oauthVerifier, (err, accessToken, accessTokenSecret) => { if (err) { if (next) { next(err); } return reject(err); } const results = { accessToken, accessTokenSecret }; if (next) { next(null, results); } resolve(results); }); }); } } // export class to have the extend ability module.exports = Twitter;