akiranetの日々淡々と頑張っていこう

akiranetのコンピューターと遊ぶ

hubotを用いた楽しいslackLife(実践編)

ak1raです!
Hubotでslacklifeを快適にしようって思って、研究室に導入して楽しんでます!
最近まで1人GithubFlowをしてやっていましたが、無理矢理仲間が増えました!

前回、hubotを用いた楽しいslackLife(入門編)はこちら

開発したものはこちらです!
accueil

ちなみに、 accueil とは、フランス語で 歓迎, もてなし です! アクイーユっていうパンケーキが人気のお店もあるので、おすすめです笑

accueilに実装した機能

1. アニメ情報取得

huboco 上記のサイトを参考にしました。上記のものでは、
* 今期放送中のアニメの一覧を表示
* 今期のアニメをタイトルで検索

を表示してくれるものでした。 自分は、指定した年に放送したアニメを出してくれるスクリプトを書きました。

# 指定年のアニメ一覧
  robot.respond /(anime|アニメ)\s+(\d{4})$/i, (msg) ->
#    msg.send msg.match[2]
    msg.send "http://api.moemoe.tokyo/anime/v1/master/#{msg.match[2]}"
    url = "http://api.moemoe.tokyo/anime/v1/master/#{msg.match[2]}"
    msg.http(url).get() (err, res, body) ->
      if err? or res.statusCode isnt 200
        return msg.reply("#{ERR_MSG}\n```\n#{err}\n```")
      animes = JSON.parse(body)
      t = new table
      for anime in animes
          t.cell('URL', anime.public_url)
          t.cell('Title', anime.title)
          t.newRow()
      if t.rows.length > 0
        return msg.reply('```\n' + t.print().trim() + '\n```')
      msg.reply(NiL_MSG)

これは、anime 2016と行うと、2016年のアニメ一覧を表示してくれる。 2016のところは、2個目の正規表現のところを用いているので、msg.match[2]で表現している。

npmの使用モジュールとしては、
* moment = require(‘moment’)
* table = require(‘easy-table’)
を用いていて、 easy-table は簡単なDBのテーブルを作成ができる!便利!

アニメのAPIサーバの使い方を利用して、
http://api.moemoe.tokyo/anime/v1/master/#{msg.match[2]}によって、 http://api.moemoe.tokyo/anime/v1/master/2016となります。

ここで、アニメAPIサーバーからのレスポンスは以下のようなものとなる。

 [AkiRa:MBP-3-/~/bot/accueil] %
(`・∀・´) >>> curl http://api.moemoe.tokyo/anime/v1/master/2016 | jq .       [~/bot/accueil][master]
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  9866  100  9866    0     0  37606      0 --:--:-- --:--:-- --:--:-- 37656
[
  {
    "id": 281,
    "title": "機動戦士ガンダム サンダーボルト"
  },
  {
    "id": 282,
    "title": "プリンス・オブ・ストライド オルタナティブ"
  },
  {
    "id": 283,
    "title": "無彩限のファントム・ワールド"
  },

上記のように、JSON形式で返ってくるので、animes = JSON.parse(body)で扱える!

2. 映画館

登録映画館の公開映画と上映時間を表示のスクリプト

スクレイピングを行うために、 cheerio = require 'cheerio'を使用していて、jQuery風に取得できます!

THEATER_IDS = JSON.parse(process.env.HUBOT_THEATER_IDS ? '["11652","11610", "11625"]') 上記でどこの映画館の公開映画などを表示するのか決められる! たとえば、TOHOシネマズ新宿だと、 https://movies.yahoo.co.jp/theater/11652/でできる!!

HEATER_IDS.reduce(((promise, theaterId) ->
      promise.then (result) ->
        baseUrl = 'http://movies.yahoo.co.jp'
        url = "#{baseUrl}/theater/#{theaterId}/"
        request(url).then (r) ->
          $ = cheerio.load r.body
          movies = []
          theater = $('h1').text().trim()
          $('#schedule_list .listview__element').each ->
            e = $ @
            title = e.find('h3 a').text().trim()
            url = baseUrl + e.find('h3 a').attr('href')
            times = []
            e.find('ul.list-inline li').each ->
              l = $ @
              time = l.find('.btn-schedule').contents().filter(->
                @type is 'text'
              ).text().trim()
            times.push time
            movies.push { title, url, times }
            result.push { theater, movies }
            result

これは、 https://movies.yahoo.co.jp/theater/11652/のHTMLのタグ<h1>や<h3>から映画館名と映画タイトルをスクレイピングしています。 上映時間は、<a class="btn-schedule>を用いて、入手しています。

実行結果は以下のように出力されます

ccueil> accueil theater
accueil> TOHOシネマズ 新宿
                   ガーディアンズ・オブ・ギャラクシー:リミックス(3D・字幕版・IMAX)            09:00  12:00  15:00  18:00  21:00
                   ガーディアンズ・オブ・ギャラクシー:リミックス(3D・字幕版・MX4D)            16:00  19:00  22:00
                                                                                                       18:30
                   アンタッチャブル (字幕版)                                                        10:00
                   ワイルド・スピード ICE BREAK(字幕版・MX4D)                          09:30  12:30

3. GitHubのIssueのオープン・クローズド・一覧表示

repo  = "MaRuG/practice"

module.exports = (robot) ->
  github = require('githubot')(robot)

  robot.respond /issue list/i, (msg) ->
    github.get "https://api.github.com/repos/#{repo}/issues", {}, (issues) ->
      issues = issues.sort (a,b) -> a.number > b.number
      texts = ["https://github.com/#{repo}/issues"]
      for i in issues
        texts.push "[#{i.number}] #{i.title}"
      text = texts.join '\n'
      msg.reply "I'm listing up your issues\n#{text}"

  robot.respond /issue create (.+) body (.+)/i, (msg) ->
    who = msg.message.user.name
    title= msg.match[1]
    body = msg.match[3]
    if body is undefined then body = ""
    query_param =
      title: title
      body: "#{title}\n\ncreated by #{who} & hubot\n\n#{body}"
      labels: ["fromHubot"]
    github.post "https://api.github.com/repos/#{repo}/issues", query_param, (issue) ->
      text = "Sure! I created an issue for you\n#{issue.html_url}"
      msg.reply text

  robot.respond /issue close (.*)/i, (msg) ->
    github.patch "/repos/#{repo}/issues/#{msg.match[1]}", {state: "closed"}, (issue, error) ->
      if error then console.log error
      text = "OK. I closed #{issue.title} issue"
      msg.reply text

これを使うには、GITHUB_TOKENを登録する必要がある

$ curl -i https://api.github.com/authorizations -d '{"scopes":["repo"]}' -u "自分のユーザー名"
$ heroku config:set HUBOT_GITHUB_TOKEN=token_value

githubotを用いると便利!

4. ランチタイムの時間に通知と店をランダムで表示

cronJob = require('cron').CronJob
random = require('hubot').Response::random


module.exports = (robot) ->


  robot.hear /(lunch)/i, (msg) ->
    lunch = msg.random [
      '一平ソバ'
      '清華'
      'コンビニ'
      'スエヒロ'
      '東館食堂'
      'サクラキッチン'
    ]
    msg.reply "#{lunch}"


  new cronJob('0 40 12 * * 1-5', () ->
    
    messages =  [
      '一平ソバ'
      '清華'
      'コンビニ'
      'スエヒロ'
      '東館食堂'
      'サクラキッチン'
    ]

    message = messages[Math.floor(Math.random() * messages.length)]
    
    robot.send( '#12th-member', message)
  ).start

決まった時刻(平日の12:40)に、ランチの時間を知らせて、店の場所を発言してくれるようにしてます! でも食べたい物とお金の事情により、この通知はガン無視してます笑

この定期実行を行っているのは、cronJob = require('cron').CronJob
new cronJob(' 秒 分 時 日 月 曜日(月-金 = 1-5)'), () -> で表示できます!

5. Yahoo!電車情報での遅延情報

https://github.com/hotatekaoru/myHubotScripts/blob/master/train-info.coffeeを参考にしました。

以下に運行情報からスクレイピングを行っています。 https://transit.yahoo.co.jp/traininfo/gc/13/

例として山手線は、[https://transit.yahoo.co.jp/traininfo/detail/21/0/]をあげる 以下のコードurlに山手線のURLを入れる。

  searchTrainCron = (url) ->
    cheerio.fetch url, (err, $, res) ->
      title = "#{$('h1').text()}"
      if $('.icnNormalLarge').length
        robot.send {room: '#12th-member'}, "#{title}は遅れてないよ。はい。"
      else
        info = $('.trouble p').text()
        robot.send {room: '#12th-member'}, "#{title}は遅れているみたい。\n#{info}"

平常運転なら、<span class="icnNormalLarge">がある。 もし遅延していたら、

<dd class="trouble">
<p>20:10頃、秋津駅で発生した人身事故の影響で、現在も一部列車に遅れや運休が出ています。<span>(5月23日 23時20分掲載)</span></p>

というのがあるので、そこを表示するようにしている。

まとめ

 今回実際に便利そうな機能を人の真似ながらですが、ソースコードについて理解できるよう勉強しました。今後は、在室管理をSlackで管理しHubotに呼びかけると、研究室にいる人と徹夜の人を表示してくれるようなものを作りたいと思います。

参考

天気情報
電車の情報を教えてくれる
3時間毎にcronを実行
huboco
bouznya
githubot用いて、issueを立てる
trim()について

hubotを用いた楽しいslackLife(入門編)

ak1raです! インターンシップに参加した企業で, hubotを見かけてから興味がでて少し作ってみました。

Hubotって何??

hubot

GitHub社が開発しMITライセンスで公開しているNode.jsでbotを作り動かすためのフレームワークです。 Hubotは, 様々なチャットツールと連携でき,「Adapter」を切り替えることでそれができる。 呼び方は, 「ヒュボット」らしい。。

Hubotは主に以下のことができる。

など様々なことができるので楽しいですよ〜

Hubotの導入方法(Mac)

今回はMacでHubotの開発環境を作りました. ほぼここ(http://qiita.com/susuwatarin/items/019e0e701754161f7c4c)で導入はできるので見てみてください。 大まかな流れは、

  1. Homebrewを入れる
  2. brew install node で Node.jsをインストー
  3. Hubotを作るための「Yeoman」というツールセットをインストーnpm install -g yo generator-hubot
  4. Hubotのプロジェクトを作っていく yo hubot
  5. Hubotをローカルで動かす bin/hubot
  6. HerokuやBluemixなどにHubotをweb上に公開する

※Herokuだと24時間稼働し続ける事ができないので, Bluemixのが良いらしい…..

Hubotの書き方

  • respondとhear
    • respond : 呼ばれて答える
    • hear: ある発言に対して反応する

ex)

robot.respond /hi$/i, (msg) ->
  msg.send "Hello!"
 
robot.hear /hi$/i, (msg) ->
  msg.send "hello!"
  • 正規表現とmsgオブジェクト
    • いくつかの文字列を一つの形式で表現するための表現方法
    • 正規表現にマッチした発言を第二引数(msg)に渡す
    • 今回, msg.match[1]だが, 正規表現が2つ書いてあり,二つ目が良いならmsg.match[2]となる

ex)

robot.respond /I am (.*)/i, (msg) ->
   msg.send "You are #{msg.match[1]}"

nodejsのライブラリからインストールして実行

  • cron(定期実行)
    • npm install cron --save
    • これが,package.jsonに加わり, scriptsで使える

ex)

cronJob = require('cron').CronJob
module.exports = (robot) ->

  new cronJob('0 30 12 * * 1-5', () ->
      robot.send ( '#12th-member', '@here 昼飯だべ~')
    ).start

ex)

request = require 'request'
cheerio = require 'cheerio'
 
module.exports = (robot) ->
  robot.respond /title (.*)/i, (msg) ->
    url = msg.match[1]
    options =
      url: url
      timeout: 2000
      headers: {'user-agent': 'node title fetcher'}
 
    request options, (error, response, body) ->
      $ = cheerio.load body
      title = $('title').text().replace(/\n/g, '')
      msg.send(title)

以上のようなことができます。

他にもAPIサーバーを用いて, アニメ情報や電車の遅延, 天気情報,映画情報をslack上で確認できるなどあります。

問題が発生した時の対処

  • 作ったスクリプトがうまく動かないときなどがあり、なんでだろうってときはローカル上でHubotを動かすとわかった
  • errorで  Unexpected 'INDENT'がよく見られたので、エラー名の通り、/bin/hubotだと何行目かわからない
  • デプロイした後,動かないときはHerokuのログを読むべし
  • ログを読み取ることが大切

思ったこと

Hubotは,実際に目に見えて動き,研究室のSlackに導入してみるとみんなが楽しんでくれてよかった。 これからは、いろいろな人の意見を聞いて改善していきたいと思う。

SlackはGitHubやIncoming Hooks, Google Calenderなど豊富なAppと連携できるのでぜひ使っていきたい

次にやりたいこと

Slackで研究室に誰がいるかわからなくて, 「誰かいる?」って聞くのは面倒くさいと思ったので, 在室管理システム的なものをNFCリーダーを用いて作りたい

NFCリーダーで学生証読み取り -> slackに誰が来たか流す

要は出席管理みたいなもんですね….

参照

初心者がHubotを使ってHeroku上で動くSlack bot作ってみた(導入編)) hubot-script cronjob

Rails Tutorial 終えてみての感想

ak1raです!

Rubyを勉強してみたくてRails Tutorialを初めてやっとおわりましたのでなんとなく感想だけでも書いてみようと思います.

Rails Tutorialをやってみて

railstutorial.jp

一通り行うと、TwitterのようなWebアプリケーションができます。 また、テスト駆動開発を行っていて、アプリケーションを開発するときに最初にテストを作成し、次にコードを作成することを行っています!

はじめてWebアプリケーションを作ってみて思ったのは難しいなって感想でした。 今回このチュートリアルをやったおかげで、MVCモデルについても理解できました。

https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSknLI3PsK7Vb1eRKUovxA8fxyZRTfjRSr46UmejQjRN2GBodL6

また、テストコードをこんなに多く書いたことがなかったので、すごく勉強になりました。 また、Rubyの大まかな書き方もわかりました。

演習問題の解答など、ここが参考になりました。

今後のやりたいこと

家に書籍(漫画や小説etc)が多いので、書籍管理アプリケーションを作ってみたいなと考えています。

サーバー構築の際に、[Serverspec]や[Puppet]などを使いこなせるようになりたいな〜〜 ServerspecやPuppetは、本家のページがすごく参考になったのでおすすめしたい!!

serverspec.org

Home | Puppet

上記ふたつを使いこなせるようになったら記事を書きたいなと思います。。

以上、ただの感想でした…….

自分的Git, GitHubの使い方

ak1raです!
研究室のプロジェクトやインターン先でGitHubを使ってから、1人GitHubFlowで遊んでいます(苦笑い)
誰か一緒にやろうぜ
その本音を実現するために、後輩に教えた際に詰まったりしていて、自分の理解が甘いことに気づきました。 そこで今回は、ブランチを切ってプルリクエストを送るまでのやり方とエラーの対処を書いていこうと思います!

PullRequestを作ろう!

Pull Requestってなんぞ?

コードレビューしたり、〇〇の機能を実装するにはどうすればいいか、問題は何かなどを書き、
コードに関するコミュニケーションの場というイメージです。 他の人のリポジトリを自分のGitHubアカウントにFork(コピー)してきて、変更を加えて、それを元のリポジトリに取り込んでもらうようにリクエストを送信する
言葉ではわかりにくいので、自分が作ったPR(Pull Request)を以下に載せます。

f:id:akiranet:20170524141155p:plain

これは自分流なので、書き方は自分や開発グループの方針に従えばいいと思います。 私は、5W1Hを基に、何の機能なのか(WHAT)・どうやって実装するか(HOW)を主に書いてます! サーバーや機能に問題あったときは、その問題がいつ起きたかなどは(WHEN)で書くなどもできると思う。

PRの方法

今回説明するのは、他人のGitHubにPRを作る方法をやっていこと思います。 また使っているのは自分が作ったHubotのコードがあるGitHub(https://github.com/MaRuG/accueil)です!

1. 他人のGitHubのサイトから自分のGitHubにForkします

f:id:akiranet:20170524142903p:plain

上図の右上にある「fork」します。 そうすることで、自分のGitHubリポジトリにコピーできます。

2. 自分のGitHubを自分のPC(ローカル)にcloneします

xxxxxxxxxxには自分のユーザ名
$ git clone https://github.com/xxxxxxxxx/accueil.git

3. ブランチをきる &ごちゃごちゃ編集する & GItHub push しよう

まずはブランチを切りましょう!
ところでブランチってなんですか??ってなりますよね。
ブランチとは、履歴の流れを分岐して記録していくためのものです。分岐したブランチは他のブランチの影響を受けないため、同じリポジトリ中で複数の変更を同時に進めていくことができます。

http://www.backlog.jp/git-guide/img/post/stepup/capture_stepup1_1_1.png

ブランチをきることで、並行作業をやりやすくなります!

$git checkout -b xxxxxxx xxxxxxxxには、任意のブランチ名を入れましょう! ここで-bは、新規のブランチを作り、そのブランチに移ります

また、現在のブランチを確認するには以下のコマンドで確認できます。 $git branch

例として、README.mdを編集したとします。 そうしたら、以下の流れでGitHubにプッシュしましょう!

$ git remote add ooooo https://github.com/xxxxxxxxx/accueil.git
$ git add README.md
$ git commit -m "README.md コードの説明追加"
$ git push ooooo xxxxxxxxx 

oooooは任意のリモートリポジトリ名をかく xxxxxxxxxはブランチ名です。

4. ついにPRを作ろうぞ!

以前やったスクショで申し訳ない….
これは[train-info-delay]ブランチで作業した時の様子です! f:id:akiranet:20170524145053p:plain

[compare & pullrequest]をクリックして作れます!
PRの書き方は、上記でやった感じ!

コードレビューの文化は大切だと思います。

slackなどで誰かに見てもらって、typoなどないかを見てもらいます!
OKが出たら、masterにマージするようします。

以上が大まかなGitHubの使い方です!

エラー対処

git commitを取り消したい

直前のだったら、以下のように行う
$ git add reset --hard HEAD^
これだとファイルの変更箇所も取り消します。

変更箇所は残して、コミットしたことのみ消したい!
$ git reset --soft HEAD^
でできます!

HEAD^ -> 直前
HEAD^^ -> 二個前
commitのハッシュ値でも指定して取り消しできます

git commitの上書き

$git commit --amend

PRでコンフリクトされて、マージができない!?orz

これは、PRのところを見ればやりかたが書いてあるので、コマンドだけ以下に示します。

git fetch origin 
git checkout -b hoge-branch origin/hoge-branch
git merge master

conflictしているファイルのコード部分を修正。

git add xxxxx               // xxxxxはファイル名
git commit -m "〇〇"   // 〇〇はコメント

以上のことを行った後、PRのページを見るとマージできるようになってました!!

参考サイト

blog.qnyp.com www.backlog.jp

www-creators.com

eng-memo.hatenadiary.com

d.hatena.ne.jp

Docker再入門

ak1raです! 以前Dockerをつかって遊んでいたのですが、最近使っていなかったので再度入門してみました。

Dockerってなんぞ?

Dockerは、Docker社(旧dotCloud)が開発するオープンソースコンテナー管理ソフトウェアの1つでコンテナー型仮想化を行います。 よく見かけるのが、VMM( 仮想マシン・モニタ)でVM(仮想マシン)を作り、仮想環境を作るというのがあると思います。 そこで、上記2つがどう違うのかを以下の図がとてもわかり易いと思います。

VMとコンテナ仮想化の違い

  • コンテナーでアプリケーションを実行するために以下の機能を持ちます。
    • コンピューターリソースの隔離および制限
    • 他のホスト、他のコンテナーとのネットワークの構成
    • ファイル/ディレクトリの世代と差分の管理

構造は以下の図のようになっています。 imagelayer

Docker入門

docker run

  • OSを起動したりできる
  • bashをつけることで、bash起動
docker run -it ubuntu:14.04 bash
  • イメージを指定して起動
docker run -it akira/testimage:1.0

docker commit

  • 現在までのDockerコンテナの変更内容を新たなイメージとして保存
docker commit コンテナID イメージ名

Dockerfile

  • FROM ベースイメージを指定
  • RUN 自動実行するためのスクリプト
  • CMD docker runをした際にそのコマンドを実行可能
  • ENTRYPOINT 予め指定したコマンドを引数を指定のみで実行可能
  • EXPOSE ポート番号を指定

Docker build

イメージをビルド!!

docker build [options] [paths]
ex) docker build -t akira/testimage:1.0 .

docker exec

docker exec -it コンテナID bash

指定したコンテナIDをbash起動

削除コマンド

  • イメージの削除
docker rmi imageID
  • コンテナの削除
docker rm コンテナID

VOLUMEってなぁに〜〜

  • 永続するデータを保存するためにコンテナ
  • コンテナ間での共有が可能

ポート変更

  • nginxのポートを80->8080
docker run -d -P 8080:80 nginx
  • -Pによって自動的にポート割当

コンテナ間のリンク

docker run -d --name dbms postgres
 
docker run -it --name website --link dbms:db ubuntu:14.04 bash

まとめ

 今回の再入門で、Dockerに使い方を思い出せました。次は、Dockerを用いてWebアプリケーションの環境やいろいろなサーバーを作りたいと考えています。また、Dockerクラスタ環境構築に「Docker Swarm」や「Kubernotes」があるらしいのでそのへんも勉強して詳しくなっていきたいです!

参考

dev.classmethod.jp

いまさら聞けないDocker入門(1):アプリ開発者もインフラ管理者も知っておきたいDockerの基礎知識 - @IT

仮想化技術はじめの一歩 − @IT

再び挨拶

はじめまして,akiranet(@akiranet2580)です。 ふと今まで書いた記事を削除したくなったので削除して,一新しようと思いました。

ここには,自分が作ったものや参考になったサイトなど書いていこうと思います。

ちなみに僕が興味あるものは以下です.

これから少しずつですが,自分が勉強になったって思ったものを書いていこうと思います。 よろしくお願いいたします。