=A!
by
noromanba
2018-01-21 [2018/01/21 04:18:00]
(Forked from
A! by
noromanba)
Hatena Antenna force bulk checker
@@ -7,9 +7,19 @@
// @license MIT License https://opensource.org/licenses/MIT
// @javascript_url
+// request part
// TODO
// - error handling
-// - request timeout
+// - timeout check
+// - responses assert
+// - exact feedback
+// - under a async request
+// TBD
+// - wait per fetch
+//
+// overall
+// TODO
+// - [Promise#]finally
// login required
(() => {
@@ -46,23 +56,20 @@
const bar = Object.assign(document.createElement('progress'), {
max,
value: 0,
- textContent: 0,
+ textContent: '0/' + max,
});
+ // TBD bulk style assign
Object.assign(bar.style, {
- zIndex: Number.MAX_SAFE_INTEGER || Number.MAX_VALUE,
+ zIndex: Number.MAX_SAFE_INTEGER,
position: 'fixed',
top: '50%',
opacity: 0.7,
});
document.body.appendChild(bar);
- // TBD merge style section
- bar.style.left = [
- 'calc(50% -',
- getComputedStyle(bar).width,
- '/ 2)',
- ].join(' ');
+ // TBD merge into style section
+ bar.style.left = 'calc(50% - ' + getComputedStyle(bar).width + ' / 2)';
return bar;
};
@@ -72,36 +79,53 @@
return new Promise(res => setTimeout(res, wait));
};
- // NOTE `await` do not working within Array/NodeList callback loops, sucks
+ const title = document.title;
+ // NOTE `await wait()` do not working within Array/NodeList callback loops, sucks
// i.e. can not use w/ Array#forEach() NodeList#forEach() and Array#map() et al. WTH
// https://stackoverflow.com/questions/37576685/using-async-await-with-a-foreach-loop
// https://qiita.com/frameair/items/e7645066075666a13063
- // TBD replace to Promise.all stepping w/ loop callback
+ // TBD replace to Promise.all-stepping w/ loop callback
(async () => {
const links = document.body.querySelectorAll([
'a[href^="./editpage?cid="]',
]);
const max = links.length;
- // TODO feedback visible text
+ // TODO visible text feedback
const feedback = progress(max);
// TBD incremental for
let done = 0;
for (const link of links) {
refresh(link);
- // TODO into feedback
- feedback.value = feedback.textContent = done += 1;
+
+ // TODO decrement from async-part
+ feedback.value = done += 1;
+ // TODO into a feedback
+ const state = [
+ String(done).padStart(String(max).length, '0'),
+ '/',
+ max,
+ ].join('');
+ feedback.textContent = state;
+ const remain = max - done;
+ document.title = '(' + remain + ') ' + title;
+
await sleep();
- // TBD omit console
- console.debug && console.debug([ //eslint-disable-line no-console
+ // TBD
+ // - omit console
+ // - show checkee url
+ // - responses status
+ console && console.debug && console.debug([ //eslint-disable-line no-console
(new Date).toTimeString().slice(0, 8),
- String(done).padStart(String(max).length, '0') + '/' + max,
+ state,
link.textContent,
link.href,
].join(' '));
}
+ // TODO into async finally
feedback.remove();
+ document.title = title;
})();
})();
// @title =A!
// @description Hatena Antenna force bulk checker
// @include http://a.hatena.ne.jp/HATENA_ID/checklist
// @include http://a.hatena.ne.jp/HATENA_ID/
// @contributor noromanba http://let.hatelabo.jp/noromanba/let/hLHUksLx6YMy
// @contributor a-kuma3 http://h.hatena.ne.jp/a-kuma3/227133357563872599 (reviewer)
// @license MIT License https://opensource.org/licenses/MIT
// @javascript_url
// request part
// TODO
// - error handling
// - timeout check
// - responses assert
// - exact feedback
// - under a async request
// TBD
// - wait per fetch
//
// overall
// TODO
// - [Promise#]finally
// login required
(() => {
'use strict';
const refresh = async (antenna) => {
const headers = new Headers();
headers.set('Content-Type', 'text/html;charset=euc-jp');
const edit = await fetch(antenna.href, {
// needs cookie
credentials: 'same-origin',
// XXX ignoring charset
headers,
});
const txt = await edit.text();
// TBD DOMParser()
const url = (txt.match(/^<td><a\s+href="(https?[^"]+)"\s+target="_blank"/m) || [])[1];
if (!url) return;
// manual checker syntax;
// http://a.hatena.ne.jp/check?url=<ENCODED_URL>[&robots=1]
// min GET interval: 5min c.f.
// http://a.hatena.ne.jp/check
const checker = new URL('http://a.hatena.ne.jp/check');
checker.searchParams.set('url', url);
await fetch(checker.href, {
credentials: 'same-origin',
});
};
const progress = (max) => {
const bar = Object.assign(document.createElement('progress'), {
max,
value: 0,
textContent: '0/' + max,
});
// TBD bulk style assign
Object.assign(bar.style, {
zIndex: Number.MAX_SAFE_INTEGER,
position: 'fixed',
top: '50%',
opacity: 0.7,
});
document.body.appendChild(bar);
// TBD merge into style section
bar.style.left = 'calc(50% - ' + getComputedStyle(bar).width + ' / 2)';
return bar;
};
const sleep = (wait = 1 * 1000) => {
//const Promise = window.Promise; // ESLint workaround
return new Promise(res => setTimeout(res, wait));
};
const title = document.title;
// NOTE `await wait()` do not working within Array/NodeList callback loops, sucks
// i.e. can not use w/ Array#forEach() NodeList#forEach() and Array#map() et al. WTH
// https://stackoverflow.com/questions/37576685/using-async-await-with-a-foreach-loop
// https://qiita.com/frameair/items/e7645066075666a13063
// TBD replace to Promise.all-stepping w/ loop callback
(async () => {
const links = document.body.querySelectorAll([
'a[href^="./editpage?cid="]',
]);
const max = links.length;
// TODO visible text feedback
const feedback = progress(max);
// TBD incremental for
let done = 0;
for (const link of links) {
refresh(link);
// TODO decrement from async-part
feedback.value = done += 1;
// TODO into a feedback
const state = [
String(done).padStart(String(max).length, '0'),
'/',
max,
].join('');
feedback.textContent = state;
const remain = max - done;
document.title = '(' + remain + ') ' + title;
await sleep();
// TBD
// - omit console
// - show checkee url
// - responses status
console && console.debug && console.debug([ //eslint-disable-line no-console
(new Date).toTimeString().slice(0, 8),
state,
link.textContent,
link.href,
].join(' '));
}
// TODO into async finally
feedback.remove();
document.title = title;
})();
})();
- Permalink
- このページへの個別リンクです。
- RAW
- 書かれたコードへの直接のリンクです。
- Packed
- 文字列が圧縮された書かれたコードへのリンクです。
- Userscript
- Greasemonkey 等で利用する場合の .user.js へのリンクです。
- Loader
- @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
- Metadata
- コード中にコメントで @xxx と書かれたメタデータの JSON です。