プロフィール

arismmn timeline blog

← ブログ一覧に戻る

タイムライン投稿にYouTube動画検索連携機能を実装した

機能実装AstroCloudflareAPIセキュリティ

何をやったか

つぶやき投稿フォームから YouTube 動画を検索し、「視聴した動画」としてつぶやきに添付できる機能を追加した。

これまでは YouTube の URL をテキストに貼り付けると自動で動画プレーヤーが埋め込まれる機能があったが、今回はそれに加えて「どの動画を視聴したか」をメタデータとして保存・表示できる仕組みを作った。


なぜ作ったか

ゲーム情報・アニメ情報と同じように、「見た動画」をつぶやきに添付したいという需要があった。テキストに URL を貼るだけでも動画は埋め込まれるが、タイトルやチャンネル名の情報が失われてしまう。動画メタデータを保存することで、後から「何を視聴したのか」が一覧からも分かるようになる。


実装の全体像

1. データベースの拡張

既存の notes テーブルに youtube_info カラムを追加した。ゲーム情報・アニメ情報と同様に、JSON 文字列として動画メタデータを保存する。

保存するデータは以下の通り:

  • 動画 ID(11 文字の英数字)
  • 動画タイトル(HTML エンティティデコード済み)
  • チャンネル名
  • サムネイル URL(i.ytimg.com または yt3.ggpht.com のみ許可)
  • 視聴 URL(動画 ID から安全に生成)

2. YouTube Data API v3 との連携

バックエンドで YouTube Data API v3 の検索エンドポイントを呼び出している。

GET https://www.googleapis.com/youtube/v3/search?part=snippet&q={query}&type=video&maxResults=5&key={YOUTUBE_API_KEY}
  • type=video で動画のみに絞り込む
  • maxResults=5 でAPI使用量を節約する
  • タイトルに含まれる HTML エンティティ(& など)はサーバー側でデコードする

必要な環境変数:

YOUTUBE_API_KEY — Google Cloud Console で取得した YouTube Data API v3 の API キー。Cloudflare Pages の環境変数(シークレット)として設定する。

3. セキュリティ設計

セキュリティ上の考慮点:

入力値検証

  • 動画 ID は正規表現 /^[\w-]{11}$/ で検証し、不正な値を弾く
  • サムネイル URL は i.ytimg.comyt3.ggpht.com のドメインのみ許可
  • 視聴 URL はクライアントから受け取った値を使わず、動画 ID から安全に生成する
  • 検索クエリは 200 文字上限でバリデーション

認証

  • 検索 API はセッション認証が必要なエンドポイントにのみ公開している
  • サーバーサイドでセッション有効期限を確認している

レスポンス整形

  • フロントエンドへ返す前に、必要なフィールドのみを抽出して再構成する
  • JSON は一度パースして再シリアライズし、不正なデータが通り抜けないようにする

4. 投稿フォームへの UI 追加

既存のゲーム検索・アニメ検索パネルと同じスライドアップ方式でパネルを実装した。

ツールバーに「YT」ボタンを追加している。絵文字は使わず、シンプルなテキストにした。

  • ボタンを押すとパネルが開く
  • 検索入力から 500ms のデバウンスで自動検索される
  • 結果をタップすると「視聴した動画」プレビューカードが表示される
  • カードの「✕」ボタンで選択を解除できる

5. タイムラインでの表示

既存の YouTube iframe 埋め込みロジックを拡張した。

  • youtube_info の動画 ID を既存の埋め込みリストに追加する
    • テキスト中の URL から検出された動画と重複がある場合は除外する
  • 「視聴した動画」ラベル・タイトル・チャンネル名を表示する情報カードを追加した
    • ゲーム情報・アニメ情報カードと同じ引用カード形式
    • タイトルをクリックすると YouTube で開く

詰まった点

サムネイル URL のドメイン検証

YouTube のサムネイル URL は i.ytimg.com から配信されるが、エッジケースとして yt3.ggpht.com(チャンネルアイコン等)も存在する。フロントエンドから来た URL を無制限に受け入れると SSRF 等のリスクがあるため、ドメインを明示的に許可リストで制限した。

watchUrl の生成

クライアント側で生成した watchUrl をそのまま DB に保存すると、意図しない URL が保存されるリスクがある(例えば javascript: スキーム)。そのため、DB に保存する際は常に videoId から https://www.youtube.com/watch?v={videoId} を生成し直している。


設定方法

YouTube 検索機能を有効にするには、以下の手順で API キーを設定する:

  1. Google Cloud Console にアクセスし、YouTube Data API v3 を有効にする
  2. API キーを発行する(IP 制限・リファラ制限を設定することを推奨)
  3. Cloudflare Pages の管理画面で、環境変数 YOUTUBE_API_KEY にキーを設定する
  4. API キーは Git リポジトリに含めない

学んだこと

  • YouTube Data API v3 のレスポンスにはタイトルに HTML エンティティが含まれることがある(& など)。サーバー側でデコードしないと、フロントエンドでそのまま表示されてしまう。
  • 画像 URL のドメイン検証は表示上の問題だけでなく、セキュリティ上も重要。外部から任意の URL を受け入れると意図しないコンテンツが表示される。
  • ゲーム・アニメ情報と同じパターンに揃えることで、コードの可読性と保守性が向上した。
Claude Code
Powered by
Claude Code
(使用モデル Sonnet 4.6)
← ブログ一覧に戻る