├── .gitignore ├── README.md ├── config.dist.js ├── index.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea 3 | config.js 4 | 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sms-cli (alpha) 2 | Stealth desktop SMS app. Compatible with Android via SMS Gateway API (http://smsgateway.me). 3 | 4 | Able to get last X messages (received and sent) and to send new messages, from your Android Device. 5 | 6 | # Usage 7 | 8 | ![Image](http://i.imgur.com/c9tJiim.png) 9 | 10 | 11 | Cyan header represents the received messages. 12 | 13 | #### Steps 14 | 15 | **Send To:** Message index (numbers on the left), phone number or nothing (defaults to the sender of the last message). 16 | 17 | **Message:** Your message content (new lines not supported) 18 | 19 | **Confirmation:** "Y" or "y" to confirm. 20 | 21 | # Installation 22 | 23 | 1. Install ["SMS Gateway API"](https://play.google.com/store/apps/details?id=networked.solutions.sms.gateway.api) app and login or signup. 24 | 25 | 2. Clone 26 | 27 | $ git clone https://github.com/atduarte/sms-cli.git 28 | $ cd sms-cli 29 | 30 | 3. Change configurations 31 | 32 | $ cp config.dist.js config.js 33 | $ vi config.js # And replace fields with your "SMS Gateway API" info 34 | 35 | 4. Get dependencies & Run it 36 | 37 | $ npm install 38 | $ sudo chmod +x index.js 39 | $ sudo ln -s ./index.js /usr/bin/sms-cli 40 | $ sms-cli 41 | 42 | # Documentation 43 | 44 | ## Configuration 45 | 46 | * email, password (strings) - Email and password used with SMS Gateway API 47 | * deviceId (number) - Device ID from the Android phone you want to use. Available on the SMS Gateway API app. 48 | * messageCount (number) - How many messages (received and sent) do you want to show? 49 | * baseUrl (string) - Base URL from SMS Gateway API. You shouldn't need to change this. 50 | 51 | # Known Problems 52 | 53 | * SMS Gateway API (http://smsgateway.me) repeats some "manual sent" messages and misses others. We are considering creating our own Android App and API Gateway 54 | -------------------------------------------------------------------------------- /config.dist.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | baseUrl: 'http://smsgateway.me/api/v3/', 3 | email: '', 4 | password: '', 5 | deviceId: null, 6 | messageCount: 5 7 | }; -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/node 2 | 3 | var _ = require('underscore'), 4 | clc = require('cli-color'), 5 | async = require('async'), 6 | request = require('request'), 7 | read = require('read'), 8 | Entities = require('html-entities').AllHtmlEntities, 9 | entities = new Entities(), 10 | config = require('./config'); 11 | 12 | request = request.defaults({ 13 | baseUrl: config.baseUrl, 14 | qs: {email: config.email, password: config.password} 15 | }); 16 | 17 | var selectMessages = function (rawMessages, count) { 18 | return _.uniq(rawMessages, false, function (value) { return value.contact.number + '|' + value.message }) 19 | .splice(0, count) 20 | .reverse(); 21 | }; 22 | 23 | var printMessages = function (messages) { 24 | var i; 25 | for (i = 0; i < messages.length; i++) { 26 | var message = messages[i]; 27 | 28 | //var date = message.received_at || message.sent_at; 29 | var color = message.received_at ? clc.cyan : clc.white; 30 | var arrow = message.received_at ? '→' : '←'; 31 | 32 | console.log(color('[' + i + '] ' + arrow + ' ' + entities.decode(message.contact.name))); 33 | console.log(entities.decode(message.message)); 34 | } 35 | console.log(''); 36 | }; 37 | 38 | var promptSend = function (messages) { 39 | var number = undefined, 40 | content = null; 41 | 42 | async.waterfall([ 43 | async.apply(read, {prompt: 'Send to: '}), 44 | function (result, isDefault, next) { 45 | result = !result ? messages.length-1 : parseInt(result, 10); 46 | 47 | if (result >= 0 && result < messages.length) { 48 | number = messages[result].contact.number; 49 | } 50 | 51 | if (result.toString().length >= 9) number = result; 52 | 53 | if (!number) return next(clc.red('Invalid input')); 54 | 55 | next(); 56 | }, 57 | async.apply(read, {prompt: 'Message: '}), 58 | function (result, isDefault, next) { 59 | if (!result) { 60 | return next(clc.yellow('Message not sent')); 61 | } 62 | 63 | content = result; 64 | 65 | read({prompt: 'Are you sure? This will go to: ' + number + '. (Y/N)'}, next); 66 | }, 67 | function (result, isDefault, next) { 68 | if (result.toUpperCase() !== 'Y') { 69 | return next(clc.yellow('Message not sent')); 70 | } 71 | 72 | sendMessage(number, content, next); 73 | } 74 | ], function (err) { 75 | if (err) console.log(err); 76 | }); 77 | }; 78 | 79 | var sendMessage = function (number, message, callback) { 80 | request.post({url: 'messages/send', qs: {device: config.deviceId, number: number, message: message}}, function (err, httpResponse, body) { 81 | if (err || httpResponse.statusCode != 200) { 82 | console.log(err); 83 | console.log(body); 84 | return callback(clc.red('Error')); 85 | } 86 | 87 | console.log(clc.green('Sent!')); 88 | callback(); 89 | }); 90 | }; 91 | 92 | request.get('messages', function (err, httpResponse, body) { 93 | if (err || httpResponse.statusCode != 200) { 94 | console.error('Couldn\'t connect to the API to get the messages'); 95 | return; 96 | } 97 | 98 | var messages = selectMessages(JSON.parse(body).result || {}, config.messageCount); 99 | 100 | if (messages.length == 0) { 101 | console.error(clc.red('No messages to show')); 102 | return; 103 | } 104 | 105 | printMessages(messages); 106 | promptSend(messages); 107 | }); 108 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sms-cli", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "async": "^1.4.2", 13 | "cli-color": "^1.0.0", 14 | "html-entities": "^1.1.3", 15 | "read": "^1.0.7", 16 | "request": "^2.64.0", 17 | "underscore": "^1.8.3" 18 | } 19 | } 20 | --------------------------------------------------------------------------------