🚀

zodでtwitterのgraphqlの戻り値をパースしたい

2024/02/12に公開

twitterのPC web版で使われているhome timelineのapiのレスポンスをnodeのzodという型ライブラリで定義したい。

正規化1

通常のツイートのjsonオブジェクトは以下のような内容

{
  "__typename":"Tweet",
  "rest_id":"123456789",
  // 他プロパティ沢山
}

結構頻繁に以下のようなオブジェクトが紛れている

{
  "__typename":"TweetWithVisibilityResults",
  "tweet":{
    "rest_id":"123456789",
    // 他プロパティ沢山
  },
  "limitedActionResults":{略}
}

自分の目的はツイートのテキスト等の人間が読む情報だけ取得できればいいので、TweetWithVisibilityResultsTweet型に正規化したい。

正規化2

Twitterは1つのツイートの中に3ツイート文の情報が含まれている。
以下の場合だと、AさんのツイートをBさんが引用RTして、Cさんが通常RTした場合。

以下のようなjsonになる。3つある各TweetTweetWithVisibilityResultsになっている可能性があるので、2^3で合計8通りの可能性がある。

{
  "__typename": "Tweet",
  "rest_id": "1754238102162543018",
  "core": {
    "user_results": {
      "result": {
        "__typename": "User",
        "rest_id": "123456789",
        "legacy": {
          "screen_name": "C"
        }
      }
    }
  },
  "legacy": {
    "full_text": "RT @B 引用RT先のツイートのテキスト",
    "retweeted_status_result": {
      "result": {
        "__typename": "Tweet",
        "core": {
          "user_results": {
            "result": {
              "__typename": "User",
              "rest_id": "123456789",
              "legacy": {
                "screen_name": "B"
              }
            }
          }
        },
        "legacy": {
          "full_text": "引用RT先のツイートのテキスト"
        },
        "quoted_status_result": {
          "result": {
            "__typename": "Tweet",
            "core": {
              "user_results": {
                "result": {
                  "__typename": "User",
                  "rest_id": "123456789",
                  "legacy": {
                    "screen_name": "A"
                  }
                }
              }
            },
            "legacy": {
              "full_text": "引用RT元のツイートのテキスト"
            }
          }
        }
      }
    }
  }
}

つまり各Tweetオブジェクトには、quoted_status_resultか、legacy.retweeted_status_result オブジェクトが存在する可能性がある。
両方同時は無いが、引用RTだけ 通常RTだけの場合もある。
Tweetオブジェクトの子や、Tweet.legacyオブジェクトの子には無数のプロパティがある。
またUserオブジェクトにも子やUser.legacyオブジェクトの子もある。

全パターン網羅しても多分20通りもいかないだろうけどプロパティ数が膨大だから毎回書くのを避けたい。

という日記

その後

zod一発で型定義するのは非現実的だと思う。
引用RTの引用RTの引用RTの…と何度も引用RTした場合の挙動もドキュメント化されてないし。
複雑にやれば出来るんだろうけど、後から見て全くわからなくなるからしたくない。

Discussion