// ==UserScript==
// @name Search posts by user
// @name:ru Поиск постов пользователя
// @description Search for posts by user in current topic
// @description:ru Найти посты пользователя в текущей теме
// @version 1.1.0
// @date 14.12.2017
// @author Halibut
// @namespace https://gf.qytechs.cn/en/users/145947-halibut
// @homepageURL https://gf.qytechs.cn/en/scripts/36319-search-posts-by-user
// @supportURL https://forum.ru-board.com/topic.cgi?forum=2&topic=5673&glp
// @license HUG-WARE
// @include http*://forum.ru-board.com/topic.cgi?forum=*&topic=*
// @noframes
// @grant none
// ==/UserScript==
/******************************************************************************
* "THE HUG-WARE LICENSE" (Revision 2): As long as you retain this notice you *
* can do whatever you want with this stuff. If we meet some day, and you *
* think this stuff is worth it, you can give me/us a hug. *
******************************************************************************/
((body, img, listener) => {
'use strict';
if (listener.isFF) {
const context = body.getAttribute("contextmenu"),
menu = context
? document.getElementById(context)
: body.appendChild(document.createElement("menu")),
mitem = menu.appendChild(document.createElement("menuitem"));
if (!context) {
menu.id = "GM_page-actions";
menu.type = "context";
body.setAttribute("contextmenu", "GM_page-actions");
};
mitem.label = "Найти все собщения пользователя в теме";
mitem.addEventListener("click", listener)
};
const button = listener.actnBox.getElementsByTagName("td")[0].appendChild(document.createTextNode(" "))
&& listener.actnBox.getElementsByTagName("td")[0].appendChild(document.createElement("a")),
imgNode = button.appendChild(document.createElement("img"));
imgNode.src = img;
button.addEventListener("click", listener)
body.addEventListener("contextmenu", e => {
let target = e.target;
while (target && target.className != "m")
target = target.parentNode;
console.log(target);
if (!target) return;
listener.setName = target.textContent;
listener.handleEvent(e)
})
})(
document.body
, "data:image/gif;base64,R0lGODlhXgAPAJEAAAAAAP///////wAAACH5BAEAAAIALAAAAABeAA8AAAKUhI+py+0PIwq02ouz3rz7HxjgSJamJ57qym5plcAvAMs0dYfuhL/hzPvlgrLLEFfT/ZDMWy5zVCqjzKozWbREt7qrsQpNcsNYr7T3bYq74N6TPF3Dpc4Dxke3ImlmuWYcNwf4hjeIFhiIp+Vn9uTIaERYNjNJ9bZo5WOHaWNTeNkSKgqiOGp6Gomquuom4foKGwtRAAA7"
, {
name: null
, set setName(str) {
this.name = str
}
, get win() {
delete this.win;
return this.win = window.top
}
, get loc() {
delete this.loc;
return this.loc = this.win.location.href
}
, get actnBox() {
delete this.actnBox;
return this.actnBox = [...document.getElementsByTagName("table")].find(el => el.querySelector("a[href^='post.cgi?action=new']"))
}
, get isFF() {
delete this.isFF;
return this.isFF = this.win.navigator.product == "Gecko"
}
, get spHd() {
delete this.spHd;
return this.spHd = this.getSpHd()
}
, get spBd() {
delete this.spBd;
return this.spBd = this.getSpBd()
}
, getSel() {
return this.win.getSelection && this.win.getSelection().toString() || ""
}
, prompt() {
const prompt = this.win.prompt('Задайте имя для поиска', "")
return prompt
}
, getPosts(url, name) {
return new Promise((res, rej) => {
let posts;
if (url == this.loc) {
posts = document.getElementsByClassName('tb');
if (posts && !!posts.length) {
posts = this.filterPosts(posts, name);
return res(posts.map(el => el.cloneNode(true)));
}
};
const xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.onload = re => {
if (!(xhr.readyState == 4 && xhr.status == 200)) return rej("error");
posts = xhr.responseXML.getElementsByClassName('tb');
if (posts && !!posts.length) {
posts = this.filterPosts(posts, name);
return res(posts);
}
};
xhr.onerror = xhr.onabort = xhr.ontimeout = () => rej("error");
xhr.responseType = "document";
xhr.send();
})
}
, filterPosts(posts, name) {
return [...posts].filter(post => !post.querySelector('a.tpc[href$="&postno=1"]')
&& post.querySelector("td.dats > a.m > b").textContent.toLowerCase().replace(/\s/g, '_') == name);
}
, getUsrName() {
return (this.name || this.getSel() || this.prompt()).trim().toLowerCase().replace(/\s/g, '_');
}
, getPages() {
const paginator = [...document.getElementsByTagName("p")].find(el => el.textContent && el.textContent.startsWith("Страницы: "));
if (paginator)
return [...paginator.getElementsByTagName("td")[0].children].map(el => el.href || this.loc);
else
return [this.loc]
}
, getSpHd() {
let spoilerHead = document.getElementById("spu-spoiler-head");
if (!spoilerHead) {
const dummyNode = this.actnBox.parentNode.insertBefore(document.createElement('div'), this.actnBox.nextElementSibling),
show = decodeURIComponent("%E2%96%BA") + ' Показать результаты поиска',
hide = decodeURIComponent("%E2%96%BC") + ' Скрыть результаты поиска';
dummyNode.outerHTML = '<table id="spu-spoiler-head" style="-moz-user-select: none ! important; cursor: pointer ! important;" width="95%" cellspacing="1" cellpadding="3" bgcolor="#999999" align="center" border="0"><tbody><tr><td valign="middle" bgcolor="#dddddd" align="left"></td></tr><td class="small" bgcolor="#dddddd" align="center">Найдено: <span id="spu-fndd"></span> Ошибок: <span id="spu-errs"></span></td></tbody></table>';
spoilerHead = this.actnBox.nextElementSibling;
spoilerHead.id = "spu-spoiler-head";
spoilerHead.hidden = true;
const spTitle = spoilerHead.getElementsByTagName('td')[0];
spoilerHead.style.cssText = '-moz-user-select: none !important;-webkit-user-select: none !important; -ms-user-select: none !important; user-select: none !important; cursor: pointer !important';
spTitle.textContent = show;
spoilerHead.onclick = e => {
if (e.button != 0 || !this.spBd) return;
e.preventDefault(); e.stopPropagation();
this.spBd.hidden = !this.spBd.hidden;
spTitle.textContent = this.spBd.hidden ? show : hide;
}
}
return spoilerHead;
}
, getSpBd() {
let spoilerBody = document.getElementById("spu-spoiler-body");
if (!spoilerBody) {
spoilerBody = this.spHd.parentNode.insertBefore(document.createElement("table"), this.spHd.nextElementSibling);
spoilerBody.id = "spu-spoiler-body";
spoilerBody.align = "center";
spoilerBody.width = "95%";
spoilerBody.style.border = "1px solid black";
spoilerBody.style.padding = "1em .5em"
spoilerBody.hidden = true;
}
return spoilerBody;
}
, handleEvent(e) {
e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation();
const name = this.getUsrName();
if (!name) return;
this.spHd.hidden = false;
const pageLinks = this.getPages(),
errsLbl = document.getElementById("spu-errs"),
findedLbl = document.getElementById("spu-fndd");
errsLbl.textContent = findedLbl.textContent = 0;
let postsCntr = 0, errorsCntr = 0; ;
if (this.spBd.children && !!this.spBd.children.length)
for (const node of [...this.spBd.children])
node.remove();
for(const link of pageLinks)
this.getPosts(link, name).then(
posts => {
if (posts && !!posts.length)
for (const post of posts) {
this.spBd.appendChild(post);
postsCntr += 1; findedLbl.textContent = postsCntr
}
}
, err => {
errorsCntr += 1; errsLbl.textContent = errorsCntr
}
);
this.name = null;
this.spHd.scrollIntoView({behavior:"smooth"});
}
}
);