var are_filters = false;
var hide_word = new Set();
var hide_name = new Set();
var hide_id = new Set();
var shobon_ver = "v0.4+";
function shobon() {
boardName = document.body.dataset.brd;
var where = document.body.classList;
var inThread = where.contains("threadpage");
if (!inThread) {
/* Create settings link */
var box = document.getElementsByClassName("links")[0];
box.appendChild(document.createTextNode(" | "));
var slnk = document.createElement("a");
slnk.href = "#";
slnk.innerHTML = "<b>Configurar</b>";
slnk.addEventListener("click", shobonSettings);
box.appendChild(slnk);
}
if (localStorage.getItem("shobon_on") == "false") return;
else console.log("Running shobon " + shobon_ver);
var newRepliesCounter = 0;
if (localStorage.getItem("shobon_usefilters") != "false") {
loadFilters();
}
var threadList = document.getElementsByClassName("thread");
for (var i = 0; i < threadList.length; i++) {
var threadId;
var thread = threadList[i];
var replyList = thread.getElementsByClassName("reply");
if (inThread) {
threadId = document.getElementsByName("parent")[0].value;
} else {
threadId = thread.getElementsByTagName("input").parent.value;
}
var lastReplyN = replyList[replyList.length - 1].attributes["data-n"].value;
if (
localStorage.getItem("shobon_newposts") == "true" &&
localStorage.getItem(boardName + "_" + threadId) == null
) {
localStorage.setItem(boardName + "_" + threadId, lastReplyN);
}
var lastSeen = localStorage.getItem(boardName + "_" + threadId);
var newRepliesInThread = 0;
for (var e = 0; e < replyList.length; e++) {
var reply = replyList[e];
var message = reply.getElementsByClassName("msg")[0];
var id = 0;
if (localStorage.getItem("shobon_newposts") == "true") {
var replyId = reply.attributes["data-n"].value;
var isNewReply = parseInt(lastSeen) < parseInt(replyId);
if (isNewReply) {
newRepliesCounter++;
newRepliesInThread++;
reply.children[0].innerHTML += " <span class='shobonNew' style='color:#CC6666; font-weight:bold;'>Nuevo!</span>";
}
}
// ocultar mensajes que coinciden con lista negra
if (are_filters) {
checkBlackList(reply);
}
// colorear IDs
if (localStorage.getItem("shobon_ids") == "true") {
paintIds(reply);
}
// insertar imágenes
if (localStorage.getItem("shobon_embedimg") == "true") {
embedImg(reply);
}
}
if (newRepliesInThread > 0 && !inThread) {
var btnNew = document.createElement("span");
btnNew.dataset.id = boardName + "_" + threadId;
btnNew.dataset.last = lastReplyN;
btnNew.textContent = "Marcar como leído";
btnNew.setAttribute(
"style",
"font-weight:bold; background:#81a2be; padding:5px; border-radius:5px; float:right; margin-bottom:10px;"
);
btnNew.onclick = function() {
localStorage.setItem(this.dataset.id, this.dataset.last);
this.hidden = true;
};
thread.getElementsByClassName("threadlinks")[0].appendChild(btnNew);
}
}
if (newRepliesCounter > 0 && !inThread) {
var banner = document.createElement("span");
banner.onclick = function() {
this.hidden = true;
};
banner.setAttribute(
"style",
"font-weight:bold; background:#8c9440; padding:8px; border-radius:30px; float:right; position:fixed; bottom:10px; right:10px"
);
banner.textContent = "Nuevas respuestas: " + newRepliesCounter;
document.body.appendChild(banner);
}
if (localStorage.getItem("shobon_newposts") == "true" && inThread) {
localStorage.setItem(boardName + "_" + threadId, lastReplyN);
}
}
function on_checked(e) {
localStorage.setItem(e.target.id, e.target.checked);
}
function createCheckbox(name, label, def) {
var lbl = document.createElement("label");
var chk = document.createElement("input");
chk.type = "checkbox";
chk.id = name;
chk.onchange = on_checked;
lbl.appendChild(chk);
lbl.insertAdjacentHTML("beforeend", " " + label + " ");
var checked = localStorage.getItem(name);
if (checked !== null) {
chk.checked = checked == "true";
} else {
chk.checked = def;
}
return lbl;
}
function createOption(name, label) {
var opt = document.createElement("option");
opt.value = name;
opt.text = label;
return opt;
}
function createButton(label, func) {
var btn = document.createElement("button");
btn.type = "button";
btn.textContent = label;
btn.onclick = func;
return btn;
}
function createTh(label, w) {
var th = document.createElement("th");
th.textContent = label;
th.width = w;
return th;
}
function loadFilters() {
var filters = JSON.parse(localStorage.getItem("shobon_filters"));
if (filters) {
are_filters = true;
hide_word = new Set(filters.word);
hide_name = new Set(filters.name);
hide_id = new Set(filters.id);
}
}
function saveFilters() {
var filters = {
word: Array.from(hide_word),
name: Array.from(hide_name),
id: Array.from(hide_id)
};
localStorage.setItem("shobon_filters", JSON.stringify(filters));
}
function deleteFilter(e) {
var tr = this.parentElement.parentElement;
var name = tr.dataset.name;
var type = tr.dataset.type;
switch (type) {
case "word":
hide_word.delete(name);
break;
case "name":
hide_name.delete(name);
break;
case "id":
hide_id.delete(name);
break;
}
saveFilters();
tr.remove();
}
function addFilter(e) {
var name = document.getElementById("txt_filter").value;
var type = document.getElementById("lst_type").value;
if (!name) {
return;
}
switch (type) {
case "word":
hide_word.add(name);
break;
case "name":
hide_name.add(name);
break;
case "id":
hide_id.add(name);
break;
}
addToFilterTable(name, type);
saveFilters();
document.getElementById("txt_filter").value = "";
}
function addToFilterTable(name, type) {
var dict = { word: "Palabra", name: "Nombre/Tripcode", id: "ID" };
var table = document.getElementById("tbl_filters");
var td_type = document.createElement("td");
td_type.textContent = dict[type];
var td_name = document.createElement("td");
td_name.textContent = name;
var td_btn = document.createElement("td");
td_btn.appendChild(createButton("X", deleteFilter));
var tr = document.createElement("tr");
tr.dataset.type = type;
tr.dataset.name = name;
tr.appendChild(td_type);
tr.appendChild(td_name);
tr.appendChild(td_btn);
table.appendChild(tr);
}
function shobonSettings(e) {
e.preventDefault();
var titlebox = document.getElementById("titlebox");
var box = document.getElementById("settings");
if (box) {
box.hidden = !box.hidden;
} else {
box = document.createElement("div");
box.id = "settings";
box.className = "innerbox";
box.style.textAlign = "center";
var p = document.createElement("div");
p.appendChild(createCheckbox("shobon_on", "<b>Activar extensión</b>", true));
p.appendChild(createCheckbox("shobon_ids", "Colorear IDs", false));
p.appendChild(createCheckbox("shobon_embedimg", "Insertar imágenes miniatura", false));
p.appendChild(createCheckbox("shobon_newposts", "Destacar mensajes nuevos", false));
p.appendChild(createCheckbox("shobon_backlink", "Mostrar quién ha citado un post", true));
p.appendChild(createCheckbox("shobon_preview", "Previsualizar citas", true));
p.appendChild(createCheckbox("shobon_usefilters", "Activar filtros", false));
/*var a = document.createElement("a");
a.href = "#";
a.textContent = "[Editar filtros]";
a.addEventListener("click", function() {
var x = document.getElementById("filters");
x.hidden = !x.hidden;
});
p.appendChild(a);*/
box.appendChild(p);
var title2 = document.createElement("h6");
title2.textContent = "Filtros";
title2.style.fontSize = "18px";
title2.style.margin = "0.5em 0";
box.appendChild(title2);
box.appendChild(document.createTextNode("Filtrar mensajes por: "));
var lst_type = document.createElement("select");
lst_type.id = "lst_type";
lst_type.appendChild(createOption("word", "Palabra"));
lst_type.appendChild(createOption("name", "Nombre/Tripcode"));
lst_type.appendChild(createOption("id", "ID"));
box.appendChild(lst_type);
var txt_filter = document.createElement("input");
txt_filter.id = "txt_filter";
txt_filter.type = "text";
box.appendChild(txt_filter);
box.appendChild(createButton("Agregar", addFilter));
var tbl_filters = document.createElement("table");
tbl_filters.id = "tbl_filters";
tbl_filters.border = "1";
tbl_filters.style.margin = "0 auto";
var row = document.createElement("tr");
row.appendChild(createTh("Tipo", 150));
row.appendChild(createTh("Filtro", 300));
row.appendChild(createTh("", 75));
tbl_filters.appendChild(row);
box.appendChild(tbl_filters);
var msg = document.createElement("a");
msg.style.display = "block";
msg.href = "#";
msg.textContent = "Actualizar para ver cambios";
msg.style.marginTop = "1em";
msg.addEventListener("click", function() {
location.reload();
});
box.appendChild(msg);
titlebox.appendChild(box);
var i;
hide_word.forEach(v => {
addToFilterTable(v, "word");
});
hide_name.forEach(v => {
addToFilterTable(v, "name");
});
hide_id.forEach(v => {
addToFilterTable(v, "id");
});
}
}
function checkBlackList(reply) {
var i;
// Check words
var low = reply.children[1].textContent.toLowerCase();
hide_word.forEach(v => {
console.log(v);
if (low.includes(v.toLowerCase())) {
hidepost(reply);
}
});
// Check name/trip
var msg_name = reply.firstElementChild
.getElementsByClassName("name")[0]
.textContent.toLowerCase();
hide_name.forEach(v => {
if (msg_name.includes(hide_name[i])) {
hidepost(reply);
}
});
// Check ID
var date_div = reply.firstElementChild.getElementsByClassName("date")[0]
.textContent;
var id_index = date_div.indexOf("ID:");
if (id_index != -1) {
var id = date_div.substr(id_index + 3);
hide_id.forEach(v => {
if (id.includes(v)) {
hidepost(reply);
}
});
}
}
var currentSel = null;
function paintIds(reply) {
var dateId = reply.getElementsByClassName("date")[0];
if (dateId.textContent.includes("ID:")) {
var postDate = dateId.textContent.split("ID:")[0];
var userId = dateId.textContent.split("ID:")[1];
var idColor = toHex(userId).substring(0, 6);
var reverseColor = invertColor(idColor);
var lastChar = userId.substring(userId.length - 1, userId.length);
dateId.innerHTML =
postDate +
"<span class='uid ID_" + userId.slice(0, -1) +
"' style='background-color:#" +
idColor +
";color:#" +
reverseColor +
";padding:0 3px;border-radius:5px; font-size:0.9em;vertical-align:top;'>ID:" +
userId +
"</span>";
}
}
function embedImg(reply) {
var links = reply.getElementsByTagName("a");
for (i = 0; i < links.length && i < 5; i++) {
var url = links[i].href;
if (url.startsWith("https://i.imgur.com")) {
var ext = url.lastIndexOf(".");
var thumburl = url.slice(0, ext) + "s" + url.slice(ext);
} else if (links[i].href.startsWith("https://pbs.twimg.com")) {
var thumburl = links[i].href + ":thumb";
} else continue;
var thumb = document.createElement("img");
thumb.src = thumburl;
links[i].appendChild(document.createElement("br"));
links[i].appendChild(thumb);
}
}
function toHex(str) {
var hex = "";
for (var i = 0; i < str.length; i++) {
hex += "" + (str.charCodeAt(i) + 125).toString(16);
}
return hex;
}
function invertColor(hex) {
if (hex.indexOf("#") === 0) {
hex = hex.slice(1);
}
// convert 3-digit hex to 6-digits.
if (hex.length === 3) {
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
}
if (hex.length !== 6) {
throw new Error("Invalid HEX color.");
}
// invert color components
var r = (255 - parseInt(hex.slice(0, 2), 16)).toString(16),
g = (255 - parseInt(hex.slice(2, 4), 16)).toString(16),
b = (255 - parseInt(hex.slice(4, 6), 16)).toString(16);
// pad each with zeros and return
return padZero(r) + padZero(g) + padZero(b);
}
function padZero(str, len) {
len = len || 2;
var zeros = new Array(len).join("0");
return (zeros + str).slice(-len);
}
document.addEventListener("DOMContentLoaded", shobon, false);