// ==UserScript==
// @name Show ctime of retweets
// @name:ja リツイート自体の日時を表示します
// @name:ko 리트윗 날짜와 시간을 표시합니다.
// @name:zh-CN 显示转发的日期和时间。
// @name:zh-TW 顯示轉發的日期和時間。
// @namespace https://gf.qytechs.cn/en/scripts/461409-show-ctime-of-retweets
// @version 1.0
// @description And shows tweet source labels.
// @description:ja ツイートソースラベルも表示できます。
// @description:ko 트윗 소스 라벨도 표시할 수 있습니다.
// @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/*
// @grant GM.getValue
// @grant GM.registerMenuCommand
// @grant GM.setValue
// @run-at document-idle
// ==/UserScript==
//
// ES2017(ES8) or later.
//
// ES2017(ES8) 以降が必要です。
//
// ES2017(ES8) 이상이 필요합니다.
//
// 需要 ES2017(ES8) 或更高版本。
//
// 需要 ES2017(ES8) 或更高版本。
(async function() { /* START */
'use strict';
// //////////// Settings //////////// //
// No GUI Settings
// Default values are used.
const NOGUI = false;
// ////////////////////////////////// //
// ///////// Default valuse ///////// //
// Date formats
// 1. 31.12.70 23:59
// 2. 31.12.70(Th) 23:59
// 3. 31.12.70 23:59:59
// 4. 31.12.70(Th) 23:59:59
//
// 5. 70-12/31 23:59
// 6. 70-12/31(Th) 23:59
// 7. 70-12/31 23:59'59
// 8. 70-12/31(Th) 23:59'59
//
// 9. 70/12/31 23:59
// 10. 70/12/31(Th) 23:59
// 11. 70/12/31 23:59:59
// 12. 70/12/31(Th) 23:59:59 [ye/mo/da(we) ho:mi:se]
//
// 0. Not Shown
const FMT = 10;
// Show source labels
// 1. Tweet only
// 2. Tweet and (Retweet)
// 0. Not shown
const SSL = 2;
// Loop interval(ms)
// const INTL = 1000;
const INTL = 800;
// ////////////////////////////////// //
const MYNAME = 'sctrt10';
const BTKN = 'AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs'
+ '=1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA';
const EBTKN = encodeURIComponent(BTKN);
let top_sr = '1';
let json_sr = [];
let json_sr_new = [];
let timeout_sr = false;
let s_mus = true;
let observer = new MutationObserver(function(mutations) {
s_mus = mutations;
});
let fmt, ssl, intl;
let dalg;
let cookie = { // "https://qiita.com/aqril_1132/items/925a7cb04276d9f916d7"
getObj: function() {
let cookie = document.cookie;
let cookieObj = {};
if (!!cookie) {
Array.prototype.forEach.call(cookie.split(';'), function(c) {
let array = [c][0].split('=').map(function(a) {return a.trim()});
let key = ~c.indexOf('=') ? unescape(array[0]) : '';
let val = ~c.indexOf('=') ? unescape(array[1]) : unescape(array[0]);
if (!cookieObj.hasOwnProperty(key)) {
cookieObj[key] = [val];
} else {
cookieObj[key].push(val);
}
});
}
return cookieObj;
},
getByName: function(name) {
let ret = [];
let cookieObj = this.getObj();
if (cookieObj.hasOwnProperty(name)) {
ret = cookieObj[name];
}
return ret;
},
deleteByName : function(name, path) {
var str = escape(name)
+ '=; expires=Thu, 01 Jan 1970 00:00:00 GMT'
+ (path ? '; path=' + path : '');
document.cookie = str;
}
};
async function main_track() {
s_mus = null; // 不要?
const SEL_END = 'main div[data-testid="primaryColumn"] section article span.css-cens5h.r-b88u0q:not([aria-label])';
const SEL_RTTO = `div[data-testid^="User-Name"] a.css-901oao.r-qvutc0:not(.us-${MYNAME})`; // UTL, HTL
const SEL_RTTO_2 = 'main div[data-testid="primaryColumn"] section article '
+ `div.css-1dbjc4n.r-1d09ksm.r-1471scf.r-18u37iz.r-1wbh5a2 a.css-901oao.r-qvutc0:not(.us-${MYNAME})`;
// Retweet def-ja, def-en, ble-ja, ble-en
const SEL_ADD = `a.us-${MYNAME}`;
let elms;
let pe, fpe, xpe, elm2, old, span, span2, a;
let sn, rtto, date;
let id, stats;
elms = document.querySelectorAll(SEL_END);
for(let elm of elms) {
pe = elm.parentNode;
fpe = elm.parentNode.parentNode.parentNode.parentNode;
sn = pe.getAttribute('href').slice(1);
xpe = elm.closest('article');
elm2 = xpe.querySelector(SEL_RTTO);
if(!elm2) elm2 = xpe.querySelector(SEL_RTTO_2);
rtto = elm2.getAttribute('href').split('/')[3];
id = await touid(sn); // screen name -> id, blue, created_at, screen_name, verified
if(!id) continue;
stats = await statsrt(id[0], rtto); // id, rtto -> tid, tca
if(!fmt) continue;
old = fpe.querySelector(SEL_ADD)
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;
fpe.appendChild(span);
fpe.appendChild(span2);
span2.appendChild(a);
s_mus = null;
} else {
date = datef(new Date(stats[1]), fmt);
if(old.textContent != date) old.textContent = date; // TZ change
}
}
}
async function touid(sn) {
if(localStorage.getItem(`${MYNAME}_idl`) === null) { // 無い時
let s = JSON.stringify(await getuid(sn)); // screen name -> id, blue, created_at, screen_name, verified
if(s) {
localStorage.setItem(`${MYNAME}_idl`, s);
} else {
console.log(`${MYNAME}: touid:error.`);
return null; // エラー
}
}
let str = localStorage.getItem(`${MYNAME}_idl`); // ある時はココから
let json = JSON.parse(str);
for(let e of json) {
if(e[3] == sn) return e;
}
json = json.concat(await getuid(sn)); // あるけど、無い時
str = JSON.stringify(json);
localStorage.setItem(`${MYNAME}_idl`, str);
for(let e of json) {
if(e[3] == sn) return e;
}
console.log(`${MYNAME}: touid:error:end.`);
return null; // エラー
}
async function getuid(s_name) {
let url = 'https://api.twitter.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:error:` + 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 statsrt(uid, rtto) { // 連続している事、entries[]の順序が正しい事
let num = localStorage.length;
let keys = [];
let str = '';
let time = null;
top_sr = '1';
json_sr = [];
json_sr_new = [];
timeout_sr = false; // 初期化
for(let i = 0; i < num; i++) {
keys.push(localStorage.key(i));
}
if(!keys.includes(`${MYNAME}_tl_` + uid)) { // 無い時
let s = JSON.stringify(await gettl(uid, null)); // id, cursor -> tid, tca, s, rtid, rtca
if(s) {
localStorage.setItem(`${MYNAME}_tl_` + uid, s);
} else {
console.log(`${MYNAME}: statsrt:error.`);
return ['0000000000000000000', 'Thu Jan 01 00:00:00 +0000 1970']; // エラー
}
}
if(localStorage.getItem(`${MYNAME}_timerl`) === null) {
time = Date.now();
localStorage.setItem(`${MYNAME}_timerl`, JSON.stringify([[uid, time]]));
} else {
let j = JSON.parse(localStorage.getItem(`${MYNAME}_timerl`));
for(let e of j) if(e[0] == uid) time = e[1];
if(!time) { // 項目が無い時
time = Date.now(); // この時点の保存値にセットされる
j = j.concat([[uid, time]]);
localStorage.setItem(`${MYNAME}_timerl`, JSON.stringify(j));
}
}
str = localStorage.getItem(`${MYNAME}_tl_` + uid); // ある時はココから
json_sr = JSON.parse(str);
for(let e of json_sr) {
if(e[3] == rtto) return [e[0], e[1]]; // あれば終わり
}
for(let e of json_sr) {
if(/^[0-9]/i.test(e[0])) {
top_sr = e[0];
break;
}
} // 上作成
await statsrt_new(uid, rtto); // json_sr、json_sr_new更新
json_sr = json_sr_new.concat(json_sr); // json_sr更新
str = JSON.stringify(json_sr); // str更新
localStorage.setItem(`${MYNAME}_tl_` + uid, str); // とりあえず、ストレージに保存
for(let e of json_sr) {
if(e[3] == rtto) return [e[0], e[1]]; // あれば終わり
}
let ret = await statsrt_old(uid, rtto); // json_sr更新、保存
if(ret) return ret;
let j = JSON.parse(localStorage.getItem(`${MYNAME}_timerl`));
for(let e of j) if(e[0] == uid) time = e[1]; // time更新
if(!timeout_sr && Date.now() - time > 600000) {
localStorage.removeItem(`${MYNAME}_tl_${uid}`); // センシティブ
console.log(`${MYNAME}: statsrt:remove:${MYNAME}_tl_${uid}.`);
j = j.filter(function(e) {
return e[0] != uid;
});
localStorage.setItem(`${MYNAME}_timerl`, JSON.stringify(j));
time = null;
}
console.log(`${MYNAME}: statsrt:end.`);
return ['0000000000000000000', 'Thu Jan 01 00:00:00 +0000 1970'];
// TLがとても古いか、センシティブか、エラー
}
async function statsrt_new(uid, rtto) { // json_sr、json_sr_new更新
let btmtmp = '';
outer_block:
for(const start = Date.now(); 1;) { // 新しい方、top_srを見る
let ret = await gettl(uid, btmtmp);
json_sr_new = json_sr_new.concat(ret); // json_sr_new更新
for(let e of json_sr_new.slice().reverse()) { // 不要
if(/^[0-9]/i.test(e[0])) {
btmtmp = e[0];
break;
}
} // 下更新
if(ret.length < 2) {
json_sr = []; // 非連続
let j = JSON.parse(localStorage.getItem(`${MYNAME}_timerl`));
j = j.filter(function(e) {
return e[0] != uid;
});
j = j.concat([[uid, Date.now()]]);
localStorage.setItem(`${MYNAME}_timerl`, JSON.stringify(j));
break;
} // 空の時は終了、一回目は無い(一個の時以外)
for(let e of json_sr_new) {
if(e[0] == top_sr) break outer_block; // あれば終了
}
if(Date.now() - start > 150000) { // 時間経過時打ち切り
json_sr = []; // 非連続かも
let j = JSON.parse(localStorage.getItem(`${MYNAME}_timerl`));
j = j.filter(function(e) {
return e[0] != uid;
});
j = j.concat([[uid, Date.now()]]);
localStorage.setItem(`${MYNAME}_timerl`, JSON.stringify(j));
break;
}
await new Promise(resolve => setTimeout(resolve, 200));
}
}
async function statsrt_old(uid, rtto) {
let btm = '';
for(const start = Date.now(); 1;) { // 古い方、rttoを見る
for(let e of json_sr.slice().reverse()) { // 不要
if(/^[0-9]/i.test(e[0])) {
btm = e[0];
break;
}
} // 下更新
let ret = await gettl(uid, btm);
json_sr = json_sr.concat(ret); // json_sr更新
let s = JSON.stringify(json_sr);
localStorage.setItem(`${MYNAME}_tl_` + uid, s); // とりあえず、ストレージに保存
if(ret.length < 2) {
break;
} // 空の時は終了
for(let e of json_sr) {
if(e[3] == rtto) return [e[0], e[1]]; // あれば終わり
}
if(Date.now() - start > 300000) {
timeout_sr = true;
break;
} // 時間経過時打ち切り
await new Promise(resolve => setTimeout(resolve, 200));
}
}
async function gettl(id, cs) {
let url = 'https://api.twitter.com/1.1/statuses/user_timeline.json';
if(/^[^:]+:\/\/[^/]+\.onion\//i.test(document.URL)) {
url = 'https://api.twitter3e4tixl4xyajtrzo62zg5vztmjuricljdp2c5kshju4avyoid.onion/'
+ '1.1/statuses/user_timeline.json';
}
let kav = '';
if(cs) kav = `&max_id=${cs}`;
let q = `?user_id=${id}&count=50${kav}`;
let eq = encodeURI(q);
let controller = new AbortController();
let req = mkreq(url, eq, EBTKN, controller);
let res = {};
let ret = [];
try {
setTimeout(function() {controller.abort()}, 60000);
res = await fetch(req);
if(!res.ok) {
console.log(`${MYNAME}: gettl:error:` + res.ok + '.');
return null;
} // 失敗なら空で終わり
} catch(err) {
console.log(`${MYNAME}: gettl:error:` + err + '.');
return null; // 失敗なら空で終わり
}
let json = JSON.parse(await res.text());
let num = Object.keys(json).length;
let tid, tca, s, rtid, rtca;
for(let i = 0; i < num; i++) {
tid = json[i].id_str;
tca = json[i].created_at;
s = json[i].source;
if(typeof(json[i].retweeted_status) !== 'undefined') {
rtid = json[i].retweeted_status.id_str;
rtca = json[i].retweeted_status.created_at;
} else {
rtid = 'none';
rtca = 'none';
}
ret.push([tid, tca, s, rtid, rtca]);
}
return ret;
}
async function addsl() {
s_mus = null; // 不要?
const SEL_END = 'main div[data-testid="primaryColumn"] section article div.css-1dbjc4n.r-1d09ksm.r-1471scf.r-18u37iz.r-1wbh5a2';
const SEL_END_RT = 'main div[data-testid="primaryColumn"] section article span.css-cens5h.r-b88u0q:not([aria-label])';
const SEL_ADD = `span.us-${MYNAME}`;
let old;
let ca, span, span2, a, a2;
let elms_end = document.querySelectorAll(SEL_END);
for(let elm of elms_end) {
let uid;
let tid;
let tsl = '?';
let rtsl = '(?)';
let 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';
}
let rthref = thref;
ca = elm.querySelector('a');
tid = ca.getAttribute('href').split('/')[3];
let detl = await getdetl(tid); // tid -> tca, s, uid, sn, uca
if(detl) {
tsl = detl[1].split('<')[1].split('>')[1];
thref = detl[1].split('"')[1];
}
let elm_end_rt = document.querySelector(SEL_END_RT);
if(elm_end_rt) {
let pe = elm_end_rt.parentNode;
let sn = pe.getAttribute('href').slice(1);
uid = await touid(sn); // screen name -> id, blue, created_at, screen_name, verified
// リツイートした人のuid
}
if(ssl == 1 || !elm_end_rt) {
;
} else if(uid && localStorage.getItem(`${MYNAME}_tl_${uid[0]}`) !== null) {
let str = localStorage.getItem(`${MYNAME}_tl_${uid[0]}`);
let json = JSON.parse(str);
for(let e of json) {
if(e[3] == tid) {
rtsl = '(' + e[2].split('<')[1].split('>')[1] + ')';
rthref = e[2].split('"')[1];
}
}
}
old = elm.querySelectorAll(SEL_ADD)
if(!old.length) {
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, null).lineHeight;
span2 = document.createElement('span');
span2.className = `us-${MYNAME}`;
span2.style.lineHeight = getComputedStyle(elm, 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;
elm.appendChild(span);
elm.appendChild(span2);
span2.appendChild(a);
if(ssl == 2 && elm_end_rt) span2.appendChild(a2);
s_mus = null;
}
}
}
async function getdetl(tid) {
let url = 'https://api.twitter.com/1.1/statuses/show.json';
if(/^[^:]+:\/\/[^/]+\.onion\//i.test(document.URL)) {
url = 'https://api.twitter3e4tixl4xyajtrzo62zg5vztmjuricljdp2c5kshju4avyoid.onion/'
+ '1.1/statuses/show.json';
}
let q = `?id=${tid}`;
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:error:` + res.ok + '.');
return null;
} // 失敗なら空で終わり
} catch(err) {
console.log(`${MYNAME}: getdtl:error:` + err + '.');
return null; // 失敗なら空で終わり
}
let json = JSON.parse(await res.text());
let num = 1; // 一個しかない
let tca, s, uid, sn, uca;
for(let i = 0; i < num; i++) {
tca = json.created_at;
s = json.source;
if(typeof(json.user) !== 'undefined') {
uid = json.user.id_str;
sn = json.user.screen_name;
uca = json.user.created_at;
} else {
uid = 'none';
sn = 'none';
uca = 'none';
}
}
return [tca, s, uid, sn, uca];
}
function mkreq(url, eq, ebt, controller) {
let req;
if(cookie.getByName('gt').length && !cookie.getByName('twid').length) {
req = new Request(`${url}${eq}`,{
headers: {
'authorization': `Bearer ${ebt}`,
'x-csrf-token': cookie.getByName('ct0')[0],
'x-guest-token': cookie.getByName('gt')[0]
},
cache: 'force-cache',
redirect: 'follow',
signal: controller.signal
});
} else {
req = new Request(`${url}${eq}`,{
headers: {
'authorization': `Bearer ${ebt}`,
'x-csrf-token': cookie.getByName('ct0')[0],
'x-twitter-auth-type': 'OAuth2Session'
},
cache: 'force-cache',
redirect: 'follow',
mode: 'cors',
credentials: 'include',
signal: controller.signal
});
}
return req;
}
function datef(date, f) {
let week_l;
let l = document.documentElement.getAttribute('lang');
l == 'ja' ? week_l = ['日', '月', '火', '水', '木', '金', '土']
: l == 'ko' ? week_l = ['일', '월', '화', '수', '목', '금', '토']
: l == 'zh-Hant' ? week_l = ['日', '一', '二', '三', '四', '五', '六']
: l == 'zh' ? week_l = ['日', '一', '二', '三', '四', '五', '六']
: l == 'ru' ? week_l = ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб']
: l == 'de' ? week_l = ['Son', 'Mon', 'Die', 'Mit', 'Don', 'Fre', 'Sam']
: l == 'it' ? week_l = ['Dom', 'Lun', 'Mar', 'Mer', 'Gio', 'Ven', 'Sab']
: l == 'fr' ? week_l = ['Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam']
: l == 'pt' ? week_l = ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'] // Add your language
: week_l = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'];
let ye, mo, da, we, ho, mi, se;
ye = date.getFullYear().toString().slice(-2);
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}(${we}) ${ho}:${mi}`
: f == 3 ? `${da}.${mo}.${ye} ${ho}:${mi}:${se}`
: f == 4 ? `${da}.${mo}.${ye}(${we}) ${ho}:${mi}:${se}`
: f == 5 ? `${ye}-${mo}/${da} ${ho}:${mi}`
: f == 6 ? `${ye}-${mo}/${da}(${we}) ${ho}:${mi}`
: f == 7 ? `${ye}-${mo}/${da} ${ho}:${mi}'${se}`
: f == 8 ? `${ye}-${mo}/${da}(${we}) ${ho}:${mi}'${se}`
: f == 9 ? `${ye}/${mo}/${da} ${ho}:${mi}`
: f == 10 ? `${ye}/${mo}/${da}(${we}) ${ho}:${mi}`
: f == 11 ? `${ye}/${mo}/${da} ${ho}:${mi}:${se}`
: f == 12 ? `${ye}/${mo}/${da}(${we}) ${ho}:${mi}:${se}`
: `${ye}/${mo}/${da}(${we}) ${ho}:${mi}:${se}`;
}
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 = '320px';
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%">';
html += `${GM.info.script.name} ${GM.info.script.version} Settings`;
html += '</span><br />\n';
html += `<input type="radio" name="fmt" value="1" class="top_r" />31.12.70 23:59`;
html += ` `;
html += `<input type="radio" name="fmt" value="9" class="top_r" />70/12/31 23:59<br />\n`;
html += `<input type="radio" name="fmt" value="2" class="mid_r" />31.12.70(Th) 23:59`;
html += ` `;
html += `<input type="radio" name="fmt" value="10" class="mid_r" />70/12/31(Th) 23:59<br />\n`;
html += `<input type="radio" name="fmt" value="3" class="mid_r" />31.12.70 23:59:59`;
html += ` `;
html += `<input type="radio" name="fmt" value="11" class="mid_r" />70/12/31 23:59:59<br />\n`;
html += `<input type="radio" name="fmt" value="4" class="mid_r" />31.12.70(Th) 23:59:59`;
html += ` `;
html += `<input type="radio" name="fmt" value="12" class="mid_r" />70/12/31(Th) 23:59:59<br />\n`;
html += `<input type="radio" name="fmt" value="5" class="mid_r" />70-12/31 23:59`;
html += ` `;
html += `<input type="radio" name="fmt" value="0" class="mid_r" />Not Shown<br />\n`;
html += `<input type="radio" name="fmt" value="6" class="mid_r" />70-12/31(Th) 23:59<br />\n`;
html += `<input type="radio" name="fmt" value="7" class="mid_r" />70-12/31 23:59'59<br />\n`;
html += `<input type="radio" name="fmt" value="8" class="btm_r" />70-12/31(Th) 23:59'59<br />\n`;
html += `<input type="radio" name="ssl" value="1" class="top_r" />Tweet source labels only`;
html += ` `;
html += `<input type="radio" name="ssl" value="0" class="top_r" />Not shown<br />\n`;
html += `<input type="radio" name="ssl" value="2" class="btm_r" />Tweet and (Retweet)<br />\n`;
html += '<span style="all: initial; font-size: 100%">';
html += 'Loop interval(ms) ';
html += '</span><input type="text" name="intl" size="10" class="top_t" /><br />\n';
html += '<input type="button" class="top_b" value="Cancel" />\n';
html += '<input type="button" class="top_b" value="Set default" />\n';
html += '<input type="button" class="top_b" value="Save & Close" />\n';
dalg.innerHTML = html;
for(let e of dalg.querySelectorAll('input.top_r, 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_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 = '1px';
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 = '6px';
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="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;
}
}
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('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('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="ssl"][value="${ssl}"]`).checked = true;
dalg.querySelector('input[name="intl"]').value = intl;
dalg.style.display = 'block';
}
});
}
console.log(`${MYNAME}: start.`);
fmt = FMT;
ssl = SSL;
intl = INTL;
if(!NOGUI) await initgui();
observer.observe(document.documentElement, {childList:true, subtree:true});
while(1) {
if(s_mus) {
if(fmt || ssl == 2) await main_track();
if(ssl) await addsl();
s_mus = null; // 初期値がtrue、非同期処理用
}
await new Promise(resolve => setTimeout(resolve, intl)); // intl は外から非同期に変更する
}
})(); /* END */