まだプログラマーですが何か?

プログラマーネタとアスリートネタ中心。たまに作成したウェブサービス関連の話も http://twitter.com/dotnsf

タグ:bluemix

「ウェブ魚拓」というサービスをご存知でしょうか?ネット上のウェブサイト(URL)を独自にキャッシュして保存するサービスのことです。ネット上のウェブサイトがなくなってしまったり、内容が変わったりしても、その保存したタイミングでのウェブサイトを後からでも参照できるように残す、というサービスです。

このウェブ魚拓もどきのサービスを Node.js 向けに作って、ソースコードを公開しました:
https://github.com/dotnsf/urlrec

2019020801


まず、この公開したサービスではあらゆる全てのサイトでキャッシュを残せるわけではありません(いわゆる「対策済みサイト」に対しては、この機能は無効です)。残せるサイトの場合は独自フォーマット(本当は MHTML にしたかったんですが、色々難しそうだったので、画像だけインライン展開するフォーマットで HTML と画像を記録できるようにしました)でキャッシュを記録します。つまり取得時点でのテキスト内容と画像をキャッシュして記録します。

また記録先として IBM CloudIBM Cloudant サービスが必要です。必要に応じて IBM Cloud のアカウントを作成し、IBM Cloudant サービスインスタンスを作成しておいてください:
2019020802


ソースコードを入手する前に、IBM Cloudant インスタンスを利用するための接続情報を確認しておきます。作成したサービスインスタンスの「サービス資格情報」メニューから「資格情報の表示」を選択(見当たらない場合は1つ新規に作成してから選択)すると JSON フォーマットの接続情報が表示されます。この中の username と password の値を後で使うことになるので、このページを開いたままにしておくなどしてコピー&ペーストできるようにしておきます:
2019020803


では改めてソースコードを入手します。https://github.com/dotnsf/urlrec から git clone するか、下図のように zip をダウンロード&展開してソースコードを手元にコピーします:
2019020804


ソースコードが入手できたら、settings.js ファイルをテキストエディタで開きます。そして exports.db_username の値を先程確認した IBM Cloudant の接続情報の username の値に、exports.db_password の値を同じく password の値に、それぞれ(コピー&ペースト等で)書き直して保存します:
exports.db_username = '(username の値)';
exports.db_password = '(password の値)';
exports.db_name = 'urlrec';
: :

Node.js が導入されていればローカル環境で動かすことも可能です。その場合は以下のコマンドを実行します:
$ npm install  (依存ライブラリを導入)

$ node app  (実行)

server stating on XXXX ...

成功すると上記のように "server starting on XXXX ..." と表示されます。この XXXX は数字になっているはずで、ウェブ魚拓サービスはこのポート番号で待ち受けている、ということを示しています。


では実際に使ってみましょう。先程確認した XXXX を使って、ウェブブラウザから http://(サーバー名 または IP アドレス):XXXX/ にアクセスします。以下のような画面が表示されれば成功です:
2019020805


画面上部の "URL" にキャッシュしたいページの URL を入力して "CHECK" ボタンを押すとプレビューが表示されます(このプレビューが表示されないページは非対応だと思ってください)。下の例では試しに自分のブログの1ページを指定してみました:
2019020801


そしてプレビュー画面で(必要に応じてテキストコメントを入力した上で) "Record" をクリックするとキャッシュがシステムに保存され、先程の画面内に一覧表示されます:
2019020802


この画面で一覧内の一番左の列(赤枠部分)をクリックすると、別ウィンドウが開いてキャッシュされた内容を確認することができる、というものです(元の URL の記事が削除されていても見れるようになります):
2019020803


UI的にもまだまだシンプルすぎる所があったり、元のページのスタイルの再現性など、まだまだ改良の余地はあると思っていますが、基本機能は実装できていると思ってます。MIT でソースコードを公開しているので、役に立つ場があればご自由に使っていただきたいです。

そろそろプロ野球のシーズン開幕前順位予想とかが始まるので、それらを片っ端から記録しておこうかなあ、と邪な考えを持っていたりします。 σ(^^;


個人的な野望としてはこれを元に更に改良してブロックチェーンと組み合わせて真偽証明付きにして・・・って感じかなあ。

(この記事は IBM Cloud アドベントカレンダー 2018 に参加しています。2日目の記事です)

先日、以下のブログエントリを公開しました。本エントリはその技術的な補足と、試験的な意味も含めてアプリ URL を一般公開する内容になっています。
お絵かき LIFF アプリを作ってみた

2018112200


技術的な説明の前に、まずは一度使ってみていただきたく、このアプリを(一時的に?)公開することにしました。少し面倒ではありますが、以下の手順で実行できるようにしたので、まずは一度使ってみてください。

①スマホに LINE アプリをインストール(お絵かきアプリは PC 版 LINE からは使えません)

②LINE を開いて誰かとのメッセージ画面(グループ LINE 可)の中に以下の文字を入力してリンクメッセージとして送信する(この作業だけは PC の LINE アプリから行ってもよい)
line://app/1624220123-mbERyVgb

2018120101


③スマホの LINE 画面内から②で送信したリンクメッセージをタップ
2018120102


④LINE 内でお絵かきアプリが起動します。ペンの色と太さを変えながら指でお絵かきします。
2018120103


⑤間違えたら reset か、一度終了してから再度リンクメッセージをタップしてやり直し。
2018120104



⑥描き終わったら post でお絵かきが画像として LINE にメッセージ送信されます(右上の×を押してアプリを終了する)
2018120105


・・・というものです。LINE はスタンプ文化が有名ですが、スタンプを持っていなくてもその場でお絵かきして送るとか、他には地図を書いて送るとか、いろいろな使い方が考えられると思っています。現状、上記のリンクを LINE のメッセージとして一度送っておく必要があり、そのリンクをタップした時に起動する、という使い方になってしまいます。技術的に興味がある人もない人も是非お試しいただきたいと思っています。


以下、このアプリの技術的な解説になります。

このアプリは LINE の新しい開発フレームワークである LIFF(LIne Front-end Framework) を使って開発しています:
https://developers.line.biz/ja/docs/liff/overview/


LIFF は LINE 内で動作するウェブアプリケーションのプラットフォームです。「LINE 内で動作する」という点と「ウェブアプリケーション」であることがキーワードです。上記のように LINE 内で特定リンクをタップすることで起動し、その中身は HTML5 と JavaScript で記述されたウェブアプリケーションです。LIFF の詳しい仕様等は上記の開発者向けページを参照いただきたいのですが、要するにパブリックインターネット上に HTML5 ベースのウェブアプリを作って、そこを参照するような LINE リンクを作っておくことで LINE アプリ内でその HTML5 ページを起動することができます。また LIFF SDK の JavaScript API を使うことで、その HTML5 アプリの情報を起動元である LINE 側に(メッセージとして)送信することも可能です。

今回作ったアプリの場合は HTML5 の Canvas を使ってお絵かきアプリを作成し、その中に描かれた絵を動的に画像に変換して、画像を貼り付ける形でメッセージを送ったことにしています。その結果、HTML5 Canvas 内に描かれた絵を LINE 上で画像添付したかのように送信させることを実現しています。

この仕組の HTML5 ウェブアプリケーション部分と、画像添付部分を IBM Cloud 上の Node.js ランタイムと IBM Cloudant を使って実現しています。HTML5 Canvas 内に描いた画像を動的に PNG 画像へ変換し、Node.js ランタイム上の REST API を使って取得し、(LIFF の場合、画像はオリジナル以外にサムネイルが必要なので)サムネイル画像を生成して IBM Cloudant データベース内に添付ファイルとして保存します:

2018120106


画像が添付できたら、今度はその画像を外部から参照できる URL を用意します。具体的には Node.js ランタイム内に Cloudant 内に格納した画像ファイルを参照できるような URL(REST API) を用意します。そして HTML5 内の LIFF SDK を使って、画像ファイルの URL をメッセージとして送信して、添付画像を付与したメッセージ送信と同じ処理を行います。これでお絵かきで作成した画像が添付されたかのような振る舞いを実現できます:
2018120107


という形で現在は実現しています。 つまり現在はこのアプリを使って作成した画像は IBM Cloudant 内に保存されるように実装されています。現在の運用環境では、このデータベースの容量にも制約があるので、しばらくはデータベースをリセットしながら運用することになります。もしうまく送信できない場合は僕がデータベースのメンテナンスを忘れていて、容量オーバーになっている可能性があることをお伝えしておきます(気付いたタイミングでリセットするようにします)。

また、この公開アプリのソースコードはこちらで(MIT ライセンスで)公開しています。IBM Cloud を使う前提で記述されたコードですが、自分なりに改良したい人がいればうまく活用してください:
https://github.com/dotnsf/line_liff_doodle


これまで LINE の API といえば Messaging API で、bot のようなバックエンド側を操作するアプリを作るには有用だったのですが、やっとフロントエンド側を操作できる API(というかフレームワーク)が出てきてくれました。公開ページ上で HTML5 アプリを置いて運用することになるので、実質的にクラウドを活用する形態が多くなると思います。そんな時に IBM Cloud の上記構成程度であれば無料のライトアカウントでも運用できるので、公開したソースコードを是非色んな人に使ってみたり改良してみてほしいです。

LINE の新しい開発フレームワークである LIFF(LIne Front-end Framework)の存在を教えていただいたので、試しに使ってみました。

この LIFF 最大の特徴はスマホの LINE アプリ内で HTML5 の Web アプリケーションを動かすことができる、という点です。この Web アプリケーション内で LIFF の SDK を併用すると、アプリケーションからLINE にメッセージや画像(やスタンプ)を送ることも可能です。

この LIFF を使って指で画面にお絵かきをするような HTML5 アプリを作り、その絵を LINE アプリに送信する、というアプリケーションを作ってみました。LINE はスタンプを送信する文化がメジャーですが、その延長で自分でその場でお絵かきした画像を送る、という使い方を想定したアプリケーションです。ソースコードは github で公開したので、興味ある方は実際に試してみてください:
2018112200



なお、今回提供しているソースコードでは IBM Cloud の NoSQL マネージド・データベースである Cloudant を使っているので、IBM Cloud のアカウントも必要です。無料のライトアカウントもあるので IBM Cloud のアカウントをお持ちでない場合はあわせて取得してください。


【IBM Cloudant の準備】
今回紹介するアプリケーションでは IBM Cloundant のインスタンスが必要です。IBM Cloud にログインし、インスタンスを1つ作成して、あらかじめ画像格納用のデータベースを用意しておきます。なお無料のライトプランの場合、Cloudant には 1GB までのデータしか格納することができないという点をご了承ください。

まず IBM Cloud にログインし、「リソースの作成」から IBM Cloudant を追加します。IBM Cloudant は「データベース」カテゴリ内に存在しています:
2018112201


作成時のロケーションはどこでも構いません(下図では「シドニー」を使っています)。ただ認証方法は従来の方式が利用できる方("Use both legacy credentials and IAM")を選択しておく必要があります:
2018112202


また価格プランも任意で構いませんが、Lite プランの場合は無料です。ただし 1GB までしかデータを格納することはできません。最後に「作成」をクリックしてインスタンスを作成します:
2018112203


Cloudant インスタンス作成直後の画面です。まずここから目的の(画像格納用の)データベースを作成するため、Cloudant のダッシュボードに移動します。下図の緑のボタンをクリック:
2018112204


Cloudant のダッシュボード画面に移動しました。データベース一覧が表示されていますが、作成直後の場合は何も存在してません。ここで「Create Database」をクリックして、データベースを作成します:
2018112205


作成するデータベースの名前を指定します。デフォルトでは "doodledb" を使います(後述の settings.js 内で指定されている名称と一致している必要があります)ので、とりあえず doodledb と入力して「Create」します:
2018112206


doodledb データベースが作成され、doodledb データベース内の文書一覧画面に移動しました(当然中身はありません)。左上の "<" 印をクリックしてデータベース一覧に戻ります:
2018112207


データベース一覧に戻りました。先程とは変わって、"doodledb" が一覧に含まれているはずです。これでデータベースの準備ができました:
2018112208


次にこのデータベースへ接続するための情報を確認します。IBM Cloud の画面に戻り、「サービス資格情報」タブを選択します。サービス資格情報は(この時点では)存在していないはずなので、「新規資格情報」ボタンをクリックして作成します:
2018112201


設定項目は変更せずに「追加」します:
2018112202


資格情報が追加されると先程の画面内に「資格情報の表示」メニューが追加されているはずです。ここをクリックして内容を確認します:
2018112203


資格情報の内容が JSON テキストで表示されます。今回必要なのは "username" と "password" の値です。これらの情報を後で利用するので、メモしておくか、コピペできるようにしておきます:
2018112204


これで IBM Cloudant の準備はできました。


【ランタイム(Web アプリケーション・サーバー)の準備】
次に LIFF が参照する Web アプリケーションサーバーを作成します。このサンプルは Node.js 上で動作するサンプルですが、今回は IBM Cloud 上にアプリケーション・サーバーを作成することにします(これもライトプランの無料枠内で作成することができます)。

Cloudant の時と同様に IBM Cloud にログイン後にリソース作成で「コンピュート」カテゴリの「SDK for Node.js」を選択します:
2018112201


ロケーションは「ダラス」を選択します(するとドメインは "mybluemix.net" となります)。そして「アプリ名」にアプリケーション名称を指定します。下図の例では "linedoodle" というアプリケーション名称としており、この場合のエンドポイント URL は https://linedoodle.mybluemix.net/ となります。なおアプリ名は他で使われていないものを指定する必要があります。自分の名前や日付を指定するなどして、ユニークなアプリケーション名称を指定してください。最後に「作成」をクリックします:
2018112202


しばらく待つとアプリケーションサーバーが起動します。これで LIFF アプリからアクセスできるパブリッククラウド上にアプリケーションサーバーが用意できました:
2018112203


【LINE Developers の準備】
LINE の LIFF アプリを作成するには LINE Developers でのチャネル登録が必要です。LINE Developer において新規にチャネルを作成します:
2018112204


チャネルの種類は「Messaging API」を選択します:
2018112205


アプリ名とプラン(Developer Trial)を選択し、作成します:
2018112206


作成すると、このチャネルにアクセストークンが割り当てられます。「アクセストークン(ロングターム)」と書かれた項目の値をこの後で使うことになるのでメモするか、コピペできるようにしておきます:
2018112207


また、ここで LIFF アプリとしてのアプリ URL を作成しておきましょう。LIFF タブを選んで「追加」ボタンをクリックします:
2018112209


名称、サイズ(Full または Tall のいずれかを選択)、そしてエンドポイント URL(上述の Node.js アプリケーションのエンドポイント URL)を入力して「保存する」をクリックします:
2018112210


すると LIFF アプリが登録され、LIFF URL が確認できるようになります。この LIFF URL は実際に LINE からアプリケーションを起動する際に利用します:
2018112208


これで LIFF アプリの登録も完了しました。あと少し。


【アプリケーションの準備】
上記で作成したアプリケーション・サーバーに HTML5 アプリケーションをデプロイします。まずはソースコードを入手します。github のリポジトリからソースコードをダウンロードまたは git clone して入手します:
https://github.com/dotnsf/line_liff_doodle

ソースコードがダウンロードできたら settings.js ファイルを環境にあわせて編集して保存します:
exports.db_username = '(Cloudant の username)';
exports.db_password = '(Cloudant の password)';
exports.db_name = 'doodledb';
exports.app_port = 0;

exports.base_url = 'https://(アプリケーション名).(ドメイン)/';

exports.line_access_token = '(LINE Developer で取得したロングタームアクセストークン)';

  :
  :

最後にこのアプリを上記で作成したアプリケーションサーバーにデプロイします。IBM Cloud では cf コマンドを使ってデプロイするので、未導入の場合は cf コマンドをダウンロード&インストールしてください:
https://github.com/cloudfoundry/cli/releases


そして cf コマンドを使って IBM Cloud へ IBM ID でログインし、アプリケーションをプッシュ(デプロイ)します:
$ cd (ソースコードのあるフォルダ)
$ cf login -a https://api.ng.bluemix.net/ -u (IBM ID)
$ cf push (アプリケーション名)

ここまでの作業が全て成功すると LIFF アプリが IBM Cloud 上にデプロイされ、LINE のチャット上で LIFF URL をクリックすると、LINE 上で同アプリケーションを呼び出すことができるようになります。


【LINE で動作確認】
では実際に LINE を使って動作確認してみます。上述で取得した LIFF URL ("line://app/" で始める文字列)をコピー&ペーストするなどして LINE のメッセージとして表示させます:
2018112201


この LIFF URL 部分をタップすると画面下部から LIFF アプリである HTML5 の Web アプリケーションの画面が表れます。今回の Web アプリはお絵かきアプリとなっていて、指でキャンバス上をドラッグして絵を描くアプリとなっています。色やフォントの太さを変えたり、失敗したら "reset" ではじめからやり直すこともできます:
2018112202


たとえばこんな絵を描いてみました。書き終わったら "post" をタップします:
2018112203


描いた絵が LINE の会話内に画像として表れます。その場でステッカーを作って送るような感覚です:
2018112204


・・・というアプリを作ってみたのでした。いかがでしょう? ちなみに iPhone 版の LINE でのみ動作確認しています。Android 版 LINE でうまく動かなかったらごめんなさい。


以前から似たようなアプリを Twitter 向けに作ってみたりしていて、同じようなのを LINE 向けにも作れたらいいなあ、と思っていました。が、LINE にはクライアント側を操作できる API が提供されておらず作ることができずに諦めていました。 が、今回 LIFF の存在を教えていただいて、「これならできるかも・・」と期待してがんばってみたら、なんとか実現できた、という経緯です。アプリ実装の詳細についてはまた別の機会にでも。

ある意味で LINE のステッカービジネスを根底から否定(苦笑)するアプリなので、あまり LINE 受けはよくないかもしれません。(^^; でも教えていただいたおかげで実現することができました。この場をお借りしてお礼申し上げます。


そうそう。繰り返しになりますが、IBM Cloud の(無料の)ライトアカウントを使って作成した場合、データベースには 1GB ぶんの画像しか格納できません。定期的にデータを削除するとか、データベースを消して作り直すとかして対応してください。



(参考)
LIFF API リファレンス


IBM Cloud の旧 Bluemix に代表される、いわゆる PaaS 環境ではアプリケーション・サーバーなどのミドルウェアまでをベンダー側が提供し、利用者はサーバーやその管理を意識せずにアプリケーションのみ提供して動かすことができます。

これはこれで便利な環境なのですが、一方で実際に動かしている環境の詳細(ミドルウェアや言語ランタイムのバージョンなど)を知りたくなることもあります。知らなくても使えるんだけど知りたい、という要望です。そういった情報が公開されていればいいのですが、多くのケースで常に最新バージョンが使われるようにメンテナンスされており、公開情報が最新版の内容を反映していないケースもあります。というわけで IBM Cloud の SDK for Node.js ランタイムを対象に実際に動いている環境からバージョンを調べる、という方法で調べてみました。

SDK for Node.js ランタイムで以下のコードをデプロイして動かします:
// app.js

var cfenv = require( 'cfenv' );
var express = require( 'express' );
var app = express();

var appEnv = cfenv.getAppEnv();

app.get( '/', function( req, res ){
  var process_version = process.version;
  res.write( JSON.stringify( { version: process_version }, 2, null ) );
  res.end();
});


var port = appEnv.port;
app.listen( port );
console.log( 'server started on ' + port );

↑プログラムコード内から process.version を参照して、現在動いている node のバージョンを取り出しています。

ちなみに package.json は以下のように Node.js v6.x の最新版が使われるように指定しています:
{
    "name": "node-v",
    "version": "0.0.1",
    "scripts": {
        "start": "node app.js"
    },
    "dependencies": {
        "cfenv": "~1.0.0",
        "express": "4.1.x"
    },
    "repository": {},
    "engines": {
        "node": "6.x"
    }
}

このコードを cf push でデプロイし、(2018/10/27 時点で)GET / を実行した結果がこちらです:
2018102701

v6.x の最新版、が使われた結果がこのようになりました。

また、package.json の同部分を "node": "8.x" に変えて再デプロイして実行するとこうなりました:
2018102702


動的に Node.js の実行バージョンを取得することができました。


IBM CloudantApache CouchDB をベースとしたマネージド NoSQL DB サービスです。IBM Cloud のライトアカウントを利用することで無料枠内で利用することも可能です。

そんな便利な IBM Cloudant ですが、IBM Cloud では(特に無料枠で使った場合)では、どのようなクラスタリング構成で運用されているのか気になりました。もともと NoSQL DB はスケーリングに優れていて、大規模運用向きと言われています。ではこの(特に無料のライトプランで提供されている)IBM Cloudant はどのような運用構成で提供されているのでしょう? 理論上は1サーバーノードで(クラスタリングなしで)提供することも可能だし、無料プランということを加味して、クラスタリング無しだったとしてもまあそうだよね・・とも考えられます。一方で無料プランと有償プランで(わざわざ)差をつけて運用しているのか?という疑問もあります。このあたりをそっと調べてみました。


まず、調べる方法は CouchDB REST API の GET /db を使うことにしました。この REST API を実行すると指定したデータベースの情報を得ることができ、その中には(クラスタリング構成になっていれば)クラスターに関する情報が含まれていることになっています。この方法で自分がローカルで構成した単一構成の CouchDB と、IBM Cloud のライトプランで契約した IBM Cloudant の2つのデータベースに対して実行し、その結果を比較してみることにします。

まず前者の単一構成 CouchDB のデータベースに対してこのコマンドを curl で実行しました(実行結果は青字):
$ curl 'http://localhost:5984/ccdb'

{"db_name":"ccdb","update_seq":"6-

g1AAAAEzeJzLYWBg4MhgTmHgzcvPy09JdcjLz8gvLskBCjMlMiTJ____PyuRAYeCJAUgmWSPX40DSE08WA0TLjUJIDX1eM3JYwGSDA1ACqhsPiF1C

yDq9uO2E6LuAETdfULmPYCoA_khCwCKxmL8","sizes":{"file":58598,"external":615,"active":1730},"purge_seq":0,"other":

{"data_size":615},"doc_del_count":2,"doc_count":2,"disk_size":58598,"disk_format_version":6,"data_size":1730,"com

pact_running":false,"instance_start_time":"0"}

指定したデータベース(上例では ccdb)の現在の状態が表示されています。各項目の意味は上述の GET /db API のリンク先で説明されているのでそちらを参照いただきたいのですが、この実行結果にはクラスタリング情報が含まれていません。実際クラスタリング構成ではなく単一構成で動いているので、この実行結果もその運用状態を正しく表しています。

次に同じコマンドを IBM Cloudant のライトプランで作成したデータベースに対して実行しました。その結果がこちらです:
{"status":true,"info":{"update_seq":"20-

g1AAAAQneJzLYWBgEMhgTmHQTElKzi9KdUhJMtFLytVNTtYtLdYtzi8tydA1NNBLzskvTUnMK9HLSy3JAWphSmRI4v___39WIgNIsxZcs6EhMbqTB

IBkkjzYAGZU24nTrwDSr49NvzlR-g1A-u0RHiDR90kOIP3-

CPtJDoAAkAHx2BxAnP4EkP58bPqJC4ACkP56sgMgjwVIMjQAKaAR_VmJTOQEAsSQCRBD5pMXEBAzFkDMWE9eYEDM2AAxYz_UM2QFyAGIGeezEhnJD

5ALEEPuUxIgDyBmvCcve0DM-AAxA5TEswCIaVtl","db_name":"statedb","sizes":

{"file":11774513,"external":10511286,"active":10543509},"purge_seq":0,"other":

{"data_size":10511286},"doc_del_count":7,"doc_count":2,"disk_size":11774513,"disk_format_version":6,"data_size":1

0543509,"compact_running":false,"cluster":{"q":16,"n":3,"w":2,"r":2},"instance_start_time":"0"}}

↑特に赤字部分に注目してほしいのですが、先程の実行結果には存在しなかったクラスタリングに関する情報が含まれています。そしてこの結果を見ると、このデータベースは
 ・シャード数: 16(!)
 ・1つのドキュメントの分散数: 3
 ・書き込みコマンドを実行した場合、2つ以上に書き込めたら書き込み成功とする
 ・読み取りコマンドを実行した場合、2つ以上から結果が返ってきたら読み取り成功とする

という条件でクラスタリングが構成されていることがわかります。無料のライトプランでも結構な好条件でクラスタリングされていたんですね、へぇ~。


 

このページのトップヘ