Twitter(現X)の前後ポストを表示する

    @@ -6,7 +6,8 @@ * @javascript_url */ -const TWITTER_EPOCH = BigInt(1288834974657); +(() => { +const TWITTER_EPOCH = 1288834974657; // 'YYYY-MM-DD_HH:mm:ss_JST'形式で日付をフォーマット const formatTwitterDate = (date) => { @@ -28,7 +29,7 @@ // 10 bits: worker_id // 12 bits: sequence number // なので 22 bit 右シフトする - const timestamp = Number((snowflake >> BigInt(22)) + TWITTER_EPOCH); + const timestamp = Number(snowflake >> 22n) + TWITTER_EPOCH; return { since: formatTwitterDate(new Date(timestamp - 60 * 60 * 1000)), // 60 分前 @@ -48,3 +49,5 @@ } main(); + +})();
  • /*
     * @title Twitter(現X)の前後ポストを表示する
     * @description 個別 Tweet の URL から前後 1 時間の投稿を RT を含めて表示する
     * @include https://twitter.com/*
     * @license MIT License
     * @javascript_url
     */
    
    (() => {
    const TWITTER_EPOCH = 1288834974657;
    
    // 'YYYY-MM-DD_HH:mm:ss_JST'形式で日付をフォーマット
    const formatTwitterDate = (date) => {
      const pad2 = (n) => n.toString().padStart(2, '0');
    
      const year = date.getFullYear();
      const month = pad2(date.getMonth() + 1);
      const day = pad2(date.getDate());
      const hour = pad2(date.getHours());
      const minute = pad2(date.getMinutes());
      const second = pad2(date.getSeconds());
      return `${year}-${month}-${day}_${hour}:${minute}:${second}_JST`;
    }
    
    // Snowflake ID 文字列を受け取り、前後 60 分の since, until を返す
    const getSearchRange = (snowflakeStr) => {
      const snowflake = BigInt(snowflakeStr);
      // 41 bits: millisec from TWITTER_EPOCH
      // 10 bits: worker_id
      // 12 bits: sequence number
      // なので 22 bit 右シフトする
      const timestamp = Number(snowflake >> 22n) + TWITTER_EPOCH;
    
      return {
        since: formatTwitterDate(new Date(timestamp - 60 * 60 * 1000)), // 60 分前
        until: formatTwitterDate(new Date(timestamp + 60 * 60 * 1000)), // 60 分後
      };
    }
    
    const main = () => {
      const match = location.href.match(/https:\/\/twitter\.com\/(?<name>[^/]+)\/status\/(?<snowflake>\d+)/);
      if (!match) {
        alert('このページは Twitter の個別 Tweet ではありません');
        return;
      }
      const range = getSearchRange(match.groups.snowflake);
      const query = `from:${match.groups.name} since:${range.since} until:${range.until} include:nativeretweets`;
      location.href = `https://twitter.com/search?f=live&q=${encodeURIComponent(query)}`;
    }
    
    main();
    
    })();
  • Permalink
    このページへの個別リンクです。
    RAW
    書かれたコードへの直接のリンクです。
    Packed
    文字列が圧縮された書かれたコードへのリンクです。
    Userscript
    Greasemonkey 等で利用する場合の .user.js へのリンクです。
    Loader
    @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
    Metadata
    コード中にコメントで @xxx と書かれたメタデータの JSON です。