誕生日からの経過日数を出力するSlack Botを作った
掲題の通りなのですが、誕生日からの経過日数を出力するSlack Botを作りました。
経緯
子供ができてからたまひよのアプリを使っていたのですが、使い勝手が悪いし、生後何日かを確認するくらいしか利用していなかったので、SlackのBotにすれば家族で共有できるし、そっちのがええやんということで作成しました。
作り方
こちらのサイト(BotkitでSlackのBotをサクッと作る方法)を参考にBotを設置しました。 Botはここから作成します。 応答を返すだけならば特に難しいことはありません。 お手本通りにやればできます。
準備
Slack公式のBotkitはNode.jsを利用するためNode.jsのインストールが必要です。インストールされていないのであれば、環境に合わせてインストールが必要ですが、Mac/Linuxで特に理由がなければnodebrewを利用するのが良いでしょう。こちらを参照してインストールします。Windowsの場合はnodistが利用できるようです。こちらが参考になります。
Node.jsのインストール・確認コマンド例(bash)
$ curl -L git.io/nodebrew | perl - setup $ echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ${HOME}/.bashrc # .bash_profileが無い。もしくは.bash_profileに.bashrcを読む設定がない場合は読みこむようにします $ cat << EOF >> ${HOME}/.bash_profile > if [ -f ~/.bashrc ]; then > . ~/.bashrc > fi > EOF $ ${SHELL} -l $ nodebrew help $ nodebrew ls-remote $ nodebrew install-binary v5.6.0 $ nodebrew use v5.6.0 $ node -e "console.log('hello world');"
Botkitのインストール
Slack公式のBotフレームワークであるBotkitを任意のディレクトリにインストールします。gitが無い場合はnodeのパッケージマネージャーであるnpmからインストールできるみたいです。コマンドは載せておきますが、自分は使っていません。
gitの場合
$ git clone https://github.com/howdyai/botkit.git <folder-name> $ cd <folder-name> # 依存関係を解決させる $ npm install
npmの場合
$ npm install --save botkit
Botの起動
ここまでできれば、もうデフォルトのBotが起動できます。起動後にBotに向けてhelloと送ると応答を返してくれるはずです。
#xxxはBotを作って手に入るAPIトークンを指定します。 $ token=xxx node bot.js
誕生日からの経過日数を出力させる
jsファイルはこちらに公開しています。 ただ使うだけであれば、bot.jsとcalcBirth.jsをBotkitのディレクトリ内に配置します。
起動中の場合はBotを再起動した状態でyourname(実際は指定したコマンド名)をSlackで入力すると次の様な情報が出力されます。
Tue Oct 20 2015 22:47:00 GMT+0900 (JST) Sun Feb 14 2016 17:18:32 GMT+0900 (JST) 満年齢:0 前回の誕生日からの経過月と日数:3か月と25日 前回の誕生日からの経過日数:116日
需要は無いと思いますが、せっかく作ったので自分メモとして残しておきます。
intel NUC NUC5CPYH にLinuxを入れて無線LANを使う
intel NUC NUC5CPYHで無線LANを利用した時のメモです。
※数カ月前にやったことなので場合によってはネタが古いかも。作業順序は特に最適化していないのでよしなにしてください。
※パスワードの暗号化について後述と書いておきながら書いていなかったので追記
環境
Fedora22 + intel nuc Network controller: Intel Corporation Wireless 3165 (rev 81)
最初はCentOSでやろうと思ったんですが、この機種に搭載されている無線LANのドライバは"kernel version +4.1 needed"なので、さくっと終わらせるためにFedora22に変更しました。
セットアップ
準備
Fedora22を自分の好みでインストールして、とりあえず有線LANを利用してお決まりのコマンドを実行して再起動します。
$ sudo dnf update $ sudo shutdown -r now
するとカーネルバージョンが上がるはずなので、カーネルバージョンを確認。
$ uname -a Linux fedora.localdomain 4.1.6-200.fc22.x86_64 #1 SMP Mon Aug 17 19:54:31 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
作業用にpciutilsを入れます。
$ sudo dnf install pciutils
ドライバのインストール
適当なディレクトリに無線LANドライバをダウンロードして展開後、ライブラリに追加してまた再起動します。
$ cd workdir $ wget https://wireless.wiki.kernel.org/_media/en/users/drivers/iwlwifi-7265-ucode-25.30.13.0.tgz $ tar xvzf iwlwifi-7265-ucode-25.30.13.0.tgz $ cd iwlwifi-7265-ucode-25.30.13.0 $ sudo cp iwlwifi-7265* /lib/firmware/ $ sudo shutdown -r now
認識されドライバが読み込まれているか確認
$ lspci $ dmesg | grep iwl
以下のログが出ていればOKです。
[ 12.749723] iwlwifi 0000:02:00.0: enabling device (0000 -> 0002) [ 13.189540] iwlwifi 0000:02:00.0: loaded firmware version 25.30.13.0 op_mode iwlmvm [ 13.490190] iwlwifi 0000:02:00.0: Detected Intel(R) Dual Band Wireless AC 3165, REV=0x210 [ 13.490590] iwlwifi 0000:02:00.0: L1 Enabled - LTR Enabled [ 13.491211] iwlwifi 0000:02:00.0: L1 Enabled - LTR Enabled [ 13.689111] ieee80211 phy0: Selected rate control algorithm 'iwl-mvm-rs' [ 13.774546] iwlwifi 0000:02:00.0 wlp2s0: renamed from wlan0
インターフェースを有効化
インターフェースをUP状態に変更します。
$ sudo ip link set up wlp2s0
インターフェースが動作することを確認
次のコマンドでアクセスポイントがリストアップされることを確認します。
$ sudo iwlist wlp2s0 scan
WPA2のクライアントをインストール
wpa_supplicantをインストールします。
$ sudo dnf install wpa_supplicant
wpa_supplicantの設定ファイルを編集します。 "your said"の箇所に接続するAPのSSIDを設定し、yourwpa2keyにパスワードを設定します。
※pskの暗号化は後述
$ sudo vi /etc/wpa_supplicant/wpa_supplicant.conf ctrl_interface=/var/run/wpa_supplicant ctrl_interface_group=wheel ap_scan=1 network={ ssid="your ssid" key_mgmt=WPA-PSK proto=WPA2 pairwise=CCMP TKIP group=CCMP TKIP WEP104 WEP40 psk=yourwpa2key }
使わなくてもwepのパスワード設定が必要らしいので適当な値を入れておく。
$ echo 'KEY="s:dummyKey"' > /etc/sysconfig/network-scripts/keys-ra0
接続テスト
手動で接続してみます。これで問題なく動けば一安心
$ sudo wpa_supplicant -c /etc/wpa_supplicant/wpa_supplicant.conf -i wlp2s0 -Dwext
次のようなログが出るはず
Successfully initialized wpa_supplicant wlp2s0: Trying to associate with x:x:x:x:x:x (SSID='your ssid' freq=5540 MHz) ioctl[SIOCSIWFREQ]: Device or resource busy wlp2s0: Association request to the driver failed wlp2s0: Associated with x:x:x:x:x:x wlp2s0: WPA: Key negotiation completed with x:x:x:x:x:x [PTK=CCMP GTK=CCMP] wlp2s0: CTRL-EVENT-CONNECTED - Connection to x:x:x:x:x:x completed [id=0 id_str=]
DHCPならdhclientを実行してIPをもらう
$ sudo dhclient wpl2s0 $ ip addr
パスワードを暗号化する(追記)
次のコマンドで暗号化されて出力された認証キーで "/etc/wpa_supplicant/wpa_supplicant.conf" の yourwpa2key(pskの値)を書き換える。 重要なポイントは"Your Wi-Fi Netowrk Name"のダブルクォート(")で囲まれた箇所をWi-Fiルータで設定されたSSID名にし、yourwpa2keyの箇所を先ほど接続に成功した平文のパスワードにすることです。
$ wpa_passphrase "Your Wi-Fi Network Name" yourwpa2key
ちなみに、パスワードをヒストリー(上キーを押すと出てくる履歴)に残したくない場合は、 一旦、ログアウトしてから再度ログインし、bashの場合はコマンドを実行したユーザーの~/.bash_historyから消したい履歴を削除して、 再度ログアウトしてから再ログインすると消すことが出来ます。
箇条書きにすると次の通り。
- ログアウト
- ログイン
- ~/.bash_history を編集
- ログアウト
- ログイン
何故ログアウトするのかというと、履歴がファイルに出力されるのが、ログアウトを実行したタイミングだからです。
手動で動作させた設定をコンフィグに登録する
インターフェースは-iの後ろにスペースを入れると動作しないので注意すること
$ sudo vi /etc/sysconfig/wpa_supplicant INTERFACES="-iwlp20a" DRIVERS="-Dwext"
systemdに自動起動登録する
$ sudo systemctl start wpa_supplicant.service $ sudo systemctl status wpa_supplicant.service
わからない人のためにsystemdのコマンド一覧
有効化 $ sudo systemctl enable wpa_supplicant 無効化 $ sudo systemctl disable wpa_supplicant 稼働中のサービス $ sudo systemctl list-units --type=service しぼらず確認 $ sudo systemctl list-unit-files 定義されているサービス一覧 $ sudo systemctl list-unit-files --type=service
NetworkManagerが起動しているとアドレス設定がうまくいかないので止める
systemdで完全に止める場合は次のコマンド
$ sudo systemctl disable NetworkManager
インターフェース毎に制御する場合はインターフェースのファイルを編集して、NM_CONTROLLED="no"を追記する
$ vi /etc/sysconfig/network-scripts/ifcfg-wlp2s0 NM_CONTROLLED="no"
NetworkManagerを停止した場合はboot時にnetworkが起動する様に設定
これ忘れると泣ける
sudo chkconfig --list sudo chkconfig network on sudo chkconfig --list
intel NUC NUC5CPYH は消費電力6Wで最高。
ただし、RAMは8Gまでなので重い処理は辛い。
- 出版社/メーカー: インテル
- 発売日: 2015/07/14
- メディア: Personal Computers
- この商品を含むブログを見る
おわり
\[Perl入学式] Mojoliciousの復習ついでにクリスマスっぽいこともする
2015/12/12に実施された「Perl入学式 in 東京 第5回」でPerl入学式デヴューを果たしたmahoyayaです。
懇親会でよっぱらったT氏にAdventCalenderへの投稿を 強要 お勧めされたので、Perl入学式Advent Calendar 2015の24日目に参加してみます。
昨日はhakata_oyukiさんのPerl入学式のもう一つの歴史でした。感想は人それぞれだと思いますが、自分はこの投稿を読んで震えました。 自分もPerl入学式をきっかけに色々なものへ貢献していきたいと強く思いました。
っていうか、いい話の後の投稿つらいwww
Mojolicious::Liteを利用したwebアプリ開発
この記事はPerl入学式で教材として利用されているMojoliciousを利用したwebアプリ開発の学習をちょびっとだけ延長した内容です。
Perl入学式のwebアプリ開発を受講していることを前提にMojolicious::Liteとmorboを利用し、教材のなかで名前のみ触れられているbootstrapを開発サーバーmorboで利用してみることが目的になります。
Perl初心者の方や、Perl入学式なにそれおいしいの?という方は、Perl入学式公式サイトに学習内容が全て公開されていますので、そちらを確認しながら読むことをおすすめします。
Perl入学式について
公式サイト http://www.perl-entrance.org/
Perl入学式Webアプリ編 https://github.com/perl-entrance-org/workshop-2015-05/blob/master/slide.md
Mojolicious::Liteについて
Mojolicious::Liteについてはこちらを見ていただいたほうが早いでしょう https://github.com/yuki-kimoto/mojolicious-guides-japanese/wiki
まずは復習
インストールはPerl入学式Webアプリ編を御覧ください。
雛形の作り方
Mojoliciousをインストールした後に次のコマンドを実行すると、雛形のファイルが作成されます。 morboを利用する場合、.pl の拡張子はあってもなくても動きます。
mojo generate lite_app (付けたい名前).pl
morbo起動!
仮に雛形の名前をtest.plとした場合、次のコマンドを入力してmorboを起動し、ブラウザから ”http://127.0.0.1:3000” にアクセスします。
morbo test.pl
きっとHello Worldが表示されたはずです。 このようにmorboを実行することで、"mojo generate"で自動生成された雛形をブラウザから確認することができます。 なお、morboを終了する場合はCtrlキーを押しながら、cキー(Crtl+c)を押します。
余談ですが、"127.0.0.1"というのはパソコンが自分自身にアクセスするための特別な表現(IPアドレス)で、ループバックアドレスと呼ばれるものです。
また、"127.0.0.1"に続く":3000"というのは、自分自身の3000番のサービス(Port番号)にアクセスするという意味です。 これだけだと初心者の方にはわからないと思うので別の表現をすると、127.0.0.1という名前のタンス(パソコン自身)の3000個目の引き出しの中身を取り出す動作に似ています。 ":3000"をつける必要がある理由は、詳細な設定をせずにmorboを利用する場合、morboが3000番のPort番号を自動的に利用する仕様だからです。 webサービスは通常Port80番を利用するルールなのですが、80番以外を利用する場合はこの様に追加指定する必要があります。
雛形の編集をする前に
この後は雛形ファイルを編集することになりますが、morboは起動時に指定したファイルが変更された場合、多少のタイムラグがあるものの自動的に再読み込みを実施してくれます。 そのため、いちいちmorboを終了してから再度ファイルを指定して実行する必要はありません。
Mojolicious::LiteへのPerlコードの埋め込み方
Perlのコード追加方法の話です。 基本的にはこう書いておけばOKです
% [perl code] <% [perl code] %>
ただし、テンプレートにPerlのコード実行結果を利用する場合は次の様に書きます。
%= [perl code] <%= [perl code] %>
%と<% ... %>の違いは、その行自体をperlのコードと見なすか、<% ... %>で囲まれた箇所の中だけをperlのコードとして見なすかというものです。
自分のはまりポイント
複数行にまたがった書き方がわからない
たとえば次のようなコード(1から100までの数字で、3の倍数か3がつく数字だった場合にAHOと表示するコードを書いてみました)
for my $i (1 .. 100) { if($i % 3 == 0 || $i =~ m/\A(?:3[0-9]|[1-9]3)\z/){ print 'AHO'; } else { print $i; } print "\n"; }
これはこう書けば良い
%for my $i (1 .. 100) { % if($i % 3 == 0 || $i =~ m/\A(?:3[0-9]|[1-9]3)\z/){ % print 'AHO'; % } else { % print $i; % } % print "\n"; %}
これでforループを実行してくれます。
printの結果がブラウザ上に表示されない
先ほどのコードだと、mobroを実行しているターミナルの標準出力にprintの実行結果が表示されます。 テンプレートにコードの実行結果を埋め込んで出力する場合は、その文字列や変数のみを記載し、%=を利用して出力させます。 具体的には下記のコードになります。
%for my $i (1 .. 100) { % if($i % 3 == 0 || $i =~ m/\A(?:3[0-9]|[1-9]3)\z/){ %= 'AHO'; % } else { %= $i; % } %= "\n"; %}
ちなみに
%= print $i;
などとした場合はprintの終了ステータス値(正常終了であれば1)が表示されてしまいます。
テンプレートに変数を渡してみる
Perl入学式ではstashという関数を利用しました。 ルーターの中で次のようなコードを利用して変数をテンプレートに伝えます。 stashの第一引数がテンプレート内で利用される名前です。
$self->stash(variable => $variable); $self->stash(arrayref => \@array); $self->stash(hashref => \%hash);
余談ですが、自分の場合は変数の中身がリファレンスである場合、arefやhrefという名前を先頭につけることにしています。 これにより後で自分が見てわかりやすい工夫を行っています。
bootstrapを導入してみる
ここまできて言うのもなんですが、そもそもbootstrapって何なんでしょう?
bootstrap公式サイトには次のように書かれています。
「Bootstrap is the most popular HTML, CSS, and JS framework for developing responsive, mobile first projects on the web.」
簡単に言うとWebのデザインをいい感じにする仕組みのようです。 ということで、さっそくこれを使ってクリスマスっぽいWebサービスを作ってみます。
ディレクトリの整備
bootstrapを導入する前に少し準備をします。 この先、テンプレートが長くなるとメンテナンスが大変になしますし、morboで静的ファイル(cssやjs等)を読み込むためには、専用のディレクトリを作る必要があります。 mobroで読み込むファイル(先ほどの例で言うとtest.pl)が置いてあるディレクトリを/(ルート:最上位ディレクトリ)とした場合、次のディレクトリ構成になるようにディレクトリを作成します。
/ |-public |-templates
それぞれのディレクトリは次の用途で利用します。
ディレクトリ | 用途 |
---|---|
public | mobroを通して参照させる静的ファイルを配置します。たとえば、publicディレクトリの下にfoo.jpgというファイルを置いた場合、http://127.0.0.1:3000/foo.jpgにアクセスすることで参照できるようになります。 |
templates | _DATA_ の下に書いているテンプレート設定を別ファイルに分ける場合に利用します。この中のファイルは _DATA_ の下に記載したテンプレートと同様に扱うことができます。 |
bootstrapの入手
Bootstrapの公式サイトでDownload Bootstrapを選択し、ファイルをダウンロードします。 ダウンロードが完了したら、bootstrapの中にあるcss, img, jsのディレクトリをpublicの下に配置します。
/ |-public | |-css | |-img | |-js |-templates
この状態にすることで、bootstrapの各ファイルにアクセスすることが出来るようになります。
bootstrapを読みこませる
先ほど作成した雛形ファイルをベースにします。 まずは雛形ファイル内の @@ layouts/default.html.ep の内容を templates/layouts/bootstrap.html.ep というファイルを新たに作成して転記します。このとき、@@ layouts/default.html.epと記載された行は転記不要です。
※Mojoliciousは _DATA_ 以下に該当のテンプレートが存在しない場合にtemplatesディレクトリ配下のテンプレートファイルを読み込むため、templates/layouts/default.html.ep ファイルを新しく作成する場合は 雛形ファイル内の @@ layouts/default.html.ep の名前を変更するか、テンプレート自体を削除する必要があります。
bootstrapを適用する
先ほど作ったbootstrap.html.epを編集してbootstrapを適用します。
<!DOCTYPE html> <html> <head> <title><%= title %></title> %#下の行を追記 <%= stylesheet 'css/bootstrap.min.css' %> </head> <body> %#下の2行を追記 <script src="http://code.jquery.com/jquery.js"></script> <%= javascript 'js/bootstrap.min.js' %> <%= content %> </body> </html>
次にindex.html.epにbootstrapを適用します。
@@ index.html.ep %# layoutの'default'を'bootstrap'に変更 % layout 'bootstrap'; % title 'Welcome'; <h1>Welcome to the Mojolicious real-time web framework!</h1> To learn more, you can browse through the documentation <%= link_to 'here' => '/perldoc' %>.
なんと、以上で適用終了です。 とりあえず適用だけならこれで終わりなので、試しに http://127.0.0.1:3000 にアクセスしてみます。 どうでしょう?若干わかりにくいですが、文字のスタイルが変わっていますね。 わかんねーよヴォケという方はindex.html.epのlayoutをdefaultに戻すと適用が解除されます。
bootstrapのスタイルを適用する
ボタン、表などへbootstrapのスタイルを適用するには次のようにします。 とりあえず雛形ファイルの@@ index.html.ep の下に貼り付けてみるのも良いでしょう。
%= submit_button '投稿する', class => 'btn btn-default' <div class="container"> <div class='table-responsive'> <table class="table table-bordered table-hover"> <thead> <tr> <th>#</th> <th>message</th> </tr> </thead> <tbody> <tr class='info' > <td>1</td> <td>message1</td> </tr> <tr class='warning' > <td>2</td> <td>message2</td> </tr> </tbody> </table> </div> </div>
ちゃんとリサーチ出来ていないので、テーブルに関してはもっと良い書き方があるのだと思いますが、共通しているのはclassに対してbootstrapのスタイルを指定するということです。 mojoliciousで対応しているhtmlタグに関してはMojolicious::Plugin::TagHelpersに記載されていますので、参考にしてください。
ここから先はMojolicousドキュメント日本語訳やBootstrap公式サイトのGetting Startedを参照してカスタマイズしていきます。 簡単な変更であればWebデザイン初心者でもできる、Bootstrapの使い方超入門がわかりやすかったです。 手元でざっと確認した限り、いくつかそのままでは動かない機能がありましたが、きっと設定が足りないのでしょう。 とりあえず使うことが目的なので、出来ることだけを使ってみます。
クリスマスっぽいことをする
ここまで出来てしまえば、あとはPerl入学式で学んだことを駆使し、無駄にMojoliciousを使ってクリスマスっぽいことをするだけです! ということで、いきなりですがこのツリーの問題を解いてみます。
そして解いた結果がこちら(3分クッキング風w
my $p = qw(*!*%/*+-!.**%/*+); for my $size (6, 16){ printf(qq/size: %02d\n/, $size); my $reaf = 0 x ($size * 2 - 1); $reaf = qq//; for(split(//,$p)){ my $len = length($reaf); last if $len == $size; printf(qq/%s\n/, qq/ / x ($size - $len) . $reaf . $_ . scalar(reverse($reaf))); $reaf .= $_; } print qq/\n/; }
このコードをベースにMojoliciousに適用してクリスマスツリーを表示してみます。 ※qq//が多用されているのは、もともとWindows環境でワンライナーだったからなので気にしないでくださいw
そして完成品がこちら(Google Chrome推奨)です!!!(3分クッキング(ry
「高さを変える▼」をクリックして高さを選択すると表示されるツリーの大きさが変わるだけのサイトです。 上のナビゲーションバーは半分飾りでHomeしか動作しません…
ちなみに、我が家の今年のクリスマスツリーはこのサイトの16段の超豪華版ツリーを使う予定です(え
というわけで、bootstrapとMojoliciousを使えば簡単に(?)こんなサイトが作れます。 みなさんも挑戦してみてくださいね。
ソース
heroku用に少しカスタマイズ(CDN利用等)したものですが、恥ずかしいソースはこちらです。 https://github.com/mahoyaya/perl-entrance/
最後に
明日は今年最後を飾るpapix校長の投稿です。どんな内容になるのかとても楽しみですね!
LXCの初歩的なメモ
Linux の pppoe-server に unnumbered で接続出来ない問題の対策
CentOSでsambaのホームディレクトリ共有が出来ない