何をやったか
つぶやき投稿フォームから 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.comとyt3.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 キーを設定する:
- Google Cloud Console にアクセスし、YouTube Data API v3 を有効にする
- API キーを発行する(IP 制限・リファラ制限を設定することを推奨)
- Cloudflare Pages の管理画面で、環境変数
YOUTUBE_API_KEYにキーを設定する - API キーは Git リポジトリに含めない
学んだこと
- YouTube Data API v3 のレスポンスにはタイトルに HTML エンティティが含まれることがある(
&など)。サーバー側でデコードしないと、フロントエンドでそのまま表示されてしまう。 - 画像 URL のドメイン検証は表示上の問題だけでなく、セキュリティ上も重要。外部から任意の URL を受け入れると意図しないコンテンツが表示される。
- ゲーム・アニメ情報と同じパターンに揃えることで、コードの可読性と保守性が向上した。