2016年9月30日金曜日

AWS Cognito を使ってユーザのサインアップを試してみた

概要

AWS Cognito はユーザ管理やフェデレーションをサポートしてくれるサービスです
今回は Cognito を使ってユーザのサインアップを試してみました

環境

  • Mac OS X 10.11.6
  • AWS Cognito 2016/09/30 時点
  • Apache httpd 2.4.18
  • Google Chrome 53.0.2785.116 (動作確認用)

User Pools の作成

まず User Pool を作成します
Cognito にログインしたページから「Manage Your User Pools」を選択します
try_cognito_login.png

まだ 1 つも User Pool が作成されていないと思います
「Click here to create a user pool.」を選択します
try_cognito_creating_user_pool.png

まずは User Pool の名前を決定します
好きな名前を入力してください
名前を入力したら今回は右側の「Step through settings」を選択してください
こちらを選択すると User Pool の設定を各項目ごとに設定することができます
try_cognito_naming_user_pool.png

で、設定時のポイントは 1 つです
初めの Attributes の設定で email にチェックが入っているのでこれを外してください
try_cognito_setting_user_pool.png

あとは特に気にすることなく Next step していけば OK です
今回は以下のような感じで User Pool が作成されました
try_cognito_created_user_pool.png

一番上の Pool Id は後で使用するのでメモしておいてください

Apps の作成

実際に Cognito を使ってアクセスするアプリを作成します
今回は Cognito を使って認証するためのアプリとユーザをサインアップするための 2 つのアプリを作成します

左メニューから「Apps」を選択したら「Add an app」を選択します
try_cognito_adding_apps.png

今回作成するアプリは「cognito」と「signup_app」にします
作成時のポイントとしては Generate client secret にチェックを入れないようにしてください
入力できたら「Create app」を選択します
try_cognito_naming_apps.png

同じように signup_app も作成しましょう
以下のようになれば OK です
try_cognito_created_apps.png

作成時に発行される App client id は後で使うのでメモしておいてください
これで User Pool の作成は完了です

Federated Identities の作成

次に Federated Identities を作成していきます
User Pool の画面上部に「Federated Identities」へのリンクがあるのでここから移動してください
try_cognito_move_page_fi.png

まだ、Federated Identities は作成されていないと思うので作成していきます
まず、好きな名前を入力し「Enable access to unauthenticated identities」にチェックを入れてください
try_cognito_naming_fi.png

そのすぐ下に「Authentication providers」という項目があるので開きます
この項目の Cognito のタブにある「User Pool ID」と「App Client ID」に先ほど User Pool で作成した cognito アプリの情報を入力します
「User Pool ID」には User Pool 作成時に取得できた Pool Id を入力し「App Cient ID」には cognito アプリ作成時に発行された App client id を入力してください
入力できたら「Create Pool」で OK です
try_cognito_setting_auth_user_pool.png

作成が完了したら「Edit identity pool」から Identity pool ID を確認しておきましょう
これもあとで使用します
try_cognito_confirm_identity_pool_id.png

これで Federated Identities の作成は完了です
アプリから Cognito を使う準備も整いました
では、実際に Javascript のクライアントアプリを作成してみましょう

ワークスペースの作成

今回は Mac 上にインストールした httpd の DocumentRoot 配下で作業していきます

  • cd /Library/WebServer/Documents
  • sudo mkdir cognito
  • cd cognito

各種必要なライブラリのダウンロード

wget で必要なライブラリを取得していきます

サインアップ処理の実装

では実際にコーディングしていきます
ユーザを登録するためのサインアップ画面を実装します

  • cd /Library/WebServer/Documents/cognito
  • vim signup.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8" />
  <title>signup</title>
  <script src="js/jsbn.js"></script>
  <script src="js/jsbn2.js"></script>
  <script src="js/sjcl.js"></script>
  <script src="js/moment.js"></script>
  <script src="js/aws-cognito-sdk.min.js"></script>
  <script src="js/amazon-cognito-identity.min.js"></script>
  <script src="js/aws-sdk.min.js"></script>
  <script src='js/jquery-3.1.1.min.js'></script>
  <script src='js/signup.js'></script>
</head>
<body>
<div>
<form>
  <h2>サインアップ</h2>
  <div id="message" style="display:none;"></div>
  <label for="inputUsername" >ユーザー名</label>
  <input type="text" id="inputUsername" placeholder="User name" required autofocus></input>
  <label for="inputPassword">パスワード</label>
  <input type="password" id="inputPassword" placeholder="Password" required></input>
  <br/>
  <input type="button" id="user_add_btn" value="ユーザーを作成する"></input>
</form>
</div>
</body>
</html>

必要な js ファイルを読み込んでユーザ名とパスワードを送信するためのフォームを作成しています

  • vim js/signup.js
AWS.config.region = 'ap-northeast-1';
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
  IdentityPoolId: 'ap-northeast-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
});
AWSCognito.config.region = 'ap-northeast-1';
AWSCognito.config.credentials = new AWS.CognitoIdentityCredentials({
  IdentityPoolId: 'ap-northeast-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
});
var data = {
  UserPoolId: 'ap-northeast-1_xxxxxxxxx',
  ClientId: 'xxxxxxxxxxxxxxxxxxxxxxxxxx',
};
var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(data);
var attributeList = [];
var cognitoUser;

$(function() {
  $("#user_add_btn").click(function(e) {
    username = $("#inputUsername").val();
    password = $("#inputPassword").val();
    if(!username || !password) { return false; }
    userPool.signUp(username, password, attributeList, null, function(err, result){
        if (err) {
            console.log(err);
            message_text = err;
            message_class = "alert-danger";
        } else {
            cognitoUser = result.user;
            console.log('user name is ' + cognitoUser.getUsername());
            message_text = cognitoUser.getUsername() + "が作成されました";
            message_class = "alert-success";
        }
        $("#message").text(message_text);
        $("#message").addClass(message_class);
        $('#message').show();
        setTimeout(function() {
          $('#message').fadeOut();
          $("#message").removeClass(message_class);
        }, 5000);
    });
  });
});

この Javascript ファイルが実際に AWS Cognito と通信を行うロジックファイルになります
設定するべき箇所は IdentityPoolId, UserPoolId, ClientId の 3 つです

IdentityPoolId は Federated Identities 作成時に発行された「Identity pool ID」を指定します
UserPoolId は User Pool 作成時に発行された「Pool Id」を指定します
ClientId は User Pool の Apps 作成時に「signup_app」と名付けたアプリの「App client id」を指定します

処理としても簡単で HTML 内のフォームボタンが押されたら jQuery 内で signUp メソッドをコールしているだけです
あとは、結果によって表示する内容を変更しています

これで基本は動作するはずなので httpd を起動してブラウザで http://localhost/cognito/signup.html にアクセスして動作確認してみましょう

動作確認

パスワードのポリシーが

  • 8 文字以上
  • 半角英数字、大文字小文字を含む
  • 半角数字を含む
  • 記号を含む

という条件になっているのでご注意ください
ポリシーをクリアしていないとエラーが返ってくるのでわかると思います

問題なくユーザ登録が完了すると以下のようになります 
try_cognito_signup.png

また User Pool の Users 項目を確認すると登録できたユーザが存在していると思います
try_cognito_signup_ret.png

これで Cognito を使ったユーザのサインアップ処理が完成しました

最後に

Web にあるサンプルが bootstrap やらいろいろとアレンジしているのが多かったのでシンプルな感じのやつを紹介しました

自画自賛ですが、わりとわかりやすい説明ができたかなと思います

今回は単純な認証しか試していませんが、Cognito は Facebook や Google などと連携して初めて効果をはっきするサービスだと思います
また、Federated Identities は IAM のロールとも連携しておりログインしたユーザが制御できる AWS のリソースを設定することもできます

次回は作成したユーザで実際にログインするところをやってみたいと思います

参考サイト

2016年9月29日木曜日

slack-ruby-client を使ってみた

概要

Slack の API をコールするのに前回slack-ruby-gem を使ってみました
今回はその派生の slack-ruby-client を使ってみました

環境

  • Mac OS X 10.10.5
  • Ruby 2.3.1
  • gem 2.5.1
  • slack-ruby-client 0.7.7

事前作業

  • bundle init
  • vim Gemfile
gem 'slack-ruby-client'
gem 'eventmachine'
gem 'faye-websocket'
  • bundle install

ソースコード

  • vim src-test.rb
require 'slack-ruby-client'

Slack.configure do |config|
  config.token = ENV['SLACK_API_TOKEN']
  config.logger = Logger.new(STDOUT)
  config.logger.level = Logger::INFO
  fail 'Missing ENV[SLACK_API_TOKEN]!' unless config.token
end

Slack::RealTime::Client.config do |config|
  config.websocket_ping = 30
end

client = Slack::RealTime::Client.new

client.on :hello do
  puts "Successfully connected, welcome '#{client.self.name}' to the '#{client.team.name}' team at https://#{client.team.domain}.slack.com."
end

client.on :message do |data|
  puts data

  client.typing channel: data.channel

  case data.text
  when 'bot hi' then
    client.message channel: data.channel, text: "Hi <@#{data.user}>!"
  when /^bot/ then
    client.message channel: data.channel, text: "Sorry <@#{data.user}>, what?"
  end
end

client.on :close do |_data|
  puts 'Connection closing, exiting.'
end

client.on :closed do |_data|
  puts 'Connection has been disconnected.'
  client.start!
end

client.start!

ほぼサンプルのままですが、再接続する機能をつけています
切断のイベントを取得したら client.start! を実行しているだけです

動作確認

  • export SLACK_API_TOKEN=xoxp-11111111111-11111111111-11111111111-xxxxxxxxxx
  • bundle exec ruby src-test.rb

で接続がはじまります
接続が完了すると「Successfully connected」が出力されるのでこれでブラウザから Slack にコメントすると以下のようにメッセージを取得することができます

channel=C1QD3RVNZ, team=T1QDA7KG9, text=hoge, ts=1475125556.000002, type=message, user=U1RK55Q20

今回のサンプルの場合だと切断時に「Connection closing, exiting. Connection has been disconnected.」というログが出力されるので、これが出力されたあと自動で Slack に再接続してくれます

最後に

slack-ruby-client を使って Slack からメッセージを取得してみました

ping を送信する設定や再接続時の処理を簡単に書けそうだった試したのですが、よくよく考えると slack-ruby-gem でも :close と :closed というイベントを拾えば再接続処理はできそうだなと、、、

上記も時間があれば試してポストしようと思います

参考サイト

2016年9月28日水曜日

独自 Gem の作成方法

概要

かなり既出な情報ですが、Ruby のライブラリ gem を作成する方法をまとめました
とりあえずローカルでインストールするところまでとなります

環境

  • Mac OS X 10.11.6
  • Ruby 2.2.3p173
  • Gem 2.4.5.1
  • Budler 1.11.2
  • Rake 11.2.2

手順

fstlib という gem を作成していきます
今回は bundler と rake を使って作成していくので事前に作成しておいてください

雛形の作成

  • bundle gem fstlib

一番初めだけ「テストの方式」「公開時のライセンス形態」「コード規約を含めるか」を聞かれます
基本は全部デフォルトのままで OK です
問題なく作成できれば以下のファイル群が作成されます

Creating gem 'fstlib'...
MIT License enabled in config
Code of conduct enabled in config
      create  fstlib/Gemfile
      create  fstlib/.gitignore
      create  fstlib/lib/fstlib.rb
      create  fstlib/lib/fstlib/version.rb
      create  fstlib/fstlib.gemspec
      create  fstlib/Rakefile
      create  fstlib/README.md
      create  fstlib/bin/console
      create  fstlib/bin/setup
      create  fstlib/LICENSE.txt
      create  fstlib/CODE_OF_CONDUCT.md

続いてメタ情報を修正していきます

  • cd fstlib
  • vim fstlib.gemspec

TODO となっている箇所を修正します

spec.authors       = ["hawksnowlog"]
spec.email         = ["hawksnowlog@gmail.com"]
spec.homepage      = "http://hawksnowlog.blogspot.com/"

...

spec.summary       = %q{This gem is a test.}
spec.description   = %q{This gem is a test.}

allowed_push_host の設定の部分は https://rubygems.org/ 以外で gem を公開するときに設定が必要になるので、不要な場合は行を削除してください

# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
# delete this section to allow pushing this gem to any host.
if spec.respond_to?(:metadata)
  spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
else
  raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
end

最低限の設定は以上で OK です

ライブラリの作成

では、実際に独自のライブラリを作成していきましょう

  • vim lib/fstlib.rb
require "fstlib/version"

module Fstlib
  def self.hello
    "Hello in Fstlib"
  end
end

「Hello in Fstlib」と表示するだけの hello という関数を定義しました

irb で動作確認

gem ファイルにする前に一旦 irb コマンドで動作確認できます

  • bundle exec irb
irb(main):001:0> require 'fstlib'
=> true
irb(main):002:0> Fstlib.hello
=> "Hello in Fstlib"

こんな感じになれば問題ないので gem の形にしていきます

ビルド

  • rake build
  • ls pkg/
fstlib-0.1.0.gem

rake -T でタスクの一覧を確認することができます
pkg 配下に gem が作成されれば OK です

インストール

ビルドして作成できた gem ファイルをローカルからインストールします

  • gem install -l pkg/fstlib-0.1.0.gem
Successfully installed fstlib-0.1.0
Parsing documentation for fstlib-0.1.0
Installing ri documentation for fstlib-0.1.0
Done installing documentation for fstlib after 0 seconds
1 gem installed
  • gem list | grep fstlib
fstlib (0.1.0)

こんな感じでインストールすることができます

動作確認

  • irb
irb(main):001:0> require 'fstlib'
=> true
irb(main):002:0> Fstlib.hello
=> "Hello in Fstlib"

今度は bundler 経由で irb を実行しないでも require することができるようになりました

Tips

バージョンアップする

  • vim lib/fstlib/version.rb
module Fstlib
  VERSION = "0.1.1"
end

で再度ビルドすれば「fstlib-0.1.1.gem」というファイルが作成されます

依存ライブラリを定義する

  • vim fstlib.gemspec
spec.add_runtime_dependency 'sinatra'

と 1 行追加しましょう
すると lib/fstlib/version.rb の中で require "sinatra" できるようになります

最後に

ローカルで gem を作成してインストールする方法を紹介しました
次回はアカウントを作成して rubygems で公開するところまでやってみたいと思います

参考サイト

2016年9月18日日曜日

Cube で RaspberryPi1 TypeB のケースを作成してみた

概要

Cube で RaspberryPi1 TypeB のケース上下をプリントアウトしてみました
元になっているデータは Thingiverse で公開されているケースのデータを使い、少しだけ TinkerCAD でアレンジしたデータを使っています

環境

  • Cube (1st and 2nd gen)
  • Cube Software 2.0.0
  • Mac OS X 10.10.5

作ったケース

上 (表)
rpi_case_is_created_by_cube_upper.jpg

上 (裏)
rpi_case_is_created_by_cube_upper_back.jpg

下 (土台付き)
rpi_case_is_created_by_cube_bottom_pre.jpg

下 (土台なし)
rpi_case_is_created_by_cube_bottom.jpg

土台部分の側面にケーブルを引っ掛けることができる爪を 5 つ追加してみました
これがアレンジした点です

合体後
rpi_case_is_created_by_cube_whole.jpg

合体後 (裏)
rpi_case_is_created_by_cube_whole_back.jpg

プリントにかかった時間は

  • 上が 2 時間 16 分
  • 下が 2 時間 46 分

でした

感想

まず、一番大変だったのは CAD でのモデリングでも Cube の設定でも、プリントでもなく、作成後にフィラメントを剥がす作業が一番大変でした

Cube の場合、中が空洞だったり、途中ではみ出したりしている部分のプリントするとプリント中に崩れないようにサポート用のプリントが行われます
サポート用のプリント自体は非常に細くかつ接合部分の面積も少ないので剥がれやすいようにはなっているのですが、今回のケースの場合その量が非常に多くサポート用のフィラメントを剥ぐ作業がかなり辛かったです

サポート用なのにかなり強力にくっついてしまっていたり、サポート用のフィラメントを剥がす際に一緒にメイン部分も剥がれてしまうなど、思った通りには全くいきませんでした

そして、今回、蓋部分のプリントを一回ミスしています
というのも一発目のプリントは天板部分を上にしてプリントしたのですが、そうすると下のほうがかなり不安定な状態でプリントがスタートするため、サポート用のフィラメントだらけになってしまい全く剥がれない状態になってしまいました
なぜ、安定している天板部分を上にしたかと言うと Cube の場合、プリントの開始、つまり一番下の裏側にあたる部分はかなり雑な感じでできあがってしまいます
なので、天板部分を下にした状態だと、できあがった時に天板が雑な感じになってしまうので、天板部分を上にしてプリントしました
そしたら予定通り、天板部分は非常に綺麗にプリントできたのですが、案の定サポート用のフィラメントだらけになってしまい失敗に終わってしまいました

で、二回目は天板部分を下にしてプリントをしたら天板は雑な感じになってしまいましたが、なんとかサポート用のフィラメントを剥ぐことができ、ケースとしてプリントすることができました

こういうのは経験してみないとわからないものです、、、

2016年9月17日土曜日

Ruby + pi_piper で RaspberryPi の GPIO を制御してみた

概要

Ruby で GPIO を制御するライブラリに pi_piper というライブラリがあります
今回はそれを使って簡単な L チカをやってみました

環境

  • Raspbian 8.0 (Jessie)
  • RaspberryPi2 TypeB
  • Linux raspberrypi 4.4.11-v7+ #888
  • ruby 2.1.5p273
  • gem 2.2.2
  • pi_piper 1.3.2

Ruby インストール

一応メモしておきます
ruby 自体は apt-get でインストールしました

  • sudo apt-get -y install ruby ruby-dev
  • sudo gem install bundler
  • bundle init
  • vim Gemfile
    • gem “pi_piper”
  • bundle install

配線

17 ピンと GND を使って配線するだけです
抵抗は 1KΩ を使っています

first_pi_piper_circuit.png

スクリプト

  • vim pi_piper.rb
require 'pi_piper'
include PiPiper

pins = [17]
led = 0

pins.each do |pin|
  begin
    File.open("/sys/class/gpio/unexport", "w") { |f| f.write("#{pin}") }
  rescue
    puts "Already unexported: #{pin}"
  end
end

pin = PiPiper::Pin.new(:pin => pins[led], :direction => :out)
pin.on
sleep 1
pin.off

簡単な L チカですが一点ポイントがあります
PiPiper::Pin.new する前に対象の GPIO を unexport する必要があります
で対象の GPIO がすでに unexport された状態で unexport しようとすると Exception が発生するので begin - rescue で囲っています

実行

  • bundle install && sudo bundle exec ruby pi_piper.rb

という感じで実行します
GPIO のファイルに直接内部で触っているので root 権限が必要です

成功すると 1 秒 LED が転送すると思います

最後に

Ruby で pi_piper を使ってみました
pi_piper は Eventmachine を使った GPIO の監視ができるためそれを使えるのがメリットだと思います

例えばタクトスイッチなどボタンを押す処理を loop ではなく Event 処理として扱うことができるようになります

イベント処理も機械があれば触ってみたいと思います

2016年9月16日金曜日

Slack の API を使ってユーザ名からユーザ ID を取得してみた

概要

Slack の API でユーザ回りの操作をするときはユーザ ID (U0123456789 みたいな ID) が必要になります
ブラウザやアプリの Slack 上では Username で mention などのやり取りをしますが、それだと API でユーザを指定することができません
なので、今回は Username からユーザ ID を取得してみました

環境

  • Mac OS X 10.10.5
  • Ruby 2.3.1p112
  • Gem 2.5.1
  • slack-api 1.2.4

事前準備

前回の記事を先行にトークンの取得まで行っておいてください
http://hawksnowlog.blogspot.jp/2016/09/try-slack-rtm-api.html

ユーザ ID を取得するスクリプトの作成

  • vim get_user.rb
if ARGV.length != 1
 exit(1)
end

@token = "xoxp-xxxxxxxxxxx-xxxxxxxxxxx-xxxxxxxxxxx-xxxxxxxxxx"

require 'slack'
Slack.configure {|config| config.token = @token }
client = Slack::Client.new

client.users_list['members'].map{ |v|
  if v['name'] == ARGV[0]
    puts "#{v['id']}"
    break
  end
}

引数にユーザ名を与えてそれに合致する名前があればユーザ ID を表示する感じです

最後に

Slack API でユーザに対する操作をするときは一旦こんな感じのスクリプトや API を使ってユーザ ID を調べてから操作する感じかなと思います

本当はユーザ名で検索できるといいのですが、ちょっとそういった API が見つからなかったので、一覧を取得してそこから検索するようにしました

参考サイト

2016年9月15日木曜日

Slack の Real Time Messaging API を使って Bot 作成

概要

Slack API の一つに Real Time Messaging (RTM) API というものがあります
これを使うとメッセージの受信や送信がリアルタイムでできるようになります
所謂ボットを作成することができます
今回は Ruby を使って実装してみました

環境

  • Mac OS X 10.10.5
  • Ruby 2.3.1p112
  • Gem 2.5.1
  • slack-api 1.2.4

API トークンの取得

まずは Slack API を使うために API をコールするためのトークンを取得します

https://api.slack.com/docs/oauth-test-tokens にアクセスし「Create token」をクリックします
Slack にログインしていないと生成できないのでログインしておきましょう
トークンを作成すると以下のように表示されると思います
slack_api_tested_api.png

そしたらそのすぐ下に API 試すリンクがあるので移動してみましょう
リンクは以下になります
https://api.slack.com/methods/auth.test/test
アクセスした「Test Method」をクリックして取得したトークンが問題ないか確認してみましょう
slack_api_created_token.png

“ok”: true になれば問題ないです

RTM を使ってメッセージを受信する

では取得したトークンを使って RTM API をコールしてみましょう

  • bundle init
  • vim Gemfile
    • gem “slack-api”
  • vim msg_receive.rb
require 'slack'
Slack.configure {|config| config.token = "xoxp-xxxxxxxxxxx-xxxxxxxxxxx-xxxxxxxxxxx-xxxxxxxxxx" }
client = Slack.realtime

client.on :hello do
  puts 'Successfully connected.'
end

client.on :message do |data|
  puts data
end

client.start

実行は

  • bundle install && bundle exec ruby msg_receive.rb

で OK です
成功すると
以下のような感じでコンソールに表示されると思います

Successfully connected.
{"type"=>"message", "channel"=>"C0XXXXXXX", "user"=>"U1XXXXXX", "text"=>"t", "ts"=>"1473922916.000034", "team"=>"T1XXXXXX"}

メッセージを受信できるのは API トークンを発行したユーザが所属しているチャネルのみになります
なので、所属していないチャネルのメッセージは受信できないのでメッセージを受信したいチャネルがあれば JOIN してください

メッセージを送信する

では次にメッセージを送信してみましょう
メッセージの送信は RTM API を使いません
先ほどのコードをちょっと改造しています

  • vim msg_send.rb
user = "@U1XXXXXXX"
@token = "xoxp-xxxxxxxxxxx-xxxxxxxxxxx-xxxxxxxxxxx-xxxxxxxxxx"

require 'slack'
Slack.configure {|config| config.token = @token }
client = Slack.realtime

client.on :hello do
  puts 'Successfully connected.'
end

def post(channel)
  params = {
    :token => @token,
    :channel => channel,
    :username => "ruby-my-bot",
    :text => 'message',
    :icon_url => 'http://blogs.microsoft.co.il/blogs/shayf/WindowsLiveWriter/GettingStartedWithDynamicLanguages_B665/ruby_logo_2.png'
  }
  Slack.chat_postMessage params
end

client.on :message do |data|
  if data['text'].include?("<#{user}>")
    post(data['channel'])
  end
end

client.start

メッセージを受信したときに text フィールドから mention かどうかを判断して、ある user に対する mention であれば Slack に返信するスクリプトになっています

返信するための関数を「post」 として作成しています
今回はメッセージを受信したチャネルに対してそのまま送信します
実体は「Slack.chat_postMessage」で指定したチャネルに対してメッセージを送信することができます

chat_postMessage に指定できるパラメータは他にもたくさんあるので詳しくは以下を参照してください
https://api.slack.com/methods/chat.postMessage

実行して動作確認してみましょう
slack_api_send_ret.png

これで、あるユーザの mention にだけ反応するボットが作成できました

最後に

RTM API を使ってオリジナルのボットを作成してみました
結構簡単にできてビックリしました

Hubot や ruboty も同じようなことをしていると思います
Hubot の場合、Hubot が参加しているチャネルのメッセージのみ受信することができ、Hubot をいろんなチャネルに JOIN させるのが嫌だったという理由もあって今回ボットを自作してみました

次回はこれとデバイスを使ってちょっとインタラクティブなことをしてみたいと思います

参考サイト

2016年9月13日火曜日

Swifter を使って iOS アプリからつぶやいてみた

概要

Swifter は iOS アプリ用の Twitter ライブラリで Twitter API を使ってツイートの取得やつぶやきを行うことができます
公式の Fabric を使う方法もありますが、カジュアルに使いたかったので Swifter を試してみました

環境

  • Mac OS X 10.11.6
  • Xcode 7.3.1 (Swift 2.1)
  • Swifter 1.7

ライブラリのインストール

あらかじめ適当なサンプルプロジェクト (今回は swifter-test )を作成しておいてください

Swifter は残念ながら CocoaPods が使えません
対応してほしいという要望は Issue でいろいろと上がって入るのですが、本記事執筆時の段階 (2016/09/13) ではまだ対応されておりません

なので、ソースをダウンロードして手動で framework をプロジェクトに紐付ける必要があります

まずソースをダウンロードします
https://github.com/mattdonnelly/Swifter/archive/1.7.zip

今回 1.7 というバージョンを使います
最新版に 2.0 というバージョンがあるのですが、Swift 3.0 対応版になっており、Swift 3.0 が使える環境でないとエラーとなるため使えません

ダウンロードしたら解凍しましょう
Swifter-1.7 というフォルダの中に Swifter.xcodeproj があれば OK です

そしたらそのファイルを Xcode にドラッグアンドドロップしてください
以下のような感じになれば OK です
try_swifter_install_lib.png

次に swifter-test を選択します

General -> Embedded Binaries

で「+」ボタンを押しダイアログから SwifteriOS.framework を探し追加してください
以下のようになれば OK です
try_swifter_added_lib.png

同時に Linked Frameworks and Libraries にも framework ファイルが追加されると思います

これでライブラリのインストールは OK です

Twitter アプリの作成

https://apps.twitter.com/
にアクセスしアプリを作成します
アプリを作成するユーザでログインしておいてください

ログインできたらアプリを作成するのですが、どうやら Twitter アカウントに電話番号の登録が完了している状態でないとアプリの新規作成はできないようです
なので、素直に Twitter アカウントに電話番号を設定してください

アプリが作成できたら「Keys And Access Tokens」から

  • Consumer Key (API Key)
  • Consumer Secret (API Secret)

を取得しましょう
また、その下に「Your Access Token」があるので新規でアクセストークンとシークレットアクセストークンも作成しておいてください

  • Access Token
  • Access Token Secret

取得したトークンは Access Level が「Read and write」になっていることも確認してください

サンプルコード

swifter-test プロジェクトにある ViewController.swift を開き viewDidLoad メソッドに以下のコードを記載してください
今回は特に UI 側は作らないのでプロジェクトを実行するだけでつぶやく感じにしたいと思います

override func viewDidLoad() {
    super.viewDidLoad()
    print("start")
    let TWITTER_CONSUMER_KEY = ""
    let TWITTER_CONSUMER_SECRET = ""
    let TWITTER_ACCESS_TOKEN = ""
    let TWITTER_ACCESS_TOKEN_SECRET = ""
    let accessToken = SwifterCredential.OAuthAccessToken(key: TWITTER_ACCESS_TOKEN, secret: TWITTER_ACCESS_TOKEN_SECRET)
    let credential = SwifterCredential(accessToken: accessToken)
    let swifter = Swifter(consumerKey: TWITTER_CONSUMER_KEY, consumerSecret: TWITTER_CONSUMER_SECRET)
    swifter.client.credential = credential
    swifter.postStatusUpdate("swifter-test", inReplyToStatusID: nil, lat: nil, long: nil, placeID: nil, displayCoordinates: nil, trimUser: nil, success: {
        (status) in
        print(status)
    }) {
        (error) in
        print(error)
    }
}

TWITTER_CONSUMER_KEY から TWITTER_ACCESS_TOKEN_SECRET までの定数は Twitter アプリ作成時に取得したトークン情報をそのままコピペしてください

基本的にはつぶやくための認証 (OAuthAccessToken) を実行して、その認証実行を使ってつぶやく (postStatusUpdate) だけです

動作確認

では実行してみましょう
Xcode で Run すれば OK です
成功するとコンソールログにレスポンス情報がだらーっと表示されると思います
また、Twitter 側にもアプリを保持しているアカウントでつぶやきが行われていると思います

UI 側は特に作成していないので、真っ白な画面が表示されるだけだと思います

Tips

認証回りについて

Twitter には様々な認証方式があります
今回は OAuth 認証を使ったのですが、他にも Application-only authentication という認証方式があります
App-only Auth はいわゆる簡易認証みたいなやつで認証に必要な情報あ「Consumer Key」と「Consumer Secret」だけになります

簡単だったらこっちを使えばいいじゃんという話になるのですが、実は App-only Auth を使うとつぶやきをするための権限がもらえません
基本は GET 系の処理だけできます
なので、今回は OAuth 認証を使いました

Swifter の公式サイトの Getting Started が App-only Auth を使った認証になっており、初めそれを使っていたのですがツイートしようとすると Twitter から「credentials do not allow access to this resource.」と怒られ全然ツイートできませんでした
もしかするとこの辺りの権限や認証方法回りは Twitter API のはまりポイントかもしれません

最後に

これで Swifter を使って iOS アプリからつぶやきができるようになりました
ライブラリの追加が少し面倒なだけで、そこを我慢すれば Fabric よりかは簡単に使えるかなと思いました

ただ、CocoaPods 対応していないのでライブラリのソースコード一式をどこかで管理しないとしけないのがちょっとつらい点ではあります
あとは git submodule を使うとかでしょうか

参考サイト