日記

シンオウ地方で指を振るために作られたブログだった

Twitter Web AppのTL自動更新スクリプト

Tweetdeckはまもなく有料化される。妥当な措置だと思うが……しかし私はTwitterに金を払いたくないのだ。

かくなる上は公式クライアントのタイムラインを自動更新可能にするしかない。

それ系の野良ブラウザ拡張は大量にあるのだが私は潔癖症だ。だから自作した。

コードを見せろ

2023.8.26 追記: [aria-label="Twitter"][aria-label="X"]に変更した。 今では鳥のかわりにXが虹色に光っている。

Tampermonkeyとかに突っ込めば動く。更新は15秒周期。動作確認はChromeでしかやってない。

// ==UserScript==
// @name         TL自動更新太郎
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://twitter.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=twitter.com
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    const anime = `@keyframes gaming{
0%, 100% { color:magenta; }
33% { color:yellow; }
66% { color:cyan; }
}`;
    const style = document.createElement('style');
    document.head.appendChild(style);
    style.sheet.insertRule(anime);

    const monitorIntr = 1000;
    const reloadIntr = 15000;
    let cnt = 0;
    setInterval(() => {
        if (cnt > 0) { cnt -= monitorIntr; }

        const el = document.querySelector('[aria-label="X"]');
        if (!el) { return; }
        const act = document.activeElement;
        const cond =
              document.visibilityState === 'visible' &&
              location.pathname === '/home' && scrollY === 0 &&
              !act.isContentEditable && !(act instanceof HTMLInputElement);
        if (cond && cnt <= 0) {
            el.click();
            cnt = reloadIntr;
        }
        const bird = el.querySelector('svg');
        if (bird) {
            if (cond) {
                bird.style.animation = 'gaming 1s linear infinite';
            } else {
                bird.style.animation = '';
            }
        }
    }, monitorIntr);
})();

ちなみに自動更新が有効なとき鳥がゲーミング発光する。

解説も聞いてやろう

ホームTLに限れば自動更新は難しくない。 あの鳥をクリックすると新しいツイートが即座に読み込まれることが利用できる*1

単に自動更新するだけならこれでも動く。

setInterval(() => {
    if(location.pathname === '/home' && scrollY === 0) {
        document.querySelector('[aria-label="Twitter"]')?.click();
    }
}, 15000);

他にいくつか条件を加えるとなお良い。

  • document.visibilityState === 'visible'
    • バックグラウンドでの更新を防ぐ
    • 更新しすぎると429 Too Many Requestsで怒られるため
  • !document.activeElement.isContentEditable
    • ツイート入力中の更新でフォーカスが移るのを防ぐ
  • !(document.activeElement instanceof HTMLInputElement)
    • 検索キーワード入力中の更新を防ぐ

以上にゲーミング発光機能をつけたのが完成したスクリプトだ。 画面スクロールやツイート入力をすると鳥が黙るので動作がわかりやすい。


更新周期の話をする。

公式クライアントであってもリクエストを飛ばしすぎると怒られる。 例えば、スクリプト制作中に更新周期を0.5秒にしたときは429 Too Many Requestsでしばらくツイートを見れない事態に陥った。 これは7月頭のイーロン超API制限とは関係がない。

X-Rate-Limit-***ヘッダによれば15分間に500回リクエストを飛ばすとまずいらしい。 逆算すると2秒周期までならセーフということになる。

ただしレートリミットの他に一日あたりのAPI制限が存在することに留意が必要だ。 無課金のアカウントで長時間稼働させると引っかかってしまう。この制限解除には最大で24時間を要するだろう。

2024年3月現在の課金にはBasic, Premium, Premium+の3つのプランが存在するが、 驚くべきことに各プランの一日あたりの閲覧上限数は公式に明示されていない。どうなってんだ。

経験的には*2、少なくともPremium (月980円) ならば上限に達することはまずないと思う。 でもPremiumではdeckが使えるからこのスクリプトは要らないんだよな。

そしてBasic (月368円) には加入したことがないのでわからない。Basicに関しては情報が錯綜していて、本当によくわからない。

以上

Twitter依存の諸兄姉に幸多からんことを。あれからFediverseやThreadsやTruth Socialに移住する人が増えそうで私は少し寂しい。

*1:「n件のツイートを表示」ボタンの出現を待つ案は微妙だった。新規ツイートがあってから出現までに数分かかる。

*2:Twitterに金を払いたくないと言ったが、やむを得ない事情により不本意ながら課金したことがあるのだ