読者です 読者をやめる 読者になる 読者になる

non vorrei lavorare

ブログ名の通りです。javascript three.js mruby rust OCaml golang julialang blender

Safariのリーディングリストをkindleに送る

先日、長男としまじろうコンサートに行って、二人で後半は昼寝気味なっていたkjunichiです。

大まかな流れ

iOSやOSXのSafariのリーディングリストはBookmarks.plistに格納されている。 この中から未読のURLをリスト化してphantomjsでスクリーンショットをpdfとして保存。 このpdfを添付メールとして@kindle宛に送れば、手元のkindle Fire HDで未読の URLを読むことができる。

MacのSafariのBookmarks.plistから未読のリーディングリストを取得

バイナリ形式からアスキー形式に変換しておく

plutil -convert xml1 -o url.plist ~/Library/Safari/Bookmarks.plist 

node-plistを使ってURLリストを作成

node-plistのインストール

npm install plist

URLリストを取得する

// リーディングリストから未読のURLを取得する
var plist = require('plist');

var obj = plist.parseFileSync('url.plist');
//console.log(JSON.stringify(obj));

//lista = data['Children']
//rl=lista[lista.size-1]['Children']
//(0..598).each{|i|
//  puts rl[i]['URIDictionary']['title'] + " " + rl[i]['URLString']
//}
var lista = obj.Children;
var rl = lista[lista.length-1].Children;
for(var i =0;i<rl.length;i++){
    if(!rl[i].ReadingList.DateLastViewed) {
        console.log(/*rl[i].URIDictionary.title + " " + */rl[i].URLString);    
    } else {
        //console.log("DL="+rl[i].ReadingList.DateLastViewed);
    }

}

動かし方

node geturls.js >urls.txt

phantomjsでスクリーンキャプチャをpdfに保存

phantomjs用のスクリプト

var webpage = require('webpage');
var fs = require('fs');

// read urls from file
//var urlList = fs.read("urls.txt");
if (phantom.args.length <= 0) {
    console.log('Usage: phantomjs rasterizes.js [FILE]');
    phantom.exit(1);
}

// HTMLコンテンツを読み込む
// コマンドライン起動前提なので同期I/Oで
//console.log(phantom.args[0]);
var urlList = fs.read(phantom.args[0], 'utf8');

//console.log(urlList);
var urlArray = urlList.split("\n");
//console.log(urlArray);

var Pile = function() {
  this.pile = [];
  this.concurrency = 0;
  this.done = null;
  this.max_concurrency = 10;
};

Pile.prototype = {
  add: function (callback) {
    this.pile.push(callback);
  },
  run: function (done,max_concurrency) {
    this.done = done || this.done;
    this.max_concurrency = max_concurrency||this.max_concurrency;
    var target = this.pile.length;
    var that = this;
    var next = function() {
      that.concurrency--;
      target--;
      if(target === 0){
        that.done();
      } else {
        that.run();
      }
    };
    while(this.concurrency<this.max_concurrency && this.pile.length > 0) {
      this.concurrency++;
      var callback = this.pile.shift();
      callback(next);
    }
  }
};

var pilex = new Pile();

for(var i = 100; i < urlArray.length; i++) {
  pilex.add(make_handler(i));
}
pilex.run(function () {
  console.log("fetch done.");
  finish();
},1);


function finish() {
    phantom.exit();
}

function make_handler(num) {
  return function (next) {
    console.log("fetching : "+urlArray[num]);
    var page = webpage.create();
    page.viewportSize = {width:960};
    page.paperSize = {format:"A4",orientation:"portrait",margin:"1cm"};
    page.open(urlArray[num], function (status) {
      if (status !== 'success') {
        console.log('Unable to load the address! : '+urlArray[num]);
        next();
      } else {
        window.setTimeout(function () {
          page.render(num+".pdf");
          console.log("done : "+num);
          next(); 
        },200);
      }
    });
  }
}

動かし方

phantomjs rasterizes.js urls.txt

pdfを@kindle.comに送る

Nodemailerを使うと超簡単

SMTPサーバはGMailのものを利用するので、25番ポートにtelnetするように簡単には行かないが、 このモジュールだとそこら辺もうまいことやってくれて、簡単にメールを送る事が出来る。

npm install nodemailer
var nodemailer = require('nodemailer');
var smtpTransport = nodemailer.createTransport("SMTP",{
service:"Gmail",
auth:{
user:"@gmail.com", // GMailのアドレス
pass:"" // GMailのパスワード
}
});

fileName = process.argv[2];

var mailOptions={
from:"@gmail.com",
to:"@kindle.com",
subject:"test",
text:"test",
attachments:[
{
filename:fileName,
filePath:fileName
}
]
};

smtpTransport.sendMail(mailOptions,function(error,response){
if(error){
console.log(error);
}else {
console.log("OK "+ response.message);
}
smtpTransport.close();
});