- // ==UserScript==
- // @name Show ctime of retweets
- // @name:ja リツイート自体の日時を表示
- // @name:ko 리트윗 날짜와 시간을 표시합니다.
- // @name:zh-CN 显示转发的日期和时间。
- // @name:zh-TW 顯示轉發的日期和時間。
- // @namespace https://gf.qytechs.cn/en/scripts/462070-show-ctime-of-retweets
- // @version 1.9.0
- // @description Also shows Twitter Blue badges and tweet source labels.
- // @description:ja Twitter Blue バッジ、ツイートソースラベルも表示できます。
- // @description:ko Twitter Blue 배지, 트윗 소스 라벨도 표시할 수 있습니다.
- // @description:zh-CN 您还可以显示推特蓝徽章、推文来源标签。
- // @description:zh-TW 您還可以顯示推特藍徽章、推文來源標籤。
- // @author AeamaN
- // @contributionURL bitcoin:1DC6uWJWzzwU3iRJDXhUquv6QAYaRvtfFJ
- // @match https://twitter.com/*
- // @match https://mobile.twitter.com/*
- // @match https://twitter3e4tixl4xyajtrzo62zg5vztmjuricljdp2c5kshju4avyoid.onion/*
- // @match https://mobile.twitter3e4tixl4xyajtrzo62zg5vztmjuricljdp2c5kshju4avyoid.onion/*
- // @match https://x.com/*
- // @match https://mobile.x.com/*
- // @require https://update.gf.qytechs.cn/scripts/467232/1197541/Legacy%20verified%2012.js
- // @require https://update.gf.qytechs.cn/scripts/467238/1197542/Legacy%20verified%2015.js
- // @require https://update.gf.qytechs.cn/scripts/467255/1197539/Legacy%20verified%2019.js
- // @require https://update.gf.qytechs.cn/scripts/467256/1197544/Legacy%20verified%2024.js
- // @require https://update.gf.qytechs.cn/scripts/467257/1197545/Legacy%20verified%2029.js
- // @require https://update.gf.qytechs.cn/scripts/467258/1197546/Legacy%20verified%203.js
- // @require https://update.gf.qytechs.cn/scripts/467259/1197547/Legacy%20verified%204.js
- // @require https://update.gf.qytechs.cn/scripts/467260/1197548/Legacy%20verified%205.js
- // @require https://update.gf.qytechs.cn/scripts/467262/1197549/Legacy%20verified%206.js
- // @require https://update.gf.qytechs.cn/scripts/467263/1197550/Legacy%20verified%207.js
- // @require https://update.gf.qytechs.cn/scripts/467264/1197553/Legacy%20verified%208.js
- // @require https://update.gf.qytechs.cn/scripts/467265/1197554/Legacy%20verified%209.js
- // @grant GM.getValue
- // @grant GM.registerMenuCommand
- // @grant GM.setValue
- // @run-at document-body
- // ==/UserScript==
-
- // ES2017(ES8) or later.
- // ES2017(ES8) 以降が必要です。
-
- (async function() { /* START */
-
-
- 'use strict';
-
- /////////////// Settings ///////////////
- // No GUI Settings
- // Default values are used
- const NOGUI = false;
- ////////////////////////////////////////
-
- //////////// Default valuse ////////////
- // Substitute TB badge
- // when TB without legacy verification
- const TB = false;
-
- // Show source labels
- // 1. Tweet only
- // 2. Tweet and (Retweet)
- // 0. Not shown
- const SSL = 2;
-
- // Date formats
- // 1. 31.12.70 23:59
- // 2. 31.12.70 23:59:59
- // 3. 31.12.70(Th) 23:59
- // 4. 31.12.70(Th) 23:59:59
- //
- // 5. 70/12/31 23:59
- // 6. 70/12/31 23:59:59
- // 7. 70/12/31(Th) 23:59
- // 8. 70/12/31(Th) 23:59:59 [ye/mo/da(we) ho:mi:se]
- //
- // 9. 70-12/31 23:59
- // 10. 70-12/31 23:59'59
- // 11. 70-12/31(Th) 23:59
- // 12. 70-12/31(Th) 23:59'59
- //
- // 13. M59-12-31 23:59
- // 14. M59-12-31 23:59:59
- // 15. M59-12-31(Th) 23:59
- // 16. M59-12-31(Th) 23:59:59
- //
- // 0. Not Shown
- const FMT = 7;
-
- // Loop interval(ms)
- const INTL = 800;
- ////////////////////////////////////////
-
- const MYNAME = 'sctrt190';
- const BTKN =
- 'AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs=' +
- '1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA';
- const EBTKN = encodeURIComponent(BTKN);
- const originalXHROpen = XMLHttpRequest.prototype.open;
-
- let s_mus = true;
- let observer = new MutationObserver(function (mutations) {
- s_mus = mutations;
- });
- let tb, ssl, fmt, intl;
- let dalg;
-
- function getcv(name) {
- let cookie = document.cookie;
- let obj = {};
- if (!cookie) return [];
-
- cookie.split(';').forEach(function (rec) {
- let kav = rec.split('=');
- let key, val;
-
- if (rec.includes('=')) {
- [key, val] = [unescape(kav[0].trim()), unescape(kav[1].trim())];
- } else {
- [key, val] = ['', unescape(kav[0].trim())];
- }
-
- if (!obj[key]) {
- obj[key] = [val];
- } else {
- obj[key].push(val);
- }
- });
-
- return obj[name] ?? [];
- }
-
- function makeDialog() {
- let dalg = document.createElement('div');
-
- dalg.className = `us-${MYNAME}`;
-
- dalg.style.all = 'initial';
- dalg.style.backgroundColor = 'rgb(235, 235, 235)';
- dalg.style.border = '3px outset';
- dalg.style.borderRadius = '1%';
- dalg.style.display = 'none';
- dalg.style.fontFamily = 'monospace';
- dalg.style.fontSize = '12px';
- dalg.style.height = '360px';
- dalg.style.width = '400px';
- dalg.style.paddingLeft = '2px';
- dalg.style.paddingRight = '2px';
- dalg.style.position = 'fixed';
- dalg.style.right = '8px';
- dalg.style.top = '8px';
- dalg.style.zIndex = '2147483647';
-
- let html =
- '<span style="all: initial; font-size: 120%; line-height: 210%">' +
- `${GM.info.script.name} ${GM.info.script.version} Settings` +
- '</span><br />\n' +
-
- '<input type="radio" name="fmt" value="1" class="top_r" />31.12.70 23:59' +
- ' ' +
- '<input type="radio" name="fmt" value="2" class="top_r" />31.12.70 23:59:59<br />\n' +
- '<input type="radio" name="fmt" value="3" class="mid_r" />31.12.70(Th) 23:59' +
- ' ' +
- '<input type="radio" name="fmt" value="4" class="mid_r" />31.12.70(Th) 23:59:59<br />\n' +
- '<input type="radio" name="fmt" value="5" class="mid_r" />70/12/31 23:59' +
- ' ' +
- '<input type="radio" name="fmt" value="6" class="mid_r" />70/12/31 23:59:59<br />\n' +
- '<input type="radio" name="fmt" value="7" class="mid_r" />70/12/31(Th) 23:59' +
- ' ' +
- '<input type="radio" name="fmt" value="8" class="mid_r" />70/12/31(Th) 23:59:59<br />\n' +
- '<input type="radio" name="fmt" value="9" class="mid_r" />70-12/31 23:59' +
- ' ' +
- '<input type="radio" name="fmt" value="10" class="mid_r" />70-12/31 23:59\'59<br />\n' +
- '<input type="radio" name="fmt" value="11" class="mid_r" />70-12/31(Th) 23:59' +
- ' ' +
- '<input type="radio" name="fmt" value="12" class="mid_r" />70-12/31(Th) 23:59\'59<br />\n' +
- '<input type="radio" name="fmt" value="13" class="mid_r" />M59-12-31 23:59' +
- ' ' +
- '<input type="radio" name="fmt" value="14" class="mid_r" />M59-12-31 23:59:59<br />\n' +
- '<input type="radio" name="fmt" value="15" class="mid_r" />M59-12-31(Th) 23:59' +
- ' ' +
- '<input type="radio" name="fmt" value="16" class="mid_r" />M59-12-31(Th) 23:59:59<br />\n' +
- '<input type="radio" name="fmt" value="0" class="btm_r" />Not Shown<br />\n' +
-
- '<input type="checkbox" name="tb" class="top_c" />Substitute TB badge<br />\n' +
-
- '<input type="radio" name="ssl" value="1" class="top_r" />Tweet source labels only' +
- ' ' +
- '<input type="radio" name="ssl" value="2" class="top_r" />Tweet and (Retweet)<br />\n' +
- '<input type="radio" name="ssl" value="0" class="btm_r" />Not shown<br />\n' +
-
- '<span style="all: initial; font-size: 100%">' +
- 'Loop interval(ms) ' +
- '</span><input type="text" name="intl" size="10" class="top_t" /><br />\n' +
-
- '<input type="button" class="top_b" value="Cancel" />\n' +
- '<input type="button" class="top_b" value="Set default" />\n' +
- '<input type="button" class="top_b" value="Save & Close" />\n';
-
- dalg.innerHTML = html;
-
- for (let e of dalg.querySelectorAll('input.top_r')) {
- e.style.all = 'initial';
- e.style.appearance = 'auto';
- e.style.marginRight = '1px';
- e.style.marginTop = '1px';
- }
- for (let e of dalg.querySelectorAll('input.mid_r, input.btm_r')) {
- e.style.all = 'initial';
- e.style.appearance = 'auto';
- e.style.marginRight = '1px';
- e.style.marginTop = '1px';
- }
- for (let e of dalg.querySelectorAll('input.top_c')) {
- e.style.all = 'initial';
- e.style.appearance = 'auto';
- e.style.marginRight = '1px';
- e.style.marginTop = '1px';
- }
- for (let e of dalg.querySelectorAll('input.top_t')) {
- e.style.all = 'initial';
- e.style.backgroundColor = 'rgb(255, 255, 255)';
- e.style.fontFamily = 'monospace';
- e.style.fontSize = '100%';
- e.style.marginLeft = '1px';
- e.style.marginRight = '1px';
- e.style.marginTop = '8px';
- e.style.marginBottom = '0px';
- e.style.paddingLeft = '1px';
- e.style.paddingRight = '1px';
- e.style.paddingTop = '1px';
- e.style.paddingBottom = '1px';
- }
- for (let e of dalg.querySelectorAll('input.top_b')) {
- e.style.all = 'initial';
- e.style.backgroundColor = 'rgb(190, 190, 190)';
- e.style.borderRadius = '10%';
- e.style.cursor = 'default';
- e.style.fontSize = '110%';
- e.style.marginTop = '10px';
- e.style.marginBottom = '0px';
- e.style.paddingTop = '6px';
- e.style.paddingBottom = '6px';
- e.style.textAlign = 'center';
- e.style.width = '90px';
- }
-
- return dalg;
- }
-
- function makeFunc(dalg) {
- dalg.addEventListener(
- 'click',
- function (event) {
- event.stopPropagation();
- },
- false,
- );
-
- dalg.querySelector('input[value="Cancel"]').addEventListener(
- 'click',
- function () {
- dalg.style.display = 'none';
- },
- false,
- );
- dalg.querySelector('input[value="Cancel"]').addEventListener(
- 'mouseenter',
- function (event) {
- event.target.style.backgroundColor = 'rgb(170, 170, 170)';
- },
- false,
- );
- dalg.querySelector('input[value="Cancel"]').addEventListener(
- 'mouseleave',
- function (event) {
- event.target.style.backgroundColor = 'rgb(190, 190, 190)';
- },
- false,
- );
-
- dalg.querySelector('input[value="Set default"]').addEventListener(
- 'click',
- function () {
- dalg.querySelector(`input[name="fmt"][value="${FMT}"]`).checked = true;
- dalg.querySelector('input[name="tb"]').checked = TB;
- dalg.querySelector(`input[name="ssl"][value="${SSL}"]`).checked = true;
- dalg.querySelector('input[name="intl"]').value = INTL;
- },
- false,
- );
- dalg.querySelector('input[value="Set default"]').addEventListener(
- 'mouseenter',
- function (event) {
- event.target.style.backgroundColor = 'rgb(170, 170, 170)';
- },
- false,
- );
- dalg.querySelector('input[value="Set default"]').addEventListener(
- 'mouseleave',
- function (event) {
- event.target.style.backgroundColor = 'rgb(190, 190, 190)';
- },
- false,
- );
-
- dalg.querySelector('input[value="Save & Close"]').addEventListener(
- 'click',
- async function () {
- for (let e of dalg.querySelectorAll('input[name="fmt"]')) {
- if (e.checked) {
- fmt = +e.value;
- break;
- }
- }
- tb = dalg.querySelector('input[name="tb"]').checked;
- for (let e of dalg.querySelectorAll('input[name="ssl"]')) {
- if (e.checked) {
- ssl = +e.value;
- break;
- }
- }
- intl = +dalg.querySelector('input[name="intl"]').value;
-
- await GM.setValue('fmt', fmt);
- await GM.setValue('tb', tb);
- await GM.setValue('ssl', ssl);
- await GM.setValue('intl', intl);
-
- dalg.style.display = 'none';
- },
- false,
- );
- dalg.querySelector('input[value="Save & Close"]').addEventListener(
- 'mouseenter',
- function (event) {
- event.target.style.backgroundColor = 'rgb(170, 170, 170)';
- },
- false,
- );
- dalg.querySelector('input[value="Save & Close"]').addEventListener(
- 'mouseleave',
- function (event) {
- event.target.style.backgroundColor = 'rgb(190, 190, 190)';
- },
- false,
- );
- }
-
- async function initgui() {
- if ((await GM.getValue('fmt')) === undefined) {
- await GM.setValue('fmt', FMT);
- } else {
- fmt = await GM.getValue('fmt');
- }
- if ((await GM.getValue('tb')) === undefined) {
- await GM.setValue('tb', TB);
- } else {
- tb = await GM.getValue('tb');
- }
- if ((await GM.getValue('ssl')) === undefined) {
- await GM.setValue('ssl', SSL);
- } else {
- ssl = await GM.getValue('ssl');
- }
- if ((await GM.getValue('intl')) === undefined) {
- await GM.setValue('intl', INTL);
- } else {
- intl = await GM.getValue('intl');
- }
-
- dalg = makeDialog();
- makeFunc(dalg);
- document.body.appendChild(dalg);
-
- GM.registerMenuCommand('Settings', function () {
- if (dalg.style.display == 'none') {
- dalg.querySelector(`input[name="fmt"][value="${fmt}"]`).checked = true;
- dalg.querySelector('input[name="tb"]').checked = tb;
- dalg.querySelector(`input[name="ssl"][value="${ssl}"]`).checked = true;
- dalg.querySelector('input[name="intl"]').value = intl;
-
- dalg.style.display = 'block';
- }
- });
- }
-
- function datef(date, f) {
- let l = document.documentElement.getAttribute('lang');
- let week_l =
- l == 'ja' ? ['日', '月', '火', '水', '木', '金', '土'] :
- l == 'ko' ? ['일', '월', '화', '수', '목', '금', '토'] :
- l == 'zh-Hant' ? ['日', '一', '二', '三', '四', '五', '六'] :
- l == 'zh' ? ['日', '一', '二', '三', '四', '五', '六'] :
- l == 'ru' ? ['ВС', 'ПН', 'ВТ', 'СР', 'ЧТ', 'ПТ', 'СБ'] :
- l == 'de' ? ['Son', 'Mon', 'Die', 'Mit', 'Don', 'Fre', 'Sam'] :
- l == 'it' ? ['Dom', 'Lun', 'Mar', 'Mer', 'Gio', 'Ven', 'Sab'] :
- l == 'fr' ? ['Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam'] :
- l == 'pt' ? ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'] : // Add your language
- ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'];
-
- let ye, ym, mo, da, we, ho, mi, se;
- ye = date.getFullYear().toString().slice(-2);
- ym = date.getFullYear() - 1911;
- mo = ('0' + (date.getMonth() + 1)).slice(-2);
- da = ('0' + date.getDate()).slice(-2);
- we = week_l[date.getDay()];
- ho = ('0' + date.getHours()).slice(-2);
- mi = ('0' + date.getMinutes()).slice(-2);
- se = ('0' + date.getSeconds()).slice(-2);
-
- return f == 1 ? `${da}.${mo}.${ye} ${ho}:${mi}` :
- f == 2 ? `${da}.${mo}.${ye} ${ho}:${mi}:${se}` :
- f == 3 ? `${da}.${mo}.${ye}(${we}) ${ho}:${mi}` :
- f == 4 ? `${da}.${mo}.${ye}(${we}) ${ho}:${mi}:${se}` :
- f == 5 ? `${ye}/${mo}/${da} ${ho}:${mi}` :
- f == 6 ? `${ye}/${mo}/${da} ${ho}:${mi}:${se}` :
- f == 7 ? `${ye}/${mo}/${da}(${we}) ${ho}:${mi}` :
- f == 8 ? `${ye}/${mo}/${da}(${we}) ${ho}:${mi}:${se}` :
- f == 9 ? `${ye}-${mo}/${da} ${ho}:${mi}` :
- f == 10 ? `${ye}-${mo}/${da} ${ho}:${mi}'${se}` :
- f == 11 ? `${ye}-${mo}/${da}(${we}) ${ho}:${mi}` :
- f == 12 ? `${ye}-${mo}/${da}(${we}) ${ho}:${mi}'${se}` :
- f == 13 ? `M${ym}-${mo}-${da} ${ho}:${mi}` :
- f == 14 ? `M${ym}-${mo}-${da} ${ho}:${mi}:${se}` :
- f == 15 ? `M${ym}-${mo}-${da}(${we}) ${ho}:${mi}` :
- f == 16 ? `M${ym}-${mo}-${da}(${we}) ${ho}:${mi}:${se}` :
- `${ye}/${mo}/${da}(${we}) ${ho}:${mi}:${se}`;
- }
-
- function mkreq(url, eq, ebt, controller) {
- let req;
-
- if (getcv('gt').length && !getcv('twid').length) {
- req = new Request(`${url}${eq}`, {
- headers: {
- authorization: `Bearer ${ebt}`,
- 'x-csrf-token': getcv('ct0')[0],
- 'x-guest-token': getcv('gt')[0],
- },
- cache: 'force-cache',
- redirect: 'follow',
- signal: controller.signal,
- });
- } else {
- req = new Request(`${url}${eq}`, {
- headers: {
- authorization: `Bearer ${ebt}`,
- 'x-csrf-token': getcv('ct0')[0],
- 'x-twitter-auth-type': 'OAuth2Session',
- },
- cache: 'force-cache',
- redirect: 'follow',
- mode: 'cors',
- credentials: 'include',
- signal: controller.signal,
- });
- }
-
- return req;
- }
-
- async function getuid(s_name) {
- let url = 'https://api.x.com/graphql/rePnxwe9LZ51nQ7Sn_xN_A/UserByScreenName';
- if (/^[^:]+:\/\/[^/]+\.onion\//i.test(document.URL)) {
- url =
- 'https://api.twitter3e4tixl4xyajtrzo62zg5vztmjuricljdp2c5kshju4avyoid.onion/' +
- 'graphql/rePnxwe9LZ51nQ7Sn_xN_A/UserByScreenName';
- }
- let q =
- '?variables={' +
- `"screen_name":"${s_name}",` +
- '"withSafetyModeUserFields":true,' +
- '"withSuperFollowsUserFields":true' +
- '}' +
- '&features={' +
- '"responsive_web_twitter_blue_verified_badge_is_enabled":true,' +
- '"responsive_web_graphql_exclude_directive_enabled":false,' + // false
- '"verified_phone_label_enabled":true,' + // false
- '"responsive_web_graphql_skip_user_profile_image_extensions_enabled":false,' +
- '"responsive_web_graphql_timeline_navigation_enabled":true' +
- '}';
- let eq = encodeURI(q);
- let controller = new AbortController();
- let req = mkreq(url, eq, EBTKN, controller);
- let res = {};
-
- try {
- setTimeout(function () {
- controller.abort();
- }, 60000);
- res = await fetch(req);
- if (!res.ok) {
- console.log(`${MYNAME}: getuid:notok:${res.ok}.`);
- return null;
- } // 失敗なら空で終わり
- } catch (err) {
- console.log(`${MYNAME}: getuid:error:${err}.`);
- return null; // 失敗なら空で終わり
- }
-
- let json = JSON.parse(await res.text());
-
- let id, bl, ca, sn, vf;
- id = json.data.user.result.rest_id;
- bl = json.data.user.result.is_blue_verified;
- ca = json.data.user.result.legacy.created_at;
- sn = json.data.user.result.legacy.screen_name;
- vf = json.data.user.result.legacy.verified;
-
- return [id, bl, ca, sn, vf];
- }
-
- async function unique(n) {
- // 要${MYNAME}_idl、${MYNAME}_twts
- let str = await GM.getValue(`${MYNAME}_cntr`);
- if (str === undefined) str = JSON.stringify([0, 0]); // 何も無い時
- let cntr = JSON.parse(str);
- let key, limit;
-
- if (n == 0) {
- key = `${MYNAME}_idl`;
- limit = 0;
- cntr = [cntr[0] + 1, cntr[1]];
- } else {
- key = `${MYNAME}_twts`;
- limit = 500;
- cntr = [cntr[0], cntr[1] + 1];
- }
-
- if (cntr[n] > limit) {
- let array = JSON.parse(await GM.getValue(key));
- array = [...new Set(array.map(JSON.stringify))].map(JSON.parse);
- await GM.setValue(key, JSON.stringify(array));
-
- cntr = n == 0 ? [0, cntr[1]] : [cntr[0], 0];
- }
-
- await GM.setValue(`${MYNAME}_cntr`, JSON.stringify(cntr));
- }
-
- async function touid(sn) {
- let str; // Temp
- str = await GM.getValue(`${MYNAME}_idl`);
- if (str === undefined) {
- // 何も無い時
- str = JSON.stringify([]);
- await GM.setValue(`${MYNAME}_idl`, str);
- }
- let array = JSON.parse(str);
- for (let e of array) {
- if (e[3].toLowerCase() == sn.toLowerCase()) return e;
- }
-
- let r = await getuid(sn); // 無い時
- if (r) {
- array = array.concat([r]);
- await GM.setValue(`${MYNAME}_idl`, JSON.stringify(array));
-
- return r.includes(sn) ? r : null;
- }
- console.log(`${MYNAME}: touid:error.`);
- return null; // エラー
- }
-
- async function getdetl(twtid) {
- let url =
- 'https://x.com/i/api/graphql/3HC_X_wzxnMmUBRIn3MWpQ/TweetResultByRestId';
-
- let q =
- '?variables={' +
- `"tweetId":"${twtid}",` +
- '"withCommunity":false,' +
- '"includePromotedContent":false,' +
- '"withVoice":false' +
- '}' +
- '&features={' +
- '"creator_subscriptions_tweet_preview_api_enabled":true,' +
- '"tweetypie_unmention_optimization_enabled":true,' +
- '"responsive_web_edit_tweet_api_enabled":true,' +
- '"graphql_is_translatable_rweb_tweet_is_translatable_enabled":true,' +
- '"view_counts_everywhere_api_enabled":true,' +
- '"longform_notetweets_consumption_enabled":true,' +
- '"responsive_web_twitter_article_tweet_consumption_enabled":false,' +
- '"tweet_awards_web_tipping_enabled":false,' +
- '"freedom_of_speech_not_reach_fetch_enabled":true,' +
- '"standardized_nudges_misinfo":true,' +
- '"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled":true,' +
- '"longform_notetweets_rich_text_read_enabled":true,' +
- '"longform_notetweets_inline_media_enabled":true,' +
- '"responsive_web_graphql_exclude_directive_enabled":true,' +
- '"verified_phone_label_enabled":false,' +
- '"responsive_web_media_download_video_enabled":false,' +
- '"responsive_web_graphql_skip_user_profile_image_extensions_enabled":false,' +
- '"responsive_web_graphql_timeline_navigation_enabled":true,' +
- '"responsive_web_enhance_cards_enabled":false' +
- '}' +
- '&fieldToggles={' +
- '"withArticleRichContentState":false,' +
- '"withAuxiliaryUserLabels":false' +
- '}';
- let eq = encodeURI(q);
-
- let controller = new AbortController();
- let req = mkreq(url, eq, EBTKN, controller);
- let res = {};
-
- try {
- setTimeout(function () {
- controller.abort();
- }, 60000);
- res = await fetch(req);
- if (!res.ok) {
- console.log(`${MYNAME}: getdtl:notok:${res.ok}.`);
- return null;
- } // 失敗なら空で終わり
- } catch (err) {
- console.log(`${MYNAME}: getdtl:error:${err}.`);
- return null; // 失敗なら空で終わり
- }
-
- let json = JSON.parse(await res.text());
-
- let tuid, tsn, tca, rtuid, rtsn, rtid, rtca, rts;
- let path_result = json.data.tweetResult.result;
- let tid = path_result.rest_id;
- if (!tid) {
- path_result = json.data.tweetResult.result.tweet;
- tid = path_result.rest_id;
- }
- let ts = path_result.source;
-
- if (typeof path_result.legacy !== 'undefined') {
- tuid = path_result.legacy.user_id_str;
- tsn = path_result.core.user_results.result.legacy.screen_name;
- tca = path_result.legacy.created_at;
- if (typeof path_result.legacy.retweeted_status_result !== 'undefined') {
- if (
- typeof path_result.legacy.retweeted_status_result.result.legacy !==
- 'undefined'
- ) {
- rtuid =
- path_result.legacy.retweeted_status_result.result.legacy.user_id_str;
- rtsn =
- path_result.legacy.retweeted_status_result.result.core.user_results
- .result.legacy.screen_name;
- rtid = path_result.legacy.retweeted_status_result.result.rest_id;
- rtca =
- path_result.legacy.retweeted_status_result.result.legacy.created_at;
- rts = path_result.legacy.retweeted_status_result.result.source;
- } else {
- rtuid =
- path_result.legacy.retweeted_status_result.result.tweet.legacy
- .user_id_str;
- rtsn =
- path_result.legacy.retweeted_status_result.result.tweet.core
- .user_results.result.legacy.screen_name;
- rtid = path_result.legacy.retweeted_status_result.result.tweet.rest_id;
- rtca =
- path_result.legacy.retweeted_status_result.result.tweet.legacy
- .created_at;
- rts = path_result.legacy.retweeted_status_result.result.tweet.source;
- }
- } else {
- rtuid = 'none';
- rtsn = 'none'; // 未確認
- rtid = 'none';
- rtca = 'none';
- rts = 'none';
- }
- } else {
- tuid = 'none';
- tsn = 'none'; // 未確認
- tca = 'none';
- rtuid = 'none';
- rtsn = 'none';
- rtid = 'none';
- rtca = 'none';
- rts = 'none';
- }
- let ret = [tuid, tsn, tid, tca, ts, rtuid, rtsn, rtid, rtca, rts];
-
- if (!tid || !ts) {
- console.log(`${MYNAME}: getdetl:error.`);
- return null; // エラー
- }
-
- let str = await GM.getValue(`${MYNAME}_twts`);
-
- if (str === undefined) {
- // 無い時
- await GM.setValue(`${MYNAME}_twts`, JSON.stringify([ret]));
- } else {
- // ある時
- let array = JSON.parse(str);
- array = array.concat([ret]);
- await GM.setValue(`${MYNAME}_twts`, JSON.stringify(array));
-
- await unique(1);
- }
-
- return ret;
- }
-
- async function gettwts(stat, text, path) {
- if (stat < 200 || stat > 299) {
- console.log(`${MYNAME}: gettwts:error:${stat}.`);
- return null; // エラー
- }
-
- let n = 0;
- let ret = [];
- let json = JSON.parse(text);
- let path_instructions =
- path.length == 4
- ? json['data'][path[0]][path[1]][path[2]][path[3]]['instructions']
- : path.length == 3
- ? json['data'][path[0]][path[1]][path[2]]['instructions']
- : json['data'][path[0]][path[1]]['instructions'];
-
- while (path_instructions[n].type != 'TimelineAddEntries')
- if (typeof path_instructions[++n] === 'undefined') return null;
-
- let path_entries = path_instructions[n].entries;
- let num = Object.keys(path_entries).length;
-
- for (let i = 0; i < num; i++) {
- if (!/^tweet-/i.test(path_entries[i].entryId)) continue;
-
- let path_tid = path_entries[i].content.itemContent.tweet_results.result;
- if (typeof path_tid.tweet !== 'undefined') {
- path_tid = path_tid.tweet;
- }
- let tid = path_tid.rest_id;
- let ts = path_tid.source;
- let tuid, tsn, tca, rtuid, rtsn, rtid, rtca, rts;
-
- if (typeof path_tid.legacy === 'undefined') {
- // 何も無い
- tuid = 'none';
- tsn = 'none'; // 未確認
- tca = 'none';
- rtuid = 'none';
- rtsn = 'none'; // 未確認
- rtid = 'none';
- rtca = 'none';
- rts = 'none';
- ret.push([tuid, tsn, tid, tca, ts, rtuid, rtsn, rtid, rtca, rts]);
- continue;
- }
-
- tuid = path_tid.legacy.user_id_str;
- tsn = path_tid.core.user_results.result.legacy.screen_name;
- tca = path_tid.legacy.created_at;
-
- if (typeof path_tid.legacy.retweeted_status_result === 'undefined') {
- // リツイートでは無い
- rtuid = 'none';
- rtsn = 'none';
- rtid = 'none';
- rtca = 'none';
- rts = 'none';
- ret.push([tuid, tsn, tid, tca, ts, rtuid, rtsn, rtid, rtca, rts]);
- continue;
- }
-
- let path_rtuid = path_tid.legacy.retweeted_status_result.result;
- if (typeof path_rtuid.tweet !== 'undefined') {
- path_rtuid = path_rtuid.tweet;
- }
-
- rtuid = path_rtuid.legacy.user_id_str;
- rtsn = path_rtuid.core.user_results.result.legacy.screen_name;
- rtca = path_rtuid.legacy.created_at;
- rts = path_rtuid.source;
-
- let path_rtid = path_rtuid.edit_control;
- if (typeof path_rtid.edit_control_initial !== 'undefined') {
- path_rtid = path_rtid.edit_control_initial;
- }
-
- rtid = path_rtid.edit_tweet_ids[5 - path_rtid.edits_remaining];
-
- ret.push([tuid, tsn, tid, tca, ts, rtuid, rtsn, rtid, rtca, rts]);
- }
-
- if (!ret) {
- console.log(`${MYNAME}: gettwts:error.`);
- return null; // エラー
- }
-
- let str = await GM.getValue(`${MYNAME}_twts`);
-
- if (str === undefined) {
- // 無い時
- await GM.setValue(`${MYNAME}_twts`, JSON.stringify(ret));
- } else {
- // ある時
- let array = JSON.parse(str);
- array = array.concat(ret);
- await GM.setValue(`${MYNAME}_twts`, JSON.stringify(array));
-
- await unique(1);
- }
- }
-
- async function gettwts_d(stat, text) {
- if (stat < 200 || stat > 299) {
- console.log(`${MYNAME}: gettwts_d:error:${stat}.`);
- return null; // エラー
- }
-
- let json = JSON.parse(text);
- let n = 0;
- let ret = [];
-
- if (json.errors) {
- console.log(`${MYNAME}: gettwts_d:error:errors.`);
- return null; // エラー
- }
-
- for (
- ;
- json.data.threaded_conversation_with_injections_v2.instructions[n].type !=
- 'TimelineAddEntries' &&
- json.data.threaded_conversation_with_injections_v2.instructions[n].type !=
- 'TimelineAddToModule';
- ++n
- );
- if (
- json.data.threaded_conversation_with_injections_v2.instructions[n].type ==
- 'TimelineAddToModule'
- ) {
- console.log(`${MYNAME}: gettwts_d:error:ne.`);
- return null; // エラー
- }
-
- let path_ents =
- json.data.threaded_conversation_with_injections_v2.instructions[n].entries;
- let num = Object.keys(path_ents).length; // 一個しかない?
-
- for (let i = 0; i < num; i++) {
- if (!/^tweet-/i.test(path_ents[i].entryId)) continue;
-
- let tuid, tsn, tca, rtuid, rtsn, rtid, rtca, rts;
- let path_result = path_ents[i].content.itemContent.tweet_results.result;
- let tid = path_result.rest_id;
- if (!tid) {
- path_result = path_ents[i].content.itemContent.tweet_results.result.tweet;
- tid = path_result.rest_id;
- }
- let ts = path_result.source;
-
- if (typeof path_result.legacy !== 'undefined') {
- tuid = path_result.legacy.user_id_str;
- tsn = path_result.core.user_results.result.legacy.screen_name;
- tca = path_result.legacy.created_at;
- if (typeof path_result.legacy.retweeted_status_result !== 'undefined') {
- if (
- typeof path_result.legacy.retweeted_status_result.result.legacy !==
- 'undefined'
- ) {
- rtuid =
- path_result.legacy.retweeted_status_result.result.legacy
- .user_id_str;
- rtsn =
- path_result.legacy.retweeted_status_result.result.core
- .user_results.result.legacy.screen_name;
- rtid = path_result.legacy.retweeted_status_result.result.rest_id;
- rtca =
- path_result.legacy.retweeted_status_result.result.legacy
- .created_at;
- rts = path_result.legacy.retweeted_status_result.result.source;
- } else {
- rtuid =
- path_result.legacy.retweeted_status_result.result.tweet.legacy
- .user_id_str;
- rtsn =
- path_result.legacy.retweeted_status_result.result.tweet.core
- .user_results.result.legacy.screen_name;
- rtid =
- path_result.legacy.retweeted_status_result.result.tweet.rest_id;
- rtca =
- path_result.legacy.retweeted_status_result.result.tweet.legacy
- .created_at;
- rts = path_result.legacy.retweeted_status_result.result.tweet.source;
- }
- } else {
- rtuid = 'none';
- rtsn = 'none'; // 未確認
- rtid = 'none';
- rtca = 'none';
- rts = 'none';
- }
- } else {
- tuid = 'none';
- tsn = 'none'; // 未確認
- tca = 'none';
- rtuid = 'none';
- rtsn = 'none';
- rtid = 'none';
- rtca = 'none';
- rts = 'none';
- }
-
- ret.push([tuid, tsn, tid, tca, ts, rtuid, rtsn, rtid, rtca, rts]);
- }
-
- if (!ret) {
- console.log(`${MYNAME}: gettwts_d:error.`);
- return null; // エラー
- }
-
- let str = await GM.getValue(`${MYNAME}_twts`);
-
- if (str === undefined) {
- // 無い時
- await GM.setValue(`${MYNAME}_twts`, JSON.stringify(ret));
- } else {
- // ある時
- let array = JSON.parse(str);
- array = array.concat(ret);
- await GM.setValue(`${MYNAME}_twts`, JSON.stringify(array));
-
- await unique(1);
- }
- }
-
- async function gettwts_r(stat, text) {
- if (stat < 200 || stat > 299) {
- console.log(`${MYNAME}: gettwts_r:error:${stat}.`);
- return null; // エラー
- }
-
- let json = JSON.parse(text);
- let path_ents = json.data;
- let num = Object.keys(path_ents).length;
- let ret = [];
-
- for (let i = 0; i < num; i++) {
- // 一個しかない?
- let tuid, tsn, tca, rtuid, rtsn, rtid, rtca, rts;
- let path_result = path_ents.tweetResult.result;
- let tid = path_result.rest_id;
- if (!tid) {
- path_result = path_ents.tweetResult.result.tweet;
- tid = path_result.rest_id;
- }
- let ts = path_result.source;
-
- if (typeof path_result.legacy !== 'undefined') {
- tuid = path_result.legacy.user_id_str;
- tsn = path_result.core.user_results.result.legacy.screen_name;
- tca = path_result.legacy.created_at;
- if (typeof path_result.legacy.retweeted_status_result !== 'undefined') {
- if (
- typeof path_result.legacy.retweeted_status_result.result.legacy !==
- 'undefined'
- ) {
- rtuid =
- path_result.legacy.retweeted_status_result.result.legacy
- .user_id_str;
- rtsn =
- path_result.legacy.retweeted_status_result.result.core
- .user_results.result.legacy.screen_name;
- rtid = path_result.legacy.retweeted_status_result.result.rest_id;
- rtca =
- path_result.legacy.retweeted_status_result.result.legacy
- .created_at;
- rts = path_result.legacy.retweeted_status_result.result.source;
- } else {
- rtuid =
- path_result.legacy.retweeted_status_result.result.tweet.legacy
- .user_id_str;
- rtsn =
- path_result.legacy.retweeted_status_result.result.tweet.core
- .user_results.result.legacy.screen_name;
- rtid =
- path_result.legacy.retweeted_status_result.result.tweet.rest_id;
- rtca =
- path_result.legacy.retweeted_status_result.result.tweet.legacy
- .created_at;
- rts = path_result.legacy.retweeted_status_result.result.tweet.source;
- }
- } else {
- rtuid = 'none';
- rtsn = 'none'; // 未確認
- rtid = 'none';
- rtca = 'none';
- rts = 'none';
- }
- } else {
- tuid = 'none';
- tsn = 'none'; // 未確認
- tca = 'none';
- rtuid = 'none';
- rtsn = 'none';
- rtid = 'none';
- rtca = 'none';
- rts = 'none';
- }
-
- ret.push([tuid, tsn, tid, tca, ts, rtuid, rtsn, rtid, rtca, rts]);
- }
-
- if (!ret) {
- console.log(`${MYNAME}: gettwts_r:error.`);
- return null; // エラー
- }
-
- let str = await GM.getValue(`${MYNAME}_twts`);
-
- if (str === undefined) {
- // 無い時
- await GM.setValue(`${MYNAME}_twts`, JSON.stringify(ret));
- } else {
- // ある時
- let array = JSON.parse(str);
- array = array.concat(ret);
- await GM.setValue(`${MYNAME}_twts`, JSON.stringify(array));
-
- await unique(1);
- }
- }
-
- async function statssn(sn) {
- let str = await GM.getValue(`${MYNAME}_twts`);
- if (!str) return null;
-
- let snl = sn.toLowerCase();
- let array = JSON.parse(str);
-
- for (let e of array) {
- let t = e[1].toLowerCase() == snl;
- let rt;
- if (!t) rt = e[6].toLowerCase() == snl;
-
- if (t || rt) return t ? [e[0], e[1]] : [e[5], e[6]];
- }
-
- return null;
- }
-
- function chklv(id) {
- let ud = +id.substring(0, 2);
-
- let l =
- ud < 13 ? LVL_12 :
- ud < 16 ? LVL_15 :
- ud < 20 ? LVL_19 :
- ud < 25 ? LVL_24 :
- ud < 30 ? LVL_29 :
- ud < 40 ? LVL_3 :
- ud < 50 ? LVL_4 :
- ud < 60 ? LVL_5 :
- ud < 70 ? LVL_6 :
- ud < 80 ? LVL_7 :
- ud < 90 ? LVL_8 :
- LVL_9;
-
- return l.includes(id);
- }
-
- async function statsrt(uid, rtid) {
- let str = await GM.getValue(`${MYNAME}_twts`);
- if (!str) return ['0000000000000000000', 'Thu Jan 01 00:00:00 +0000 1970'];
-
- let array = JSON.parse(str);
-
- for (let e of array) {
- if (e[0] == uid && e[7] == rtid) return [e[2], e[3]]; // あれば終わり
- }
-
- console.log(`${MYNAME}: statsrt:end.`);
- return ['0000000000000000000', 'Thu Jan 01 00:00:00 +0000 1970'];
- // エラー
- }
-
- function twXHRStateHandler({ target: xhr }, res) {
- if (xhr.readyState === 4) {
- const stat = xhr.status;
- const rawText = xhr.responseText;
- if (res == 1)
- gettwts(stat, rawText, ['user', 'result', 'timeline_v2', 'timeline']);
- else if (res == 2) gettwts(stat, rawText, ['home', 'home_timeline_urt']);
- else if (res == 3) gettwts(stat, rawText, ['home', 'home_timeline_urt']);
- else if (res == 4)
- gettwts(stat, rawText, ['list', 'tweets_timeline', 'timeline']);
- else if (res == 5)
- gettwts(stat, rawText, [
- 'search_by_raw_query',
- 'search_timeline',
- 'timeline',
- ]);
- else if (res == 6) gettwts_d(stat, rawText);
- else if (res == 7) gettwts_r(stat, rawText);
- }
- }
-
- function isTwtsURL(url) {
- if (!url.includes('/graphql/')) return 0;
- else if (url.includes('/UserTweets?')) return 1;
- else if (url.includes('/HomeTimeline')) return 2;
- else if (url.includes('/HomeLatestTimeline')) return 3;
- else if (url.includes('/ListLatestTweetsTimeline?')) return 4;
- else if (url.includes('/SearchTimeline?')) return 5;
- else if (url.includes('/TweetDetail?')) return 6;
- else if (url.includes('/TweetResultByRestId?')) return 7;
- else return 0;
- }
-
- function overrideXHROpen() {
- XMLHttpRequest.prototype.open = function () {
- let res = isTwtsURL(arguments[1]);
- if (res) {
- this.addEventListener('readystatechange', function (evt) {
- twXHRStateHandler(evt, res);
- });
- }
- return originalXHROpen.apply(this, arguments);
- };
-
- console.log(`${MYNAME}: XMLHttpRequest.open overriden.`);
- }
-
- async function subsbadge() {
- const SEL_V = 'path[d^="M20.396 11c-.018-.646-.215-1.275-.57-1"]';
- const SEL_B = 'path[d^="M16.5 3H2v18h15c3.038 0 5.5-2.46 5.5-5"]';
-
- let elms = document.querySelectorAll(`${SEL_V}, ${SEL_B}`);
-
- for (let e of elms) {
- const SEL_E =
- 'svg.r-4qtqp9.r-yyyyoo.r-lwhw9o.r-dnmrzs.r-bnwqim.' +
- 'r-1plcrui.r-lrvibr.r-cnnz9e';
- // def-ja, def-en, ble-ja, ble-en
- const SEL_E2 =
- 'svg.r-4qtqp9.r-yyyyoo.r-1xvli5t.r-dnmrzs.r-bnwqim.' +
- 'r-1plcrui.r-f5ekn1.r-17h40o6.r-lrvibr';
- // def-ja, def-en, ble-ja, ble-en
- const D_V =
- 'M20.396 11c-.018-.646-.215-1.275-.57-1.816-.354-.54-.852-.972-1.438-1.246.223-.6' +
- '07.27-1.264.14-1.897-.131-.634-.437-1.218-.882-1.687-.47-.445-1.053-.75-1.687-.8' +
- '82-.633-.13-1.29-.083-1.897.14-.273-.587-.704-1.086-1.245-1.44S11.647 1.62 11 1.' +
- '604c-.646.017-1.273.213-1.813.568s-.969.854-1.24 1.44c-.608-.223-1.267-.272-1.90' +
- '2-.14-.635.13-1.22.436-1.69.882-.445.47-.749 1.055-.878 1.688-.13.633-.08 1.29.1' +
- '44 1.896-.587.274-1.087.705-1.443 1.245-.356.54-.555 1.17-.574 1.817.02.647.218 ' +
- '1.276.574 1.817.356.54.856.972 1.443 1.245-.224.606-.274 1.263-.144 1.896.13.634' +
- '.433 1.218.877 1.688.47.443 1.054.747 1.687.878.633.132 1.29.084 1.897-.136.274.' +
- '586.705 1.084 1.246 1.439.54.354 1.17.551 1.816.569.647-.016 1.276-.213 1.817-.5' +
- '67s.972-.854 1.245-1.44c.604.239 1.266.296 1.903.164.636-.132 1.22-.447 1.68-.90' +
- '7.46-.46.776-1.044.908-1.681s.075-1.299-.165-1.903c.586-.274 1.084-.705 1.439-1.' +
- '246.354-.54.551-1.17.569-1.816zM9.662 14.85l-3.429-3.428 1.293-1.302 2.072 2.072' +
- ' 4.4-4.794 1.347 1.246z';
- const D_B =
- 'M16.5 3H2v18h15c3.038 0 5.5-2.46 5.5-5.5 0-1.4-.524-2.68-1.385-3.65-.08-.09-.089' +
- '-.22-.023-.32.574-.87.908-1.91.908-3.03C22 5.46 19.538 3 16.5 3zm-.796 5.99c.457' +
- '-.05.892-.17 1.296-.35-.302.45-.684.84-1.125 1.15.004.1.006.19.006.29 0 2.94-2.2' +
- '69 6.32-6.421 6.32-1.274 0-2.46-.37-3.459-1 .177.02.357.03.539.03 1.057 0 2.03-.' +
- '35 2.803-.95-.988-.02-1.821-.66-2.109-1.54.138.03.28.04.425.04.206 0 .405-.03.59' +
- '5-.08-1.033-.2-1.811-1.1-1.811-2.18v-.03c.305.17.652.27 1.023.28-.606-.4-1.004-1' +
- '.08-1.004-1.85 0-.4.111-.78.305-1.11 1.113 1.34 2.775 2.22 4.652 2.32-.038-.17-.' +
- '058-.33-.058-.51 0-1.23 1.01-2.22 2.256-2.22.649 0 1.235.27 1.647.7.514-.1.997-.' +
- '28 1.433-.54-.168.52-.526.96-.992 1.23z';
- const SEL_P_KS = 'form div[data-testid="TypeaheadUser"]'; // キーワード検索
- const SEL_P_KSR = 'form div[data-testid="typeaheadRecentSearchesItem"]'; // キーワード検索(最新)
- const SEL_P_DS =
- 'div[aria-labelledby="modal-header"] div.css-175oi2r.r-1wbh5a2.r-dnmrzs.r-1ny4l3l>' +
- 'div[data-testid^="User-Name"]'; // 表示をカスタマイズする、ノート
- const SEL_P_VRRT =
- 'main section article div[data-testid="card.layoutLarge.detail"]'; // ビデオ引用RT
- const SEL_P_T2 =
- 'main div[data-testid="primaryColumn"] div[data-testid="UserName"]'; // トップ2
- const SEL_P_RRT = 'main section article div[data-testid^="User-Name"]'; // 引用RT
- const SEL_KS =
- 'div.css-175oi2r.r-1awozwy.r-18u37iz.r-1wbh5a2 div.css-1rynq56.r-1wvb978 span'; // バグ?対策 def-ja, def-en
- const SEL =
- 'div.css-175oi2r.r-18u37iz.r-1wbh5a2.r-13hce6t span.css-1qaijid.r-bcqeeo.r-qvutc0';
- // def-ja, def-en, ble-ja, ble-en
- const SEL_2 =
- 'div.css-175oi2r.r-1awozwy.r-18u37iz.r-1wbh5a2 span.css-1qaijid.r-bcqeeo.r-qvutc0';
- // def-ja, def-en, ble-ja, ble-en
-
- let spe = e.parentNode.parentNode;
- let tpe = e.parentNode.parentNode.parentNode;
- let sn;
- let ss; // Temp.
-
- if (tpe.querySelector(`${SEL_E}, ${SEL_E2}`)) continue;
-
- if (spe.style.color == 'rgb(232, 134, 143)') {
- ss = s_mus;
- spe.style.color = 'rgb(29, 155, 240)';
- s_mus = ss;
- }
-
- let xpe = e.closest('main div[data-testid="primaryColumn"] h2[role="heading"]'); // トップ
- if (xpe) {
- sn = document.URL.split('/')[3];
- }
-
- if (!sn && spe.getAttribute('data-testid') == 'verificationBadge')
- sn = document.URL.split('/')[3];
- // 認証済アカウントポップアップ
-
- if (!sn) {
- let xpe = e.closest(SEL_P_KS);
- let sne;
- if (xpe) sne = xpe.querySelector(SEL_KS);
- if (sne) sn = sne.textContent.split('@')[1];
- }
- if (!sn) {
- let xpe = e.closest(SEL_P_KSR);
- let sne;
- if (xpe) sne = xpe.querySelector(SEL_KS);
- if (sne) sn = sne.textContent.split('@')[1];
- }
- if (!sn) {
- let xpe = e.closest(SEL_P_DS);
- let sne;
- if (xpe) sne = xpe.querySelector(SEL);
- if (sne) sn = sne.textContent.split('@')[1];
- }
- if (!sn) {
- let xpe = e.closest(SEL_P_VRRT);
- let sne;
- if (xpe) sne = xpe.querySelector(SEL);
- if (sne) sn = sne.textContent.split('@')[1];
- }
- if (!sn) {
- let xpe = e.closest(SEL_P_T2);
- let sne;
- if (xpe) sne = xpe.querySelector(SEL_2);
- if (sne) sn = sne.textContent.split('@')[1];
- }
- if (!sn) {
- let xpe = e.closest(SEL_P_RRT);
- let sne;
- if (xpe) sne = xpe.querySelector(SEL);
- if (sne) sn = sne.textContent.split('@')[1];
- }
-
- if (!sn) {
- let xpe = e.closest('a'); // ビデオ引用TW、TL等
- if (xpe) {
- let a = xpe.getAttribute('href').split('/')[1];
- let b = xpe.getAttribute('href').split('/')[2];
- let c = xpe.getAttribute('href').split('/')[3];
-
- if (a == 'i' && b == 'status') {
- let str = await GM.getValue(`${MYNAME}_twts`);
- let array = [];
- if (str) array = JSON.parse(str);
-
- for (let e of array) {
- if (e[2] == c) {
- sn = e[1];
- break;
- } else if (e[7] == c) {
- sn = e[6];
- break;
- }
- }
-
- if (!sn) {
- let detl = await getdetl(c);
- if (detl) sn = detl[1];
- }
- } else {
- sn = a;
- }
- }
- }
-
- if (!sn) {
- ss = s_mus;
- spe.style.color = 'rgb(232, 134, 143)';
- s_mus = ss;
- continue;
- }
-
- let a = [
- '',
- 'compose',
- 'explore',
- 'home',
- 'i',
- 'login',
- 'messages',
- 'notifications',
- 'search',
- 'search-advanced',
- 'settings',
- ];
-
- if (a.includes(sn.toLowerCase())) {
- ss = s_mus;
- spe.style.color = 'rgb(232, 134, 143)';
- s_mus = ss;
- continue;
- }
-
- let pr = await statssn(sn); // screen name -> id, screen_name
- if (!pr) pr = await touid(sn); // screen name -> id, blue, created_at, screen_name, verified
- let r = pr ? chklv(pr[0]) : pr;
-
- ss = s_mus;
- if (r === true) {
- e.setAttribute('d', D_V);
- } else if (r === false) {
- e.setAttribute('d', D_B);
- } else {
- spe.style.color = 'rgb(232, 134, 143)';
- }
- s_mus = ss;
- }
- }
-
- async function addsl() {
- const SEL_END =
- 'main div[data-testid="primaryColumn"] section article ' +
- 'div.css-175oi2r.r-1d09ksm.r-1471scf.r-18u37iz.r-1wbh5a2';
- const SEL_END_RT =
- 'main div[data-testid="primaryColumn"] section article ' +
- 'span[id].r-8akbws.r-krxsd3.r-n6v787.r-1cwl3u0.r-b88u0q';
- const SEL_ADD = `span.us-${MYNAME}`;
-
- let uid, tid, tsl, rtsl, thref, rthref, detl;
- let ca, span, span2, a, a2;
-
- let elm_end = document.querySelector(SEL_END);
- let elm_end_rt = document.querySelector(SEL_END_RT);
- if (!elm_end) return;
-
- let old = elm_end.querySelectorAll(SEL_ADD);
- if (old.length) return;
-
- tsl = '?';
- rtsl = '(?)';
- thref = 'https://help.twitter.com/using-twitter/how-to-tweet#source-labels';
- if (/^[^:]+:\/\/[^/]+\.onion\//i.test(document.URL)) {
- thref =
- 'https://help.twitter3e4tixl4xyajtrzo62zg5vztmjuricljdp2c5kshju4avyoid.onion' +
- '/using-twitter/how-to-tweet#source-labels';
- }
- rthref = thref;
-
- ca = elm_end.querySelector('a');
- tid = ca.getAttribute('href').split('/')[3];
-
- if (elm_end_rt) {
- let pe = elm_end_rt.parentNode;
- let sn = pe.getAttribute('href').slice(1);
-
- uid = await statssn(sn); // screen name -> id, screen_name
- if (!uid) uid = await touid(sn); // screen name -> id, blue, created_at, screen_name, verified
- // リツイートした人のuid
- }
-
- let str = await GM.getValue(`${MYNAME}_twts`); // 出来るだけ遅らせる?
- let array = [];
- if (str) array = JSON.parse(str);
-
- let i = 2;
- if (document.URL.split('/')[5] != tid) i = 7;
-
- for (let e of array) {
- if (e[i] == tid) {
- detl = e;
- break;
- }
- }
-
- if (!detl) detl = await getdetl(tid); // ツイートはtid、rtidどちらにもなり得る
-
- if (detl) {
- tsl = detl[4].split('<')[1].split('>')[1];
- thref = detl[4].split('"')[1];
- } else {
- console.log(`${MYNAME}: addsl:error.`); // エラー
- }
-
- if (ssl == 1 || !elm_end_rt) {
- } else if (uid) {
- for (let e of array) {
- if (e[0] == uid[0] && e[7] == tid) {
- // リツイートは一つしか無い
- rtsl = `(${e[4].split('<')[1].split('>')[1]})`;
- rthref = e[4].split('"')[1];
- break;
- }
- }
- }
-
- span = document.createElement('span');
- span.className = `us-${MYNAME}`;
- span.style.margin = '0px 3px 0px 3px';
- span.textContent = '·';
- span.style.color = getComputedStyle(ca, null).color;
- span.style.font = getComputedStyle(ca, null).font;
- span.style.lineHeight = getComputedStyle(elm_end, null).lineHeight;
-
- span2 = document.createElement('span');
- span2.className = `us-${MYNAME}`;
- span2.style.lineHeight = getComputedStyle(elm_end, null).lineHeight;
- span2.style.display = 'inline-block';
-
- a = document.createElement('a');
- a.className = `us-${MYNAME}`;
- a.setAttribute('role', 'link');
- a.setAttribute('href', thref);
- a.setAttribute('target', '_blank');
- a.setAttribute('rel', 'nofollow noopener noreferrer');
- a.textContent = tsl;
- a.style.color = getComputedStyle(ca, null).color;
- a.style.font = getComputedStyle(ca, null).font;
- a.style.textDecoration = getComputedStyle(ca, null).textDecoration;
-
- a2 = document.createElement('a');
- a2.className = `us-${MYNAME}`;
- a2.setAttribute('role', 'link');
- a2.setAttribute('href', rthref);
- a2.setAttribute('target', '_blank');
- a2.setAttribute('rel', 'nofollow noopener noreferrer');
- a2.textContent = rtsl;
- a2.style.color = getComputedStyle(ca, null).color;
- a2.style.font = getComputedStyle(ca, null).font;
- a2.style.textDecoration = getComputedStyle(ca, null).textDecoration;
-
- let ss = s_mus;
-
- elm_end.appendChild(span);
- elm_end.appendChild(span2);
- span2.appendChild(a);
- if (ssl == 2 && elm_end_rt) span2.appendChild(a2);
-
- s_mus = ss;
- }
-
- async function main_track() {
- const SEL_END_RT =
- 'main div[data-testid="primaryColumn"] section article ' +
- 'span[id].r-8akbws.r-krxsd3.r-n6v787.r-1cwl3u0.r-b88u0q';
-
- let elms = document.querySelectorAll(SEL_END_RT);
-
- for (let elm of elms) {
- const SEL_RTTO = `div[data-testid^="User-Name"] a.css-146c3p1.r-qvutc0:not(.us-${MYNAME})`; // UTL, HTL
- const SEL_RTTO_2 =
- 'main div[data-testid="primaryColumn"] section article ' +
- `div.css-175oi2r.r-1d09ksm.r-1471scf.r-18u37iz.r-1wbh5a2 a.css-1jxf684.r-qvutc0:not(.us-${MYNAME})`;
- // Retweet def-ja, def-en, ble-ja, ble-en
- const SEL_ADD = `a.us-${MYNAME}`;
-
- let pe = elm.parentNode;
- let fpe = elm.parentNode.parentNode.parentNode.parentNode;
- let xpe = elm.closest('article');
- let elm2 = xpe.querySelector(SEL_RTTO);
- if (!elm2) elm2 = xpe.querySelector(SEL_RTTO_2);
- let old = fpe.querySelector(SEL_ADD);
-
- let sn = pe.getAttribute('href').slice(1);
- if (sn.includes('/')) continue;
-
- let rtid = elm2.getAttribute('href').split('/')[3];
-
- let id = await statssn(sn); // screen name -> id, screen_name
- if (!id) id = await touid(sn); // screen name -> id, blue, created_at, screen_name, verified
- if (!id) continue;
-
- let stats = await statsrt(id[0], rtid); // id, rtid -> tid, tca
-
- let span, span2, a;
- let date;
- let ss; // Temp.
-
- if (!fmt) continue;
-
- if (!old) {
- span = document.createElement('span');
- span.className = `us-${MYNAME}`;
- span.style.margin = '0px 3px 0px 3px';
- span.textContent = '·';
- span.style.color = getComputedStyle(elm, null).color;
- span.style.font = getComputedStyle(elm, null).font;
- span.style.lineHeight = getComputedStyle(pe, null).lineHeight;
-
- span2 = document.createElement('span');
- span2.className = `us-${MYNAME}`;
- span2.style.lineHeight = getComputedStyle(pe, null).lineHeight;
- span2.style.display = 'inline-block';
-
- a = document.createElement('a');
- a.className = `us-${MYNAME}`;
- a.setAttribute('dir', 'ltr');
- a.setAttribute('role', 'link');
- a.setAttribute('href', `/${sn}/status/${stats[0]}`);
- a.setAttribute('target', '_blank');
- a.setAttribute('rel', 'noopener noreferrer');
- date = datef(new Date(stats[1]), fmt);
- a.textContent = date;
- a.style.color = getComputedStyle(elm, null).color;
- a.style.font = getComputedStyle(elm, null).font;
- a.style.textDecoration = getComputedStyle(elm, null).textDecoration;
-
- ss = s_mus;
-
- fpe.appendChild(span);
- fpe.appendChild(span2);
- span2.appendChild(a);
-
- s_mus = ss;
- } else {
- ss = s_mus;
-
- date = datef(new Date(stats[1]), fmt);
- if (old.textContent != date) old.textContent = date; // TZ change
-
- s_mus = ss;
- }
- }
- }
-
- console.log(`${MYNAME}: start.`);
-
- tb = TB;
- ssl = SSL;
- fmt = FMT;
- intl = INTL;
-
- if (!NOGUI) await initgui();
- overrideXHROpen();
- observer.observe(document.documentElement, { childList: true, subtree: true });
-
- while (1) {
- if (s_mus) {
- s_mus = null; // 初期値がtrue、変更もしない
- if (tb) await subsbadge();
- if (ssl) await addsl();
- if (fmt || ssl == 2) await main_track();
- }
-
- await new Promise((resolve) => setTimeout(resolve, intl)); // intl は外から非同期に変更する
- }
-
-
- })(); /* END */