您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
API WykopObserve dla dodatków na wykop.pl - daje API, które robi pętlę z callbackiem, po wpisach z filtrowaniem wedłów różnych kryteriów.
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/437595/1002297/WykopObserve.js
- // observe module start
- const {wykopObserve, filterGroups, loginUser, getAdjacentEls} = (function () {
- const headerProfileElement = "header-profile-element";
- const linkPageAuthorElement = "link-page-author-element"; // element osoby która dodała ten link
- const mikroblogPageComment = "mikroblog-page-comment";
- const mikroblogPageSubComment = "mikroblog-page-sub-comment";
- const linkPageComment = "link-page-comment";
- const linkPageSubComment = "link-page-sub-comment";
- const wpisPageComment = "wpis-page-comment";
- const wpisPageSubComment = "wpis-page-sub-comment";
- const tagPageComment = "tag-page-comment";
- const tagPageSubComment = "tag-page-sub-comment";
- const mojPageComment = "moj-page-comment";
- const mojPageSubComment = "moj-page-sub-comment";
- const mikroblogPageWriteElement = "mikroblog-page-write-element";
- const linkPageWriteElement = "link-page-write-element";
- const wpisPageWriteElement = "wpis-page-write-element";
- const tagPageWriteElement = "tag-page-write-element";
- const ludziePageWriteElement = "ludzie-page-write-element";
- const mojPageWriteElement = "moj-page-write-element";
- const ludziePageLinkSubComment = "ludzie-page-link-sub-comment";
- const ludziePageWpisComment = "ludzie-page-wpis-comment";
- const ludziePageWpisSubComment = "ludzie-page-wpis-sub-comment";
- const glownaPageComment = "glowna-page-comment";
- const mikroblogLinkWpisGlownaTagMojComment = [
- mikroblogPageComment,
- linkPageComment,
- wpisPageComment,
- glownaPageComment,
- tagPageComment,
- mojPageComment,
- ];
- const mikroblogLinkWpisTagSubMojComment = [
- mikroblogPageSubComment,
- linkPageSubComment,
- wpisPageSubComment,
- tagPageSubComment,
- mojPageSubComment,
- ];
- const mikroblogLinkWpisGlownaTagMojCommentOrSubComment = [
- ...mikroblogLinkWpisGlownaTagMojComment,
- ...mikroblogLinkWpisTagSubMojComment,
- ];
- const ludziePageCommentOrSubComment = [
- ludziePageLinkSubComment,
- ludziePageWpisComment,
- ludziePageWpisSubComment
- ]
- const writeElement = [
- mikroblogPageWriteElement,
- linkPageWriteElement,
- wpisPageWriteElement,
- tagPageWriteElement,
- ludziePageWriteElement,
- mojPageWriteElement,
- ];
- const places = [
- headerProfileElement,
- linkPageAuthorElement,
- mikroblogPageComment,
- mikroblogPageSubComment,
- linkPageComment,
- linkPageSubComment,
- wpisPageComment,
- wpisPageSubComment,
- tagPageComment,
- tagPageSubComment,
- mojPageComment,
- mojPageSubComment,
- mikroblogPageWriteElement,
- linkPageWriteElement,
- wpisPageWriteElement,
- tagPageWriteElement,
- ludziePageWriteElement,
- mojPageWriteElement,
- ludziePageLinkSubComment,
- ludziePageWpisComment,
- ludziePageWpisSubComment,
- glownaPageComment,
- //"chat-page-comment",
- //"chat-page-write-element",
- //"own-page-author-element", // element osoby która utworzyła własną treść w edytorze wykopowym
- ];
- const otherFilter = "other";
- const getWykopPageType = ()=>location.pathname.split("/")[1];
- const hasSub = (profileEl)=>profileEl.parentElement.parentElement.parentElement.classList.contains("sub");
- const getSub = (profileEl)=>hasSub(profileEl)?"-sub":"";
- function getProfiles (scopeEl, placesFilter) {
- const profiles = [];
- const loggedUserEl = document.querySelector('.logged-user > a');
- if (loggedUserEl && placesFilter.includes(headerProfileElement)) {
- profiles.push(loggedUserEl);
- }
- const userCardEl = document.querySelector('.usercard > a');
- if (getWykopPageType() === "link" && userCardEl && placesFilter.includes(linkPageAuthorElement)) {
- profiles.push(userCardEl);
- }
- // UWAGA: to filtruje tylko wstępnie. później filtruje się pojedynczo w observer
- //if (getWykopPageType() === "mikroblog" && placesArr.includes(mikroblogPageComment)) {
- //profiles.push(...Array.from(scopeEl.querySelectorAll('[data-type="entry"] .profile')));
- //}
- //if (getWykopPageType() === "mikroblog" && placesFilter.includes(mikroblogPageSubComment)) {
- profiles.push(...Array.from(scopeEl.querySelectorAll('[data-type="entrycomment"] .profile')));
- //}
- if (getWykopPageType() === "link" && placesFilter.includes(linkPageComment)) {
- profiles.push(...Array.from(scopeEl.querySelectorAll(':not(.sub) [data-type="comment"] .profile')));
- } // nie odkomentowywać, bo dam się dynamicznie nie aktualizują ani nie doładowują ukryte, bo one są tylko hidden.
- if (getWykopPageType() === "link" && placesFilter.includes(linkPageSubComment)) {
- profiles.push(...Array.from(scopeEl.querySelectorAll('.sub [data-type="comment"] .profile')));
- }
- //if (getWykopPageType() === "wpis" && placesArr.includes(wpisPageComment)) {
- //profiles.push(...Array.from(scopeEl.querySelectorAll('[data-type="entry"] .profile')));
- //}
- //if (getWykopPageType() === "wpis" && placesFilter.includes(wpisPageSubComment)) {
- profiles.push(...Array.from(scopeEl.querySelectorAll('[data-type="entrycomment"] .profile')));
- //}
- //if (getWykopPageType() === "tag" && placesArr.includes(tagPageComment)) {
- //profiles.push(...Array.from(scopeEl.querySelectorAll('[data-type="entry"] .profile')));
- //}
- //if (getWykopPageType() === "tag" && placesFilter.includes(tagPageSubComment)) {
- profiles.push(...Array.from(scopeEl.querySelectorAll('[data-type="entrycomment"] .profile')));
- //}
- //if (getWykopPageType() === "moj" && placesFilter.includes(mojPageSubComment)) {
- profiles.push(...Array.from(scopeEl.querySelectorAll('[data-type="entrycomment"] .profile')));
- //}
- if (getWykopPageType() === "mikroblog" && placesFilter.includes(mikroblogPageWriteElement)) {
- profiles.push(...Array.from(scopeEl.querySelectorAll('[data-submitflag="commentSubmit"] .profile')));
- }
- if (getWykopPageType() === "link" && placesFilter.includes(linkPageWriteElement)) {
- profiles.push(...Array.from(scopeEl.querySelectorAll('[data-submitflag="commentSubmit"] .profile')));
- }
- if (getWykopPageType() === "wpis" && placesFilter.includes(wpisPageWriteElement)) {
- profiles.push(...Array.from(scopeEl.querySelectorAll('[data-submitflag="commentSubmit"] .profile')));
- }
- if (getWykopPageType() === "tag" && placesFilter.includes(tagPageWriteElement)) {
- profiles.push(...Array.from(scopeEl.querySelectorAll('[data-submitflag="commentSubmit"] .profile')));
- }
- if (getWykopPageType() === "ludzie" && placesFilter.includes(ludziePageWriteElement)) {
- profiles.push(...Array.from(scopeEl.querySelectorAll('[data-submitflag="commentSubmit"] .profile')));
- }
- if (getWykopPageType() === "moj" && placesFilter.includes(mojPageWriteElement)) {
- profiles.push(...Array.from(scopeEl.querySelectorAll('[data-submitflag="commentSubmit"] .profile')));
- }
- if (getWykopPageType() === "ludzie" && placesFilter.includes(ludziePageLinkSubComment)) {
- profiles.push(...Array.from(scopeEl.querySelectorAll(':not(.sub) [data-type="comment"] .profile')));
- }
- //if (getWykopPageType() === "ludzie" && placesArr.includes(ludziePageWpisComment)) {
- profiles.push(...Array.from(scopeEl.querySelectorAll('[data-type="entry"] .profile')));
- // bez if-a, żeby observer się dodał, a filtrowane w observer-ze i w allFn
- // reszta zapytań [data-type="entry"] .profile za-komentowana, żeby nie powielać.
- // glownaPageComment też
- //}
- //if (getWykopPageType() === "ludzie" && placesFilter.includes(ludziePageWpisSubComment)) {
- profiles.push(...Array.from(scopeEl.querySelectorAll('[data-type="entrycomment"] .profile')));
- //}
- if (profiles.length===0) { console.log("profiles is empty"); }
- return profiles;
- }
- function getPlace (profileEl) {
- let place = "other";
- if (profileEl === document.querySelector('.logged-user > a')) {
- place = headerProfileElement;
- } else
- if (getWykopPageType() === "link" && profileEl === document.querySelector('.usercard > a')) {
- place = linkPageAuthorElement;
- } else
- if (getWykopPageType() === "ludzie" && profileEl.parentElement.matches('[data-type="comment"]')) {
- place = ludziePageLinkSubComment;
- } else
- if (getWykopPageType() === "ludzie" && profileEl.parentElement.matches('[data-type="entry"]')) {
- place = ludziePageWpisComment;
- } else
- if (getWykopPageType() === "ludzie" && profileEl.parentElement.matches('[data-type="entrycomment"]')) {
- place = ludziePageWpisSubComment;
- } else
- if (getWykopPageType() === "ludzie" && profileEl.parentElement.matches('[data-submitflag="commentSubmit"]')) {
- place = ludziePageWpisSubComment;
- } else
- if (document.querySelector(".grid .info")?.textContent?.includes("Strona główna")
- &&
- profileEl.parentElement.matches('[data-type="entry"]')) {
- place = glownaPageComment;
- } else
- if (["ludzie","link","tag","mikroblog","wpis","moj"].includes(getWykopPageType())) {
- place = `${getWykopPageType()}-page${getSub(profileEl)}-comment`;
- }
- if (place === "") { console.log("place null", profileEl); }
- return place;
- }
- function getProfileElNick(profileEl) {
- const nickB = profileEl.getAttribute("href").split("/");
- const nick = nickB[nickB.length-2];
- return nick;
- }
- const getSex = avatarEl=>avatarEl.classList.contains("male")?"male":avatarEl.classList.contains("female")?"female":null;
- async function wykopObserve (userFilters, callbackFn, {once=false,delay=null}) {
- const cleanP = [...(new Set(userFilters.flat(Infinity)))];
- userFilters = cleanP.filter(p=>[...places, otherFilter].includes(p));
- const ff = cleanP.filter(p=>![...places, otherFilter].includes(p));
- if (ff.length>0) { console.warn(`[WykopObserve] faulty filters: ${ff.map(f=>`"${f}"`).join(", ")}.`); }
- const sym = Symbol();
- function getAttrs (profileEl) {
- const avatarEl = profileEl.querySelector(".avatar");
- const place = getPlace(profileEl);
- const isFirstTime = profileEl.parentElement.parentElement[sym]!==true;
- const nick = getProfileElNick(profileEl);
- const authorSex = getSex(avatarEl);
- const attrs = {place, isFirstTime, nick, authorSex};
- return attrs;
- }
- function getElements (profileEl) {
- const liEL = profileEl.parentElement.parentElement;
- return {
- profileEl,
- liEl: liEL.matches("li")?liEL:null,
- contentEl: profileEl.parentElement.querySelector(".text > p")
- };
- }
- async function cbFn (elements, attrs) {
- await callbackFn(elements, attrs);
- //if (delay >= 0) { await delayFn(delay); }
- }
- function addCommentOrSubCommentChangeObserver (cbFn, parentProfileEl, placesFilter) {
- const profileElObserver = new MutationObserver((mutations)=> {
- //console.log("profilEl mutation");
- const target = mutations[0].target;
- if (!(target instanceof HTMLElement)) { return false; }
- const profileEl = target.querySelector(".profile");
- const attrs = getAttrs(profileEl);
- const elements = getElements(profileEl);
- if (placesFilter.includes(attrs.place)) {
- cbFn(elements, attrs);
- }
- });
- profileElObserver.observe( parentProfileEl.parentElement.parentElement, {childList: true} );
- };
- async function cbAndObserveChanges (scopeEl, observe=true) {
- const placesFilter = userFilters;
- const profiles = getProfiles(scopeEl, placesFilter);
- for (const profileEl of profiles) {
- const attrs = getAttrs(profileEl);
- const elements = getElements(profileEl);
- if (placesFilter.includes(attrs.place) && (observe===false || once === false || attrs.isFirstTime === true)) {
- await cbFn(elements, attrs);
- if (observe) { addCommentOrSubCommentChangeObserver(cbFn, profileEl, placesFilter); }
- profileEl.parentElement.parentElement[sym] = true;
- }
- // addCommentOrSubCommentChangeObserver
- // trzeba dodać do każdego Comment i SubComment, bo to obserwuje modyfikację konkretnego elementu pod względem posiadania
- // brody. nie sprawdza ilości a modyfikację elementu (np. usunięcie, edycję).
- // obsługuje: usunięcie(stan "usunięty"), stan edycji(jak jest pole do wpisywania to też odświeża avatar), stan po edycji.
- // modyfikacja WpisPageComment też trigger-uje observera.
- }
- }
- function addSubObserver (subOrStreamEl, callback=()=>{}) {
- //if (subOrStreamEl.dataset.hasOwnProperty("childCount")) { return false; }
- if (subOrStreamEl[sym]===true) { return false; }
- //subOrStreamEl.dataset.childCount = `${subOrStreamEl.childElementCount}`;
- const subObserver = new MutationObserver(async function(mutations) {
- const target = mutations[0].target;
- if (!(target instanceof HTMLElement)) { return false; }
- //target.dataset.childCount = `${target.childElementCount}`;
- await cbAndObserveChanges(target);
- callback();
- });
- subObserver.observe( subOrStreamEl, {childList: true} );
- subOrStreamEl[sym]=false;
- };
- function observeExpandSubComments () {
- const subEls = Array.from( document.querySelectorAll(".sub") );
- subEls.forEach((subEl)=>addSubObserver(subEl));
- }
- function cbAndObserveOnNewAndInfiniteScrollInTagPage () {
- const streamEl = document.querySelector(".comments-stream");
- addSubObserver(streamEl, observeExpandSubComments);
- }
- await cbAndObserveChanges(document);
- // dodaje do wpisPageComment lub wpisPgeSubComment i obserwuje modyfikacje
- // nie reaguje na ładowanie dodatkowych postów w tagu.
- observeExpandSubComments();
- // dodaje dla wpisPageSubComment, gdy rozwinąć dodatkowe zwinięte komentarze wpisPageSubComment
- // w link, mikroblog, na profilu też działa doładowywanie. (w link niepotrzebne właściwie)
- cbAndObserveOnNewAndInfiniteScrollInTagPage();
- // dodaje dla tagPageComment, doładowane jako nowe albo z infinite scroll
- // nie dodaje observer dla expandSubComments
- const refresh = ()=>cbAndObserveChanges(document, false);
- return {refresh};
- // const wpisZeroObserver = new MutationObserver(async function(mutations) {
- // const liEl = mutations[0].target;
- // if (!(liEl instanceof HTMLElement)) { return false; }
- // const subEl = liEl.querySelector(".sub");
- // if (!(subEl instanceof HTMLElement)) { return false; }
- // if (!(liEl.childElementCount !== 1 && subEl)) { return false; }
- // await cbAndObserveChanges(subEl);
- // subEl.dataset.childCount = `${subEl.childElementCount}`;
- // addSubObserver(subEl);
- // });
- // function subZeroFn () {
- // const streamElChildren = Array.from( document.querySelector(".comments-stream").children );
- // streamElChildren.forEach((liEl)=>{
- // if (!(liEl.childElementCount === 1)) { return false; }
- // wpisZeroObserver.observe( liEl, {childList: true} );
- // });
- // }
- //subZeroFn();
- // raczej nic nie robi
- // dodaje dla wpisPageSubComment ale setNowAndObserveChanges też to robi?
- // nie dodaje gdy zmienia się liczba wpisPageSubComment
- // nie dodaje, gdy rozwinąć dodatkowe zwinięte komentarze wpisPageSubComment
- }
- function getLogin () {
- const avatarEl = document.querySelector(".logged-user img.avatar");
- if (!(avatarEl instanceof HTMLImageElement)) { return false; }
- return {login:avatarEl.alt, sex:getSex(avatarEl)};
- }
- function getAdjacentEls(liEl) {
- return liEl?.parentElement?.children||[];
- }
- //} // observe lib end
- return {wykopObserve, loginUser:getLogin(), getAdjacentEls, filterGroups: {
- all: places,
- mikroblogLinkWpisGlownaTagMojComment,
- mikroblogLinkWpisTagSubMojComment,
- mikroblogLinkWpisGlownaTagMojCommentOrSubComment,
- ludziePageCommentOrSubComment,
- writeElement,
- }};
- })();
- // observe module end
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址