Skip to content
This repository has been archived by the owner on May 2, 2019. It is now read-only.

Commit

Permalink
first version
Browse files Browse the repository at this point in the history
  • Loading branch information
matteocontrini committed Feb 10, 2017
1 parent 657e307 commit 897b4db
Show file tree
Hide file tree
Showing 10 changed files with 298 additions and 0 deletions.
43 changes: 43 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"rules": {
"indent": ["error", "tab"],
"quotes": ["error", "single"],
"quote-props": ["error", "consistent"],
"semi": ["error", "always"],
"keyword-spacing": ["error"],
"no-unused-vars": ["warn", { "vars": "all", "args": "none" }],
"no-console": ["off"],
"no-mixed-spaces-and-tabs": ["error", "smart-tabs"],
"no-new-object": ["error"],
"no-array-constructor": ["error"],
"space-before-blocks": ["error", "always"],
"space-before-function-paren": ["error", "never"],
"space-in-parens": ["error", "never"],
"space-infix-ops": ["error"],
"space-unary-ops": ["error", { "words": true, "nonwords": false }],
"object-curly-spacing": ["error", "always"],
"array-bracket-spacing": ["error", "never"],
"guard-for-in": "error",
"no-spaced-func": "error",
"no-trailing-spaces": ["error", { "skipBlankLines": true }],
"handle-callback-err": "error",
"comma-spacing": ["error", {"before": false, "after": true}],
"one-var": ["error", "never"],
"no-redeclare": 0,
"comma-dangle": ["error", "never"],
"arrow-parens": ["warn", "always"],
"arrow-spacing": ["error"],
"no-confusing-arrow": ["error"],
"no-useless-computed-key": ["error"],
"object-shorthand": ["warn", "methods"],
"prefer-arrow-callback": ["error"],
"prefer-rest-params": ["warn"],
"template-curly-spacing": ["warn", "never"]
},
"env": {
"node": true,
"mocha": true,
"es6": true
},
"extends": "eslint:recommended"
}
45 changes: 45 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Created by https://www.gitignore.io/api/node,windows

### Node ###
# Logs
logs
*.log
Expand All @@ -7,6 +10,7 @@ npm-debug.log*
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
Expand All @@ -20,6 +24,9 @@ coverage
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

Expand All @@ -33,5 +40,43 @@ jspm_packages
# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env


### Windows ###
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db

# Folder config file
Desktop.ini

# Recycle Bin used on file shares
$RECYCLE.BIN/

# Windows Installer files
*.cab
*.msi
*.msm
*.msp

# Windows shortcuts
*.lnk

# End of https://www.gitignore.io/api/node,windows

config.json
18 changes: 18 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const bole = require('bole');

// Initialize the logger
bole.output([{ level: 'debug', stream: process.stdout }]);

let logger = bole('index');
logger.info('TerremotiBot Social is booting...');

// When an expection occurs,
// log the 'Error' and euthanasia
process.on('uncaughtException', (err) => {
logger.error(err);
// We can safely exit because the only logger output is stdout,
// which is flushed automatically when the process shuts down
process.exit(1);
});

require('./src/social.js');
26 changes: 26 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "terremotibot-social",
"version": "1.0.0",
"description": "Automatic earthquakes poster to Twitter and Facebook",
"main": "index.js",
"scripts": {
"lint": "eslint src"
},
"repository": "botfactoryit/terremotibot-social",
"author": "Matteo Contrini <m.contrini@gmail.com>",
"license": "MIT",
"bugs": {
"url": "/~https://github.com/botfactoryit/terremotibot-social/issues"
},
"homepage": "/~https://github.com/botfactoryit/terremotibot-social#readme",
"dependencies": {
"aws-sdk": "^2.11.0",
"bole": "^3.0.2",
"fb": "^1.1.1",
"sqs-consumer": "^3.4.0",
"twit": "^2.2.5"
},
"devDependencies": {
"eslint": "^3.15.0"
}
}
19 changes: 19 additions & 0 deletions src/config/example.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"sqs": {
"queueUrl": "",
"accessKeyId": "",
"secretAccessKey": "",
"region": "eu-central-1",
"apiVersion": "2012-11-05"
},
"facebook": {
"accessToken": "",
"pageId": ""
},
"twitter": {
"consumerKey": "",
"consumerSecret": "",
"accessToken": "",
"accessTokenSecret": ""
}
}
8 changes: 8 additions & 0 deletions src/config/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const fs = require('fs');

let content = fs.readFileSync(__dirname + '/config.json').toString();
const config = JSON.parse(content);

module.exports = function(module) {
return config[module] || {};
};
29 changes: 29 additions & 0 deletions src/networks/facebook.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
const FB = require('fb');
const config = require('../config')('facebook');

let fb = new FB.Facebook();

fb.setAccessToken(config.accessToken);

module.exports.upload = function(options, callback) {
let req = {
source: {
value: options['buffer'],
options: {
contentType: 'image/jpeg',
filename: 'terremoto.jpg' // because facebook
}
},
backdated_time: Math.round(options['date'].getTime() / 1000),
caption: options['text']
};

fb.api(config.pageId + '/photos', 'post', req, (res) => {
if (res.error) {
callback && callback(res.error);
}
else {
callback && callback(null, res);
}
});
};
2 changes: 2 additions & 0 deletions src/networks/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
module.exports.twitter = require('./twitter.js');
module.exports.facebook = require('./facebook.js');
38 changes: 38 additions & 0 deletions src/networks/twitter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
const Twit = require('twit');
const config = require('../config')('twitter');

let tw = new Twit({
consumer_key: config.consumerKey,
consumer_secret: config.consumerSecret,
access_token: config.accessToken,
access_token_secret: config.accessTokenSecret
});

module.exports.upload = function upload(options, callback) {
let b64 = options['buffer'].toString('base64');

tw.post('media/upload', { media_data: b64 }, (err, data, response) => {
if (err) {
callback && callback(err);
return;
}

let mediaId = data['media_id_string'];

let params = {
status: options['text'],
lat: options['origin']['lat'],
long: options['origin']['lon'],
media_ids: [mediaId]
};

tw.post('statuses/update', params, (err, data, response) => {
if (err) {
callback && callback(err);
}
else {
callback && callback(null, data);
}
});
});
};
70 changes: 70 additions & 0 deletions src/social.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
const AWS = require('aws-sdk');
const Consumer = require('sqs-consumer');
const config = require('./config');
const networks = require('./networks');
const logger = require('bole')('social');

const sqs = Consumer.create({
queueUrl: config('sqs').queueUrl,
messageAttributeNames: ['Card'],
handleMessage: handleMessage,
sqs: new AWS.SQS({
accessKeyId: config('sqs').accessKeyId,
secretAccessKey: config('sqs').secretAccessKey,
region: config('sqs').region,
apiVersion: config('sqs').apiVersion
}),
batchSize: 1
});

sqs.on('error', (err) => {
logger.error(err);
});

sqs.start();

function handleMessage(message, done) {
logger.info('Received new message');

let body = JSON.parse(message['Body']);
let buffer = message.MessageAttributes.Card.BinaryValue;

let date = new Date(body['date']);
let time = ('0' + date.getHours()).slice(-2) + ':' + ('0' + date.getMinutes()).slice(-2);

let magnitude = body['magnitude']['value'];
let uncertainty = body['magnitude']['uncertainty'];
let type = body['magnitude']['type'];
let city = body['city'];

let text = `#terremoto alle ${time}\n\nEpicentro: ${city}\nMagnitudo: ${magnitude} ± ${uncertainty} (${type})`;

let options = {
origin: body['origin'],
text: text,
buffer: buffer,
date: date
};

logger.info('Uploading to Twitter');

networks.twitter.upload(options, (err) => {
if (err) {
logger.error(err);
done(err);
return;
}

logger.info('Done');
logger.info('Uploading to Facebook');

networks.facebook.upload(options, (err) => {
if (err) {
logger.error(err);
}

logger.info('Done');
done();
});
});
}

0 comments on commit 897b4db

Please sign in to comment.