みかづきブログ・カスタム

基本的にはちょちょいのほいです。

Next.js + Vercel + Twitter APIでツイートの検索結果をウェブページに表示する 🦜

f:id:kimizuka:20210103011013j:plain

ツイッターの検索結果をウェブページに埋め込みたいとき、昔は公式のウィジェットがあったのですが、2018年に廃止されました。
でも、どうしても検索結果をウェブページに埋め込みたくて諸々調査した結果。

Next.js + Vercel + Twitter API で割と簡単に埋め込めそうでした。

ただし、

・最新100件まで
・過去7日まで
・15分間で180回の表示まで

という制約があるので、プロダクトとして使うには、どこかにキャッシュするなど、ひと工夫必要そうです。
僕の場合は検証のためにちょちょいと試したかっただけなので、下記の方法で実装しました。

手順

❶ Twitterの開発者登録をしてアプリをつくる

developer.twitter.com から登録します。(詳細は割愛します)

developer.twitter.com

❷ .envに必要事項を記入する

アプリをつくると、consumer_key、consumer_secret、access_token_key、access_token_secretが手に入るので.envに記入しましょう。

consumer_key = 'XXXXXXXX'
consumer_secret = 'XXXXXXXXj'
access_token_key =  'XXXXXXXX'
access_token_secret = 'XXXXXXXX'

❸ Next.jsでAPIをつくる

pages/api/tweets.ts
import Twitter from 'twitter';
import dotenv from 'dotenv';

dotenv.config();

const client = new Twitter({
  consumer_key: process.env.consumer_key,
  consumer_secret: process.env.consumer_secret,
  access_token_key: process.env.access_token_key,
  access_token_secret: process.env.access_token_secret
});

export default async (req, res) => {
  const { q } = req.query;

  if (!q) {
    return res.status(200).json([]);
  }

  const data = await (() => {
    return new Promise((resolve, reject) => {
      client.get('search/tweets', { q, count: 100 }, function(error, tweets, response) {
        resolve(tweets);
      });
    });
  })();
  const statuses = (data as {
    statuses: {
      text: string;
    }[]
  }).statuses;

  const param : {
    text: string;
  }[] = [];

  if (statuses) {
    statuses.forEach((tweet) => {
      param.push({
        text: tweet.text
      });
    });
  }

  return res.status(200).json(param);
}

ざっくり書くとこんな感じです。
上記例ではツイート本文しか取得していませんが、本当はいろいろ取得できます。

❹ 表示用のページをつくる

pages/index.ts
import axios from 'axios';
import { useEffect, useState } from 'react';

export default function IndexPage() {
  const [tweets, setTweets ] = useState([]);

  useEffect(async () => {
    if (tweets.length) {
      return;
    }

    const q = '寿司';
    const { data } = await axios.get(`/api/tweets?q=${ encodeURIComponent(q) }`);

    if (data.length) {
      setTweets(data);
    }
  }, [tweets]);

  return (
    <ol>{
      tweets.map((tweet, i) => {
        return (
          <li key={ i }>{ tweet.text }</li>
        )
      })
    }</ol>
  )
}

ざっくり書くとこんな感じです。
上記例では「寿司」の検索結果を表示します。

❺ Vercelにデプロイ

Vercelにデプロイします。
その際に、.envの内容をEnvironment Variablesから登録しましょう。

vercel.com


手続きは以上となります。ちょっとした検証に使うのであればこれで充分な気がしました。