kinoppyd.dev

blog

products

accounts & contact

kinoppyd dev - page 6

kinoppyd blog

Mobbの基本的な書き方

2018-12-03 00:23:45 +0900

このエントリは、Mobb/Repp Advent Calendar の三日目です

Mobbの基本的な機能

Mobb/Reppがなんなのかは昨日までのエントリで書いたので、今回はMobbで書ける基本的な機能を紹介します。

以下に上げるのは、Mobbのほとんどすべての機能なので、これを知っていれば秒でBotが作れます!

特定の文字列との完全マッチ

receive 'テクテクテクテク' do
  # テクテクテクテク という発言があったらこのブロックに入る
end

on 'ポッポポッポハトポッポ' do
  # on は receive のエイリアス
end

秒でBotを作れるMobb、その裏にあるReppって何者?

2018-12-02 01:06:24 +0900

このエントリは、Mobb/Repp Advent Calendar の2日目です

Reppというもの

昨日のエントリで、Mobbという秒でBotを作るための強力なフレームワークを紹介しました。このエントリでは、そのMobbを支えるReppという仕組みに関して書いていきます。

Webサービスを作ることに詳しいRubyプログラマ向けに説明すると、MobbとはSinatraであり、ReppとはRackです。それで理解できる方は、此処から先はそれ以上の情報が書かれていないので読む必要はありません。

ReppとはRackと言われてピンとこなかった方のために、Botを作るための複雑性を排除し、いかに秒でBotを作るかという話を交えつつ、Mobbに対してReppが何者を説明したいと思います。

Botを秒で作るために必要なもの

Botを秒で作るために必要なものは、複雑な物事をうまく隠す方法です。そしてSlackやTwitterを始めとした各種サービスとの結合部分は、その複雑な物事の最たるものです。

例えば、フレームワークに頼らず自前でBotを作るとしましょう。各サービスのSDKを探してきて、そのドキュメントを軽く読み、データの受取と投稿部分のコードを書きます。そしてその後、自分のbotが本当にやりたいロジックを書き、サービスと連携するコードと結合します。ドキュメント読むの、面倒じゃないですか? サービスと接続する部分の実装、面倒じゃないですか? こんなのでは秒でBotを作れません。

秒でBotを作るためには、サービスとの結合部分を徹底的に隠さなくてはいけません。サービスとの接続に手間取っているようでは、それは複雑も複雑であり、怪奇です。また、サービスとの接続部分は使いまわせなくてはいけません。あなたが作りたいBotは、一つではないからです。秒でBotを作るということは、毎秒新しいBotのアイディアを思いついて、すぐに実装する。そういうことです。


アイディアが閃いた? それすぐにSlackBotにしましょう。秒で。

2018-12-01 00:11:37 +0900

この記事は、Slack Advent CalendarMobb/Repp Advent Calendar 共通の1日目の記事です

Slack Bot を秒で作る方法

日常生活を送っていると、突然身の回りで何かが流行ることがありませんか? 私はよくあります。例えば、ある日突然絵文字をシャッフルすることが流行ったり、ちょっと昔には「Yo」と言ったら「Yo」と返すのが突然流行ったりしました。

何かが流行ったとき、それはbotを作るチャンスです。幸いあなたはプログラマで、流行った何かを更に面白くするアイディアとロジックは一瞬で頭に浮かびます!

けれど、そのロジックを実装するのは簡単ですが、実際にその機能をbotとしてSlackの野に放つのは簡単でしょうか? 私はあまり簡単ではないと思います。

例えば、多くの言語にはBot用のフレームワークが存在します。RubyであればRuboty、JSであればHubot、Pythonであればslackbot、JavaであればJBotなどが存在しますし、そもそも各言語のSlack用ライブラリが必ず存在するので、それを使えばフレームワークすら必要とせずにBotを作れます。

しかし、それらは本当に簡単でしょうか? 楽しいアイディアを思いついて、それをBot化するまでの間に情熱が冷めてしまうほど時間がかかりませんか? そして他の人が似たアイディアのBotをSlackに先に放ち、「俺の考えてたアイディアのほうが面白いのに、先を越された」なんていう愚痴をSlackで吐いたりするようなことになってしまいやしませんか?

Botのアイディアは、秒で形に出来なくてはいけません。そして毎秒クソボットを作れるくらいのスピード感が必要なのです。けど、そんなこと本当に可能なのでしょうか?

可能です。あなたがRubyプログラマであれば。


技術書典5にて、Sinatraのコード解説本を頒布します。あと執筆環境の話。

2018-10-06 22:24:34 +0900

技術書典5に参加します

2018/10/08 に池袋サンシャインシティで開催される技術書典5にサークル参加します。すぺーすは「い22」です。よろしくお願いします。

頒布する本の内容は、ここ半年ほど作っていたMobbというボットフレームワークのコードを書くために読み込んだSinatraの、コードリーディングと解説の本です。Sinatraは非常にミニマルながらも強力な黒魔術と設計に支えられた、Ruby力を上げる教材としてとても良い題材だと思ったので、その知見を広く共有するために本にしました。

本の詳細と言い訳

頒布する本は、本文44ページで頒布価格は1000円にする予定です。これは、印刷した本の45%が売れた場合に、印刷代と参加費、その他諸経費がペイするように設定しました。45%の根拠は、同じサークルの檻総君が夏と冬に刷っている同人誌の売れ行きを観察するに、これくらいの数値設定が妥当だとおもわれるためです。

本文は、おおよそ二週間かからずに書き終わりました。しかし、その特急スケジュールのおかげで文字以外の図解などを作る暇がなく、やや読んでて疲れる本になってしまったという自覚があります。今回の技術書典でこの本を求めてくれる人が多ければ、もっと読みやすくした版を後日作成し、本を買っていただいた方には何かしらの形で無料で配れればと思ったりもしますが、その思いを実行できるくらい当日売れることを祈るばかりです。


Mobb 0.3 をリリースしました、これで実践的に毎秒クソボットをリリースできます

2018-09-17 22:07:05 +0900

Mobb 0.3.0 をリリースしました

今回のリリースでは、 cron/every キーワードが Mobb DSL に追加されています。

https://github.com/kinoppyd/mobb/pull/5

これらのキーワードは、 Mobb(およびRepp) になにかを定期実行させるためのものであり、このリリースによってようやく Mobb は実用的で最も簡易な Bot フレームワークを名乗ることができるようになったと思います。

最初に Mobb を作ろうと考えたときに、秒でクソボットを作れるようになるために必要なものはなんだろうと考えました。そして、必要だと考えたのは、シンプルなシンタックスで書けること、条件分岐がフレームワークの機能に備わっていること、なにかを定期実行できること、の三点でした。 Mobb 0.3 のリリースにより、これら3つの要素が全て揃い、ようやく Mobb が実用的な Botフレームワークとして皆さんに使ってもらえる機能を備えました。

Syntax

cron/every キーワードは、名前の通りなにかを定期実行するためのものです。具体的なシンタックスは、次のように書きます。

cron '0 12-21 * * *', dest_to: 'times_kinoppyd' do
  "Hi bro, wazup?
end

この例では、毎日12時から21時までの毎事0分に、botが times_kinoppyd という配信先(Slackであれば #times_kinoppyd) に対して、 “Hi bro, wazup?” というメッセージを配信します。

cron キーワードは、そのまま Cron の文法が使えます。具体的には、 parse-cron というGemを使ってパースできるものであれば動作します。

また、 cron の簡易的な使い方を目的として、 every というキーワードも追加しています。

every :day, at: '14:00', dest_to: 'times_kinoppyd' do
  "ぞい"
end

cron よりも、より直感的に定期実行を記述できます。これも、 whenever というGemを内部で利用しており、 whenever が解釈できる引数をそのまま渡すことができます。例えば次の例では、2というIntegerオブジェクトへのWheneverの拡張により、hoursというメソッドが追加されていて、それをそのまま使用することができます。

every 2.hours, dest_to: 'times_kinoppyd' do
  'ぞい'
end

every キーワードが受け取る事のできるシンタックスに関しては、 whenever のREADMEを参考にしてください。

注意点として、 cron/every キーワードでは、必ず dest_to というコンディションが必要な点に注意してください。これを設定しないと、Botはどこのチャネルにポストすれば良いのかがわからず、メッセージが闇に消えることになります。(Shellアダプタなど、チャネルの区別が無い環境であれば必要ありません)


Mobb 0.2.0 out now

2018-08-27 01:45:21 +0900

Mobb 0.2.0 をリリースしました

このバージョンでの大きな変更点は、helpersメソッドの追加とconditionメソッドの追加です。それぞれ、Mobb DSLのベースとなっているSinatraでは非常に大きな役目を果たしていたけれど、まだ移植が終わっていなかった機能です。

https://github.com/kinoppyd/mobb/releases/tag/v0.2.0

新機能の解説

0.2.0では、 helpers と condition が大きな変更点です。

helpers

helpersメソッドは、onイベントの中でアクセス可能なメソッドをMobbアプリケーションのトップレベルに定義するためのメソッドです。

require 'mobb'

helpers do
  def greet(name)
    "Hello #{name}"
  end
end

on "Hello" do
  greet(@env.user.name)
end

このように、 on メソッドのブロックの中でアクセスできる greet メソッドのような、ヘルパーと呼ばれるメソッドを定義します。

本来、 on メソッドのブロックは、この記述の場合は main オブジェクトに対するクロージャになっています。しかし、MobbやSinatraは内部でこの binding を書き換えるトリックを使っており、通常の手順では main オブジェクトに定義したメソッドや値を参照できません。例えば、次のコードは実際にブロックの中が呼び出される時にエラーになります。

require 'mobb'

def yo
  "Yo"
end

on 'Yo' do
  yo # error on runtime!
end

そのため、 helpers というメソッドを使い、一時的に self を on メソッドのブロックが実行される時と同じスコープに書き換えます。そして、そのスコープ内で def を使ってメソッドを定義することで、 on のブロックからアクセスできるヘルパーメソッドを定義することができるのです。


技術書展5で、Sinatraのコードリーディング本を頒布します

2018-08-23 23:43:31 +0900

技術書展5に当選しました

当選してしまったので、技術系の同人誌を書こうと思います。

最近の個人的な活動の成果として、SinatraのDSLっぽくBotが書けるMobbというプロダクトを作っています。そしてその過程で得たSinatraのコードリーディングの知見を広く共有するのが良いだろうと思っているので、同人誌にしようと思います。

たまたま、今日の夕方に会社のイベントでこういう発表をしたのですが、これを更に詳細に掘り下げた本になると思います。

kinoppydさんの「Sinatra trick」 / kinoppyd さん - ニコナレ

スペースはどこ

◎貴サークル「トレイリア学園」は、 い22 に配置されました。

どういう本にするの

Sinatraの全コードの解説を目指します。一冊読めば、自分でSinatraライクのDSLを書けるようになるくらいの本にしたいと思っています。対象読者層は、メタプログラミングRubyを読んだことがあるRubyエンジニアを想定していますが、それではあまりにもリーチが狭い(気がする)ので、メタプログラミングRubyの本を読んでいなくても簡単なエッセンスくらいは理解できる感じに解説を入れようと思っています。

また、現在コミットをしているMobbというBotフレームワークのプロジェクトに関しても、簡単な解説本を書こうと思っています。


追伸:Rubyのサンドボックスを作って、evalするBotを作った

2018-07-14 20:38:30 +0900

注意:安全じゃないです

あらすじ

  • 入力されたRubyのコード文字列を安全にEvalするBotを作ったと主張する

  • 次々と安全ではないことがわかる

  • ちょっとずつ安全に向けて改良したが、まだまだ安全じゃない

詳細はここ↓

http://tolarian-academy.net/ruby-sandbox-eval-bot/

たくさん届いた指摘

前回の最後の追伸から一夜明けて、またいくつかの指摘を頂いた。それぞれに関して対策を講じていく。


Rubyのサンドボックスを作って、evalするBotを作った

2018-07-10 01:04:56 +0900

注意:安全じゃありません

RubyのSnadbox環境

Sansbox環境とは、外部から入力されたプログラムを安全に実行する環境のことです。任意のコードを入力可能な場所で、いきなり system(“rm -rf ~/) とか入力されて、それが本当に実行されたら困りますよね? 自分は困ります。ですが、外部から入力されたコードを安全に実行する環境というのはそれなりに需要があり、最もわかりやすいところではJavaScriptを実行するブラウザ、わかりにくいところでは今回作ろうとしているeval用のbotです。

ブラウザに関しては、インターネットという非常に治安の悪い場所から送られてくるコードを自分の環境で実行するので、サンドボックスが必要です。同じように、会社のSlackで公開するRubyの任意のコードを実行してくれるBotでも、社内の邪悪な人から投げ込まれたコマンドで自分の環境を破壊されると困るわけです。競技プログラミングの採点サーバーなどで、送られてきたコードを実行するときに邪悪な奴だったら困りますよね? そういう邪悪なコードから身を守るために、サンドボックスは必要です。

その一方で、Rubyは結構自由すぎる言語で、任意の入力に対する安全なコードの実行というのはなかなか難しいです。Rubyには、汚染マークとセキュリティレベルという、外部からの入力を安全に扱う機構があり、これはメタプログラミングRubyでも紹介されています。詳細はリンク先のページを見てもらえると解りますが、しかしこの機構には一つ大きな問題があり、それは汚染された文字列をevalすることができないということです。そのため、汚染された文字列を自分の手で安全だとマークしない限り、evalの引数に渡して実行することができないのです。それはつまり、セキュリティレベルで保護されている内容と同じレベルの安全性であることを自分で保証しなくてはならないということです。それって、セキュリティレベルを自分でもう一度チェックしなくちゃいけないということなので、ハッキリ言って意味が無いです。

なので、セキュリティレベルに頼ることなく、危険なコードを事前に実行できないように、サンドボックス環境を用意する必要があります。


Ruby製の軽量Botフレームワーク Mobb をリリースしました

2018-07-01 02:10:48 +0900

TL;DR

Sinatra-isiに記述できるBotフレームワークMobbと、Botとサービスの間を取り持つRackに相当するReppを作って公開しました。

require 'mobb'

on "Hello" do
  "Hi!"
end

作ろうと思った理由

RubyでBotを作ろうと思うと、大体の人はRubotyを選択すると思います。GoogleでRubyを使ってSlack Botを作る方法なんかをいくつか探していると、そのうち自然とRubotyに行き着くと思います。ドキュメントやサンプルも日本語で多数用意されており、日本のRuby界隈におけるBotの選択肢としてはデファクトスタンダードではないかと思っています。

Rubotyはとてもよく作られたBotフレームワークですが、個人的にはプラグインのロードにBundlerを使って$LOADPATHから順次プラグインをロードしている点がやや使いづらいと感じていました。公にできない自作プラグインや業務レベルのロジックを乗せるには、それを回避する手順が煩雑になってしまい、Rubotyのロードの仕組みを調べることで本来やりたかったことに使うべき時間を奪われてしまうのが悩ましいところでした。

また、RubotyはHandlerとActionというクラスをきちんと定義しており、その流れに乗っていれば特に迷うことは無いのですが、本当にどうしようもないほどにくだらない機能(例えば、渡された言葉をシャッフルしてechoするだけのしょうもない単機能のbot)しか持っていないbotを作るには、あまりにもリッチ過ぎる制約を持っていました。また、プラグインのロードの都合上、Handlerは自分たちのロジックとは違うモジュール名空間に置かなくてはいけないことも気になる点でした。

この煩雑さを回避したい、毎秒クソボットを作りたいと思うようになると、まるでRailsのようなRubotyの壮大な世界観が少し扱いづらくなってきました。そこで、この悩みを解決するためにSinatraのような手軽さで書けるRuby製Botフレームワークが必要だと感じたために、Mobb プロジェクトを開始しました。

また、世の中には数多のBotフレームワークがありますが、その殆どが自らのコードに特化したサービス接続用のプラグインを持っており、他の世界観で使い回すことができないことも大きな問題だと思いました。これはちょうど、Web ApplicationとWeb Serverの接続部分を解決したRackのようなものがBotの世界にも必要だということであり、Rack(のような)インターフェイスにしたがってBotエンジンを記述すれば、サービスとの接続部分を使いまわせると考えたことが、ReppというBot用の共通のサービス接続インターフェイスを作ろうと思った動機です。