やりたいこと
写真はよくスマホで取るので溜まっていくけど、数が増えてくると過去の写真って埋もれていくよね. botが適当な写真を選んで送ってくれたりすると楽しいのでは.
ということで、Googleフォトの特定のアルバムからランダムに写真を選んで、LINEのトークに送信する、という機能をbotに実装した. ルーム内の発言に反応して送ったり、定期的にルームに投稿したりする.
準備
- LINE Messaging APIを使える状態にする
- 公式としてはこちら https://developers.line.me/messaging-api/getting-started
- こちらのブログ LINEのMessaging APIを使うメモ:事前知識と登録編 に日本語で親切に書いてある
- LINEのトークとは関係なく、一方的に写真を送るならwebhookは不要
- GoogleのAPIを使える状態にする
- https://console.developers.google.com から、プロジェクト登録、認証情報取得をする
- http://www.yoheim.net/blog.php?q=20160411 あたりを参考に
- GoogleフォトのAPIは、特に有効にしなくても使える (APIの一覧に出てこない)
- Oauth2 access tokenの取得は http://qiita.com/giiko_/items/b0b2ff41dfb0a62d628b を参考にした
実装
rubyでやる. LINE, Googleともに色々な言語でライブラリが出ているので、好きなものを使えば良いと思う.
Googleフォトからランダムに写真を取得
Picasa Web Album Data API を使う. rubyから使うので、https://github.com/morgoth/picasa を使用した.
こんな感じ. get_random_photo_url
を呼ぶと、アルバム中写真から、どれか一枚のURLが返る.
require 'signet/oauth_2/client'
require 'picasa'
require 'dotenv'
Dotenv.load
class PicasaClient
def initialize
@client = nil
end
def client
@client ||= Picasa::Client.new(user_id: ENV['GOOGLE_USER_ID'], access_token: access_token)
end
def access_token
signet = Signet::OAuth2::Client.new(
client_id: ENV['GOOGLE_CLIENT_ID'],
client_secret: ENV['GOOGLE_CLIENT_SECRET'],
token_credential_uri: "https://www.googleapis.com/oauth2/v3/token",
refresh_token: ENV['GOOGLE_REFRESH_TOKEN']
)
signet.refresh!
# Use access token with picasa gem
puts "access_token:" + signet.access_token
signet.access_token
end
def get_random_photo_url
album = client.album.list.entries.find{ |a| a.title == ENV['GOOGLE_PHOTO_ALBUM_NAME'] }
photo = client.album.show(album.id).entries.sample
photo.content.src
end
end
LINE Botから画像を送る
一方的に写真を送るようなコマンドを作ってみる. こんな感じ. ENV['LINE_SEND_TARGET']
の部分は、送信先のユーザまたはグループのID. 前者は"U...", 後者は"C..."みたいな形をしている. (これはどこから取るのが楽なんだろう. 自分は、webhook用に立てたサーバで、受信したイベントを出力して取得した)
require 'line/bot'
require 'dotenv'
Dotenv.load
def line_send_image(target, image_url)
line_client = Line::Bot::Client.new { |config|
config.channel_secret = ENV['LINE_CHANNEL_SECRET']
config.channel_token = ENV['LINE_CHANNEL_TOKEN']
}
message = {
type: "image",
originalContentUrl: image_url,
previewImageUrl: image_url
}
line_client.push_message(target, message)
end
log = Logger.new(STDOUT) # !> assigned but unused variable - log
picasa = PicasaClient.new
line = LineClient.new
photo_url = picasa.get_random_photo_url
res = line.send_image(ENV['LINE_SEND_TARGET'], photo_url)
会話に反応して画像を送る
Botのwebhook URLで指定したURLにWebサーバを立てることになる. ここでは、トーク内で'p' (photoのこと) と発言されたら、上と同じ要領でランダムな画像をピックアップして返すようにする.
require "sinatra/base"
require 'line/bot'
require 'dotenv'
module MyBotserver
class Server < Sinatra::Base
Dotenv.load
helpers do
def client
@client ||= Line::Bot::Client.new { |config|
config.channel_secret = ENV["LINE_CHANNEL_SECRET"]
config.channel_token = ENV["LINE_CHANNEL_TOKEN"]
}
end
end
post '/line' do
request.body.rewind
body = request.body.read
events = client.parse_events_from(body)
events.each do |event|
case event
when Line::Bot::Event::Message
when Line::Bot::Event::MessageType::Text
message = {}
case event.message['text']
when /^p$/
logger.info "Sending photo"
picasa = PicasaClient.new
photo_url = picasa.get_random_photo_url
message = {
type: 'image',
originalContentUrl: photo_url,
previewImageUrl: photo_url
}
res = client.reply_message(event['replyToken'], message)
logger.warn "Message send error: " + res.body unless res.is_a?(Net::HTTPOK)
end
unless message.empty?
logger.info "Sending message #{message}"
client.reply_message(event['replyToken'], message)
end
end
end
end
end
end
まとめ
LINE Messaging APIを使って、Googleフォトからランダムな写真をLINEトークに送信する機能を実装してみた. 自分は、cronで毎朝一枚送信、あとはリクエストしたら適宜送ってくれるような感じにして使っている. なかなか楽しい.
子供の昔の写真を送るとか、空腹な時間を狙って飯画像を送るとか、遊ぶと良いと思う.