完成イメージ
完成コード
require 'slack-ruby-client'
def send_data(info)
Slack.configure do |config|
# APIトークンを設定
config.token = "xoxb-xxxxxxx-xxxxxxxx-xxxxxxxxxxxxx"
end
# APIクライアントを生成
client = Slack::Web::Client.new
# #チャンネル名 of @ユーザー名
channel = '投稿先のチャンネル名'
# メッセージ
text = info
# メッセージの送信
client.chat_postMessage(channel: '#slack_test', text: text, as_user: true)
end
require "rexml/document"
require "open-uri"
def get_programs(span)
url = "http://cal.syoboi.jp/cal_chk.php?days=#{span}" # span: どれくらい先まで取得するかの期間を日にちで指定
xml = REXML::Document.new(URI.open(url).read)
programs = []
xml.elements.each("syobocal/ProgItems/ProgItem") { |item|
start_time = Time.parse(item.attribute("StTime").to_s).hour
night_time = 20
midnigth_time = 4
if night_time < start_time || start_time < midnigth_time
programs << {
title: item.attribute("Title").to_s, # タイトル
sub_title: item.attribute("SubTitle").to_s, # サブタイトル
st_time: Time.parse(item.attribute("StTime").to_s), # 開始時刻
ed_time: Time.parse(item.attribute("EdTime").to_s), # 終了時刻
ch_name: item.attribute("ChName").to_s, # チャンネル名
ch_id: item.attribute("ChID").to_s.to_i # チャンネルID
}
end
}
programs.select{ |program|
# データの取得期間を現在時刻から翌日の朝5時までに絞る
st = Time.now
day = Time.now.hour < 5 ? Date.today : Date.today + 1
ed = Time.new(day.year, day.month, day.day, 5)
# 自分が住んでいる地域で放送されているチャンネルのIDを選択
# チャンネルIDの調べ方: http://cal.syoboi.jp/mng?Action=ShowChList
ch_ids = [
1, # NHK総合
3, # フジテレビ
4, # 日本テレビ
5, # TBS
6, # テレビ朝日
7, # テレビ東京
19, # TOKYO MX
]
st < program[:st_time] and program[:st_time] < ed and ch_ids.include?(program[:ch_id])
}.sort_by{ |program| program[:st_time] }
end
require "./slack.rb"
require "./anime.rb"
def format_time(time)
ymd = time.to_s.split(" ")[0]
hms = time.to_s.split(" ")[1]
"#{ymd} #{hms}"
end
programs = get_programs(1)
info = ""
programs.each do |program|
info += <<~TEXT
開始時刻:#{format_time(program[:st_time])}
チャンネル:#{program[:ch_name]}
タイトル:#{program[:title]}
--------------------------------------------------
TEXT
end
send_data(info)
実行環境
Ruby : 2.7.3
概要手順
- slackのアプリを作る
- Rubyで
しょぼいカレンダー
のデータを受信するコードを作成 - Rubyでslackにメッセージを送る
- 2で取得したデータをslackに送信するコードを作る
詳細手順
1. slackアプリを作る
アプリの作り方はこちらのわかりやすい記事をご参照ください。(割愛)
@kou_pg_0131 さん
引用元: Slack APIを使用してメッセージを送信する
2. Rubyでしょぼいカレンダーのデータを受信する
今回はこちらの記事を参考にしていきます。
@kazama1209 さん
引用元:【Ruby】今夜放送予定のアニメ番組一覧を取得してGoogleカレンダーに書き込む
2-1 しょぼいカレンダーから番組を受信する
コードの内容はほぼお借りしてますので違う点はGoogleカレンダーに追加する部分が省かれているくらいです
@kazama1209 さまに感謝です。
require "rexml/document"
require "open-uri"
# しょぼいカレンダーから番組を取得する
def get_programs(span)
url = "http://cal.syoboi.jp/cal_chk.php?days=#{span}" # span: どれくらい先まで取得するかの期間を日にちで指定
xml = REXML::Document.new(open(url).read)
programs = []
xml.elements.each("syobocal/ProgItems/ProgItem") { |item|
programs << {
title: item.attribute("Title").to_s, # タイトル
sub_title: item.attribute("SubTitle").to_s, # サブタイトル
st_time: Time.parse(item.attribute("StTime").to_s), # 開始時刻
ed_time: Time.parse(item.attribute("EdTime").to_s), # 終了時刻
ch_name: item.attribute("ChName").to_s, # チャンネル名
ch_id: item.attribute("ChID").to_s.to_i # チャンネルID
}
}
programs.select{ |program|
# データの取得期間を現在時刻から翌日の朝5時までに絞る
st = Time.now
day = Time.now.hour < 5 ? Date.today : Date.today + 1
ed = Time.new(day.year, day.month, day.day, 5)
# 自分が住んでいる地域で放送されているチャンネルのIDを選択
# チャンネルIDの調べ方: http://cal.syoboi.jp/mng?Action=ShowChList
ch_ids = [
1, # NHK総合
2, # NHK Eテレ
3, # フジテレビ
4, # 日本テレビ
5, # TBS
6, # テレビ朝日
7, # テレビ東京
19, # TOKYO MX
]
st < program[:st_time] and program[:st_time] < ed and ch_ids.include?(program[:ch_id])
}.sort_by{ |program| program[:st_time] }
end
# 日時をISO 8601規格に整形する
def format_time(time)
ymd = time.to_s.split(" ")[0]
hms = time.to_s.split(" ")[1]
"#{ymd}T#{hms}+09:00"
end
# 番組を取得してターミナルに出力する
programs = get_programs(1)
programs.each do |program|
puts program[:title]
puts program[:sub_title]
puts program[:ch_name]
puts format_time(program[:st_time])
puts format_time(program[:ed_time])
end
最後のputs
連打は後で改善しますのでとりあえずターミナルで実行すると下記のように出力されると思います
このときwarning: calling URI.open via Kernel#open is deprecated, call URI.open directly or use URI#open
と出ますが後で対処しますので一旦放置します。
実行結果のイメージ
無職転生~異世界行ったら本気だす~
無職転生
TOKYO MX
2021-07-12T00:00:00+09:00
2021-07-12T00:30:00+09:00
探偵はもう、死んでいる。
今も、ずっと、憶えてる
TOKYO MX
2021-07-12T00:30:00+09:00
2021-07-12T01:00:00+09:00
指先から本気の熱情2-恋人は消防士-
だから、しっかり涼を充電しとく。
TOKYO MX
2021-07-12T01:00:00+09:00
2021-07-12T01:05:00+09:00
東京リベンジャーズ
Break up
テレビ東京
2021-07-12T01:35:00+09:00
2021-07-12T02:05:00+09:00
不滅のあなたへ
フシの旅路
NHK総合
2021-07-12T01:35:00+09:00
2021-07-12T02:00:00+09:00
闇芝居(第9期)
鼠嫁ぎ
テレビ東京
2021-07-12T03:05:00+09:00
2021-07-12T03:10:00+09:00
ちょっと見にくいですが受信はできました!
後で色々と調整するので、まずは次に行きます!
Rubyからslackにメッセージを送信する
3-1 slack-ruby-clientをインストール
下記のコマンドかGemfile
を作り追加する
$ gem install slack-ruby-client
gem 'slack-ruby-client'
3-2 slack-ruby-clientの動作確認
※必須ではないので飛ばしても大丈夫です。
公式ドキュメントを参考に行います。
今回はgithubに上げる予定はないので.env
は使わない方向でやります
# ENV['SLACK_API_TOKEN']の部分に自分のトークン(xoxb-~~~~)を入れる
Slack.configure do |config|
config.token = ENV['SLACK_API_TOKEN']
end
client = Slack::Web::Client.new
client.auth_test
上記を記載したファイルを実行
config.token = xxxx
の部分をミスるとエラーが出ますが成功時は何も出ません。
何も出ないと言う事は疎通可能となります。
3-3 Rubyからslackにメッセージを送信する
Rubyからslackにメッセージを送るテストをします
require 'slack-ruby-client'
Slack.configure do |config|
# APIトークンを入れる
config.token = 'xoxb-xxxxxxxxxxxx-xxxxxxxxxxxx-xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
end
# APIクライアント生成
client = Slack::Web::Client.new
# #チャンネル名 か @ユーザー名 今回はチャンネル名
channel = '#投稿するチャンネル名'
# メッセージの送信
client.chat_postMessage(channel: '#general', text: 'Hello World', as_user: true)
# メッセージ部分を動的にする場合
text = '任意のメッセージ'
client.chat_postMessage(channel: '#general', text: text, as_user: true)
ファイルを実行するとslackにHello World
と表示されているはずです。
これでRubyからslackにメッセージの送信が可能になりました。
受信したデータをslackに送信する
大まかな流れとしては
- まず役割毎にファイルを分割する
- しょぼいカレンダーがアニメのデータを取得する
- 取得したデータを
client.chat_postMessage(~~, text: ここに入れたい)
同じようなコードを繰り返すことになるので3の部分だけの振り返りだけします。
上記を終わらせると最初の完成コードになるので参考にどうぞ。(1部分+αしてるので全く同じではないですが要点は同様です)
4-1 slackで送るメッセージを動的にしたい
- 今回の場合はアニメ一覧が日毎に変わるので
client.chat_postMessage(~~, text: アニメ一覧情報)
を入れたい - アニメ一覧情報の部分を変数で持てれば良い
- アニメ一覧を取得した際の結果を
変数x
に格納する - その
変数x
をtext: x
部分に持って来れれば実現できる
上記を実装すると完成コードの一部変更になるが
require 'slack-ruby-client'
def send_data(info)
Slack.configure do |config|
# APIトークンを設定
config.token = "xoxb-xxxxxxx-xxxxxxxx-xxxxxxxxxxxxx"
end
# APIクライアントを生成
client = Slack::Web::Client.new
# #チャンネル名 of @ユーザー名
channel = '投稿先のチャンネル名'
# メッセージ
text = info # アニメの情報一覧を入れる
# メッセージの送信
client.chat_postMessage(channel: '#slack_test', text: text, as_user: true)
end
require "rexml/document"
require "open-uri"
# しょぼいカレンダーから番組を取得する
def get_programs(span)
url = "http://cal.syoboi.jp/cal_chk.php?days=#{span}" # span: どれくらい先まで取得するかの期間を日にちで指定
xml = REXML::Document.new(open(url).read)
programs = []
xml.elements.each("syobocal/ProgItems/ProgItem") { |item|
programs << {
title: item.attribute("Title").to_s, # タイトル
sub_title: item.attribute("SubTitle").to_s, # サブタイトル
st_time: Time.parse(item.attribute("StTime").to_s), # 開始時刻
ed_time: Time.parse(item.attribute("EdTime").to_s), # 終了時刻
ch_name: item.attribute("ChName").to_s, # チャンネル名
ch_id: item.attribute("ChID").to_s.to_i # チャンネルID
}
}
programs.select{ |program|
# データの取得期間を現在時刻から翌日の朝5時までに絞る
st = Time.now
day = Time.now.hour < 5 ? Date.today : Date.today + 1
ed = Time.new(day.year, day.month, day.day, 5)
# 自分が住んでいる地域で放送されているチャンネルのIDを選択
# チャンネルIDの調べ方: http://cal.syoboi.jp/mng?Action=ShowChList
ch_ids = [
1, # NHK総合
2, # NHK Eテレ
3, # フジテレビ
4, # 日本テレビ
5, # TBS
6, # テレビ朝日
7, # テレビ東京
19, # TOKYO MX
]
st < program[:st_time] and program[:st_time] < ed and ch_ids.include?(program[:ch_id])
}.sort_by{ |program| program[:st_time] }
end
require "./slack.rb"
require "./anime.rb"
def format_time(time)
ymd = time.to_s.split(" ")[0]
hms = time.to_s.split(" ")[1]
"#{ymd} #{hms}+09:00"
end
programs = get_programs(1)
info = ""
programs.each do |program|
info += <<~TEXT
program[:title]
program[:sub_title]
program[:ch_name]
format_time(program[:st_time])
format_time(program[:ed_time])
TEXT
end
send_data(info)
これでmain.rb
を実行すると先ほどのターミナルと同様の情報がslackに送信されます!
しかし、これだけでは少し使いづらいので出来ないなりに改善してみます!
改良点
- slackで送られてくるメッセージをもう少し見やすくしたい(時間表示も含めて)
- 夕方のアニメは見ないので夜のアニメだけに限定したい
- 実行には影響ないけどターミナルに出るwarningを消したい
それぞれ対処していきます。
1. 送られてくるメッセージを見やすくする
現状のままだとデータが剥き出しで送られてくるので欲しい情報の選定と表示方法を変えようと思います
def format_time(time)
ymd = time.to_s.split(" ")[0]
hms = time.to_s.split(" ")[1]
"#{ymd} #{hms}" # {hms}の後の[ +09:00 ]があると見にくいので削除
end
programs = get_programs(1)
info = ""
programs.each do |program|
# ヒアドキュメント内の情報を自分が欲しいものだけにして区切りの線を引くことで対応しました
info += <<~TEXT
開始時刻:#{format_time(program[:st_time])}
チャンネル:#{program[:ch_name]}
タイトル:#{program[:title]}
--------------------------------------------------
TEXT
end
2. 夜のアニメだけに限定する
僕は朝や夕方のアニメは見ないので夜の一定の時間のものだけに限定しました。
あと初期の段階ではNHK総合も含まれるので不要なデータが増えるので調整します
require "rexml/document"
require "open-uri"
def get_programs(span)
url = "http://cal.syoboi.jp/cal_chk.php?days=#{span}" # span: どれくらい先まで取得するかの期間を日にちで指定
xml = REXML::Document.new(URI.open(url).read)
programs = []
xml.elements.each("syobocal/ProgItems/ProgItem") { |item|
start_time = Time.parse(item.attribute("StTime").to_s).hour # 放送開始時刻
night_time = 20 # 20時
midnigth_time = 4 # 深夜4時
# 20時以降に放送か深夜4時以内に開始しているアニメに限定
if night_time < start_time || start_time < midnigth_time
programs << {
title: item.attribute("Title").to_s, # タイトル
sub_title: item.attribute("SubTitle").to_s, # サブタイトル
st_time: Time.parse(item.attribute("StTime").to_s), # 開始時刻
ed_time: Time.parse(item.attribute("EdTime").to_s), # 終了時刻
ch_name: item.attribute("ChName").to_s, # チャンネル名
ch_id: item.attribute("ChID").to_s.to_i # チャンネルID
}
end
}
programs.select{ |program|
# データの取得期間を現在時刻から翌日の朝5時までに絞る
st = Time.now
day = Time.now.hour < 5 ? Date.today : Date.today + 1
ed = Time.new(day.year, day.month, day.day, 5)
# 自分が住んでいる地域で放送されているチャンネルのIDを選択
# チャンネルIDの調べ方: http://cal.syoboi.jp/mng?Action=ShowChList
ch_ids = [
1, # NHK総合
# 2, NHK Eテレを削除
3, # フジテレビ
4, # 日本テレビ
5, # TBS
6, # テレビ朝日
7, # テレビ東京
19, # TOKYO MX
]
st < program[:st_time] and program[:st_time] < ed and ch_ids.include?(program[:ch_id])
}.sort_by{ |program| program[:st_time] }
end
3. ターミナルに出るwarningを消す
Ruby 2.7以降にKernelモジュールのopenメソッドでURLを開くと警告が出るそうです。
詳しくはこちらをどうぞ
def get_programs(span)
url = "http://cal.syoboi.jp/cal_chk.php?days=#{span}" # span: どれくらい先まで取得するかの期間を日にちで指定
# xml = REXML::Document.new(open(url).read) 下記のように変更する
xml = REXML::Document.new(URI.open(url).read)
programs = []
.... 省略
end
まとめ
これで冒頭に載せたイメージのものができると思います。
自分で初めてAPIを触って自分好みに欲しい情報や機能を付けられるのは頭が一筋縄ではいきませんが面白かったです!
今回は自分で記事を書く事への抵抗を無くす練習でもあるので、メソッドやクラスの命名方法など荒いと思いますがご容赦ください。