Skip to content

Instantly share code, notes, and snippets.

@udzura
Created June 2, 2014 03:31
Show Gist options
  • Save udzura/0cb2447c305c51670414 to your computer and use it in GitHub Desktop.
Save udzura/0cb2447c305c51670414 to your computer and use it in GitHub Desktop.
Hubot + CoffeeScript ではじめるやわらかプログラミング入門

やわらかプログラミング入門

  • Hubot であそぼう


始めに、地図を描く


Joel on Software - 5つの世界

  • パッケージ
  • インターナル
  • 組み込み
  • ゲーム
  • 使い捨て

パッケージ && Webサービスの世界の地図

  • Windows と UN*X
  • クライアントとサーバー
  • アプリとバッチ
  • ブラウザとネイティブ

演習

  • プログラミング言語を地図の上に置く
    • Ruby
    • JavaScript
    • Perl
    • Python
    • PHP
    • Java
    • Haskell
    • C
    • C++
    • Lua
    • Objective-C
    • C#
    • VisualBasic

まとめ

  • プログラミングでできることは果てしなく広い
  • 何のためにプログラミングをするかが重要、目的がはっきりしていればそれに向いた言語を学べ、学習が効率的になる

CoffeeScriptとHubot


今日の仮の目的

  • どのプログラミング言語でも使えるような基本中の基本を学ぶ
  • なるべく短い時間でSUGEEE経験をする
  • なるべく身近な役立つツールを作る

CoffeeScriptとは

  • 「スクリプト言語」
  • JavaScriptに変換できる言語
  • JavaScriptなので、サーバ(node.js)、クライアント(ブラウザやTitanium)、バッチ(Grunt)に使えて便利

言語的に難解すぎない割にモダンな特徴を持っている

  • たとえば
    • オブジェクト指向
    • 無名関数
    • 非同期
    • 動的型付け
  • JavaScript、Ruby、Pythonにステップアップできる(と思う

Hubotとは

  • 「Bot」のための「フレームワーク」
  • 「フレームワーク」は雑な言い方をすれば、ソフトウェアを作るためのソフトウェア
  • 皆さんが今後毎日使うIRCのBotを簡単に作る
  • IRC以外にも、HipchatなどAPIの公開されたチャットサービスの多くで使えるようになっている(skypeはもうすぐ使えなくなる、残念!)

セットアップとHello, world


CoffeeScriptのインストール

  • まず、JavaScriptを入れる
    • 同じ言語でも、いろいろな実装があることを覚えておく。今回はnode.js
  • npmが一緒に入る
    • node package manager = node の便利なツール、ライブラリを入れてくれるコマンド

Mac

$ curl -L git.io/nodebrew | perl - setup
$ echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.bash_profile
$ source ~/.bash_profile
$ nodebrew install-binary v0.10.28
$ nodebrew use v0.10.28

Windows


そしたら

  • やっとhubotをインストール
$ npm install -g coffee-script hubot

Windowsの方へ...

  • 将来、Webサービスの開発に行くならLinuxかせめてOS Xを使おう
  • どうしても動かない時は https://www.nitrous.io/ を使う

エディタのインストール

  • ファイルの編集
  • Vim, Emacs, 別にいいけど...今日教えること何もありません
  • 秀丸、TeraPad、さくらエディタ、たぶんJavaScriptなんで使えるけど...
  • それっぽいのなら Sublime Text 評価版だが、永遠に使える...

Hubotのプロジェクトを作る

  • コマンドライン操作
  • PATHを通す必要があるかも
$ hubot -c yawaraka-hubot

Hello, hubot

  • shellアダプター
  • デフォルトの機能(pingとかyoutubeとか)
$ cd yawaraka-hubot
$ npm install
$ echo "[]" > hubot-scripts.json
(ファイルの中身 ["redis-brain.coffee", "shipit.coffee"] -> [] )
$ ./bin/hubot
Hubot> 
Hubot> hubot, ping
Hubot> PONG

IRC に接続する

$ npm install --save hubot-irc

スクリプトをいじる

  • bin/hubot-irc というファイルを新規作成して実行権限を付ける
#!/bin/sh

export PATH="node_modules/.bin:node_modules/hubot/node_modules/.bin:$PATH"

npm install

export HUBOT_IRC_SERVER="irc.example.jp" # サーバ名
export HUBOT_IRC_PORT=6668 # ポート
export HUBOT_IRC_ROOMS="#bot_test" # channel
export HUBOT_IRC_NICK="hubot-udzura" # ニックネーム
export HUBOT_IRC_PASSWORD="XXXXXX" # パスワード
export HUBOT_IRC_USESSL="true" # SSLを使う
export HUBOT_IRC_SERVER_FAKE_SSL="true" # SSLが社内独自なので
export HUBOT_IRC_SEND_NOTICE_MODE="true" # 全発言をNotice
export HUBOT_IRC_DEBUG="true" # デバッグ

exec node_modules/.bin/hubot "$@"

exportとか暗号が出てきた


Windowsの

  • TODO そもそも hubot-irc がインスコできないよ〜
@echo off

SET HUBOT_IRC_SERVER=irc.example.jp
SET HUBOT_IRC_PORT=6668
SET HUBOT_IRC_ROOMS=#bot_test
SET HUBOT_IRC_NICK=hubot-udzura
SET HUBOT_IRC_PASSWORD=XXXXXX
SET HUBOT_IRC_USESSL=true
SET HUBOT_IRC_SERVER_FAKE_SSL=true
SET HUBOT_IRC_SEND_NOTICE_MODE=true
SET HUBOT_IRC_DEBUG=true

npm install && node_modules\.bin\hubot.cmd %*

起動?どう?

./bin/hubot-irc

Bot完成!おめでとう!

未完


Hubot script を書く


CoffeeScript入門

$ coffee
coffee> 1 + 2
coffee> 3 * 9
coffee> Math.power 3, 2

coffee> process.exit()

言語の基本

  • 制御構造
  • データ構造

関数

./sample.coffee というファイルに以下を書く(ここからのサンプルも同様)

power2 = (num) ->
  num * num
console.log power(1234)

$ coffee sample.coffee すると?


分岐(if)

is_odd_even = (num) ->
  if num % 2 == 0
    'even'
  else
    'odd'

console.log '4 is', is_odd_even(4)
console.log '185 is', is_odd_even(185)

繰り返し

for i in [1 .. 10]
  console.log "Hello! #{i}"

1, 2, 3 #=> 整数
1.2, 3.45 #=> 小数
"Coffee" #=> 文字列

(val) -> console.log(val)
#=> 関数、手続き

配列

fib = [1, 1, 2, 3, 5, 8]
branches = ["Tokyo", "Fukuoka", "Kyoto"]
# 繰り返しに便利
for city in branches
  console.log "Welcome to #{city}!!"

連想配列

whereis = {
  "lolipop": "Fukuoka",
  "minne": ["Fukuoka", "Tokyo", "Kyoto"],
  "suzuri": "Tokyo"
}

console.log 'lolipop is located in', whereis["lolipop"]
  • オブジェクト、ハッシュテーブル、辞書、などとも

Hubotスクリプトを書く

$ open scripts/yawaraka.coffee

なかみ

# Description:
#   説明を書く
#
# Commands:
#   コマンドの説明を書く
#   hubot hello, I am <名前> - <名前> に挨拶をする
#
module.exports = (robot) ->
  robot.respond /hello, I am (.*)/i, (msg) ->
    # この中で処理を書く
    name = msg.match[1] # () の中が取れる
    msg.send "Test" # 発言をする
    msg.send "ちょりーっす、 #{name}"
    
  robot.respond /goodbye (.*)/i, (msg) ->
    # いくつでもコマンドを追加できる

試し方

$ ./bin/hubot
Hubot> hubot, hello ...
# ローカルで試してからIRCでも試す!

ほらちゃんにだけツンデレbot

module.exports = (robot) ->
  robot.respond /hello, I am (.*)/i, (msg) ->
    name = msg.match[1]
    if name == "horaotoko"
      msg.send "べ、別にあんたに挨拶なんかしたくないんだからねっ!"
    else
      msg.send "ちょりーっす、 #{name}"

局長にだけテンションが高いbot

module.exports = (robot) ->
  robot.respond /hello, I am (.*)/i, (msg) ->
    name = msg.match[1]
    if name == "kyokutyo"
      for i in [1 .. 3]
        msg.send "ちょりーっす、 #{name}"
    else
      msg.send "ちょりーっす、 #{name}"

うらないボット

random = (n) -> Math.floor(Math.random() * n)

module.exports = (robot) ->
  robot.respond /今日の運勢/i, (msg) ->
    fortunes = [
      '大吉',
      '末吉',
      '大凶'
    ]
    result = fortunes[random(3)]
    msg.send "今日の運勢: #{result}"

他己紹介ボット

module.exports = (robot) ->
  robot.respond /about (.*)/i, (msg) ->
    name = msg.match[1]
    profiles = {
      'udzura' : '基盤ティーム',
      'horaotoko' : '3.5期生',
      'kyokutyo' : '隠れ変態'
    }
    result = profiles[name]
    if result
      msg.send "#{name}さんのプロフィール: #{result}"
    else
      msg.send "#{name}さんのことなんて知りません"

課題

  • (1) 電卓ボット(記号を見て四則計算する)
  • (2) 現在時刻を教えてくれるボット
now = new Date
now.toString()
now.getFullYear(), now.getFullYear(), now.getDay() #...
  • (3) クイズを出すボット

応用編


tiqav 画像検索ボット


Web API

  • 外部サービスと連携する!!
  • あたらしいnpmモジュールを入れる
$ npm install --save request

実装の例

module.exports = (robot) ->
  robot.respond /tiqav (.*)/i, (msg) ->
    request = require('request');
    request.get("http://api.tiqav.com/search.json?q=#{msg.match[1]}", (error, response, body) ->
      if error or response.statusCode != 200
        return msg.send('画像検索に失敗しました...')
      data = JSON.parse(body)[0]
      # robot.logger.info data
      msg.send "画像の様子です: http://img.tiqav.com/#{data.id}.#{data.ext}" )

デプロイをする

  • デプロイ=配備
  • 準備OKにする

デーモン化する必要性

  • 皆さんの使うプログラムは、人間が立ち上げ、人間が終了させる(アプリケーション)
  • 今回は、ボットなので、ずっと立ち上がっていなければいけない
  • ずっと立ち上がっているプログラムをサーバとかデーモンと呼ぶ

社内ツール専用のPaaS - Dokku


セットアップ(簡易)

  • 今回研修用に用意した秘密鍵 を取ってくる(取り扱い注意だよ〜)
  • $ chmod 600 ~/.ssh/id_dsa.pb
  • 疎通確認
  • .ssh/config を編集
Host dokku001.tokyo.lan
    HostName dokku001.tokyo.lan
    User dokku
    IdentityFile ~/.ssh/id_dsa.pb
  • Procfile を編集
web: bin/hubot-irc -a irc

注:社外向け解説


Gitでデプロイ

  • みんなもちろんGitは入ってるよね???(Macなら最初から入ってます)
$ git init .
$ git add .
$ git commit
$ git remote add dokku [email protected]:udzura-hubot
$ git push dokku master

デモ


終わりに


いい話


Enjoy Programming!


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment