├── config.json ├── bin └── cli ├── .npmignore ├── .gitignore ├── libs ├── utils.js ├── kindle.js ├── mail.js ├── parser.js └── cli.js ├── index.js ├── examples └── index.js ├── package.json └── README.md /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "mime": "false" 3 | } -------------------------------------------------------------------------------- /bin/cli: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | require('../libs/cli')(); 4 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .gitignore 2 | .npmignore 3 | node_* 4 | examples 5 | config-mime.* -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_* 3 | *.sublime* 4 | config-*.* 5 | bin/index.md -------------------------------------------------------------------------------- /libs/utils.js: -------------------------------------------------------------------------------- 1 | var email = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/; 2 | 3 | exports.checkEmail = function(str) { 4 | return email.test(str); 5 | } -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Kindle 4 | * @author: [turingou](http://guoyu.me) 5 | * @created: [2013/07/20] 6 | * 7 | **/ 8 | 9 | module.exports = require('./libs/kindle'); -------------------------------------------------------------------------------- /libs/kindle.js: -------------------------------------------------------------------------------- 1 | var mail = require('./mail'); 2 | var path = require('path'); 3 | var fs = require('fsplus'); 4 | var configFile = path.resolve(__dirname, '../config.json'); 5 | var configs = fs.readJSON(configFile); 6 | 7 | /** 8 | * 9 | * Push files via SMTP mailer 10 | * @to[Srting] 11 | * @from[String] 12 | * @sender[Object] 13 | * @files[Array] 14 | * 15 | **/ 16 | exports.push = function(params, callback) { 17 | return mail.send({ 18 | to: params.to || configs.mime, 19 | from: params.from || configs.sender.email, 20 | sender: params.sender || configs.sender, 21 | files: params.files 22 | }, callback); 23 | } 24 | 25 | exports.config = function(param, value) { 26 | configs[param] = value; 27 | } -------------------------------------------------------------------------------- /examples/index.js: -------------------------------------------------------------------------------- 1 | var kindle = require('../libs/kindle'); 2 | 3 | kindle.push({ 4 | to: 'abc@abc.com', 5 | from: 'a@b.com', 6 | sender: { 7 | email: 'xxx', 8 | password: 'xxx' 9 | }, 10 | files: ['./my_code.txt'] // file need to be send 11 | }, function(err, result){ 12 | // do sth 13 | }); 14 | 15 | // config a sender's email 16 | kindle.config('sender', { 17 | email: 'my@my.com', 18 | password: '123123123' 19 | }); 20 | 21 | // config a receiver's email 22 | kindle.config('mime', 'my@free.kindle.com'); 23 | 24 | // a shortcut to push files quickly, 25 | // by default, it will search emails be configed before. 26 | kindle.push({ 27 | files: ['./my_code.txt'] // 需要发送的文件 28 | },function(err, result) { 29 | // do sth 30 | }); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kindle", 3 | "version": "0.1.0", 4 | "description": "a command line file pusher for your kindle", 5 | "main": "index.js", 6 | "bin": "bin/cli", 7 | "author": "turing ", 8 | "license": "MIT", 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/turingou/kindle" 12 | }, 13 | "keywords": [ 14 | "kindle", 15 | "mobi", 16 | "elink", 17 | "e-link", 18 | "sendmail", 19 | "ebook", 20 | "book", 21 | "mail" 22 | ], 23 | "bugs": { 24 | "url": "https://github.com/turingou/kindle/issues" 25 | }, 26 | "dependencies": { 27 | "async": "^0.9.0", 28 | "consoler": "^0.2.0", 29 | "fsplus": "^0.1.0", 30 | "nodemailer": "0.7.0", 31 | "colorful": "*", 32 | "optimist": "*", 33 | "markdown-pdf": "*" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /libs/mail.js: -------------------------------------------------------------------------------- 1 | var nodemailer = require("nodemailer"); 2 | var parser = require('./parser'); 3 | var async = require('async'); 4 | 5 | function sendMail(smtpTransport, mailOptions, callback) { 6 | return smtpTransport.sendMail(mailOptions, function(error, response) { 7 | if (!error) return callback(response); 8 | callback({ 9 | stat: 'error', 10 | error: error 11 | }); 12 | return smtpTransport.close(); 13 | }); 14 | }; 15 | 16 | 17 | exports.send = function(params, cb) { 18 | 19 | var smtpTransport = nodemailer.createTransport("SMTP", { 20 | auth: { 21 | user: params.sender.email, 22 | pass: params.sender.password 23 | } 24 | }); 25 | 26 | var mailOptions = { 27 | from: 'Kindle Pusher <' + params.from + '>', 28 | to: params.to, 29 | subject: 'kindle' 30 | } 31 | 32 | function wash(file, cb) { 33 | parser(file, function(result) { 34 | mailOptions.attachments.push(result); 35 | cb(); 36 | }) 37 | }; 38 | 39 | if (params.files && params.files.length > 0) { 40 | mailOptions['attachments'] = []; 41 | async.each(params.files, wash, function(err) { 42 | if (!err) return sendMail(smtpTransport, mailOptions, cb) 43 | }); 44 | } else { 45 | sendMail(smtpTransport, mailOptions, cb) 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /libs/parser.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var md = require('markdown-pdf'); 3 | var color = require('colorful'); 4 | 5 | var list = [ 6 | 'py', 7 | 'js', 8 | 'css', 9 | 'less', 10 | 'sass', 11 | 'scss', 12 | 'rb' 13 | ]; 14 | 15 | // 现在的困境是转换成pdf的话 16 | module.exports = function(string, cb) { 17 | var afterfix = string.substr(string.lastIndexOf('.') + 1); 18 | if (string.indexOf('http://') == 0 || string.indexOf('https://') == 0) { 19 | // 这里自己使用request抓下来,变成html之后转换成pdf 20 | cb({ 21 | fileName: string.substr(string.indexOf('//') + 2, string.indexOf('.') + 1) + '.txt', 22 | filePath: string 23 | }); 24 | } else if (afterfix == 'md' || afterfix == 'markdown') { 25 | console.log('正在分析' + afterfix + '文件,请稍等'); 26 | md(string, { 27 | paperFormat: 'Legal', 28 | paperBorder: '20px' 29 | }, function(err, pdfPath) { 30 | if (!err) { 31 | cb({ 32 | fileName: string + '.pdf', 33 | filePath: pdfPath 34 | }); 35 | } else { 36 | console.log(color.red('抱歉,转换失败,详情如下:')) 37 | console.log(err); 38 | console.log(color.yellow('尝试以txt格式发送')); 39 | fs.readFile(string, function(err, file) { 40 | cb({ 41 | fileName: string + '.txt', 42 | contents: file.toString() 43 | }); 44 | }); 45 | } 46 | }); 47 | } else if (list.indexOf(afterfix) > -1) { 48 | console.log('正在分析' + afterfix + '文件'); 49 | cb({ 50 | fileName: string + '.html', 51 | filePath: string 52 | }); 53 | } else { 54 | cb({ 55 | filePath: string 56 | }); 57 | } 58 | } -------------------------------------------------------------------------------- /libs/cli.js: -------------------------------------------------------------------------------- 1 | var fs = require('fsplus'); 2 | var path = require('path'); 3 | var consoler = require('consoler'); 4 | var utils = require('./utils'); 5 | var color = require('colorful'); 6 | var optimist = require('optimist'); 7 | var kindle = require('./kindle'); 8 | 9 | var configFile = path.resolve(__dirname, '../config.json'); 10 | var configs = fs.readJSON(configFile); 11 | 12 | module.exports = function() { 13 | 14 | var to = ''; 15 | var argv = optimist.argv; 16 | var argument = argv._; 17 | 18 | // 检查是不是设置接收邮箱 19 | if (argv.m) { 20 | if (utils.checkEmail(argv.m)) { 21 | fs.updateJSON(configFile, { 22 | mime: argv.m 23 | }); 24 | console.log(color.green('常用kindle收件邮箱的地址已成功变更为') + color.yellow(argv.m)) 25 | } else { 26 | console.log(color.red('你输入的邮箱地址好像不对?')) 27 | return false; 28 | } 29 | } else if (argv.sender) { 30 | if (argument.length == 1) { 31 | if (utils.checkEmail(argv.sender)) { 32 | fs.updateJSON(configFile, { 33 | sender: { 34 | email: argv.sender, 35 | password: argument[0] 36 | } 37 | }); 38 | console.log(color.green('恭喜,发件箱地址成功变更为') + color.yellow(argv.sender)) 39 | } else { 40 | console.log(color.red('你输入的邮箱地址好像不对?')); 41 | return false; 42 | } 43 | } else { 44 | console.log(color.red('密码是不是输入错了?我没看到有密码哦')) 45 | return false; 46 | } 47 | } else { 48 | 49 | if (argv.s) { 50 | if (utils.checkEmail(argv.s)) { 51 | to = argv.s; 52 | } else { 53 | console.log(color.red('你输入的邮箱地址好像不对?')) 54 | return false; 55 | } 56 | } else { 57 | if (configs.mime != 'false') { 58 | to = configs.mime.toString() 59 | } else { 60 | console.log(color.red('抱歉,你好像没有指定kindle邮箱地址,请使用 --sender 或者 -m 设置常用地址')) 61 | return false; 62 | } 63 | } 64 | 65 | if (argument.length > 0) { 66 | if (configs.sender) { 67 | console.log(color.yellow('文件发送中...')); 68 | var clock = setInterval(function() { 69 | console.log(color.green('...')) 70 | }, 800); 71 | kindle.push({ 72 | to: to, 73 | from: configs.sender.email, 74 | sender: configs.sender, 75 | files: argument 76 | }, function(result) { 77 | clearInterval(clock); 78 | if (result.stat != 'error') { 79 | console.log(color.green('恭喜,' + argument[0] + ' 等 ' + argument.length + ' 个文件已成功推送到您的 kindle!')); 80 | } else { 81 | console.log(color.red('发送失败...失败详情如下')) 82 | console.log(result.error); 83 | return false; 84 | } 85 | }); 86 | } else { 87 | console.log(color.red('没有找到邮箱设置,请先设置一个发件邮箱 -> kindle --sender a@bcd.com')) 88 | return false; 89 | } 90 | } else { 91 | console.log(color.red('话说你到底要发送哪个文件?')) 92 | return false; 93 | } 94 | 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## kindle ![npm](https://badge.fury.io/js/kindle.png) 2 | 3 | a command line file pusher for your kindle. 4 | 5 | ![screenshot](http://ww3.sinaimg.cn/large/61ff0de3gw1e6wsmhtwdgj20jv0eddh9.jpg) 6 | 7 | ### Installation 8 | ``` 9 | $ [sudo] npm install kindle -g 10 | ``` 11 | 12 | ### Setup Guide 13 | 14 | 1. setup your sender's email(SMTP) via `$ kindle --sender` and `$ kindle -m`. 15 | 2. setup your sender's email be trusted in [Amazon Kindle Dashboard](#/#). 16 | 3. push files via command line like `$ kindle mybook.pdf` to your @free.kindle.com email account. 17 | 3. enjoy reading :) 18 | 19 | ### Configs Guide 20 | 21 | config sender's email 22 | ``` 23 | $ kindle --sender email password 24 | ``` 25 | configs @free.kindle.com email 26 | ``` 27 | $ kindle -m email 28 | ``` 29 | 30 | ### Example 31 | 32 | ```javascript 33 | var kindle = require('kindle'); 34 | 35 | kindle.push({ 36 | to: 'abc@abc.com', 37 | from: 'a@b.com', 38 | sender: { 39 | email: 'xxx', 40 | password: 'xxx' 41 | }, 42 | files: ['./my_code.txt'] // file need to be send 43 | }, function(err, result){ 44 | // do sth 45 | }); 46 | 47 | // config a sender's email 48 | kindle.config('sender', { 49 | email: 'my@my.com', 50 | password: '123123123' 51 | }); 52 | 53 | // config a receiver's email 54 | kindle.config('mime', 'my@free.kindle.com'); 55 | 56 | // a shortcut to push files quickly, 57 | // by default, it will search emails be configed before. 58 | kindle.push({ 59 | files: ['./my_code.txt'] // 需要发送的文件 60 | },function(err, result) { 61 | // do sth 62 | }); 63 | ``` 64 | 65 | ### Contributing 66 | - Fork this repo 67 | - Clone your repo 68 | - Install dependencies 69 | - Checkout a feature branch 70 | - Feel free to add your features 71 | - Make sure your features are fully tested 72 | - Open a pull request, and enjoy <3 73 | 74 | ### MIT license 75 | Copyright (c) 2014 turing <o.u.turing@gmail.com> 76 | 77 | Permission is hereby granted, free of charge, to any person obtaining a copy 78 | of this software and associated documentation files (the "Software"), to deal 79 | in the Software without restriction, including without limitation the rights 80 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 81 | copies of the Software, and to permit persons to whom the Software is 82 | furnished to do so, subject to the following conditions: 83 | 84 | The above copyright notice and this permission notice shall be included in 85 | all copies or substantial portions of the Software. 86 | 87 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 88 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 89 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 90 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 91 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 92 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 93 | THE SOFTWARE. 94 | 95 | --- 96 | ![docor](https://cdn1.iconfinder.com/data/icons/windows8_icons_iconpharm/26/doctor.png) 97 | built upon love by [docor](https://github.com/turingou/docor.git) v0.1.3 98 | --------------------------------------------------------------------------------