RubyからYoutubeAPIを使ってクラロワ動画を概要欄で絞り込んでみた

はじめに

私はクラッシュロワイヤル(通称クラロワ)というスマホゲームでよく遊んでいます。クラロワは8枚のカードでデッキを組んで相手と戦うカードゲームです。

clashroyale.com

そのクラロワのスキルアップのために、 YouTube で 『Stats Royal』というチャンネルの動画をよく観ています。クラロワの試合の動画がひたすらアップされているチャンネルです。

www.youtube.com

私はクラロワで『ゴーレム』というカードが好きなので、『Stats Royal』の動画のうちゴーレムが使われている試合の動画だけを観たいなと思いました。

f:id:wai-doi:20211020000034p:plain
ゴーレム

動画のサムネイルには一応デッキの画像が載っていますが、ひとつひとつ『ゴーレム』の動画を探していくのは疲れるため辛いです。 また、YouTubeで「Stats Royale ゴーレム」などと検索しても、他の動画が出てしまったりしてうまく絞り込むことができませんでした。

ただし、動画の概要欄には親切にも、その動画の試合に使われているデッキのカードが載っていました!

f:id:wai-doi:20211020002600p:plain

概要欄に情報があるなら、YouTube API を使えばうまく絞り込めそうだなと思いました。

YouTube APIを使ってみた

そこで YouTube API を使って『Stats Royal』チャンネルの内、『ゴーレム』が利用されている動画だけ検索してみることにしました。

チャンネルID

まず必要になるのが 『Stats Royale』 のチャンネルIDです。チャンネルIDはチャンネルページのURLのパスの末尾になります。

https://www.youtube.com/channel/UC698QxCg2KVVWh4G6NQLX_wUC698QxCg2KVVWh4G6NQLX_w の部分です。

APIキーの作成

YoutubeAPI を利用するには APIキーを作成しないといけません。 API キーの作り方などはこちらの記事を参考にしました。

qiita.com

利用した Gem

RubyからAPIを楽に利用するため google-api-ruby-client というGemを用いました。

github.com

Gemfile には以下の様に書きました。

gem 'google-api-client'

実際に書いたスクリプト

YouTube API から取得できるデータはこちらのドキュメントを参考にしました。

developers.google.cn

処理の手順は以下になります。

  1. YouTubeService オブジェクトを作る。
  2. チャンネルIDを使って「Channels: list」のAPIを叩いて、チャンネルのアップロード動画のプレイリストIDを取得する。
  3. 取得したプレイリストIDを使って「PlaylistItems: list」のAPIを叩いて、アップロードリスト内の動画の概要欄と動画IDを取得する。
  4. 概要欄のテキストから、デッキに『ゴーレム』が入っている動画だけに絞り込む。
  5. 絞り込んだ動画の動画IDから動画のURLを作成してHTMLに埋め込む。

以下が実際に書いた Ruby スクリプトです。

require 'google/apis/youtube_v3'

# `YouTubeService` オブジェクトを作ります
youtube = Google::Apis::YoutubeV3::YouTubeService.new
youtube.key = "API Key"

# 『Stats Royale』のチャンネルIDです
channnel_id = "UC698QxCg2KVVWh4G6NQLX_w"

# チャンネルIDを使って「Channels: list」のAPIを叩いて、チャンネルのアップロード動画のプレイリストIDを取得します
response = youtube.list_channels('contentDetails', id: channnel_id)
uploads_playlist_id = response.items.first.content_details.related_playlists.uploads


# 取得したプレイリストIDを使って「PlaylistItems: list」のAPIを叩いて、アップロードリスト内の動画の概要欄と動画IDを取得します
# 10 * 50件の動画の情報を取得する
uploaded_video_items = []
next_page_token = nil
10.times do
  response = youtube.list_playlist_items('snippet', playlist_id: uploads_playlist_id, max_results: 50, page_token: next_page_token)
  uploaded_video_items += response.items
  puts "#{uploaded_video_items.size} 件取得"
  next_page_token = response.next_page_token
  break if next_page_token.nil?
  sleep 0.1
end


# 概要欄のテキストから、デッキに『ゴーレム』が入っている動画だけに絞り込みます
golem_video_items = uploaded_video_items
  .select { |item| item.snippet.description.scan(/deck:\n(.+)\n/).flatten.any? { |m| m.split(", ").include?("Golem")} }

# 埋め込み式の動画タグをHTMLにして出力します
div_tags = golem_video_items.map do |item|
  published_at = Time.parse(item.snippet.published_at).localtime.strftime('%F %T')
  id = item.snippet.resource_id.video_id

  <<~DIV
    <div style="margin-bottom: 100px">
      <p> #{published_at} </p>
      <iframe width="1120" height="630" src="https://www.youtube.com/embed/#{id}" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
    </div>
  DIV
end.join("\n")


html = <<~HTML
  <!DOCTYPE html>
  <html lang="ja">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
  </head>
  <body>
    #{div_tags}
  </body>
  </html>
HTML

File.write("output.html", html)

出力したHTML

スクリプトで最後に出力されたHTMLです。 『ゴーレム』の試合の動画ばかりが並べることができ、目的を達成することができました。

f:id:wai-doi:20211020011128p:plain
出力したHTML

おわりに

YouTubeAPI は初めて触ったので利用の仕方など勉強になりました。趣味のゲームを対象にしましたが、技術で楽にすることができたのでよかったです。

今回はRubyスクリプトから使ってみましたが、今後はRailsアプリなどにして動画検索をしやすくしてみたいです。

FactoryBot 6.0 から enum の traits が自動生成されるようになった

はじめに

2020 年 6 月にリリースされていた FactoryBot バージョン 6.0.0 から ActiveModel の enum の列挙子ごとに traits が自動で作られるようになっていました。これについて技術記事があまりなかったので書いてみることにしました。

例えば以下のような status という enum のカラムをもつ Task モデルがあるとします。

# app/models/task.rb

class Task < ActiveRecord::Base
  enum status: {queued: 0, started: 1, finished: 2}
end

v6.0以前では traits を書く必要があった

6.0 以前では factory の定義に自分で traits を書く必要があるので面倒です。

# spec/factories/tasks.rb

FactoryBot.define do
  factory :task do
    trait :queued do
      status { :queued }
    end

    trait :started do
      status { :started }
    end

    trait :finished do
      status { :finished }
    end
  end
end

v6.0 以降では traits を書く必要がなくなった

Added: automatic definition of traits for Active Record enum attributes, enabled by default

github.com

6.0 以降で factory の定義だけを書きます。

FactoryBot.define do
  factory :task do
  end
end

これだけで enum の traits が使えるようになります。

task = FactoryBot.build(:task, :started)
task.status
#=> "started"

詳しくは GETTING_STARTEDPRをご覧ください。

おわりに

とても便利な機能なのでまだ FactoryBot 6.0 未満を使っている方はバージョンアップすることをオススメします。

Ruby 3.0 で Hash のキーを別のキーに置換する方法

例えば {foo: 1, bar: 2, baz: 3} という Hash のキーのうち、 :baz:foobar に置換して {foo: 1, bar: 2, foobar: 3} にしたいとします。

Ruby 2.7 以前の場合

Ruby 2.7 以前だと Hash#transform_keys のブロックの中で条件分岐させたりと少し面倒です。

# 2.7.2

hash = {foo: 1, bar: 2, baz: 3}

hash.transform_keys { |key| key == :baz ? :foobar : key }
#=> {:foo=>1, :bar=>2, :foobar=>3}

Hash#transform_keys (Ruby 3.0.0 リファレンスマニュアル)

他には Hash#delete を使って元の Hash を破壊してしまう方法もあります。

# 2.7.2

hash = {foo: 1, bar: 2, baz: 3}

hash[:foobar] = hash.delete(:baz)
hash
#=> {:foo=>1, :bar=>2, :foobar=>3}

Hash#delete (Ruby 3.0.0 リファレンスマニュアル)

Ruby 3.0 の場合

Ruby 3.0 では Hash#transform_keys の引数に {置換前のキー => 置換後のキー} の Hash を渡すことで簡単に置換できます。

# 3.0.0-preview2

hash = {foo: 1, bar: 2, baz: 3}

hash.transform_keys(baz: :foobar)
#=> {:foo=>1, :bar=>2, :foobar=>3}

参考

bugs.ruby-lang.org

stackoverflow.com

Ruby で使われる OpenSSL のバージョンを更新する

先日 OpenSSL 1.1.1i がリリースされ、それを反映した ruby-build のバージョンがリリースされていました。

その際にローカルにインストールしている Ruby で使われる OpenSSL のバージョンを最新に更新したので、その方法を書きます。これがベストかわかりませんが自分はこうしたという方法です。

試した環境

MacOS 10.15.7

Rubyruby-build + rbenv で管理しています。 今回は Ruby 2.7.2 を使います。

方法

方法は単純でただ Ruby を再インストールしただけです。

まず最初の状態です。以下のようにすることで OpenSSL 1.1.1h が使われてることが確認できます。

$ ruby -r openssl -e 'p OpenSSL::OPENSSL_LIBRARY_VERSION'
"OpenSSL 1.1.1h  22 Sep 2020"

次に最新の ruby-build を取得、さらに更新したい Ruby をアンインストールして再度インストールします。

$ brew upgrade ruby-build
$ rbenv uninstall 2.7.2
$ rbenv install 2.7.2

再度確認すると OpenSSL 1.1.1i (2020/12/10 時点で最新バージョン)が使われています!

$ ruby -r openssl -e 'p OpenSSL::OPENSSL_LIBRARY_VERSION'
"OpenSSL 1.1.1i  8 Dec 2020"

他の Ruby バージョンも更新するには、また同じように Ruby を再インストールする必要があると思います。

参考

blog.manabusakai.com

masutaka.net

ターミナルと VS Code から GitHub のリポジトリのページをすぐに開く方法

開発をしていると、PR を開きたかったり PR のレビューをしたいなどで、GitHubリポジトリのページをブラウザで開きたいことが多々あります。 そんな時にすぐに開くことができる方法を2つ紹介します。

※この記事はMacの開発環境を想定しています。

ターミナルから開く方法

GitHub が公式に開発している gh コマンドを使うのが便利です。

github.com

Mac であれば Homebrew から簡単にインストールして使えます。

$ brew install gh

gh コマンドには GitHub のページを開くコマンドが提供されています。

gh repo | GitHub CLI

cd で対象のリポジトリディレクトリに移動して以下のコマンドを実行してください。すると GitHubリポジトリのページが自動的にブラウザで開きます。

$ gh repo view --web

私は頻繁に使うのでエイリアスに登録しています。

alias repo='gh repo view --web'

gh にはこれ以外にも便利なコマンドがあるようなので使ってみます。

VS Code から開く方法

拡張機能GitLens を使います。 GitLens はコードの blame を見たりするのに便利で使っているのですが、他の機能もあります。

marketplace.visualstudio.com

インストールしたら Command + Shift + p でコマンドパレットを開いて、GitLens: Open Respository on Remote のコマンドを検索し実行してください。

f:id:wai-doi:20201207233648p:plain

するとブラウザが起動し自動的にリポジトリのページが開いてくれます。これを頻繁に使うのであればショートカットも設定するのもよいでしょう。