// ==UserScript==
// @name 4chan Post Randomizer
// @namespace http://www.4chan.org/
// @version 0.6
// @description Adds a button that redirects to a random post on a random board
// @include http://boards.4chan.org/*
// @include https://boards.4chan.org/*
// @grant none
// @run-at document-end
// @downloadURL none
// ==/UserScript==
// use fancy mobile-like buttons on 4chan X, simple HTML form button otherwise
var is_4chanx = document.documentElement.classList.contains('fourchan-x');
if (is_4chanx) {
var randomizer_button = document.createElement('a');
randomizer_button.classList.add('qr-link');
// dummy href like original button
randomizer_button.href = 'javascript:;';
var randomizer_container = document.createElement('div');
randomizer_container.classList.add('qr-link-container');
// always force visible (Onee-Chan hides the quicklink by default)
randomizer_container.style['display'] = 'block';
// no extra margins please
randomizer_container.appendChild(randomizer_button);
} else {
var randomizer_button = document.createElement('button');
randomizer_button.style['display'] = 'block';
randomizer_button.style['margin-left'] = 'auto';
randomizer_button.style['margin-right'] = 'auto';
randomizer_button.style['margin-bottom'] = '8px';
randomizer_button.style['font-family'] = 'inherit';
var randomizer_container = randomizer_button;
}
randomizer_button.setAttribute('id', 'throwthedice');
randomizer_button.appendChild(document.createTextNode('Go to Random Post'));
// insert below lower blotter line, or the full-width
on /f/, or "Back to (board)" link on the 404 page
if (location.pathname.startsWith('/f/')) {
var insert_before = document.querySelector('body > script');
if (insert_before !== null) {
insert_before.parentNode.insertBefore(randomizer_container, insert_before);
} else {
console.log('Could not find insertion anchor on /f/!');
return;
}
// hehe, lambda bracket mayhem
} else if ((() => {
var boxbar = document.querySelector('div.boxbar > h2');
return boxbar !== null && boxbar.textContent === '404 Not Found'})()) {
var insert_parent = document.querySelector('.boxcontent');
if (insert_parent !== null) {
// 4chan X does not apply styles to the 404 page
if (is_4chanx) {
randomizer_container.classList.remove('qr-link-container');
randomizer_container.style['text-align'] = 'center';
randomizer_container.insertBefore(document.createTextNode('['), randomizer_container.firstChild);
randomizer_container.appendChild(document.createTextNode(']'));
}
insert_parent.appendChild(randomizer_container);
} else {
console.log('Could not find insertion anchor on 404 page!');
return;
}
} else {
var insert_before = document.querySelector('.middlead');
if (insert_before !== null) {
insert_before.parentNode.insertBefore(randomizer_container, insert_before);
} else {
console.log('Could not find insertion anchor on board!');
return;
}
}
randomizer_button.addEventListener('click', function() {
randomizer_button.textContent = 'Picking random board...';
var xhr = new XMLHttpRequest();
// cascaded re-use of the XMLHttpRequest for the board list, catalog and thread
xhr.open('GET', '//a.4cdn.org/boards.json');
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200 && xhr.getResponseHeader("Content-Type") == "application/json") {
var boards = JSON.parse(xhr.response)['boards'].map(b => b.board);
var random_board = boards[Math.floor(boards.length * Math.random())];
randomizer_button.textContent = 'Picking random thread on /' + random_board + '/...';
xhr.open('GET', '//a.4cdn.org/' + random_board + '/catalog.json');
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200 && xhr.getResponseHeader("Content-Type") == "application/json") {
var threads = JSON.parse(xhr.response).map(page => page['threads'].map(thread => thread['no'])).reduce((p1, p2) => p1.concat(p2), []).slice(-150);
var random_thread = threads[Math.floor(threads.length * Math.random())];
randomizer_button.textContent = 'Picking random post in thread...';
xhr.open('GET', '//a.4cdn.org/' + random_board + '/thread/' + random_thread + '.json');
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200 && xhr.getResponseHeader("Content-Type") == "application/json") {
var posts = JSON.parse(xhr.response)['posts'].map(p => p.no);
var redirect_link = '//boards.4chan.org/' + random_board + '/thread/' + random_thread;
var post_index = Math.floor(posts.length * Math.random());
if (post_index > 0) {
redirect_link += '#p' + posts[post_index];
}
randomizer_button.textContent = 'Off we go!';
location.href = redirect_link;
}
};
xhr.send();
}
};
xhr.send();
}
};
xhr.send();
});