コンテンツにスキップ

英文维基 | 中文维基 | 日文维基 | 草榴社区

利用者:Syunsyunminmin/script/AbuseFilterContribs.js

お知らせ: 保存した後、ブラウザのキャッシュをクリアしてページを再読み込みする必要があります。

多くの WindowsLinux のブラウザ

  • Ctrl を押しながら F5 を押す。

Mac における Safari

  • Shift を押しながら、更新ボタン をクリックする。

Mac における ChromeFirefox

  • Cmd Shift を押しながら R を押す。

詳細についてはWikipedia:キャッシュを消すをご覧ください。

/*
* Fork from: https://en-two.iwiki.icu/wiki/User:Ingenuity/AbuseFilterContribs.js --[[:w:en:User:Ingenuity/AbuseFilterContribs.js]] @User:Ingenuity
* Description: https://en-two.iwiki.icu/wiki/User:Ingenuity/AbuseFilterContribs 参照
* Show edits disallowed by the abuse filter in the Special:Contributions
*
* フォーク元: https://en-two.iwiki.icu/wiki/User:Ingenuity/AbuseFilterContribs.js --[[:w:en:User:Ingenuity/AbuseFilterContribs.js]] @User:Ingenuity
* 説明: https://en-two.iwiki.icu/wiki/User:Ingenuity/AbuseFilterContribs 参照
* 特別:投稿記録で編集フィルターによって不許可となった編集を表示します
*/
const afcAPI = new mw.Api();

if (mw.config.get('wgCanonicalSpecialPageName') == 'Contributions' && mw.config.values.wgRelevantUserName) {
	addToContribs(mw.config.values.wgRelevantUserName);
}

async function loadAbuseFilterLog(user) {
	return (await afcAPI.get({
		action: "query",
		list: "abuselog",
		afllimit: 50,
		afluser: user
	})).query.abuselog.filter(e => e.result === "disallow").sort((a, b) => new Date(a.timestamp) - new Date(b.timestamp));
}

function groupAbuseLog(log) {
	const data = [];
	outer: for (const item of log) {
		for (const i of data) {
			if (i.timestamp === item.timestamp && i.title === item.title) {
				i.filters.push(item.filter_id);
				if (item.filter_id) {
					i.id = item.id;
				}
				continue outer;
			}
		}

		data.push({
			timestamp: item.timestamp,
			filters: [item.filter_id],
			id: item.id,
			title: item.title
		});
	}
	return data;
}

async function addToContribs(user) {
	const log = groupAbuseLog(await loadAbuseFilterLog(user));
	const cList = document.querySelectorAll(".mw-contributions-list");
	const children = [];
	for (const item of cList) {
		children.push(...item.children);
	}
	const settings = await getSettings();
	const offset = getOffset(settings);
	const times = await getTimes(children.map(e => e.attributes["data-mw-revid"].value));

	hits: for (const hit of log) {
		for (let i = children.length - 1; i > -1; i--) {
			const child = children[i];
			const id = Array.prototype.slice.call(child.attributes).filter(a => a.nodeName === "data-mw-revid")[0].value;
			const ts = times.filter(e => e.id === Number(id))[0].timestamp;
			if (new Date(hit.timestamp) < new Date(ts)) {
				const elem = document.createElement("li");
				child.parentElement.insertBefore(elem, child.nextSibling);
				elem.innerHTML = createText(hit, offset, settings);
				continue hits;
			}
		}

		const noContribsElem = document.querySelector("#mw-content-text > p");
		if (!noContribsElem) {
			const contribsList = document.querySelector(".mw-contributions-list");
			const elem = document.createElement("li");
			contribsList.insertBefore(elem, contribsList.children[0]);
			elem.innerHTML = createText(hit, offset, settings);
		} else {
			noContribsElem.remove();
			const ul = document.createElement("ul");
			ul.innerHTML = `<ul class="mw-contributions-list"><li>${createText(hit, offset, settings)}</li></ul>`;
			document.querySelector("#mw-content-text").insertBefore(ul, document.querySelector(".mw-contributions-footer"));
		}
	}
}

function createText(hit, offset, settings) {
	const adj = new Date(new Date(hit.timestamp).getTime() + offset * 60 * 1000);
	const details = hit.filters.filter(e => e).length ? `(<a href="/wiki/Special:AbuseLog/${hit.id}">詳細</a> | <a href="/wiki/Special:AbuseFilter/examine/log/${hit.id}">分析</a>)` : "";

	return `
		${getTimestampString(settings, adj.getUTCFullYear(), adj.getUTCMonth(), adj.getUTCDate(), adj.getUTCHours(), adj.getUTCMinutes(), adj.getUTCSeconds())}:
		<a href="/wiki/${encodeURIComponent(hit.title)}">${hit.title}</a>で${getLogText(hit.filters)}が発動しました。
		${details}
	`;
}

function getLogText(filters) {
	var logText;
	if (filters.length === 1) {
		if (filters[0] && /^global\-/.test(filters[0])) {
			logText = '<a href="//meta.wikimedia.org/wiki/Special:AbuseFilter/' + filters[0].replace(/^global\-/, "") + '">グローバルフィルター' + filters[0].replace(/^global\-/, "") + '</a>';
		} else if (filters[0] && !/^global\-/.test(filters[0])){
			logText = `<a href="/wiki/Special:AbuseFilter/${filters[0]}">フィルター${filters[0]}</a>`;
		}	else {
			logText = "非公開フィルター";
		}
		return logText;
	}

	return `${filters.length}つのフィルター (${filters.map(e => {
		if (e && /^global\-/.test(e)) {
			logText = '<a href="//meta.wikimedia.org/wiki/Special:AbuseFilter/' + e.replace(/^global\-/, "") + '">G' + e.replace(/^global\-/, "") + '</a>';
		} else if (e && !/^global\-/.test(e)){
			logText = `<a href="/wiki/Special:AbuseFilter/${e}">${e}</a>`;
		}	else {
			logText = "非公開";
		}
		return logText;
	}).join(", ")})`;
}

async function getTimes(ids) {
	if (ids.length === 0) {
		return [];
	}
	const data = [];

	Object.values((await afcAPI.get({
		action: "query",
		revids: ids.join("|"),
		prop: "revisions",
		rvprop: "timestamp|ids"
	})).query.pages).forEach(e => {
		for (const r of e.revisions) {
			data.push({
				id: r.revid,
				timestamp: r.timestamp
			});
		}
	});

	return data.sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp));
}

async function getSettings() {
	return (await afcAPI.get({
		action: "query",
		meta: "userinfo",
		uiprop: "options"
	})).query.userinfo.options;
}

function getOffset(settings) {
	return Number(settings.timecorrection.match(/(\d+)/)[1]);
}

function getTimestampString(settings, year, month, day, hour, minute, second) {
	const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
	switch (settings.date) {
		case "dmy":
		case "default":
			return `${pad(hour)}:${pad(minute)}, ${day} ${monthNames[month]} ${year}`;
		case "mdy":
			return `${pad(hour)}:${pad(minute)}, ${monthNames[month]} ${day}, ${year}`;
		case "ymd":
			return `${pad(hour)}:${pad(minute)}, ${year} ${monthNames[month]} ${day}`;
		case "nengo":
			return `${new Date(year, month, day).toLocaleDateString("ja-JP-u-ca-japanese", {era: "long", year: "numeric", month: "long", day: "numeric", weekday: "narrow"})} ${pad(hour)}:${pad(minute)}`;
		default:
			return `${year}-${pad(month + 1)}-${pad(day)}T${pad(hour)}:${pad(minute)}:${pad(second)}`;
	}
}

function pad(num) {
	return num < 10 ? "0" + num : num;
}