// ==UserScript==
// @name 4chan: Redirect 404s to Archive (updated)
// @namespace user@user
// @match *://boards.4chan.org/*/thread/*
// @version 1.2
// @description Redirect dead 4chan threads to their respective board archives
// @grant none
// @run-at document-end
// @license Apache 2.0
// ==/UserScript==
(() => {
'use strict';
const archives = {
'fgts.jp': ['asp','b','cm','h','hc','hm','n','p','qa','r','s','soc','toy','y'],
'archived.moe': ['a','an','biz','c','co','diy','fit','gd','gif','i','jp','k','m','mlp','out','po','r9k','s4s','sci','tg','tv','u','v','vg','vp','vr','wsg'],
'4plebs.org': ['adv','f','hr','o','pol','trv','x'],
'desuarchive.org': ['int', 'g'],
'warosu.org': ['3','cgl','ck','fa','ic','lit'],
'archive.rebeccablacktech.com': ['mu','w'],
'archive.loveisover.me': ['d','e','lgbt','t'],
'archive.nyafuu.org': ['wg'],
'totally.not4plebs.org': ['sp']
};
const boardToHost = Object.entries(archives).reduce((map, [host, boards]) => {
boards.forEach(b => map.set(b, host));
return map;
}, new Map());
const parts = location.pathname.split('/').filter(Boolean);
if (parts.length < 3) {
alert('4chan-redirect: unexpected path structure:', location.pathname);
return;
}
const board = parts[0].toLowerCase();
const threadIndex = parts.indexOf('thread');
const threadId = (threadIndex >= 0 && parts.length > threadIndex + 1) ? parts[threadIndex + 1] : null;
if (!threadId) {
alert('4chan-redirect: could not determine thread id from', location.pathname);
return;
}
const isDead = (() => {
const title = (document.title || '').toLowerCase();
if (title.includes('404') || title.includes('not found')) return true;
try {
const bodyText = (document.body && document.body.textContent) ? document.body.textContent.toLowerCase() : '';
if (bodyText.includes('404 not found') || bodyText.includes('not found') || bodyText.includes('page not found')) return true;
} catch (e) {
}
return false;
})();
if (!isDead) {
return;
}
const host = boardToHost.get(board);
if (!host) {
alert(`4chan-redirect: no archive specified for board /${board}/`);
return;
}
const archiveUrl = `https://${host}/${encodeURIComponent(board)}/thread/${encodeURIComponent(threadId)}`;
//use the code below for debugging purpose
//
//alert(`4chan-redirect: redirecting /${board}/thread/${threadId} → ${archiveUrl}`);
location.replace(archiveUrl);
})();