ほんじゃらねっと

ダイエット中プログラマのブログ

Node.jsとGruntでフォルダ監視ツールを作る

f:id:piro_suke:20160414001322j:plain

コミュニケーションというのはなかなか難しいもので、

「急いで確認したいから資料ができたら共有フォルダに入れて、すぐ連絡してよ」

と強めに伝えても、

資料はとっくにできてるのに

やれ後で連絡するつもりだっただの、

もうちょっと確認してから連絡するつもりだっただの、

今メール書いてただので、

一本内線をくれるだけで良いのになかなか連絡がもらえないことがある。

そんなストレスフルな行き違いは

「このやろう!」と毎回怒りを爆発させるよりも

ツールを使って解決の仕組みを用意してしまうに限る。

ということで今回は指定したフォルダを監視して、

ファイルが追加されたり更新されたりしたら

自動で通知してくれるスクリプトをつくってみたい。

続きを読む

正規表現を使ったエレガントな置換処理を学びつつ簡易なファイル名一括変換ツールを作る

文字列を検索したりマッチしたものを置換したり、という作業は

技術者が制作・開発する時だけでなく、例えばExcelやWordで文書を編集する際や

Webページ内で目的の文章を探したりする場合にも行うもので、

「作業の効率化」という点では欠かせないものだ。

今回扱う「正規表現」を使った検索・置換については、

標準の機能として備えているツールやテキストエディタも多いが、

プログラマ以外には馴染みの薄いものかもしれない。

(少なくとも私に面倒な変換作業を依頼してくる人たちは間違いなく知らないと思う)

「正規表現」を全く知らない人は、

このつまらなそうな言葉を見ただけでスルーしてしまいそうだが、

使いこなせば大変強力なものであり

プログラマ以外の

パソコンを使用して何かしらの仕事をしている人にとっても

作業効率が劇的に上がること間違いなしの技術なので、

ここで紹介しておきたい。

続きを読む

プログラミングはしたくないけど自動化はしたい人のための、Grunt.jsによる作業自動化入門

前回書いたNode.js入門記事の続き。

blog.honjala.net

前回から引き続き、

いかにプログラムの勉強無しで自動化できることを増やすか、

もとい、

いかに他部署のノンプログラマに自動化ツールを使わせて自分への作業依頼を減らすか、

をマイテーマに少しずつ情報をまとめていく。

Node.jsを紹介しただけでは、「Javascript…難しそう。いつかやるわ。」

となりそうなので、

今回はプログラミング要素最小限で使えるGruntを紹介する!

続きを読む

作業自動化のための Node.js 入門

これまでいくつかの記事でNode.jsを使ったスクリプトを載せてきたが、

自動化のためのスクリプトを書いて動かす環境として

Node.jsは手軽だし速いし色々ライブラリは揃ってきているし

なかなか良い環境だと感じている。

Web系の仕事をしていればJavascriptはある程度親しみのある言語だろうし、

GruntやGulpのようなWeb関連作業を自動化する

機能満載のタスクランナーまで用意されている。

実行環境もインストーラをダウンロードしてインストールすれば

パッケージ管理ツール付きで入手することができるので、

すぐに開発を始めることができる。

非同期処理が得意なサーバアプリケーションを作るための環境として

紹介されることが多いけど、この手軽に導入できて

Javascriptでサクッとアプリが作れるところだけでも十分に価値があると思う。

ノンプログラマが仕事を効率化するためにプログラミングを始めるなら、

とりあえずNode.jsから始めてみたらいいんじゃないだろうか。

今回はこのブログで紹介しているNode.jsのサンプルを試していただけるよう、

Node.js実行環境のインストールから

簡単なサンプルプログラムを作って実行するところまでを紹介したい。

自分でプログラムを作成するところまでいかなくても、

入手したプログラムを実行できるようになれば自動化作業も捗るのではないかと思う。

続きを読む

IFTTTのMakerチャンネルを使って、いろんなサービスの更新情報を通知してくれる仕組みを作る

仕事でチーム間のコミュニケーションツールとして使い始めたチャットワークだが、

最近は「いろんなサービスやスクリプトからの通知を集めるツール」としての利用がメインになってきている。

www.chatwork.com

以前記事にした、

「Subversionのコミット情報にメンバーがすぐに気づけるように通知するスクリプト」

blog.honjala.net

を書いたのがきっかけで、

この仕組みを流用すればメールを汚さずにいろんな通知を一元管理できるのでは?

と思いついて色々チャットワークに自動通知するスクリプトを書き始めた。

ただ通知するだけなのだけど、ボットが

「ブログのはてブが増えたよ!」とか

「AmazonにKindle本が追加されたよ!」とか

発言してくれることでチェックの手間が減るのが楽しい。

本題

そんな時に、「IFTTTにMakerチャンネルができた」という話を聞いて、

これを使えば自動通知がさらに捗りそうだ、ということで試してみた、というのが今回の本題だ。

IFTTT(If This Then That)とは

EvernoteやTwitter等様々なアプリやWebサービス(チャンネルと呼ばれる)の更新を監視して、

更新が発生するとをあらかじめ登録しておいたアクションを実行してくれるというサービスで、

これを使えばプログラムを自作しなくても手軽に連携の仕組みが作れるという、

自動化心をくすぐられるサービスだ。

ifttt.com

IFTTTは便利なサービスなのだが、以前はチャンネルが用意されていないサービス間の連携がしにくい、という欠点があった。

チャットワークもチャンネルが用意されていない。

それが、Makerチャンネルが使えるようになったことで多少やりやすくなった。

ifttt.com

Makerチャンネルは簡単に言うと「他のチャンネルとWebアプリを連携できる」チャンネルだ。

自作のWebアプリをトリガーとしてMakerチャンネル経由で他のチャンネルを呼び出したり、

特定のチャンネルで更新が発生したら指定したURLにリクエストを飛ばすようなことができる。

これを使えば、何かしらのサービスで更新が発生した時に自作のWebアプリを経由してチャットワークにメッセージを保存する、みたいなこともできるわけだ。

Makerチャンネルを使ってチャットワークに連携するサンプルを作る

試しに、Node.jsで作成したWebアプリ経由で「Date&Timeチャンネルをトリガーに、定時になったらチャットワークに通知するレシピ」を作ってみた。

Webアプリを準備する

まずはIFTTTからアクセス可能なWebアプリを用意する。

ここがややハードルの高いところ。

今回は「http://自分のサーバのドメイン:3000/ifttt/notify_workend」というURLを用意し、

POSTリクエストで「time:時間」「message:メッセージテキスト」をJSON形式で渡すとその内容をチャットワークに送れるようにした。

下記はnode.js + Express4のサンプルソース:

(Webアプリでパラメータを受け取れたら環境は問わないので、Apache + PHP環境とかでも可)

REST API Sample For IFTTT Maker Channel.

こういうものを1つ用意しておけば、URLを追加していくだけでいろんなチャンネルと連携できるようになる。

IFTTTのレシピを作成する

次はITFFF側で用意したURLを呼び出すレシピを作成する。

トリガーとなるチャンネルの選択後、Makerをアクションとして選択して新しいレシピを作成する。

f:id:piro_suke:20160215013908p:plain

アクションの設定を行って、

f:id:piro_suke:20160215013918p:plain

作成したWebアプリのURLとパラメータを定義する。

「Content Type」を「application/json」にしておき、BodyでJSONを渡すようにしている。

f:id:piro_suke:20160215013928p:plain

この内容で登録しておくと、平日の17:30になったら、「Time to leave work」というメッセージが

用意したURLに飛び、そこを経由してチャットルームにメッセージが投稿される。

おわり

とりあえず仕組みが作ってみたが、まだまだ活用法は模索中。

また良い通知レシピを思いついたら試してみたい。

実践Node.jsプログラミング Programmer's SELECTION

実践Node.jsプログラミング Programmer's SELECTION

Node.jsでドメインのはてなブックマーク合計件数を取得する

ブログを書いていると、

自分が書いた記事にどれくらいブックマークがついているかが

気になるものである。

はてなブログでブログを管理している場合は、

ブログ管理画面や「はてなのお知らせ」というChrome拡張で

ブックマークされたことを知ることができる。

chrome.google.com

Wordpress等でブログを管理している場合は、

はてなブックマークのトップページの検索欄にブログのURLを入力すると

記事ごとのブックマーク数を表示してくれる。

このブログなら下記のページ:

『ほんじゃら堂』 の新着エントリー - はてなブックマーク

まあ確認するにはこれで十分なのだけど、

「もっとサクッとブックマークの総数が知りたいんや!」

という人向けに(かどうかは知らないが)

はてなブックマークのAPIに、

「指定したドメインの合計はてブ件数を取得できるAPI」

というものがちゃんと用意されている。

下記サイトの「被ブックマーク合計数取得API」のところだ。

はてなブックマーク件数取得API - Hatena Developer Center

XMLRPC経由ではてブ合計件数が知りたいドメインを渡すと、

その件数を返してくれる。

このAPIを使えば、

例えばブックマーク件数が増えた時に通知する、みたいなこともできそうだ。

このAPIを呼び出すスクリプトを作成して、

前回の件数と異なる件数が返ってきたらメールなりチャットなりに通知するような

内容にしておけば、即座に知ることができるだろう。

Node.jsでAPIにアクセスするスクリプトを作る

今回はXMLRPC経由で件数を取得するだけのスクリプトを作成してみよう。

練習も兼ねてNode.jsで作成してみた。

Node.js XMLRPC Client Sample

sample_hatebu.jsを実行するとはてブ件数が表示される。

Hatebu.getHatebuCountに渡しているURLを変更すれば

好きなドメインのはてブ数を表示することができる。

XMLRPCには下記のライブラリを使用している:

github.com

Node.js実行環境のインストール方法やスクリプトの実行方法については

入門記事を作成したので、下記を参照いただきたい:

blog.honjala.net

おわり

モチベーションアップに繋がるので、

こういったポジティブな情報の取得はどんどん自動化して

目に入るようにしておきたいものだ。

Subversionにコミットしたらチャットワークに通知するNode.jsスクリプト

ある開発プロジェクトで、

非技術系のメンバーにも進捗を知っておいてもらいたいものの、

「お前らSubversion入れろ」とか「リポジトリログを見ろ」といっても見そうになく、

いちいち伝えるのも面倒大変そうだったので、

Subversionにコミットがあったらメッセージ内容がリアルタイムで

チャットワークに流れる仕組みを作ってやった。

www.chatwork.com

チャットワークはチーム間でのやりとりに使っていたので、ここに流してやろうというわけだ。

チャットワークはプレビュー版ながらAPIを公開してくれているので、

developer.chatwork.com

API経由でメッセージ投稿を行うスクリプトと、

Subversionのフック機能を組み合わせることで実現することができた。

Node.jsでチャットワークのAPIにアクセスするスクリプトを作成する

今回はNode.jsでスクリプトを作成した。

手軽に環境が作れて、速くて、一通りライブラリが揃っているので気に入っている。

スクリプトの内容としては、

コマンドラインからリポジトリパスとリビジョン番号を受け取って、

svnlookコマンドでリビジョンをコミットしたユーザー名、メッセージログを取得して、

メッセージを組み立てて、

チャットワークのAPI経由で投稿している。

Subversionが動いているサーバにnode.js環境をインストールして、このスクリプトを配置する。

svn2chatwork.js

var execSync = require('child_process').execSync;
var _ = require('underscore');
var request = require('request');

if (process.argv.length < 4) {
    return;
}

var repo = process.argv[2];
var rev = process.argv[3];

var cwApiKey = '<ChatworkのAPIキー>';
var endpointBase = 'https://api.chatwork.com/v1/';

var svnRootPath = '/var/www/svn'; //Subversionのリポジトリルートパス

var targetRepos = {}; 
// このtargetReposにリポジトリパスを追加したら複数のリポジトリに対応可能
targetRepos[svnRootPath + '/<SVNリポジトリパス>'] = {'roomId': '<投稿先ChatworkのルームID>'};

var post2Chatwork = function (roomId, message, callback) {
    var options = { 
        url: endpointBase + 'rooms/' + roomId + '/messages',
         headers: {
             'X-ChatWorkToken': cwApiKey
         },  
        form: {
            body: message
        },
        json: true
    };

    request.post(options, function (error, response, body) {
        if (!error &amp;&amp; response.statusCode == 200) {
            callback(body);
        }   
    }); 
}
if (_.has(targetRepos, repo)) {
    var repoInfo = targetRepos[repo];
    var message = 'New Commit\n';

    var result = '' + execSync('svnlook author ' + repo + ' -r ' + rev);
    message += 'User:' + result;

    result = '' + execSync('svnlook log ' + repo + ' -r ' + rev);
    message += result;

    // 下記のコメントを外すと更新ファイル一覧もメッセージに追加できる(大量にファイルが更新されると結構うざい)
    // result = '' + execSync('svnlook changed ' + repo + ' -r ' + rev);
    // message += 'Files Updated:\n';
    // message += result;

    post2Chatwork(repoInfo.roomId, message, function (body) {});
}

Subversionのフックスクリプトを作成する

Subversionのリポジトリを作成すると、その中にhooksフォルダが作成され、

そこに置いたフックスクリプトを各種タイミングで実行してくれる。

Subversion フックスクリプト

今回はコミット後に上で作成したスクリプトを実行してもらいたいので、

「post-commit」という名前で下記のような内容のファイルを作成する。

作成したスクリプトにパラメータとしてリポジトリパスとリビジョン番号を渡し、nodeコマンドで実行するコマンドを書いてる。

最初のexport文を書かないと、日本語が文字化けしてしまうので注意。

あと、node.jsのバージョンとか、どこにsvn2chatwork.jsを置いたかでパスが変わるので注意。

post-commit

export LANG=ja_JP.UTF-8

REPOS='$1'
REV='$2'

# <nodeコマンドへのパス> <svn2chatwork.jsへのパス> $REPOS $REV
/usr/local/node-v0.12.7/bin/node /home/test/svn2chatwork/svn2chatwork.js $REPOS $REV

編集後、post-commitに実行権限をつけたら以降のコミットがチャットワークに通知されるはず。

おわり

ソースを整理したり、リポジトリとルームの関連付けを外部化したりしたものをGitHubに置いている。

よかったら参考にしていただきたい。

github.com

今時Subversionなんか使わねーよ!と言われるかもしれないが。

blog.honjala.net

Subversion実践入門:達人プログラマに学ぶバージョン管理(第2版)

Subversion実践入門:達人プログラマに学ぶバージョン管理(第2版)

Node.jsでRedmineのREST APIにアクセスしてチケット取得&一括登録

とあるWeb開発プロジェクトで

WBS(Excel製)に書かれた、機能ごとの開発担当・開始日・期日・予定工数を

そのままRedmineのチケットとして登録するという、

手作業でやったらえらく時間のかかりそうな作業があったので、

RedmineのAPI経由でチケットを一括登録できるスクリプトを作成した。

続きを読む

Node.jsのRESTクライアントモジュールでBit.lyのAPIにアクセスする

Node.jsのRESTクライアントモジュールを試すため、 以前Groovyで作成したBit.lyの履歴を取得するスクリプトをNode.jsで焼きなおしてみる。

node-rest-client」というモジュールを使用した。

get_bitlinks.js

var RestClient = require('node-rest-client').Client;

var ACCESS_TOKEN = '<your access token>';
var ENDPOINT_BASE = 'https://api-ssl.bitly.com/';
var bitlyClient = new RestClient();

bitlyClient.get(ENDPOINT_BASE + 'v3/user/link_history', {
    headers: {
        'Content-type': 'application/json'
    },
    parameters: {
        access_token: ACCESS_TOKEN,
        limit: 10,
        offset: 0
    }
}, function (data, response) {
    var result = JSON.parse(data.toString('utf8'));
    var linkList = result.data.link_history;
    linkList.forEach(function (link) {
        console.log(link.title);
    }); 
});

RestClientで呼び出すメソッドをgetからpostやputに変更すれば 登録、更新も行えるようなので、これ1つ覚えておけば色々なAPIアクセスに 使用できそうだ。

RESTful Webサービス

RESTful Webサービス

MongoDBに保存したデータをNode.js+ExpressでWeb表示する簡単なサンプル

そろそろNode.jsスクリプト作成にも慣れてきたので、

簡単なWebアプリ作成に挑戦してみた。

Meteor、MEAN.js、Sails.jsなど色々あって迷ったけど、

まずはシンプルにExpressを使ってみる。

MongoDBコレクションに保存された情報を

Webページ上に一覧表示するスクリプトを、

Node.js+Express+MongoDBで作成した。

続きを読む

ApacheのアクセスログをMongoDBコレクションにインポートするNode.jsスクリプト

MongoDBの勉強を兼ねて、Apacheアクセスログを後でログ分析や ビジュアライズに使えるようにMongoDBにインポートするスクリプトを書いた。

下記のスクリプトはログファイルを行単位で読み込んでMongoDBの 特定のコレクションに登録する。 行単位のファイル読み込み処理はNode.js標準で簡単にできる方法が用意されていない ようなので、node-bylineを使用している。

log_importer.js

var fs = require('fs');
var byline = require('byline');
var MongoClient = require('mongodb').MongoClient;

var dbUrl = 'mongodb://localhost:27017/<database name>';
var targetPath = '<path to access log>';

var logPattern = /(\S+) \- \- \[([^\]]+)\] '([^']+)' (\d+) (\S+) '([^']+)' '([^']*)'/;

var rs = fs.createReadStream(targetPath);
var stream = byline.createStream(rs);

MongoClient.connect(dbUrl, function (err, db) {
    if (err) {
        throw err;
    }   

    var apacheLogs = db.collection('apache_logs');

    var i = 0;
    stream.on('readable', function () {

        var line = null;
        while (null !== (line = stream.read())) {
            console.log(i + ':line start ' + line);
            var match = logPattern.exec(line);
            if (match != null) {
                var methodParams = match[3].split(' ');
                var method = methodParams[0];
                var path = methodParams[1];
                var http = methodParams[2];
                var log = {
                    host: match[1],
                    ts: match[2],
                    method: method,
                    path: path,
                    http: http,
                    status: match[4],
                    size: match[5],
                    agent: match[7]
                };
                apacheLogs.insert(log, function (err, result) {
                    if (err) {
                        console.log('log insert error:', err);
                    } else {
                        console.log(i + ':inserted');
                    }
                });
            } else {
                console.log(i + ':match error');
            }
            i++;
        }
    });
    stream.on('end', function () {
        db.close();
    });
});

参考にしたサイトや使用したライブラリ:

RegExp - Mdn https://developer.mozilla.org/ja/doc/Web/JavaScript/Reference/Global_Objects/RegExp

Read large text files in nodejs https://coderwall.com/p/ohjerg/read-large-text-files-in-nodejs

Node.js how to read one line of numbers from a file into an array http://stackoverflow.com/questions/7379310/node-js-how-to-read-one-line-of-numbers-from-a-file-into-an-array

npm line-reader https://github.com/nickewing/line-reader

npm node-byline https://github.com/jahewson/node-byline

JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス

JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス

Nashornスクリプト実行時のクラスパス設定を容易にするためにNasven.jsを使う

Nashornというのは、Java8に同梱されている新しいJavascriptエンジンで、 Javaライブラリを呼び出して利用するJavascriptプログラムを作成することができる。 Node.jsで適当なライブラリが見つからない場合やJavaライブラリに精通していて ちょっとしたスクリプトを作成したい場合の良い選択肢になりそうだ。

Java8環境をインストールしたら標準で付属してくる「jjs」コマンドを使うことで 作成したNashornスクリプトを実行することができる。

Javascriptの言語仕様に加えて、いくつかJavaクラスを呼び出すための関数が 追加されている。Node.jsでnpmライブラリをrequireする感覚でJavaのライブラリを 呼び出せるようになる。

詳細は下記のユーザーガイド参照: Nashorn User's guide https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/

ここからが今回の本題。

NashornスクリプトはJavaのクラスと同じ扱いなので Apache Projectや自作のJar等の標準以外のJavaライブラリを使おうとすると、 当然ながらクラスパスにそのJarファイルを追加して実行する必要がある。

jjsコマンドにはclasspathオプションがあり、ここでjarファイルを指定すれば それで実行できるのだけど、多くのjarファイルを使用している場合などは 毎回classpathを指定するのが面倒で、せっかくコンパイル無しでサクッと 実行できるのだからクラスパス指定ももっと簡単にしたい。

と思って探してみたら、「Nasven.js」(Nashorn + Maven + .js)というスクリプトが 公開されてた。これを使うとMavenと同じ感じでビルドファイルを作成しておき、 そこでクラスパス等のビルド情報を記述しておくことができる。

詳細は下記の記事参照: Nashorn Maven: Easy Library Classpath Setup https://blogs.oracle.com/brunoborges/entry/nashorn_maven_easy_library_classpath

試しにApache POIを使用するスクリプトを作ってみたら、うまく動作した。

nasven.jsを使用するNashornスクリプトの入手から作成・実行までの手順:

  1. Githubからnasven.jsをダウンロード
  2. nasven.jsようのビルドファイル(例:app1.mvn)を作成する
  3. メインのNashornスクリプトを作成する
  4. nasven.js経由でNashornスクリプトを実行する

ビルドファイルの例:

app1.mvn

var maven = { 
    main: 'app1.js',
    options: '-scripting',
    dependencies: [
      'org.apache.poi:poi:3.11',
      'org.apache.poi:poi-ooxml:3.11',
      'org.mongodb:mongo-java-driver:3.0.0'
    ]   
};

Nashornスクリプトの例:

app1.js

var Biff8EncryptionKey = Java.type('org.apache.poi.hssf.record.crypto.Biff8EncryptionKey');
var WorkbookFactory = Java.type('org.apache.poi.ss.usermodel.WorkbookFactory');
var XSSFWorkbook = Java.type('org.apache.poi.xssf.usermodel.XSSFWorkbook');
var MongoClient = Java.type('com.mongodb.MongoClient');
...

Nashornスクリプトを実行する(Linux環境の場合):

$ nashven.js -- app1.mvn

Windows7環境では下記のようにコマンドを変更したら動作した。

Nashornスクリプトを実行する(Windows環境の場合):

$ jjs -scripting nashven.js -- app1.mvn

Maven Centralからのライブラリのダウンロードも自動化されるので、 スクリプトの作成から実行までの手間が軽減され、手軽に使用できるようになった。

Apache Maven 3クックブック Javaソフトウェア開発のための特選レシピ集

Apache Maven 3クックブック Javaソフトウェア開発のための特選レシピ集

Javascriptでできることを調べて、メイン言語にするメリットを確認する

Javascriptプログラミング言語としてどうか、ということはさておいて、 「もうJavascriptさえ覚えておけば何でもできるんじゃない?」 というくらいJavascriptでできることが増えているので、それをまとめてみる。

Javascriptでできること

  1. Webサイトのクライアント側言語として使える
  2. Node.js+npmでWindowsも含めたクロスプラットフォームなバッチスクリプトが作れる
  3. Node.js+Gruntで作業自動化ツールが作れる
  4. Node.js+Express等でWebアプリのサーバサイド開発もできる
  5. Phantom.jsで擬似ブラウザを作成してキャプチャ取得等を自動化できる
  6. Java8以降ならNashornでJavaライブラリを使ったプログラムを作って実行できる
  7. JScriptExcel操作スクリプトが書ける
  8. Windows8アプリが作れる
  9. JXAでMac操作自動化スクリプトが作れる
  10. ElectronでクロスプラットフォームGUIアプリが作れる
  11. Atomテキストエディタの拡張に使える
  12. MongoDBのデータ操作に使える
  13. Microsoftのmainfold.jsでiOSAndroidWindowsアプリが作れる
  14. Google Apps ScriptもJavascriptベースな言語で作れる

つらくなったらこの記事を読み返して、モチベーションを回復しよう。 また思いついたら追加します。

パーフェクトJavaScript

パーフェクトJavaScript

Javascript(node.js)でExcelのシート一覧を出力する

node.jsはWindowsでもLinuxでも同じスクリプトが そこそこ安定して動くので嬉しい。

今回は、ExcelJSモジュールを使って、 Excelのシート一覧を出力するスクリプトを書いた。 リダイレクトでファイルに出力できる。 簡単なスクリプトだけど、こういうものを作っておくと必要な時にすぐ使えて便利。

output_excel_sheets.js

var Excel = require('exceljs');

var targetExcelPath = '<Excelファイルのパス>';

var workbook = new Excel.Workbook();
workbook.xlsx.readFile(targetExcelPath).then(function () {
    workbook.eachSheet(function (worksheet, sheetId) {
        console.log(worksheet.name);
    }); 
});