Improve update thread functions

ご主人様
not manx 4 years ago
parent 50718e4ac5
commit 878250343e
Signed by: C-xC-c
GPG Key ID: F52ED472284EF2F4

@ -11,7 +11,7 @@
// @exclude http*://archive.nyafuu.org/bant/statistics/ // @exclude http*://archive.nyafuu.org/bant/statistics/
// @exclude http*://archived.moe/bant/statistics/ // @exclude http*://archived.moe/bant/statistics/
// @exclude http*://thebarchive.com/bant/statistics/ // @exclude http*://thebarchive.com/bant/statistics/
// @version 2.0.1 // @version 2.1.0
// @grant GM_xmlhttpRequest // @grant GM_xmlhttpRequest
// @grant GM_getValue // @grant GM_getValue
// @grant GM_setValue // @grant GM_setValue

@ -11,7 +11,7 @@
// @exclude http*://archive.nyafuu.org/bant/statistics/ // @exclude http*://archive.nyafuu.org/bant/statistics/
// @exclude http*://archived.moe/bant/statistics/ // @exclude http*://archived.moe/bant/statistics/
// @exclude http*://thebarchive.com/bant/statistics/ // @exclude http*://thebarchive.com/bant/statistics/
// @version 2.0.1 // @version 2.1.0
// @grant GM_xmlhttpRequest // @grant GM_xmlhttpRequest
// @grant GM_getValue // @grant GM_getValue
// @grant GM_setValue // @grant GM_setValue
@ -29,7 +29,7 @@
// /bant/ Flags is licensed under the GNU AGPL Version 3.0 or later. // /bant/ Flags is licensed under the GNU AGPL Version 3.0 or later.
// see the LICENSE file or <https://www.gnu.org/licenses/> // see the LICENSE file or <https://www.gnu.org/licenses/>
// Change this if you want verbose debuging information in the console. // This will print a load of shit to the console
const debugMode = false; const debugMode = false;
const isGM4 = typeof GM_setValue === 'undefined'; const isGM4 = typeof GM_setValue === 'undefined';
@ -37,9 +37,6 @@ const setValue = isGM4 ? GM.setValue : GM_setValue;
const getValue = isGM4 ? GM.getValue : GM_getValue; const getValue = isGM4 ? GM.getValue : GM_getValue;
const xmlHttpRequest = isGM4 ? GM.xmlHttpRequest : GM_xmlhttpRequest; const xmlHttpRequest = isGM4 ? GM.xmlHttpRequest : GM_xmlhttpRequest;
//
// DO NOT EDIT ANYTHING IN THIS SCRIPT DIRECTLY - YOUR FLAGS SHOULD BE CONFIGURED USING THE FLAG SELECT
//
const version = encodeURIComponent(2); // Breaking changes. const version = encodeURIComponent(2); // Breaking changes.
const back_end = 'https://flags.plum.moe/'; const back_end = 'https://flags.plum.moe/';
const api_flags = back_end + 'api/flags'; const api_flags = back_end + 'api/flags';
@ -55,9 +52,6 @@ let regions = []; // The flags we have selected.
let postNrs = []; // all post numbers in the thread. let postNrs = []; // all post numbers in the thread.
let board_id = ""; // The board we get flags for. let board_id = ""; // The board we get flags for.
let flagsLoaded = false; let flagsLoaded = false;
//
// DO NOT EDIT ANYTHING IN THIS SCRIPT DIRECTLY - YOUR FLAGS SHOULD BE CONFIGURED USING THE FLAG SELECT
//
const debug = text => { const debug = text => {
if (debugMode) if (debugMode)
@ -72,19 +66,12 @@ const software = {
}; };
const makeElement = (tag, options) => Object.assign(document.createElement(tag), options); const makeElement = (tag, options) => Object.assign(document.createElement(tag), options);
const toggleFlagButton = state => document.getElementById('append_flag_button').disabled = state === 'off' ? true : false; const toggleFlagButton = state => document.getElementById('append_flag_button').disabled = state === 'off' ? true : false;
const flagSource = flag => flag_dir + flag + '.png';
const flagSource = flag => flag_dir + flag + ".png";
/** Add styles to the <head> */ /** Add styles to the <head> */
const addGlobalStyle = css => document.head.appendChild(makeElement('style', { innerHTML: css })); const addStyle = css => document.head.appendChild(makeElement('style', { innerHTML: css }));
/** Wrapper around GM_xmlhttpRequest.
* @param {string} method - The HTTP method (GET, POST).
* @param {string} url - The URL of the request.
* @param {string} data - text for the form body.
* @param {Function} func - The function run when we recieve a response. Response data is sent directly to it. */
const makeRequest = ((method, url, data, func) => { const makeRequest = ((method, url, data, func) => {
xmlHttpRequest({ xmlHttpRequest({
method: method, method: method,
@ -100,56 +87,51 @@ function saveFlags() {
regions = []; regions = [];
const selectedFlags = document.querySelectorAll(".bantflags_flag"); const selectedFlags = document.querySelectorAll(".bantflags_flag");
for (var i = 0; i < selectedFlags.length; i++) { for (let i = 0; i < selectedFlags.length; i++) {
regions[i] = selectedFlags[i].title; regions[i] = selectedFlags[i].title;
} }
setValue(namespace, regions); setValue(namespace, regions);
} }
/** Add a flag to our selection. /** Add a flag to our selection. */
* @param {string} flag - The flag to add to our selection. Either passed from saved flags or the current value of flagSelect */
function setFlag(flag) { function setFlag(flag) {
let UID = Math.random().toString(36).substring(7); const flagName = flag ? flag : document.querySelector('#flagSelect input').value;
let flagName = flag ? flag : document.querySelector('#flagSelect input').value; const flagContainer = document.getElementById('bantflags_container');
let flagContainer = document.getElementById('bantflags_container');
flagContainer.appendChild(makeElement('img', { flagContainer.appendChild(makeElement('img', {
title: flagName, title: flagName,
src: flagSource(flagName), src: flagSource(flagName),
id: UID, className: 'bantflags_flag',
className: 'bantflags_flag' onclick: function() {
flagContainer.removeChild(this);
if (flagsLoaded)
toggleFlagButton('on');
saveFlags();
}
})); }));
if (flagContainer.children.length >= max_flags) if (flagContainer.children.length >= max_flags)
toggleFlagButton('off'); toggleFlagButton('off');
document.getElementById(UID).addEventListener("click", e => {
flagContainer.removeChild(e.target);
toggleFlagButton('on');
saveFlags();
});
if (!flag) // We've added a new flag to our selection if (!flag) // We've added a new flag to our selection
saveFlags(); saveFlags();
} }
function init() { function init() {
let flagsForm = makeElement('div', { const flagsForm = makeElement('div', {
className: 'flagsForm', className: 'flagsForm',
innerHTML: '<span id="bantflags_container"></span><button type="button" id="append_flag_button" title="Click to add selected flag to your flags. Click on flags to remove them. Saving happens automatically, you only need to refresh the pages that have an outdated flaglist on the page."><<</button><button id="flagLoad" type="button">Click to load flags.</button><div id="flagSelect" ><ul class="hide"></ul><input type="button" value="(You)" onclick=""></div>' innerHTML: '<span id="bantflags_container"></span><button type="button" id="append_flag_button" title="Click to add selected flag to your flags. Click on flags to remove them." disabled="true"><<</button><button id="flagLoad" type="button">Click to load flags.</button><div id="flagSelect" ><ul class="hide"></ul><input type="button" value="(You)" onclick=""></div>'
}); });
// Where do we append the flagsForm to? // Where do we append the flagsForm to?
if (software.yotsuba) { document.getElementById('delform').appendChild(flagsForm); } if (software.yotsuba) { document.getElementById('delform').appendChild(flagsForm); }
else if (software.nodegucaDoushio) { document.querySelector('section').append(flagsForm); } // As posts are added the flagForm moves up the page. Could we append this after .section? else if (software.nodegucaDoushio) { document.querySelector('section').insertAdjacentElement('afterEnd', flagsForm); }
for (let i = 0; i < regions.length; i++) { for (let i = 0; i < regions.length; i++) {
setFlag(regions[i]); setFlag(regions[i]);
} }
document.getElementById('append_flag_button').addEventListener('click', () => flagsLoaded ? setFlag() : alert('Load flags before adding them.'));
document.getElementById('flagLoad').addEventListener('click', makeFlagSelect, { once: true }); document.getElementById('flagLoad').addEventListener('click', makeFlagSelect, { once: true });
} }
@ -168,19 +150,19 @@ function makeFlagSelect() {
} }
let flagSelect = document.getElementById('flagSelect'); let flagSelect = document.getElementById('flagSelect');
let flagList = flagSelect.querySelector('ul');
let flagInput = flagSelect.querySelector('input'); let flagInput = flagSelect.querySelector('input');
let flags = resp.responseText.split('\n'); let flagList = flagSelect.querySelector('ul');
for (var i = 0; i < flags.length; i++) { let flags = resp.responseText.split('\n');
let flag = flags[i]; for (let i = 0; i < flags.length; i++) {
const flag = flags[i];
flagList.appendChild(makeElement('li',{ flagList.appendChild(makeElement('li',{
innerHTML: `<img src="${flagSource(flag)}" title="${flag}"><span>${flag}</span>` innerHTML: `<img src="${flagSource(flag)}" title="${flag}"><span>${flag}</span>`
})); }));
} }
flagSelect.addEventListener('click', function (e) { flagSelect.addEventListener('click', e => {
// So it works if we click the flag image // Maybe we clicked the flag image
const node = e.target.nodeName === 'LI' ? e.target : e.target.parentNode; const node = e.target.nodeName === 'LI' ? e.target : e.target.parentNode;
if (node.nodeName === 'LI') if (node.nodeName === 'LI')
flagInput.value = node.querySelector('span').innerHTML; flagInput.value = node.querySelector('span').innerHTML;
@ -188,6 +170,10 @@ function makeFlagSelect() {
flagList.classList.toggle('hide'); flagList.classList.toggle('hide');
}); });
const flagButton = document.getElementById('append_flag_button');
flagButton.addEventListener('click', () => setFlag());
flagButton.disabled = false;
document.getElementById('flagLoad').style.display = 'none'; document.getElementById('flagLoad').style.display = 'none';
document.querySelector('.flagsForm').style.marginRight = "200px"; // flagsForm has position: absolute and is ~200px long. document.querySelector('.flagsForm').style.marginRight = "200px"; // flagsForm has position: absolute and is ~200px long.
flagSelect.style.display = 'inline-block'; flagSelect.style.display = 'inline-block';
@ -226,10 +212,9 @@ function resolveFlags() {
debug(`JSON: ${resp.responseText}`); debug(`JSON: ${resp.responseText}`);
Object.keys(jsonData).forEach(post => { Object.keys(jsonData).forEach(post => {
let flags = jsonData[post]; const flags = jsonData[post];
if (flags.length <= 0) if (flags.length <= 0) return;
return;
debug(`Resolving flags for >>${post}`); debug(`Resolving flags for >>${post}`);
@ -241,14 +226,12 @@ function resolveFlags() {
for (let i = 0; i < flags.length; i++) { for (let i = 0; i < flags.length; i++) {
const flag = flags[i]; const flag = flags[i];
const newFlag = makeElement('a', { flagContainer.append(makeElement('a', {
innerHTML: `<img src="${flagSource(flag)}" title="${flag}">`, innerHTML: `<img src="${flagSource(flag)}" title="${flag}">`,
className: 'bantFlag', className: 'bantFlag',
target: '_blank', target: '_blank',
title: flag title: flag
}); }));
flagContainer.append(newFlag);
debug(`\t -> ${flag}`); debug(`\t -> ${flag}`);
} }
@ -259,46 +242,45 @@ function resolveFlags() {
} }
function main() { function main() {
if (!regions) { if (!regions) {
regions = []; regions = [];
} }
// See Docs/styles.css // See Docs/styles.css
addGlobalStyle('.bantFlag{padding: 0px 0px 0px 5px; display: inline-block; width: 16px; height: 11px; position: relative;} .bantflags_flag{padding: 1px;} [title^="Romania"]{ position: relative; animation: shakeAnim 0.1s linear infinite;} @keyframes shakeAnim{ 0% {left: 1px;} 25% {top: 2px;} 50% {left: 1px;} 75% {left: 0px;} 100% {left: 2px;}}.flagsForm{float: right; clear: right; margin: 20px 10px;} #flagSelect{display:none;} #flagSelect ul{list-style-type: none;padding: 0;margin-bottom: 0;cursor: pointer;bottom: 100%;height: 200px;overflow: auto;position: absolute;width:200px;background-color:#fff} #flagSelect ul li {display: block;} #flagSelect ul li:hover {background-color: #ddd;}#flagSelect {position: absolute;}#flagSelect input {width: 200px;} #flagSelect .hide {display: none;}#flagSelect img {margin-left: 2px;}') addStyle('.bantFlag{padding: 0px 0px 0px 5px; display: inline-block; width: 16px; height: 11px; position: relative;} .bantflags_flag{padding: 1px;} [title^="Romania"]{ position: relative; animation: shakeAnim 0.1s linear infinite;} @keyframes shakeAnim{ 0% {left: 1px;} 25% {top: 2px;} 50% {left: 1px;} 75% {left: 0px;} 100% {left: 2px;}}.flagsForm{float: right; clear: right; margin: 20px 10px;} #flagSelect{display:none;} #flagSelect ul{list-style-type: none;padding: 0;margin-bottom: 0;cursor: pointer;bottom: 100%;height: 200px;overflow: auto;position: absolute;width:200px;background-color:#fff} #flagSelect ul li {display: block;} #flagSelect ul li:hover {background-color: #ddd;}#flagSelect {position: absolute;}#flagSelect input {width: 200px;} #flagSelect .hide {display: none;}#flagSelect img {margin-left: 2px;}')
if (software.yotsuba) { if (software.yotsuba) {
getPosts('.postContainer'); getPosts('.postContainer');
addGlobalStyle('.flag{top: 0px;left: -1px}'); addStyle('.flag{top: 0px;left: -1px}');
init(); init();
} }
if (software.nodegucaDoushio) { else if (software.nodegucaDoushio) {
getPosts('section[id], article[id]'); getPosts('section[id], article[id]');
addGlobalStyle('.bantFlag {cursor: default} .bantFlag img {pointer-events: none;}'); addStyle('.bantFlag {cursor: default} .bantFlag img {pointer-events: none;}');
init(); init();
} }
if (software.foolfuuka) { else if (software.foolfuuka) {
getPosts('article[id]'); getPosts('article[id]');
addGlobalStyle('.bantFlag{top: -2px !important;left: -1px !important}'); addStyle('.bantFlag{top: -2px !important;left: -1px !important}');
} }
board_id = window.location.pathname.split('/')[1]; board_id = window.location.pathname.split('/')[1];
debug(board_id); debug(`board: ${board_id}`);
try { try {
resolveFlags(); resolveFlags();
} }
catch (fuckywucky) { catch (fuckywucky) {
console.log(`Wah! Manx fucked something up ;~;\nPoke him somewhere this this:\n${fuckywucky}`) console.log(`Wah! Manx fucked something up ;~;\nPoke him somewhere with this:\n${fuckywucky}`)
} }
} }
if (isGM4) { // Fuck you GM4 if (isGM4) { // Fuck you GreaseMonkey
(async () => { (async () => {
regions = await getValue(namespace); regions = await getValue(namespace);
main(); main();
@ -316,48 +298,35 @@ const postFlags = (post_nr, func = resp => debug(resp.responseText)) => makeRequ
func); func);
if (software.yotsuba) { if (software.yotsuba) {
const GetEvDetail = e => e.detail || e.wrappedJSObject.detail; const e_detail = e => e.detail || e.wrappedJSObject.detail// what?
document.addEventListener('QRPostSuccessful', e => postFlags(e_detail(e).postID));
// 4chanX and native extension respectively document.addEventListener('4chanQRPostSuccess', e => postFlags(e_detail(e).postId));
document.addEventListener('QRPostSuccessful', e => postFlags(e.detail.postID));
document.addEventListener('4chanQRPostSuccess', e => postFlags(GetEvDetail(e).postId));
// I need to look at these. document.addEventListener('ThreadUpdate', e => {
document.addEventListener('ThreadUpdate', function (e) { const d = e_detail(e)
var evDetail = GetEvDetail(e); if (d[404]) return;
var evDetailClone = typeof cloneInto === 'function' ? cloneInto(evDetail, unsafeWindow) : evDetail;
//ignore if 404 event d.newPosts.forEach(post => postNrs.push(post.split('.')[1]));
if (evDetail[404] === true) {
return;
}
evDetailClone.newPosts.forEach(function (post_board_nr) {
var post_nr = post_board_nr.split('.')[1];
postNrs.push(post_nr);
});
resolveFlags(); resolveFlags();
}, false); });
document.addEventListener('4chanThreadUpdated', function (e) { document.addEventListener('4chanThreadUpdated', e => {
var evDetail = GetEvDetail(e); const d = e_detail(e);
let threadID = window.location.pathname.split('/')[3]; if (d.count <= 0) return;
let postsContainer = Array.prototype.slice.call(document.getElementById('t' + threadID).childNodes);
let lastPosts = postsContainer.slice(Math.max(postsContainer.length - evDetail.count, 1)); //get the last n elements (where n is evDetail.count)
lastPosts.forEach(function (post_container) { // Get the added posts in reverse order, take post numbers from ID
var post_nr = post_container.id.replace('pc', ''); const posts = document.querySelectorAll('.postContainer');
postNrs.push(post_nr); for (let i = 0; i < d.count; i++) {
}); postNrs.push(posts[posts.length - 1 - i].id.substr(2));
}
resolveFlags(); resolveFlags();
}, false); });
} }
if (software.nodegucaDoushio) { if (software.nodegucaDoushio) {
const postFunc = () => {
const postFunc = function() {
postNrs.push(mutation.target.id); postNrs.push(mutation.target.id);
resolveFlags(); resolveFlags();
} }
@ -369,7 +338,7 @@ if (software.nodegucaDoushio) {
if (mutation.addedNodes.length <= 0) if (mutation.addedNodes.length <= 0)
return; // We only care if something post was added return; // We only care if something post was added
var firstAddedNode = mutation.addedNodes[0].nodeName; const firstAddedNode = mutation.addedNodes[0].nodeName;
// Enter a thread / change boards // Enter a thread / change boards
if (mutation.target.nodeName === 'THREADS') { if (mutation.target.nodeName === 'THREADS') {

Loading…
Cancel
Save