=A!
by
noromanba
2018-01-21 [2018/01/21 04:18:00]
(Forked from
A! by
noromanba)
Hatena Antenna force bulk checker
@@ -1,28 +1,25 @@
-/*
- * @title =A!
- * @description Hatena Antenna force bulk checker
- * @include http://a.hatena.ne.jp/YOUR_ID/checklist
- * @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
- */
+// @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
// TODO
// - error handling
// - request timeout
-// - general page handling
-// - http://a.hatena.ne.jp/HATENA_ID/
// login required
(() => {
'use strict';
- const refresh = async (content) => {
+ const refresh = async (antenna) => {
const headers = new Headers();
headers.set('Content-Type', 'text/html;charset=euc-jp');
- const edit = await fetch(content.href, {
+ const edit = await fetch(antenna.href, {
// needs cookie
credentials: 'same-origin',
// XXX ignoring charset
@@ -30,13 +27,13 @@
});
const txt = await edit.text();
// TBD DOMParser()
- const url = (txt.match(/^<td><a href="(https?[^"]+)"\s+target="_blank"/m) || [])[1];
+ 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?url=
+ // http://a.hatena.ne.jp/check
const checker = new URL('http://a.hatena.ne.jp/check');
checker.searchParams.set('url', url);
@@ -46,15 +43,15 @@
};
const sleep = (wait = 1 * 1000) => {
- const Promise = window.Promise; // ESLint workaround
+ //const Promise = window.Promise; // ESLint workaround
return new Promise(res => setTimeout(res, wait));
- //return Promise.all([callback, res => setTimeout(res, wait)]);
};
- // NOTE await do not working within Array/NodeList callback loops, sucks
+ // NOTE `await` 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 () => {
// TODO calm progress feedback; spinner or indicator
window.alert('start');
@@ -63,11 +60,11 @@
])) {
refresh(link);
await sleep();
- console.debug([ // eslint-disable-line no-console
+ console.debug([ //eslint-disable-line no-console
link.textContent,
link.href,
'...',
- ].join());
+ ].join(' '));
}
window.alert('done');
})();
// @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
// TODO
// - error handling
// - request timeout
// 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 sleep = (wait = 1 * 1000) => {
//const Promise = window.Promise; // ESLint workaround
return new Promise(res => setTimeout(res, wait));
};
// NOTE `await` 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 () => {
// TODO calm progress feedback; spinner or indicator
window.alert('start');
for (const link of document.body.querySelectorAll([
'a[href^="./editpage?cid="]',
])) {
refresh(link);
await sleep();
console.debug([ //eslint-disable-line no-console
link.textContent,
link.href,
'...',
].join(' '));
}
window.alert('done');
})();
})();
- Permalink
- このページへの個別リンクです。
- RAW
- 書かれたコードへの直接のリンクです。
- Packed
- 文字列が圧縮された書かれたコードへのリンクです。
- Userscript
- Greasemonkey 等で利用する場合の .user.js へのリンクです。
- Loader
- @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
- Metadata
- コード中にコメントで @xxx と書かれたメタデータの JSON です。