なぜこんなことをするのか
Typetalkには「いいね」つける機能があります。
しかしTypetalkには「いいね」を集計するツールがありません。
仕方ないのでapiを叩いて、調べることにしました。
ここで問題が発生しました。
Typetalkのapiは、トピック(掲示板でいうスレッド)の中の投稿の情報が
最新から200件のみしか取得できません。
従って、全件の情報をアプリケーションのデータベースに保持しておきたい場合
定期的にバッチ処理をして、データベースに記録しておきます。
その上で「いいね」数をカウントしてデータベースに格納します。
バッチ処理にはrakeファイルを使う
以下がrakeファイルのソースコードです。
# encoding: utf-8
namespace :post do
desc "投稿データを取得する。"
# $ rake post:update
# :environmentは超大事。ないとモデルにアクセスできない
task :update => :environment do
topics = Topic.all
# httpインスタンスの生成
http = Net::HTTP.new('typetalk.in', 443)
http.use_ssl = true
# Typetalkのトークンの代入
client_id = ENV['CLIENT_ID']
client_secret = ENV['CLIENT_SECRET']
# アクセストークンの発行
res = http.post(
'/oauth2/access_token',
"client_id=#{client_id}&client_secret=#{client_secret}&grant_type=client_credentials&scope=topic.read"
)
if res.code != '200'
next
end
json = JSON.parse(res.body)
access_token = json['access_token']
topics.each do |topic|
req = Net::HTTP::Get.new("/api/v1/topics/#{topic.topicId}?count=200&direction=backward")
req['Authorization'] = "Bearer #{access_token}"
res = http.request(req)
if res.code != '200'
next
end
res= JSON.parse(res.body)
res['posts'].each do |post|
if Post.where(post_id: post['id']).exists? then
@post = Post.find_by(post_id: post['id'])
if post['account']['isBot'] == true
@post.destroy if @post
next
end
@post.like = post['likes'].count
else
if post['account']['isBot'] == true
next
end
@post = Post.new
@post.topic = topic
@post.post_id = post['id'].to_s
@post.like = post['likes'].count
p "UTC時間"
p post['createdAt']
p "JST時間"
p post['createdAt'].in_time_zone
@post.posted = Time.parse(post['createdAt']).in_time_zone
end
@post.save
end
topic.updated_at = Time.now()
topic.save
end
end
end
解説
トピック情報を記録するTopic
テーブル
投稿情報を記録するPost
テーブル
の2つを使用して処理をしています。
まず前準備として、Topic
テーブルにTypetalkから取得できるトピックのIDを入れてください。
topicオブジェクトをeachメソッドで処理して、各トピックごとに先頭200件の投稿情報を取得します。
apiのcount
パラメーターは最大値200にしておきます。
ここらへんは下記のapiのリファレンスを参照ください。
投稿メッセージリストの取得
topics.each do |topic|
req = Net::HTTP::Get.new("/api/v1/topics/#{topic.topicId}?count=200&direction=backward")
req['Authorization'] = "Bearer #{access_token}"
res = http.request(req)
返却されたjsonは、posts単位の情報が、先ほどのcount
パラメーターで設定した数の情報が返却されます。
postのIDが登録済みであれば、update処理、存在しなければcreate処理を行います。
res['posts'].each do |post|
if Post.where(post_id: post['id']).exists? then
各投稿の['account']['isBot']には、botか人間かの判定が格納されているので、
botは必要がなければ、データベースにinsertしないようにしましょう。
if post['account']['isBot'] == true
['likes]は「いいね」をしてくれたアカウントの情報が配列で入っているので、count
メソッドを使用して「いいね」数を計測しましょう。
@post.like = post['likes'].count
このrakeファイルの実行コマンドは下記の通り
このコマンドをジョブスケジュラーに登録して、定期実行する
これでTypetalkの全発言を補足することができる。
自分は、Herokuを利用しているのでHeroku Scheduler
を利用している。
$ rake post:update
最後に
毎度のことながら、Typetalkのapi関連の記事は需要があるのだろうか
一応、備忘録のために残しておこう。