Greasy Fork is available in English.

Wykop XS - Lista plusujących, animowane awatary, mikroczat

Wykop XS - Darmowy dostęp do Mikroczatu. Dodatkowe funkcje na wykopie: animowane avatary, przywrócenie listy plusujących wpisy i komentarze oraz przycisku Ulubione

Nainštalovať tento skript?
Autor skriptu navrhuje

Tiež sa vám môže páčiť Wykop XS 3.0.

Nainštalovať tento skript
  1. // ==UserScript==
  2. // @name Wykop XS - Lista plusujących, animowane awatary, mikroczat
  3. // @name:pl Wykop XS - Lista plusujących, animowane awatary, mikroczat
  4. // @name:en Wykop XS - Lista plusujących, animowane awatary, mikroczat
  5.  
  6. // @version 3.0.81
  7.  
  8. // @description Wykop XS - Darmowy dostęp do Mikroczatu. Dodatkowe funkcje na wykopie: animowane avatary, przywrócenie listy plusujących wpisy i komentarze oraz przycisku Ulubione
  9. // @description:en Wykop XS - Darmowy dostęp do Mikroczatu. Dodatkowe funkcje na wykopie: animowane avatary, przywrócenie listy plusujących wpisy i komentarze oraz przycisku Ulubione
  10.  
  11.  
  12. // Chcesz wesprzeć projekt Wykop X? Postaw kawkę:
  13. // @contributionURL https://buycoffee.to/wykopx
  14.  
  15. // @author Wykop X <wykopx@gmail.com>
  16.  
  17.  
  18.  
  19.  
  20.  
  21.  
  22.  
  23.  
  24.  
  25. // @match https://wykop.pl/*
  26. // @supportURL http://wykop.pl/tag/wykopx
  27. // @namespace Violentmonkey Scripts
  28. // @compatible chrome, firefox, opera, safari, edge
  29. // @license No License
  30. // @icon https://www.google.com/s2/favicons?sz=64&domain=wykop.pl
  31.  
  32.  
  33. // @require https://unpkg.com/localforage@1.10.0/dist/localforage.min.js
  34. // @require https://cdn.jsdelivr.net/npm/dayjs@1.11.10/dayjs.min.js
  35. // @require https://cdn.jsdelivr.net/npm/dayjs@1.11.10/locale/pl.js
  36. // @require https://cdn.jsdelivr.net/npm/dayjs@1.11.10/plugin/relativeTime.js
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43. // ==/UserScript==
  44.  
  45.  
  46. 'use strict';
  47.  
  48. const currentVersion = "3.0.80";
  49. let dev = true;
  50.  
  51. const promoString = " - Wykop XS / #wykopx";
  52.  
  53.  
  54. const root = document.documentElement;
  55. const head = document.head;
  56. const body = document.body;
  57. const bodySection = body.querySelector("section");
  58.  
  59. dayjs.locale("pl");
  60. dayjs.extend(window.dayjs_plugin_relativeTime); //dayjs.extend(relativeTime); // https://day.js.org/docs/en/plugin/relative-time // https://www.jsdelivr.com/package/npm/dayjs?tab=files&path=plugin
  61.  
  62. const wykopxSettings = getComputedStyle(head);
  63. const settings = {};
  64.  
  65. const styleElement = document.createElement('style');
  66. styleElement.id = "wykopxs_mikroczat";
  67. let CSS = "";
  68.  
  69. function setSettingsValueFromCSSProperty(settingName, defaultValueForWykopXS = true, propertyValueInsteadOfBoolean = false)
  70. {
  71. if (propertyValueInsteadOfBoolean) settings[settingName] = wykopxSettings.getPropertyValue(`--${settingName}`) ? wykopxSettings.getPropertyValue(`--${settingName}`).trim() : defaultValueForWykopXS;
  72. else settings[settingName] = wykopxSettings.getPropertyValue(`--${settingName}`) ? wykopxSettings.getPropertyValue(`--${settingName}`).trim() === '1' : defaultValueForWykopXS;
  73. }
  74.  
  75. //setSettingsValueFromCSSProperty("WykopXSEnabled");
  76. //if (settings.WykopXSEnabled == false) return;
  77.  
  78.  
  79. /* WYKOP XS HEADER */
  80.  
  81.  
  82.  
  83.  
  84.  
  85.  
  86. /* --- ZMIANA USTAWIEŃ ---
  87. jeśli chcesz zmienić domyślne ustawienia nie zmieniaj ich w tym kodzie.
  88. Zmień je w przeglądarce w następujący sposób:
  89.  
  90. 1. Wejdź na Wykop
  91. 2. Otwórz panel narzędzi deweloperskich klawiszem *F12* lub skrótem klawiaturowym *CTRL* + *SHIFT* + *C*
  92. 3. Przejdź na zakładkę "Aplikacja"
  93. 4. w panelu po lewej w sekcji "Pamięć" wybierz "Pamięć lokalna" i znajdź na liście https://wykop.pl
  94. 5. w głównym okienku pojawi się lista kilku wartości. Znajdź opcję "wykopx/settings/settings"
  95. 6. zmień wybraną opcję na true (aby ją włączyć) lub false (aby wyłączyć)
  96.  
  97.  
  98. Domyślne wartości wyglądają przykładowo tak:
  99.  
  100. {"entryVotersListExpandIfLessThan": 5, "votersFollow":true, "votersBlacklist":true, "votersBanned":true, "votersSuspended":true, "votersRemoved":true, "votersGenderF":false, "votersGenderM":false, "votersColorGreen":true, "votersColorOrange":false,"votersColorBurgundy":true}
  101.  
  102. */
  103.  
  104.  
  105.  
  106. // DEFAULT SETTINGS - nie zmieniaj wartości settings w kodzie.
  107. // Zmień je w sposób opisany powyżej
  108.  
  109. setSettingsValueFromCSSProperty("entryVotersListEnable"); // włącza pokazywanie listy plusujących z Wykop X Style
  110. setSettingsValueFromCSSProperty("entryVotersListExpandIfLessThan", 50, true);
  111. setSettingsValueFromCSSProperty("hideAds"); // blokuje wszystkie reklamy na wykopie
  112.  
  113.  
  114. // entryVotersListExpandIfLessThan - domyślnie Wykop pokazywał 5 osób, które zaplusowały.
  115. // Możesz zmienić tę wartość na np. 10 albo 25. Jeśli wpis ma mniej plusów niż ta liczba, zostaną od razu wyświetleni wszyscy plusujący bez przycisku "+15 INNYCH"
  116.  
  117. settings.showAnimatedAvatars = true; // pokazuje animowane avatary
  118.  
  119. if (settings.entryVotersListEnable)
  120. {
  121. // entryVotersListExpandIfLessThan - domyślnie Wykop pokazywał 5 osób, które zaplusowały.
  122. // Możesz zmienić tę wartość na np. 10 albo 25. Jeśli wpis ma mniej plusów niż ta liczba, zostaną od razu wyświetleni wszyscy plusujący bez przycisku "+15 INNYCH"
  123. if (!settings.entryVotersListExpandIfLessThan) settings.entryVotersListExpandIfLessThan = 20;
  124. settings.votersFollow = true; // pokazuje 🔔 przed użytkownikami, których obserwujesz
  125. settings.votersBlacklist = true; // pokazuje ⛔ przed użytkownikami, których blokujesz
  126. settings.votersBanned = true; // pokazuje użytkowników z aktywnym banem w kolorze i z ikonką 🍌
  127. settings.votersSuspended = true; // pokazuje ✖ przed kontami, które są w trakcie usuwania
  128. settings.votersRemoved = true; // pokazuje ✖ przed kontami, które są usunięte
  129. settings.votersGenderF = false; // pokazuje różową kropkę przed kobietami
  130. settings.votersGenderM = false; // pokazuje niebieską kropkę przed mężczyznami
  131. settings.votersColorGreen = true; // pokazuje zielonki w kolorze
  132. settings.votersColorOrange = false; // pokazuje pomarańczowych użytkowników w kolorze
  133. settings.votersColorBurgundy = true; // pokazuje użytkowników bordo w kolorze
  134. settings.votersFollowFirst = true; // pokazuje użytkowników, których obserwujesz pierwszych na liście
  135. settings.votersBlackFirst = false; // pokazuje plusy od moderacji pierwsze na liście (konta typu @wykop, @m__b, @a__s itd.)
  136. settings.votersBurgundyFirst = false; // pokazuje użytkowników bordo pierwszych na liście
  137. settings.votersOrangeFirst = false; // pokazuje zielonki pierwszych na liście
  138. settings.votersGreenFirst = false; // pokazuje pomarańczki pierwszych na liście
  139. settings.votersBlacklistLast = false; // pokazuje użytkowników, których zablokowałeś na końcu listy
  140. settings.votersRemovedLast = false; // pokazuje usunięte konta na końcu listy
  141. settings.votersBannedLast = false; // pokazuje zbanowanych na końcu listy
  142. settings.votersSuspendedLast = false; // pokazuje konta w trakcie usuwania na końcu listy
  143. }
  144.  
  145. settings.hideShareButton = true; // ukrywa przycisk "Udostępnij"
  146. settings.showFavouriteButton = true; // pokazuje przycisk "Dodaj do ulubionych" (samą gwiazdkę)
  147. settings.showFavouriteButtonLabel = true; // pokazuje oprócz gwiazdki także tekst "Ulubione"
  148. // settings.addCommentPlusWhenVotingOnEntry = false; // gdy plusujesz wpis, dodaje komentarz "+1"
  149. // settings.addCommentPlusWhenVotingOnComment = false; // gdy plusujesz komentarz, dodaje komentarz "+1"
  150.  
  151.  
  152.  
  153. settings.mikroczatShowLeftMenuButton = false;
  154. settings.mikroczatShowLeftMenuLink = true;
  155. settings.mikroczatShowTopNavButton = true;
  156. settings.mikroczatOpenMikroczatOnMiddleClick = false;
  157. settings.mikroczatOpenMikroczatOnCTRLLeftClick = true;
  158. settings.mikroczatOpenMikroczatOnCTRLMiddleClick = true;
  159.  
  160. (async function ()
  161. {
  162. // LOCALSTORAGE
  163. const localStorageSettings = localforage.createInstance({
  164. driver: localforage.LOCALSTORAGE,
  165. name: "wykopx",
  166. storeName: "settings",
  167. });
  168.  
  169. await localStorageSettings.getItem('settings').then(async (localSettings) =>
  170. {
  171. if (localSettings)
  172. {
  173. mergeSettings(localSettings, settings);
  174. }
  175. else
  176. {
  177. localStorageSettings.setItem('settings', settings);
  178. }
  179. await localStorageSettings.setItem('settings', settings);
  180. }).catch((err) =>
  181. {
  182. console.error('Error', err);
  183. });
  184. function mergeSettings(localSettings, defaultSettings)
  185. {
  186. for (let key in defaultSettings)
  187. {
  188. if (key in localSettings)
  189. {
  190. settings[key] = localSettings[key];
  191. }
  192.  
  193. else if (!(key in localSettings))
  194. {
  195. settings[key] = defaultSettings[key];
  196. }
  197.  
  198. }
  199. }
  200.  
  201.  
  202. function createNewNavBarButton(options)
  203. {
  204. let nav_ul;
  205.  
  206. if (options.position == "left") nav_ul = document.querySelector("body header div.left nav.main ul");
  207. else if (options.position == "center") nav_ul = document.querySelector("body header div.right nav aside"); // doodle
  208. else nav_ul = document.querySelector("body header div.right nav ul"); // brak na wersji mobilnej
  209.  
  210. if (nav_ul)
  211. {
  212. let nav_ul_li; // ! = nav_ul.querySelector(`li.wykopx_${options.class}_li`);
  213.  
  214. if (!nav_ul_li)
  215. {
  216. nav_ul_li = document.createElement("li");
  217.  
  218. if (options.data) nav_ul_li.setAttribute(options.data, null);
  219. if (options.hideWithoutXStyle == true) nav_ul_li.classList.add("wykopxs");
  220. addWykopXSClassesToElement(nav_ul_li, options.class, "li") // class="wykopx_aaaaaa_li"
  221.  
  222. let nav_ul_li_a = document.createElement("a");
  223.  
  224. nav_ul_li.dataset["v-6c2d0fdd"] = "";
  225. nav_ul_li_a.dataset["v-6c2d0fdd"] = "";
  226.  
  227. if (options.url) nav_ul_li_a.setAttribute("href", options.url);
  228. if (options.href) nav_ul_li_a.setAttribute("href", options.href);
  229. if (options.target) nav_ul_li_a.setAttribute("target", options.target);
  230. if (options.title) nav_ul_li_a.setAttribute("title", options.title);
  231. if (options.data) nav_ul_li_a.setAttribute(options.data, null);
  232.  
  233. nav_ul_li_a.classList.add("hybrid");
  234. if (options.class) addWykopXSClassesToElement(nav_ul_li_a, options.class);
  235.  
  236. let nav_ul_li_a_span = document.createElement("span");
  237. nav_ul_li_a_span.innerHTML = options.text;
  238.  
  239. nav_ul_li_a.appendChild(nav_ul_li_a_span);
  240. nav_ul_li.appendChild(nav_ul_li_a);
  241.  
  242. if (options.insertAfter != null)
  243. {
  244. let section = nav_ul.querySelector(options.insertAfter);
  245. section.insertAdjacentElement('afterend', nav_ul_li);
  246. }
  247. else
  248. {
  249. nav_ul.appendChild(nav_ul_li);
  250. }
  251. }
  252. }
  253. }
  254.  
  255.  
  256. function createLeftMenuButtons(asideLeftPanel = null)
  257. {
  258. if (dev) console.log("createLeftMenuButtons(), asideLeftPanel: ", asideLeftPanel);
  259.  
  260. if (!asideLeftPanel)
  261. {
  262. asideLeftPanel = document.querySelector("body > section > div.main-content > aside.left-panel");
  263. }
  264.  
  265. if (!asideLeftPanel) return;
  266.  
  267. let aside_section_div_ul_li = document.createElement('li');
  268.  
  269. aside_section_div_ul_li.classList.add('mikroczat');
  270. aside_section_div_ul_li.title = mikroczatButtonOpenTitle;
  271. aside_section_div_ul_li.innerHTML = `
  272. <div class="popper-button">
  273. <span>
  274. <span class="button">
  275. <a href="https://wykop.pl/czat" target="_mikroczat" class="wykopx_open_mikroczat hybrid">
  276. <span>${mikroczatButtonOpenLabel}</span>
  277. </a>
  278. </span>
  279. </span>
  280. </div>`;
  281.  
  282. if (settings.mikroczatShowLeftMenuButton)
  283. {
  284. const aside_section_buttons_div_ul = asideLeftPanel.querySelector("section.buttons > div.content > ul");
  285. if (aside_section_buttons_div_ul && !aside_section_buttons_div_ul.querySelector("li.mikroczat"))
  286. {
  287. let clone = aside_section_div_ul_li.cloneNode(true);
  288. aside_section_buttons_div_ul.appendChild(clone);
  289. }
  290. }
  291.  
  292. if (settings.mikroczatShowLeftMenuLink)
  293. {
  294. const aside_section_links_div_ul = asideLeftPanel.querySelector("section.links > div.content > ul");
  295. if (aside_section_links_div_ul && !aside_section_links_div_ul.querySelector("li.mikroczat"))
  296. {
  297.  
  298. let clone = aside_section_div_ul_li.cloneNode(true);
  299. aside_section_links_div_ul.appendChild(clone);
  300.  
  301. }
  302. }
  303. }
  304.  
  305.  
  306.  
  307.  
  308. function addWykopXSClassesToElement(element, inputClassOrArray, suffix = null)
  309. {
  310. if (inputClassOrArray)
  311. {
  312. if (typeof inputClassOrArray === 'string')
  313. {
  314. element.classList.add(`wykopx_${inputClassOrArray}${suffix != null ? "_" + suffix : ""}`);
  315. }
  316. else if (Array.isArray(inputClassOrArray) && inputClassOrArray.every(item => typeof item === 'string'))
  317. {
  318. inputClassOrArray.map(item =>
  319. {
  320. element.classList.add(`wykopx_${item}${suffix != null ? "_" + suffix : ""}`);
  321. });
  322. }
  323. }
  324. }
  325.  
  326.  
  327.  
  328.  
  329.  
  330. // XS MIKROCZAT -- START
  331. let wykopDomain = "https://wykop.pl";
  332. let wxDomain = "https://wykopx.pl";
  333. const mikroczatDomain = "https://mikroczat.pl";
  334. const mikroczatPath = "/"; /* /czat */
  335. const mikroczatMainChannelPath = "czat";
  336. const mikroczaDefaultChannel = "mikroblog+";
  337. // let mikroczatChannel = "/";
  338. let mikroczatWindow = null;
  339. const mikroczatButtonOpenTitle = `Wykopowy Mikroczat
  340.  
  341. Otwieranie czatu w 𝗡𝗢𝗪𝗘𝗝 𝗞𝗔𝗥𝗖𝗜𝗘:
  342. - 𝗟𝗣𝗠 - klik lewym przyciskiem myszy
  343.  
  344. Otwieranie czatu w 𝗡𝗢𝗪𝗬𝗠 𝗢𝗞𝗡𝗜𝗘:
  345. - ŚPM - klik środkowym przyciskiem myszy
  346. - klawisz 𝗖𝗧𝗥𝗟 + klik
  347. - klawisz 𝗦𝗛𝗜𝗙𝗧 + klik
  348. - klawisz 𝗔𝗟𝗧 + klik
  349.  
  350. EXTRA:
  351. - będąc na stronie #tagu otworzysz kanał tematyczny czatu
  352. - będąc na stronie wpisu otworzysz widok dyskusji
  353. - będąc na profilu użytkownika lub rozmowie otworzysz kanał prywatnej rozmowy
  354. `;
  355.  
  356.  
  357.  
  358.  
  359. const mikroczatButtonOpenLabel = "Czat";
  360.  
  361.  
  362.  
  363.  
  364. // OTWIERANIE MIKROCZATU Z PRZYCISKÓW CZAT
  365. if (settings.mikroczatShowLeftMenuButton || settings.mikroczatShowLeftMenuLink || settings.mikroczatShowTopNavButton)
  366. {
  367.  
  368. document.addEventListener("mousedown", (e) =>
  369. {
  370. if (e.target.matches("a.wykopx_open_mikroczat") || e.target.matches("a.wykopx_open_mikroczat > span"))
  371. {
  372. e.preventDefault();
  373. e.stopImmediatePropagation();
  374. e.stopPropagation();
  375.  
  376. wykopx_open_mikroczat_event(e);
  377. }
  378. });
  379. document.addEventListener("click", (e) =>
  380. {
  381. if (e.target.matches("a.wykopx_open_mikroczat") || e.target.matches("a.wykopx_open_mikroczat > span"))
  382. {
  383. e.preventDefault();
  384. }
  385. });
  386. document.addEventListener("auxclick", (e) =>
  387. {
  388. if (e.target.matches("a.wykopx_open_mikroczat") || e.target.matches("a.wykopx_open_mikroczat > span"))
  389. {
  390. e.preventDefault();
  391. }
  392. });
  393.  
  394.  
  395. document.addEventListener("mouseout", (e) =>
  396. {
  397. if (e.target.matches("a.wykopx_open_mikroczat") && e.target.href != "https://wykop.pl/czat")
  398. {
  399. e.target.href = "https://wykop.pl/czat";
  400. }
  401. });
  402. document.addEventListener("contextmenu", (e) =>
  403. {
  404. if (e.target.matches("a.wykopx_open_mikroczat"))
  405. {
  406. e.target.href = "https://mikroczat.pl";
  407. }
  408. if (e.target.matches("a.wykopx_open_mikroczat > span"))
  409. {
  410. e.target.closest("a").href = "https://mikroczat.pl";
  411. }
  412. });
  413. }
  414.  
  415. function wykopx_open_mikroczat_event(e)
  416. {
  417. if (e.target.matches("a.wykopx_open_mikroczat") || e.target.matches("a.wykopx_open_mikroczat > span"))
  418. {
  419. if (e.button === 2) return; // RIGHT MOUSE CLICK OFF
  420.  
  421. let windowOptions = "";
  422.  
  423. if (e.shiftKey || e.ctrlKey || e.metaKey || e.altKey || e.button === 1) // ŚPM
  424. {
  425. windowOptions = "popup";
  426. }
  427.  
  428. openMikroczat(new URL(document.URL).pathname, windowOptions);
  429. }
  430. }
  431.  
  432.  
  433.  
  434. function openMikroczat(hrefURL, windowOptions, target = "mikroczat")
  435. {
  436. let urlPathnameArray = hrefURL;
  437. let mikroczatURL = `${mikroczatDomain}`;
  438.  
  439. if (hrefURL.startsWith("https://mikroczat.pl"))
  440. {
  441. mikroczatURL = hrefURL;
  442. }
  443. else
  444. {
  445. if (hrefURL.startsWith("https://wykop.pl"))
  446. {
  447. urlPathnameArray = hrefURL.replace("https://wykop.pl", "");
  448. }
  449.  
  450. urlPathnameArray = urlPathnameArray.split("/");
  451.  
  452. let channel = ""
  453.  
  454. if (Array.isArray(urlPathnameArray))
  455. {
  456. // #nazwatagu
  457. if (urlPathnameArray[1] == "tag")
  458. {
  459. channel = `${mikroczatMainChannelPath}/${urlPathnameArray[2]}`;
  460. }
  461. else if (urlPathnameArray[1] == "mikroblog")
  462. {
  463. if (urlPathnameArray[2] == "najnowsze") // /mikroblog/najnowsze
  464. {
  465. channel = `${mikroczatMainChannelPath}/mikroblog+`;
  466. }
  467. // TODO pathnameArray[2] == "aktywne"
  468. // TODO pathnameArray[2] == "gorace"
  469. else
  470. {
  471. channel = `${mikroczatMainChannelPath}/${mikroczaDefaultChannel}`; // TODO
  472. }
  473. }
  474. // /obserwowane
  475. else if (urlPathnameArray[1] == "obserwowane")
  476. {
  477. channel = `${mikroczatMainChannelPath}/observed`; // Mikroczat "observed" 🤍
  478. // TODO pathnameArray[2] == "profile"
  479. // TODO pathnameArray[2] == "tagi"
  480. }
  481. // uzytkownik - profil lub rozmowa z użytkownikiem
  482. else if (urlPathnameArray[1] == "ludzie" || urlPathnameArray[1] == "wiadomosci")
  483. {
  484. channel = "pm/@" + urlPathnameArray[2];
  485. }
  486. else if (urlPathnameArray[1] == "wpis")
  487. {
  488. channel = `${mikroczatMainChannelPath}/${mikroczaDefaultChannel}/#${urlPathnameArray[2]}`; // id wpisu - discussion view
  489. }
  490. else if (urlPathnameArray[1] == "") // ze strony głównej
  491. {
  492. channel = `${mikroczatMainChannelPath}/observed/#wybierz`;
  493. }
  494. else // z innych stron
  495. {
  496. channel = `${mikroczatMainChannelPath}/observed/#wybierz`;
  497. }
  498. }
  499. mikroczatURL += `${mikroczatPath}${channel}`;
  500. }
  501.  
  502.  
  503. clearKeysDatasetFromBody();
  504.  
  505. mikroczatWindow = window.open(mikroczatURL, target, windowOptions);
  506. }
  507.  
  508.  
  509.  
  510.  
  511. function clearKeysDatasetFromBody()
  512. {
  513. if (bodySection.dataset.key_shift) delete bodySection.dataset.key_shift;
  514. if (bodySection.dataset.key_ctrl) delete bodySection.dataset.key_ctrl;
  515. if (bodySection.dataset.key_alt) delete bodySection.dataset.key_alt;
  516. }
  517.  
  518.  
  519.  
  520.  
  521.  
  522. const keys = {};
  523.  
  524.  
  525. // KEYDOWN CTRL SHIFT ALT
  526. if (settings.mikroczatOpenMikroczatOnCTRLLeftClick || settings.mikroczatOpenMikroczatOnCTRLMiddleClick)
  527. {
  528. document.addEventListener("keydown", (e) =>
  529. {
  530. if (e.target.tagName.toLowerCase() === 'textarea' || e.target.tagName.toLowerCase() === 'input') return;
  531. if (!keys["CTRL"] && e.key == "Control")
  532. {
  533. keys["CTRL"] = true;
  534. bodySection.dataset.key_ctrl = "true";
  535. }
  536. // if (!keys["SHIFT"] && e.key == "Shift")
  537. // {
  538. // keys["SHIFT"] = true;
  539. // bodySection.dataset.key_shift = "true";
  540. // }
  541. // if (!keys["ALT"] && (e.key == "Alt" || e.key == "AltGraph"))
  542. // {
  543. // keys["ALT"] = true;
  544. // bodySection.dataset.key_alt = "true";
  545. // }
  546. });
  547.  
  548. document.addEventListener("keyup", (e) =>
  549. {
  550. if (e.target.tagName.toLowerCase() === 'textarea' || e.target.tagName.toLowerCase() === 'input') return;
  551.  
  552. // if (keys["SHIFT"] && e.key == "Shift")
  553. // {
  554. // keys["SHIFT"] = false;
  555. // delete bodySection.dataset.key_shift;
  556. // }
  557. if (keys["CTRL"] && e.key == "Control")
  558. {
  559. keys["CTRL"] = false;
  560. delete bodySection.dataset.key_ctrl;
  561. }
  562. // if (keys["ALT"] && (e.key == "Alt" || e.key == "AltGraph"))
  563. // {
  564. // keys["ALT"] = false;
  565. // delete bodySection.dataset.key_alt;
  566. // }
  567. });
  568. }
  569.  
  570.  
  571.  
  572.  
  573. const performanceObserver = new PerformanceObserver((PerformanceObserverEntryList, PerformanceObserver) =>
  574. {
  575. if (settings.mikroczatOpenMikroczatOnCTRLLeftClick || settings.mikroczatOpenMikroczatOnCTRLMiddleClick)
  576. {
  577. clearKeysDatasetFromBody();
  578. }
  579.  
  580. if (dev) console.log("PerformanceObserverEntryList", PerformanceObserverEntryList);
  581. if (dev) console.log("PerformanceObserverEntryList.getEntries", PerformanceObserverEntryList.getEntries()[0].name);
  582. /*
  583. {
  584. duration: 0
  585. entryType: "soft-navigation",
  586. name: "https://wykop.pl/wpis/76597433/ponad-700-wykopow-glowna-i-poprawnosc-polityczna-m#268853079",
  587. navigationId: "229d696d-dc59-4874-a63b-fd753787d4fd",
  588. source: Window {0: Window, 1: global, 2: global, 3: global, 4: global, 5: global, 6: global, 7: global, 8: global, 9: global, 10: global, 11: global, 12: global, 13: Window, 14: global, window: Window, self: Window, document: document, name: '', location: Location, …}
  589. startTime: 82282.70000000298
  590. }
  591. */
  592. });
  593. performanceObserver.observe({ type: "soft-navigation", buffered: true });
  594.  
  595.  
  596.  
  597.  
  598.  
  599.  
  600. document.addEventListener("mouseover", (e) =>
  601. {
  602. if (!e.target.matches(`a[href^="https://mikroczat.pl"]`)) return;
  603.  
  604. e.target.title = `Otwórz wykopowy Mikroczat`;
  605.  
  606. e.target.addEventListener("click", mikroczatHrefClickEventListenerPreventDefault);
  607. e.target.addEventListener("auxclick", mikroczatHrefClickEventListenerPreventDefault);
  608. e.target.addEventListener("mousedown", mikroczatHrefMouseDownEventListenerWithShift);
  609. });
  610.  
  611. document.addEventListener("mouseout", (e) =>
  612. {
  613. if (!e.target.matches(`a[href^="https://mikroczat.pl"]`)) return;
  614. removeEventListenersFromMikroczatHref(e.target);
  615. });
  616.  
  617. function mikroczatHrefClickEventListenerPreventDefault(e)
  618. {
  619. e.preventDefault();
  620. }
  621.  
  622. function removeEventListeners(etarget)
  623. {
  624. etarget.removeEventListener("click", hrefClickEventListenerPreventDefault, true);
  625. etarget.removeEventListener("mousedown", hrefMouseDownEventListenerWithShift, true);
  626. }
  627. function removeEventListenersFromMikroczatHref(etarget)
  628. {
  629. etarget.removeEventListener("click", mikroczatHrefClickEventListenerPreventDefault, true);
  630. etarget.removeEventListener("auxclick", mikroczatHrefClickEventListenerPreventDefault, true);
  631. etarget.removeEventListener("mousedown", mikroczatHrefMouseDownEventListenerWithShift, true);
  632. }
  633.  
  634.  
  635.  
  636. // MOUSE OVER LINKS
  637. if (settings.mikroczatOpenMikroczatOnCTRLLeftClick || settings.mikroczatOpenMikroczatOnCTRLMiddleClick || settings.mikroczatOpenMikroczatOnMiddleClick)
  638. {
  639. document.addEventListener("mouseover", (e) =>
  640. {
  641. if (!e.target.matches(`a[href^="/tag/"]`)
  642. && !e.target.matches(`a[href^="/ludzie/"]`)
  643. // && !e.target.matches(`a.username[href^="/ludzie/"] > span`)
  644. //&& !e.target.matches(`a[href^="/ludzie/"]:not(:has(> span))`)
  645. && !e.target.matches(`a[href^="/wpis/"] > time`)) return;
  646.  
  647. // ⇧ 𝗦𝗛𝗜𝗙𝗧
  648. // ⌘ 𝗖𝗧𝗥𝗟
  649. // ⎇ 𝗔𝗟𝗧
  650. // #heheszki
  651.  
  652.  
  653.  
  654. if (e.target.matches(`a[href^="/tag/"]`))
  655. {
  656. e.target.addEventListener("click", hrefClickEventListenerPreventDefault);
  657. e.target.addEventListener("auxclick", hrefClickEventListenerPreventDefault);
  658. e.target.addEventListener("mousedown", hrefMouseDownEventListenerWithShift);
  659. // e.target.addEventListener("mouseup", hrefMouseUpEventListenerWithShift, true);
  660.  
  661. e.target.title = `Klikając w tag wciśnij klawisz 𝗖𝗧𝗥𝗟,
  662. lub kliknij w tag śordkowym przyciskiem myszy,
  663. żeby otworzyć na 🗯 𝗠𝗶𝗸𝗿𝗼𝗰𝘇𝗮𝗰𝗶𝗲 kanał tematyczny
  664.  
  665. Kanał tematyczny #${e.target.innerText}:
  666.  
  667. 𝗖𝗧𝗥𝗟 + kliknięcie LPM - w nowej karcie
  668. 𝗖𝗧𝗥𝗟 + kliknięcie ŚPM - w nowym oknie
  669. `;
  670. }
  671.  
  672. // @NadiaFrance
  673. else if (e.target.matches(`a[href^="/ludzie/"]`))
  674. {
  675. e.target.addEventListener("click", hrefClickEventListenerPreventDefault);
  676. e.target.addEventListener("auxclick", hrefClickEventListenerPreventDefault);
  677. e.target.addEventListener("mousedown", hrefMouseDownEventListenerWithShift);
  678. // e.target.addEventListener("mouseup", hrefMouseUpEventListenerWithShift, true);
  679.  
  680. e.target.title = `Wciśnij klawisz 𝗖𝗧𝗥𝗟 klikając w login użytkownika,
  681. aby otworzyć rozmowę prywatną (PM) na 🗯 Mikroczacie
  682.  
  683. Rozmowa prywatna:
  684. 𝗖𝗧𝗥𝗟 + kliknięcie LPM - w nowej karcie
  685. 𝗖𝗧𝗥𝗟 + kliknięcie ŚPM - w nowym oknie
  686. `;
  687. }
  688. // PERMALINK DO WPISU
  689. else if (e.target.matches(`a[href^="/wpis/"] > time`))
  690. {
  691. e.target.addEventListener("click", hrefClickEventListenerPreventDefault);
  692. e.target.addEventListener("auxclick", hrefClickEventListenerPreventDefault);
  693. e.target.addEventListener("mousedown", hrefMouseDownEventListenerWithShift);
  694.  
  695. // e.target.addEventListener("mouseup", hrefMouseUpEventListenerWithShift, true);
  696.  
  697. const dateObj = dayjs(e.target.dateTime);
  698. const dateFull = dateObj.format('D MMMM YYYY');
  699. const timeFull = dateObj.format('HH:mm:ss');
  700. const dateDayOfWeek = dateObj.format('dddd');
  701. const daysAgo = dateObj.fromNow();
  702.  
  703. e.target.title = `Dodany:
  704. ${daysAgo}, ${timeFull}
  705. 📅 ${dateDayOfWeek}, ${dateFull} r.
  706.  
  707. Klikając w datę wpisu/komentarza wciśnij klawisz 𝗖𝗧𝗥𝗟
  708. lub kliknij datę środkowym przyciskiem myszy,
  709. żeby otworzyć całą dyskusję ze wszystkimi komentarzami na 🗯 𝗠𝗶𝗸𝗿𝗼𝗰𝘇𝗮𝗰𝗶𝗲
  710.  
  711. Widok dyskusji:
  712.  
  713. 𝗖𝗧𝗥𝗟 + kliknięcie LPM - w nowej karcie
  714. 𝗖𝗧𝗥𝗟 + kliknięcie ŚPM - w nowym oknie
  715. `;
  716. }
  717.  
  718. });
  719.  
  720.  
  721. // MOUSE OUT
  722. document.addEventListener("mouseout", (e) =>
  723. {
  724. if (e.target.matches(`a[href^="/tag/"]`) || e.target.matches(`a[href^="/ludzie/"]`) || e.target.matches(`a[href^="/wpis/"] > time`))
  725. {
  726. removeEventListeners(e.target);
  727. }
  728. });
  729. }
  730.  
  731.  
  732.  
  733.  
  734.  
  735. // CLICK EVENT
  736. function hrefClickEventListenerPreventDefault(e)
  737. {
  738. // ŚPM
  739. if (settings.mikroczatOpenMikroczatOnMiddleClick)
  740. {
  741. if (e.button === 1 && !e.shiftKey && !e.altKey && !e.ctrlKey && !e.metaKey)
  742. {
  743. e.preventDefault();
  744. }
  745. }
  746.  
  747. // ŚPM + CTRL
  748. if (settings.mikroczatOpenMikroczatOnCTRLMiddleClick)
  749. {
  750. if (e.button === 1 && !e.shiftKey && !e.altKey && (e.ctrlKey || e.metaKey))
  751. {
  752. e.preventDefault();
  753. }
  754. }
  755. // LPM + CTRL
  756. if (settings.mikroczatOpenMikroczatOnCTRLLeftClick)
  757. {
  758. if (e.button === 0 && !e.shiftKey && !e.altKey && (e.ctrlKey || e.metaKey))
  759. {
  760. e.preventDefault();
  761. }
  762. }
  763. }
  764.  
  765.  
  766. function mikroczatHrefMouseDownEventListenerWithShift(e)
  767. {
  768. // new window
  769. if (e.button === 1 // ŚPM
  770. || (e.button === 0 && !e.shiftKey && !e.altKey && (e.ctrlKey || e.metaKey)) // LPM + CTRL
  771. )
  772. {
  773. e.preventDefault();
  774. e.stopImmediatePropagation();
  775. e.stopPropagation();
  776. let ahrefElement = e.target;
  777. if (e.target.tagName != "A") ahrefElement = e.target.closest("a"); // <a><span>
  778. openMikroczat(ahrefElement.href, "popup"); // new window popup
  779. }
  780.  
  781. // LPM
  782. else if (e.button === 0)
  783. {
  784. e.preventDefault();
  785. e.stopImmediatePropagation();
  786. e.stopPropagation();
  787. let ahrefElement = e.target;
  788. openMikroczat(ahrefElement.href, null, "_blank"); // new tab
  789. }
  790. }
  791.  
  792.  
  793.  
  794. // MOUSE DOWN
  795. function hrefMouseDownEventListenerWithShift(e)
  796. {
  797. // ŚPM
  798. if (settings.mikroczatOpenMikroczatOnMiddleClick)
  799. {
  800. if (e.button === 1 && !e.shiftKey && !e.altKey && !e.ctrlKey && !e.metaKey)
  801. {
  802. e.preventDefault();
  803. e.stopImmediatePropagation();
  804. e.stopPropagation();
  805.  
  806. let ahrefElement = e.target;
  807. if (e.target.tagName != "A") ahrefElement = e.target.closest("a"); // <a><time>
  808.  
  809. openMikroczat(ahrefElement.href, null, "_blank"); // new tab
  810. }
  811. }
  812.  
  813. // ŚPM + CTRL
  814. if (settings.mikroczatOpenMikroczatOnCTRLMiddleClick)
  815. {
  816. if (e.button === 1 && !e.shiftKey && !e.altKey && (e.ctrlKey || e.metaKey))
  817. {
  818. e.preventDefault();
  819. e.stopImmediatePropagation();
  820. e.stopPropagation();
  821.  
  822. let ahrefElement = e.target;
  823. if (e.target.tagName != "A") ahrefElement = e.target.closest("a"); // <a><time>
  824.  
  825. openMikroczat(ahrefElement.href, "popup"); // new window popup
  826. }
  827. }
  828. // LPM + CTRL
  829. if (settings.mikroczatOpenMikroczatOnCTRLLeftClick)
  830. {
  831. if (e.button === 0 && !e.shiftKey && !e.altKey && (e.ctrlKey || e.metaKey))
  832. {
  833. e.preventDefault();
  834. e.stopImmediatePropagation();
  835. e.stopPropagation();
  836.  
  837. let ahrefElement = e.target;
  838. if (e.target.tagName != "A") ahrefElement = e.target.closest("a"); // <a><time>
  839.  
  840. openMikroczat(ahrefElement.href, null, "_blank"); // new tab
  841. }
  842. }
  843.  
  844. }
  845.  
  846.  
  847.  
  848.  
  849.  
  850.  
  851.  
  852.  
  853.  
  854.  
  855.  
  856.  
  857.  
  858.  
  859.  
  860.  
  861.  
  862. // WIADOMOŚCI OD MIKROCZAT.PL
  863. window.addEventListener('message', function (event)
  864. {
  865. if (event.origin !== mikroczatDomain) return;
  866. if (dev) console.log('Wiadomość z mikroczat.pl', event.data);
  867.  
  868. //if (event.data == "MikroCzatOpened") mikroczatWindow.postMessage({ type: "token", token: window.localStorage.getItem("token") }, mikroczatDomain);
  869.  
  870. if (event.data == "MikroCzatOpened")
  871. {
  872. mikroczatWindow.postMessage({ type: "TokensObject", userKeep: window.localStorage.getItem("userKeep") }, mikroczatDomain);
  873. // mikroczatWindow.postMessage({ type: "TokensObject", token: window.localStorage.getItem("token"), userKeep: window.localStorage.getItem("userKeep") }, mikroczatDomain);
  874. }
  875.  
  876. if (event.data == "MikroCzatLoggedIn")
  877. {
  878. if (dev) console.log("event.data", event.data)
  879. bodySection.dataset.mikroczatLogged = true;
  880. }
  881.  
  882. if (event.data == "MikroCzatClosed")
  883. {
  884. bodySection.dataset.mikroczatLogged = false;
  885. mikroczatWindow = null;
  886. }
  887. }, false);
  888.  
  889.  
  890.  
  891.  
  892. // CSS
  893. {
  894. CSS += `
  895. /* LEFT MENU MIKROCZAT BUTTON - START */
  896.  
  897. body aside.left-panel > section.links > div.content > ul > li
  898. {
  899. position: relative;
  900. transition: none;
  901. }
  902.  
  903. body aside.left-panel:not(.mini):has(section.buttons > div.content > ul > li.mikroczat) > section.links > div.content > ul > li.mikroczat
  904. {
  905. display: none;
  906. }
  907. body aside.left-panel > section.links > div.content > ul > li a.hybrid[class] /* [data-v-5687662b] */
  908. {
  909. padding: 0 6px;
  910. display: block;
  911. -webkit-box-sizing: border-box;
  912. box-sizing: border-box;
  913. font-weight: 400;
  914. text-decoration: none;
  915. font-size: 16px;
  916. line-height: 36px;
  917. height: 36px;
  918.  
  919. cursor: pointer;
  920. transition: none;
  921. }
  922. body aside.left-panel > section.links > div.content > ul > li a.hybrid[class]:before /* [data-v-5687662b] */
  923. {
  924. content: '';
  925. display: block;
  926. position: absolute;
  927. -webkit-mask-repeat: no-repeat;
  928. mask-repeat: no-repeat;
  929. -webkit-mask-position: center;
  930. mask-position: center;
  931. -webkit-mask-size: cover;
  932. mask-size: cover;
  933. background: var(--gullGray);
  934. top: 50%;
  935. left: 24px;
  936. z-index: 1;
  937. transition: none;
  938. }
  939. body aside.left-panel > section.links > div.content > ul > li.mikroczat a.hybrid[class]:before
  940. {
  941. -webkit-mask-image: url(https://i.imgur.com/82a9CyK.png);
  942. mask-image: url(https://i.imgur.com/82a9CyK.png);
  943. -webkit-mask-size: 22px 22px;
  944. mask-size: 22px 22px;
  945. width: 22px;
  946. height: 22px;
  947. margin-top: 0px;
  948.  
  949. transition: none;
  950. }
  951. body aside.left-panel > section.links > div.content > ul > li.mikroczat a.hybrid[class]:before
  952. {
  953. top: 7px;
  954. left: 13px;
  955. }
  956.  
  957. body aside.left-panel > section.links > div.content > ul > li a > span
  958. {
  959. display: block;
  960. padding: 0 16px 0 38px;
  961. border-radius: 6px;
  962. white-space: nowrap;
  963. overflow: hidden;
  964. text-overflow: ellipsis;
  965. position: relative;
  966.  
  967. /* em */
  968. font-style: normal;
  969. color: var(--steelBluish);
  970. transition: none;
  971. position: relative;
  972. }
  973.  
  974. body aside.left-panel > section.links > div.content > ul > li:hover a > span
  975. {
  976. background: var(--squeeze);
  977. cursor: pointer;
  978. }
  979. body aside.left-panel.mini > section.links > div.content > ul > li.mikroczat a > span
  980. {
  981. font-size: 0;
  982. }
  983. `;
  984.  
  985.  
  986. //if (settings.mikroczatShowLeftMenuButton)
  987. {
  988. CSS += `
  989. /* 4 BUTTONS */
  990. body aside.left-panel:not(.mini) > section.buttons > div.content > ul:has(li.mikroczat)
  991. {
  992. display: flex;
  993. flex-wrap: wrap;
  994. justify-content: space-around;
  995. column-gap: 0px;
  996. }
  997. body aside.left-panel:not(.mini) > section.buttons > div.content > ul > li
  998. {
  999. flex-basis: 47%;
  1000. box-sizing: border-box;
  1001. padding: 0px;
  1002. margin-top: 7px;
  1003. }
  1004.  
  1005. body aside.left-panel > section > div.content > ul > li
  1006. {
  1007. position: relative;
  1008. cursor: pointer;
  1009. }
  1010.  
  1011. body aside.left-panel.mini > section > div.content > ul > li:hover,
  1012. body aside.left-panel:not(.mini) > section.buttons > div.content > ul > li:hover a::before
  1013. {
  1014. background: var(--squeeze);
  1015. }
  1016.  
  1017. aside.left-panel>section.buttons>.content ul li a /* [data-v-5687662b] */
  1018. {
  1019. display: block;
  1020. position: relative;
  1021. color: var(--steelBluish);
  1022. font-size: 0;
  1023. }
  1024.  
  1025. aside.left-panel>section.buttons>.content ul li.active a, /* [data-v-5687662b] */
  1026. aside.left-panel>section.buttons>.content ul li:hover a /* [data-v-5687662b] */
  1027. {
  1028. color: var(--tuna);
  1029. font-weight: 600;
  1030. }
  1031.  
  1032. aside.left-panel>section.buttons>.content ul li a:before /* [data-v-5687662b] */
  1033. {
  1034. content: '';
  1035. display: block;
  1036. width: 100%;
  1037. height: 36px;
  1038. border: 1px solid var(--porcelain);
  1039. border-radius: 6px;
  1040. box-sizing: border-box;
  1041. transition: background .2s ease, border .2s ease;
  1042. }
  1043. [data-night-mode] aside.left-panel>section.buttons>.content ul li a:before /* [data-v-5687662b] */
  1044. {
  1045. border-color: #303032;
  1046. }
  1047.  
  1048. aside.left-panel:not(.mini)>section.buttons>.content ul li:hover a:before,
  1049. [data-night-mode] aside.left-panel:not(.mini)>section.buttons>.content ul li:hover a:before
  1050. {
  1051. border-color: var(--tuna);
  1052. }
  1053.  
  1054. aside.left-panel:not(.mini)>section.buttons>.content ul li a:after /* [data-v-5687662b] */
  1055. {
  1056. content: '';
  1057. display: block;
  1058. position: absolute;
  1059. -webkit-mask-repeat: no-repeat;
  1060. mask-repeat: no-repeat;
  1061. -webkit-mask-position: center;
  1062. mask-position: center;
  1063. background: var(--gullGray);
  1064. height: 34px;
  1065. width: 100%;
  1066. top: 0;
  1067. left: 0;
  1068. -webkit-transition: background .2s ease;
  1069. transition: background .2s ease;
  1070. }
  1071.  
  1072. aside.left-panel:not(.mini)>section.buttons>.content ul li.mikroczat a:after /* [data-v-5687662b] */
  1073. {
  1074. -webkit-mask-image: url(https://i.imgur.com/82a9CyK.png);
  1075. mask-image: url(https://i.imgur.com/82a9CyK.png);
  1076. -webkit-mask-size: 22px 22px;
  1077. mask-size: 22px 22px;
  1078. }
  1079. aside.left-panel:not(.mini)>section.buttons>.content ul li a>span /*[data-v-5687662b] */
  1080. {
  1081. position: relative;
  1082. display: inline-block;
  1083. font-size: 11px;
  1084. left: 50%;
  1085. -webkit-transform: translateX(-50%);
  1086. transform: translateX(-50%);
  1087. white-space: nowrap;
  1088. margin-top: 2px;
  1089. line-height: 16px;
  1090. height: 16px;
  1091. }`;
  1092. /* LEFT MENU MIKROCZAT BUTTON - END */
  1093. }
  1094.  
  1095.  
  1096.  
  1097.  
  1098. /* MIKROCZAT TAG LINKS */
  1099. CSS += `
  1100. section:is(.entry-content, .link-block)[class]
  1101. { overflow: visible!important; }
  1102.  
  1103. section:is(.entry-content, .link-block) a[href^="/tag/"]
  1104. {
  1105. padding-right: 2px !important;
  1106. margin-right: 1px;
  1107. transition: none!important;
  1108. }
  1109.  
  1110. section:is(.entry-content, .link-block) a[href^="https://mikroczat.pl/"]
  1111. {
  1112. padding-right: 2px!important;
  1113. padding-left: 2px!important;
  1114. }
  1115.  
  1116.  
  1117.  
  1118.  
  1119. section.sidebar a[href^="/tag/"],
  1120. section:is(.entry-content, .link-block) a[href^="/tag/"],
  1121. section.entry div.right a[href^="/wpis/"],
  1122. section.entry-content a[href^="/ludzie/"],
  1123. section.entry div.right a.username[href^="/ludzie/"],
  1124. section.link-block a.username[href^="/ludzie/"],
  1125. section.entry-content .wrapper a[href^="https://mikroczat.pl/"]
  1126. {
  1127. border: 1px solid transparent!important;
  1128. position: relative!important;
  1129. cursor: pointer!important;
  1130. transition: none!important;
  1131. }
  1132.  
  1133.  
  1134.  
  1135.  
  1136. body > section[data-key_ctrl="true"] section.sidebar a[href^="/tag/"],
  1137. body > section[data-key_ctrl="true"] section:is(.entry-content, .link-block) a[href^="/tag/"],
  1138. body > section[data-key_ctrl="true"] section:is(.entry-content, .link-block) a[href^="/tag/"] *,
  1139. body > section[data-key_ctrl="true"] section.entry div.right a[href^="/wpis/"] *,
  1140. body > section[data-key_ctrl="true"] section.entry-content a[href^="https://mikroczat.pl/"],
  1141. body > section[data-key_ctrl="true"] section.entry-content a[href^="https://mikroczat.pl/"] *
  1142. {
  1143. color: var(--tagChannelColor)!important;
  1144. }
  1145. body > section[data-key_ctrl="true"] section.sidebar a[href^="/tag/"],
  1146. body > section[data-key_ctrl="true"] section:is(.entry-content, .link-block) a[href^="/tag/"],
  1147. body > section[data-key_ctrl="true"] section.entry div.right a[href^="/wpis/"],
  1148. body > section[data-key_ctrl="true"] section.entry-content a[href^="https://mikroczat.pl/"]
  1149. {
  1150. border-color: var(--tagChannelColor)!important;
  1151. background-color: color-mix(in srgb, var(--whitish) 90%, var(--tagChannelColor))!important;
  1152. border-radius: var(--smallBorderRadius)!important;
  1153. }
  1154. body > section[data-key_ctrl="true"] section.sidebar a[href^="/tag/"]:hover,
  1155. body > section[data-key_ctrl="true"] section:is(.entry-content, .link-block) a[href^="/tag/"]:hover,
  1156. body > section[data-key_ctrl="true"] section.entry div.right a[href^="/wpis/"]:hover,
  1157. body > section[data-key_ctrl="true"] section.entry-content a[href^="https://mikroczat.pl/"]:hover
  1158. {
  1159. background-color: color-mix(in srgb, var(--whitish) 60%, var(--tagChannelColor))!important;
  1160. }
  1161. body > section[data-key_ctrl="true"] section.sidebar a[href^="/tag/"],
  1162. body > section[data-key_ctrl="true"] section:is(.entry-content, .link-block) a[href^="/tag/"],
  1163. body > section[data-key_ctrl="true"] section.entry-content a[href^="/ludzie/"],
  1164. body > section[data-key_ctrl="true"] section.link-block a.username[href^="/ludzie/"]
  1165. {
  1166. padding-left: 3px !important;
  1167. margin-left: -12px !important;
  1168. }
  1169. body > section[data-key_ctrl="true"] section.sidebar a[href^="/tag/"]:hover,
  1170. body > section[data-key_ctrl="true"] section:is(.entry-content, .link-block) a[href^="/tag/"]:hover,
  1171. body > section[data-key_ctrl="true"] section.entry div.right a[href^="/wpis/"]:hover,
  1172. body > section[data-key_ctrl="true"] section:is(.entry-content, .link-block) a[href^="/ludzie/"]:hover
  1173. {
  1174. text-decoration: none!important;
  1175. }
  1176. body > section[data-key_ctrl="true"] section.sidebar a[href^="/tag/"]::before,
  1177. body > section[data-key_ctrl="true"] section:is(.entry-content, .link-block) a[href^="/tag/"]::before
  1178. {
  1179. content: "#";
  1180. }
  1181.  
  1182.  
  1183.  
  1184.  
  1185. body > section[data-key_ctrl="true"] section.entry-content a[href^="/ludzie/"],
  1186. body > section[data-key_ctrl="true"] section.entry div.right a.username[href^="/ludzie/"],
  1187. body > section[data-key_ctrl="true"] section.link-block a.username[href^="/ludzie/"],
  1188. body > section[data-key_ctrl="true"] section.entry-content a[href^="https://mikroczat.pl/pm/"],
  1189. body > section[data-key_ctrl="true"] section.entry-content a[href^="https://mikroczat.pl/room/"]
  1190. {
  1191. color: var(--pmChannelColor)!important;
  1192. border-color: var(--pmChannelColor)!important;
  1193. background-color: color-mix(in srgb, var(--whitish) 90%, var(--pmChannelColor))!important;
  1194. padding: 0px 3px;
  1195. margin-left: 3px;
  1196. }
  1197. body > section[data-key_ctrl="true"] section.entry-content a[href^="/ludzie/"]:hover,
  1198. body > section[data-key_ctrl="true"] section.entry div.right a.username[href^="/ludzie/"]:hover,
  1199. body > section[data-key_ctrl="true"] section.link-block a.username[href^="/ludzie/"]:hover,
  1200. body > section[data-key_ctrl="true"] section.entry-content a[href^="https://mikroczat.pl/pm/"]:hover,
  1201. body > section[data-key_ctrl="true"] section.entry-content a[href^="https://mikroczat.pl/room/"]:hover
  1202. {
  1203. background-color: color-mix(in srgb, var(--whitish) 60%, var(--pmChannelColor))!important;
  1204. }
  1205. body > section[data-key_ctrl="true"] section.entry-content a[href^="/ludzie/"]::before,
  1206. body > section[data-key_ctrl="true"] section.entry div.right a.username[href^="/ludzie/"]::before,
  1207. body > section[data-key_ctrl="true"] section.link-block a.username[href^="/ludzie/"]::before
  1208. {
  1209. content: "";
  1210. }
  1211.  
  1212. `;
  1213.  
  1214.  
  1215.  
  1216. // /*
  1217. // body > section[data-key_ctrl="true"] section.entry-content a[href^="/tag/"]::after,
  1218. // body > section[data-key_ctrl="true"] section.entry-content a[href^="/ludzie/"]::after,
  1219. // body > section[data-key_ctrl="true"] section.entry div.right a.username[href^="/ludzie/"]::after,
  1220. // body > section[data-key_ctrl="true"] section.entry-content a[href^="https://mikroczat.pl/"]::after
  1221. // {
  1222. // color: white;
  1223. // content: "🗯";
  1224. // position: absolute;
  1225. // top: -1em;
  1226. // right: -0.5em;
  1227. // }
  1228. // */
  1229.  
  1230.  
  1231.  
  1232.  
  1233. CSS += `
  1234. /* TOP NAV CZAT BUTTON */
  1235. body > section.open-left-panel > header.header > div.left > nav.main > ul > li.wykopx_open_mikroczat_li
  1236. {
  1237. display: none;
  1238. }
  1239. /*body > section[data-mikroczat-logged="true"] li.wykopx_open_mikroczat_li span:after
  1240. {
  1241. content: "•";
  1242. color: white;
  1243. position: absolute;
  1244. top: 4px;
  1245. right: 5px;
  1246. }*/
  1247. body > section[data-mikroczat-logged="false"] li.wykopx_open_mikroczat_li span:after
  1248. {
  1249. content: "•";
  1250. color: rgb(255, 255, 255, 0.3);
  1251. position: absolute;
  1252. top: 4px;
  1253. right: 5px;
  1254. }`;
  1255. }
  1256.  
  1257.  
  1258.  
  1259.  
  1260.  
  1261.  
  1262.  
  1263. function throttle(func, delay)
  1264. {
  1265. let promise = Promise.resolve();
  1266. return function (...args)
  1267. {
  1268. promise = promise.then(() =>
  1269. {
  1270. return new Promise((resolve) =>
  1271. {
  1272. setTimeout(() =>
  1273. {
  1274. func(...args);
  1275. resolve();
  1276. }, delay);
  1277. });
  1278. });
  1279. };
  1280. }
  1281.  
  1282. const throttledAddVotersList = throttle(addVotersList, 200);
  1283.  
  1284. let observer = new MutationObserver((mutations) =>
  1285. {
  1286. console.log(`--- ${mutations.length} mutations`, mutations);
  1287.  
  1288. mutations.forEach((mutation) =>
  1289. {
  1290. if (dev || true)
  1291. {
  1292. console.log("---------- new mutation -----");
  1293. console.log(mutation);
  1294.  
  1295. if (mutation.type)
  1296. {
  1297. console.log(`⭐ mutation.type: `, mutation.type)
  1298. }
  1299. if (mutation.attributeName)
  1300. {
  1301. console.log(`⭐ mutation.attributeName: ${mutation.attributeName}`, mutation.attributeName)
  1302. }
  1303. if (mutation.addedNodes.length > 0 && mutation.addedNodes[0] && mutation.addedNodes[0] instanceof Element)
  1304. {
  1305. console.log(`⭐ mutation.addedNodes.length: ${mutation.addedNodes.length}`, mutation.addedNodes[0])
  1306. }
  1307.  
  1308. if (mutation.target)
  1309. {
  1310. console.log(`⭐ mutation.target: ${mutation.target.tagName}`, mutation.target)
  1311.  
  1312. if (mutation.target.tagName === "SECTION")
  1313. {
  1314.  
  1315. }
  1316. }
  1317. }
  1318.  
  1319. // ADDED NODES
  1320. if (mutation.addedNodes.length > 0 && mutation.addedNodes[0] && mutation.addedNodes[0].nodeType === Node.ELEMENT_NODE) // && mutation.addedNodes[0] instanceof Element)
  1321. {
  1322.  
  1323. if (mutation.addedNodes[0].matches("section.entry[id]") && mutation.addedNodes[0].__vue__?.item?.resource != "link_comment")
  1324. {
  1325. const sectionEntry = mutation.addedNodes[0];
  1326. if (dev) console.log("mutation 1", sectionEntry);
  1327.  
  1328. processSectionEntry(sectionEntry)
  1329.  
  1330. const sectionCommentsArray = sectionEntry.querySelectorAll("section.entry[id]");
  1331. if (dev) console.log("mutation 1 - forEach: sectionEntryArray", sectionCommentsArray);
  1332.  
  1333. sectionCommentsArray.forEach((sectionComment) =>
  1334. {
  1335. if (sectionComment.__vue__?.item?.resource != "link_comment")
  1336. {
  1337. processSectionEntry(sectionComment)
  1338. }
  1339. });
  1340.  
  1341. }
  1342. else if (mutation.addedNodes[0].matches("div.content:has(>section.entry[id])"))
  1343. {
  1344. const sectionEntriesArray = mutation.addedNodes[0].querySelectorAll("section.entry[id]");
  1345. if (dev) console.log("mutation 2 - forEach: sectionEntriesArray", sectionEntriesArray);
  1346.  
  1347. sectionEntriesArray.forEach((sectionEntry) =>
  1348. {
  1349. if (sectionEntry.__vue__?.item?.resource != "link_comment")
  1350. {
  1351. processSectionEntry(sectionEntry)
  1352. }
  1353. })
  1354. }
  1355. else if (mutation.target.tagName === "SECTION" && mutation.target.matches("section.entry.detailed[id]"))
  1356. {
  1357. const sectionEntry = mutation.target;
  1358.  
  1359. if (dev) console.log("mutation 3", sectionEntry)
  1360. if (dev) console.log("mutation 3: mutation.target", mutation.target);
  1361.  
  1362. if (sectionEntry.__vue__?.item?.resource != "link_comment")
  1363. {
  1364. processSectionEntry(sectionEntry)
  1365. }
  1366.  
  1367. const sectionCommentsArray = sectionEntry.querySelectorAll("section.entry[id]");
  1368. if (dev) console.log("mutation 3 - forEach: sectionEntryArray", sectionCommentsArray);
  1369.  
  1370. sectionCommentsArray.forEach((sectionComment) =>
  1371. {
  1372. if (sectionComment.__vue__?.item?.resource != "link_comment")
  1373. {
  1374. processSectionEntry(sectionComment)
  1375. }
  1376. });
  1377. }
  1378. else if (settings.showAnimatedAvatars && mutation.addedNodes[0].matches("aside.profile-top"))
  1379. {
  1380. animatedAvatar(mutation.addedNodes[0]);
  1381. }
  1382. // LEFT SIDE CATEGORY MENU OPENED
  1383. else if ((settings.mikroczatShowLeftMenuButton || settings.mikroczatShowLeftMenuLink) && mutation.addedNodes[0]?.matches("section.links"))
  1384. {
  1385. createLeftMenuButtons();
  1386. }
  1387. }
  1388. else if (mutation.removedNodes.length > 0 && mutation.removedNodes[0] && mutation.removedNodes[0].nodeType === Node.ELEMENT_NODE)
  1389. {
  1390. // LEFT SIDE CATEGORY MENU CLOSED
  1391. if ((settings.mikroczatShowLeftMenuButton || settings.mikroczatShowLeftMenuLink) && mutation.removedNodes[0]?.nodeType === Node.ELEMENT_NODE && mutation.removedNodes[0]?.matches("section.links"))
  1392. {
  1393. createLeftMenuButtons();
  1394. }
  1395. }
  1396.  
  1397. });
  1398. });
  1399.  
  1400.  
  1401.  
  1402. if (settings.mikroczatShowLeftMenuButton || settings.mikroczatShowLeftMenuLink)
  1403. {
  1404. createLeftMenuButtons();
  1405. }
  1406. if (settings.mikroczatShowTopNavButton)
  1407. {
  1408. createNewNavBarButton({
  1409. position: "left",
  1410. // text: "Mikro<strong>czat</strong>",
  1411. text: mikroczatButtonOpenLabel,
  1412. title: mikroczatButtonOpenTitle,
  1413. class: "open_mikroczat", // wykopx_open_mikroczat_li
  1414. hideWithoutXStyle: false,
  1415. //url: mikroczatDomain,
  1416. url: "https://wykop.pl/czat",
  1417. target: "_mikroczat",
  1418. number: null,
  1419. });
  1420. }
  1421.  
  1422. // CONTENT LOADED
  1423. let mainSection;
  1424.  
  1425.  
  1426.  
  1427. document.addEventListener('readystatechange', (event) =>
  1428. {
  1429. if (dev) console.log('readyState:' + document.readyState);
  1430. mainSection = document.querySelector('body > section');
  1431.  
  1432. if (mainSection)
  1433. {
  1434. const sectionEntryArray = mainSection.querySelectorAll("section.entry[id]");
  1435.  
  1436. // if (dev) console.log("sectionEntryArray", sectionEntryArray);
  1437. sectionEntryArray.forEach((sectionEntry) =>
  1438. {
  1439. if (sectionEntry.__vue__?.item?.resource != "link_comment")
  1440. {
  1441. processSectionEntry(sectionEntry)
  1442. }
  1443. })
  1444. const config = {
  1445. childList: true,
  1446. subtree: true,
  1447. };
  1448.  
  1449. observer.observe(mainSection, config);
  1450.  
  1451. if (settings.showAnimatedAvatars)
  1452. {
  1453. const asideProfileTop = mainSection.querySelector("aside.profile-top");
  1454. if (asideProfileTop) animatedAvatar(asideProfileTop);
  1455. }
  1456. }
  1457.  
  1458. });
  1459.  
  1460.  
  1461.  
  1462. function processSectionEntry(sectionEntry)
  1463. {
  1464. if (dev) console.log("processSectionEntry()", sectionEntry)
  1465.  
  1466. if (!sectionEntry) return;
  1467.  
  1468. if (settings.showAnimatedAvatars) animatedAvatar(sectionEntry);
  1469.  
  1470. if (settings.showFavouriteButton) addFavouriteButton(sectionEntry);
  1471.  
  1472. if (settings.entryVotersListEnable && sectionEntry?.__vue__?.item)
  1473. {
  1474. if (dev) console.log("sectionEntry?.__vue__.item.id", sectionEntry?.__vue__.item.id);
  1475. if (dev) console.log("sectionEntry.dataset?.votersLoaded", sectionEntry.dataset?.votersLoaded);
  1476.  
  1477. if (sectionEntry.dataset?.votersLoaded == sectionEntry?.__vue__.item.id) return;
  1478. if (sectionEntry?.__vue__.item.votes.up == 0)
  1479. {
  1480. removeVotersListWhenNoVoters(sectionEntry);
  1481. return;
  1482. }
  1483.  
  1484. if (settings.entryVotersListExpandIfLessThan > 5 && sectionEntry?.__vue__.item.votes.up <= settings.entryVotersListExpandIfLessThan && sectionEntry?.__vue__.item.votes.up > 5)
  1485. {
  1486. if (dev) console.log(`processSectionEntry() wybrano 💛throttledAddVotersList ${sectionEntry.__vue__.item.id} | plusow: ${sectionEntry.__vue__.item.votes.up}`,)
  1487. throttledAddVotersList(sectionEntry);
  1488. }
  1489. else
  1490. {
  1491. if (dev) console.log(`processSectionEntry() wybrano 🤎addVotersList ${sectionEntry.__vue__.item.id} | plusow: ${sectionEntry.__vue__.item.votes.up}`,)
  1492. addVotersList(sectionEntry)
  1493. }
  1494. }
  1495. }
  1496.  
  1497.  
  1498. function animatedAvatar(sectionEntry)
  1499. {
  1500. const image = sectionEntry.querySelector('a.avatar figure img'); // Replace with your actual selector
  1501. if (image)
  1502. {
  1503. const currentSrc = image.getAttribute('src');
  1504. if (currentSrc.endsWith('.gif'))
  1505. {
  1506. const modifiedSrc = currentSrc.replace(/,.*?\./, '.');
  1507. image.setAttribute('src', modifiedSrc);
  1508. }
  1509. }
  1510. }
  1511.  
  1512. function removeVotersListWhenNoVoters(sectionEntry)
  1513. {
  1514. if (sectionEntry)
  1515. {
  1516. delete sectionEntry.dataset?.votersLoaded;
  1517. sectionEntry.querySelector("section.entry-voters")?.remove();
  1518. }
  1519.  
  1520. }
  1521.  
  1522. async function addVotersList(sectionEntry)
  1523. {
  1524. if (!sectionEntry || !sectionEntry.__vue__) return;
  1525. if (sectionEntry.dataset?.votersLoaded == sectionEntry?.__vue__.item.id) return;
  1526.  
  1527. if (sectionEntry?.__vue__ && sectionEntry?.__vue__.item.votes.up > 0)
  1528. {
  1529. if (sectionEntry?.__vue__ && settings.entryVotersListExpandIfLessThan > 5 && sectionEntry?.__vue__.item.votes.up <= settings.entryVotersListExpandIfLessThan && sectionEntry?.__vue__.item.votes.up > 5)
  1530. {
  1531. let entryId, commentId;
  1532. if (sectionEntry?.__vue__?.item.resource == "entry")
  1533. {
  1534. entryId = sectionEntry?.__vue__?.item.id;
  1535. }
  1536. else if (sectionEntry?.__vue__?.item.resource == "entry_comment")
  1537. {
  1538. entryId = sectionEntry?.__vue__?.item.parent.id;
  1539. commentId = sectionEntry?.__vue__?.item.id;
  1540. }
  1541. let voters = await fetchAllVotersFromAPI(entryId, commentId);
  1542.  
  1543. appendVotersToEntry(sectionEntry, voters);
  1544.  
  1545. }
  1546. else
  1547. {
  1548. appendVotersToEntry(sectionEntry, sectionEntry?.__vue__?.item?.votes?.users);
  1549. }
  1550. }
  1551. }
  1552.  
  1553. function addFavouriteButton(sectionEntry)
  1554. {
  1555. if (sectionEntry && sectionEntry?.__vue__)
  1556. {
  1557. const sectionActionsUL = sectionEntry.querySelector("section.actions:not(:has(li.favourite)) > ul");
  1558. if (!sectionActionsUL) return;
  1559.  
  1560. let entryId, commentId;
  1561.  
  1562. let isFavourite = sectionEntry?.__vue__?.item.favourite;
  1563.  
  1564. if (sectionEntry?.__vue__?.item.resource == "entry")
  1565. {
  1566. entryId = sectionEntry?.__vue__?.item.id;
  1567. }
  1568. else if (sectionEntry?.__vue__?.item.resource == "entry_comment")
  1569. {
  1570. entryId = sectionEntry?.__vue__?.item.parent.id;
  1571. commentId = sectionEntry?.__vue__?.item.id;
  1572. }
  1573.  
  1574.  
  1575. const favButtonLI = document.createElement("li");
  1576. favButtonLI.classList.add("favourite", "icon", "icon-favourite");
  1577.  
  1578.  
  1579. if (isFavourite) { favButtonLI.classList.add("active"); }
  1580. const favButtonSpan = document.createElement("span");
  1581. favButtonSpan.classList.add("favouriteButton");
  1582.  
  1583. // VUE SENSITIVE
  1584. /*
  1585. data-v-90179052
  1586. */
  1587. favButtonLI.setAttribute('data-v-90179052', '');
  1588. favButtonSpan.setAttribute('data-v-90179052', '');
  1589.  
  1590. favButtonSpan.dataset.isFavourite = isFavourite;
  1591. favButtonSpan.dataset.entryId = entryId;
  1592. if (commentId) favButtonSpan.dataset.commentId = commentId;
  1593. if (settings.showFavouriteButtonLabel) favButtonSpan.innerText = `Ulubione`;
  1594. favButtonLI.appendChild(favButtonSpan);
  1595.  
  1596. const sharingElement = sectionActionsUL.querySelector(".sharing");
  1597. if (sharingElement) sharingElement.insertAdjacentElement("afterend", favButtonLI);
  1598.  
  1599. }
  1600.  
  1601. }
  1602.  
  1603.  
  1604.  
  1605.  
  1606. function appendVotersToEntry(sectionEntry, voters)
  1607. {
  1608. if (!sectionEntry) return;
  1609. const divEditWrapperElement = sectionEntry.querySelector('article > div.edit-wrapper');
  1610. if (!divEditWrapperElement) return;
  1611.  
  1612. sectionEntry.dataset.votersLoaded = sectionEntry?.__vue__?.item.id;
  1613.  
  1614. const fiveVoters = voters;
  1615.  
  1616. if (!fiveVoters || fiveVoters.length < 1) return false;
  1617.  
  1618. let sectionEntryVotersHTML = `<ul>`;
  1619.  
  1620. fiveVoters.forEach(voter =>
  1621. {
  1622. sectionEntryVotersHTML += getListItemForUser(voter);
  1623. });
  1624.  
  1625. // <li class="more">
  1626. if (sectionEntry?.__vue__?.item?.votes.up > settings.entryVotersListExpandIfLessThan && voters.length <= settings.entryVotersListExpandIfLessThan)
  1627. {
  1628. sectionEntryVotersHTML += `
  1629. <li data-no-bubble="" class="more">
  1630. <span data-votes-up="${sectionEntry?.__vue__?.item?.votes.up}"`;
  1631.  
  1632. if (sectionEntry?.__vue__?.item.resource == "entry")
  1633. {
  1634. sectionEntryVotersHTML += `data-entry-id="${sectionEntry?.__vue__?.item.id}"`;
  1635. }
  1636. else if (sectionEntry?.__vue__?.item.resource == "entry_comment")
  1637. {
  1638. sectionEntryVotersHTML += `data-entry-id="${sectionEntry?.__vue__?.item.parent.id}"`;
  1639. sectionEntryVotersHTML += `data-comment-id="${sectionEntry?.__vue__?.item.id}"`;
  1640. }
  1641.  
  1642. sectionEntryVotersHTML += `>+${sectionEntry?.__vue__?.item?.votes.up - 5} innych</span></li>`;
  1643. }
  1644. sectionEntryVotersHTML += `</ul>`;
  1645.  
  1646. const sectionEntryVoters = document.createElement("section");
  1647. sectionEntryVoters.classList.add("entry-voters");
  1648. sectionEntryVoters.innerHTML = sectionEntryVotersHTML;
  1649.  
  1650. const sectionEntryVotersElement = divEditWrapperElement.querySelector('section.entry-voters');
  1651.  
  1652. if (sectionEntryVotersElement)
  1653. {
  1654. let parentElement = sectionEntryVotersElement.parentNode;
  1655. parentElement.replaceChild(sectionEntryVoters, sectionEntryVotersElement);
  1656. }
  1657. else
  1658. {
  1659. const editWrapper = sectionEntry.querySelector(".edit-wrapper");
  1660. if (editWrapper) editWrapper.appendChild(sectionEntryVoters);
  1661. }
  1662. }
  1663.  
  1664. function getListItemForUser(voter)
  1665. {
  1666. let userHTML = `<li>
  1667. <a href="/ludzie/${voter.username}" class="username`;
  1668.  
  1669. userHTML += ` ${voter.color}-profile`; // orange-profile green-profile burgundy-profile
  1670. userHTML += ` ${voter.status}`; // active banned suspended removed
  1671. userHTML += ` follow-${voter.follow}`; // follow-true follow-false
  1672. userHTML += ` verified-${voter.verified}`; // verified-false
  1673. userHTML += ` blacklist-${voter.blacklist}`;// blacklist-true blacklist-false
  1674. userHTML += ` online-${voter.online}`; // online-true online-false
  1675.  
  1676. userHTML += ` ${voter.gender}-gender`; // m-gender, f-gender, null-gender
  1677. if (voter.gender == "m") userHTML += ` male`;
  1678. else if (voter.gender == "f") userHTML += ` female`;
  1679. userHTML += `">`;
  1680.  
  1681.  
  1682. if (settings?.votersFollow && voter.follow) userHTML += `<i class="follow-true" title="Obserwujesz tego użytkownika"></i>`;
  1683. if (settings?.votersVerified && voter.verified) userHTML += `<i class="verified-true" title="Ten użytkownik jest zweryfikowany"></i>`;
  1684. if (settings?.votersBlacklist && voter.blacklist) userHTML += `<i class="blacklist-true" title="Ten użytkownik jest na Twojej czarnej liście"></i>`;
  1685. if (settings?.votersOffline && !voter.online) userHTML += `<i class="online-false" title="Ten uzytkownik jest teraz offline"></i>`;
  1686. if (settings?.votersOnline && voter.online) userHTML += `<i class="online-true" title="Ten uzytkownik jest teraz online"></i>`;
  1687. if (settings?.votersBanned && voter.status == "banned") userHTML += `<i class="banned" title="Użytkownik dostał bana. Z dodatkiem Wykop XS - Ban Info możesz szybko sprawdzić przyczynę i długość trwania bana."></i>`;
  1688. if (settings?.votersSuspended && voter.status == "suspended") userHTML += `<i class="suspended" title="To konto jest w trakcie usuwania."></i>`;
  1689. if (settings?.votersRemoved && voter.status == "removed") userHTML += `<i class="removed" title="Konto usunięte"></i>`;
  1690. if (settings?.votersGenderM && voter.gender == "m") userHTML += `<i class="${voter.gender}-gender" title="Wpis od niebieskiego"></i>`;
  1691. if (settings?.votersGenderF && voter.gender == "f") userHTML += `<i class="${voter.gender}-gender" title="Plus od różowej"></i>`;
  1692.  
  1693. userHTML += `<span>${voter.username}</span>
  1694. </a>
  1695. </li>`;
  1696.  
  1697. return userHTML;
  1698. }
  1699.  
  1700.  
  1701. /*
  1702. <section data-v-6e6ed6ee="" data-v-2aacfeb5="" class="entry-voters">
  1703. <ul data-v-6e6ed6ee="">
  1704. <li data-v-6e6ed6ee="" class="">
  1705. <a data-v-ed9f6c56="" data-v-6e6ed6ee="" href="/ludzie/NaczelnyAgnostyk" class="username orange-profile active">
  1706. <span data-v-ed9f6c56="">
  1707. NaczelnyAgnostyk<!---->
  1708. </span>
  1709. </a>
  1710. </li>
  1711. <li data-v-6e6ed6ee="" data-no-bubble="" class="more">
  1712. <span data-v-6e6ed6ee="">+5 innych</span>
  1713. </li>
  1714. </ul>
  1715. </section>
  1716. */
  1717.  
  1718. function fetchAllVotersFromAPI(entryId, commentId)
  1719. {
  1720. if (dev) console.log(`fetchAllVotersFromAPI: ${entryId}, ${commentId}`)
  1721. let apiURL = `https://wykop.pl/api/v3/entries/${entryId}/votes?page=1`
  1722. if (commentId) apiURL = `https://wykop.pl/api/v3/entries/${entryId}/comments/${commentId}/votes`;
  1723.  
  1724. return new Promise(async (resolve, reject) =>
  1725. {
  1726. await fetch(apiURL, {
  1727. method: "GET",
  1728. headers: {
  1729. "Content-Type": "application/json",
  1730. Authorization: "Bearer " + window.localStorage.getItem("token"),
  1731. },
  1732. })
  1733. .then((response) =>
  1734. {
  1735. if (!response.ok)
  1736. {
  1737. if (dev) console.log("HTTP error! status: ${response.status}");
  1738. // throw new Error(`HTTP error! status: ${response.status}`);
  1739. }
  1740. return response.json();
  1741. })
  1742. .then(async (responseJSON) =>
  1743. {
  1744. resolve(responseJSON.data);
  1745.  
  1746. }).catch((error) =>
  1747. {
  1748. if (error instanceof TypeError)
  1749. {
  1750. console.error('Network error:', error); // AWARIA SERWERA WYPOKU
  1751. } else
  1752. {
  1753. console.error('Other error:', error);
  1754. }
  1755. reject(error);
  1756. });
  1757. });
  1758. }
  1759.  
  1760. function postFavouriteToAPI(favourite, resource, id)
  1761. {
  1762. let apiURL = `https://wykop.pl/api/v3/favourites`;
  1763. const method = favourite ? "POST" : "DELETE";
  1764. const body = {
  1765. data: {
  1766. type: resource,
  1767. source_id: id
  1768. }
  1769. }
  1770.  
  1771. return new Promise(async (resolve, reject) =>
  1772. {
  1773. await fetch(apiURL, {
  1774. method: method,
  1775. headers: {
  1776. "Content-Type": "application/json",
  1777. Authorization: "Bearer " + window.localStorage.getItem("token"),
  1778. },
  1779. body: JSON.stringify(body)
  1780. })
  1781. .then((response) =>
  1782. {
  1783. if (!response.ok)
  1784. {
  1785. if (dev) console.log("HTTP error! status: ${response.status}");
  1786. // throw new Error(`HTTP error! status: ${response.status}`);
  1787. }
  1788. return response.json();
  1789. })
  1790. .then(async (responseJSON) =>
  1791. {
  1792. resolve(responseJSON.data);
  1793.  
  1794. }).catch((error) =>
  1795. {
  1796. if (error instanceof TypeError)
  1797. {
  1798. console.error('Network error:', error); // AWARIA SERWERA WYPOKU
  1799. } else
  1800. {
  1801. console.error('Other error:', error);
  1802. }
  1803. reject(error);
  1804. });
  1805. });
  1806. }
  1807.  
  1808. // settings.addCommentPlusWhenVotingOnEntry, settings.addCommentPlusWhenVotingOnComment
  1809. function postCommentPlus1ToAPI(sectionEntry)
  1810. {
  1811. if (!sectionEntry || !sectionEntry.__vue__) return;
  1812.  
  1813. const resource = sectionEntry.__vue__.item.resource;
  1814. let entryId;
  1815. let authorUsername = sectionEntry.__vue__.item.author.username;
  1816. if (resource === "entry")
  1817. entryId = sectionEntry.__vue__.item.id;
  1818.  
  1819. else if (resource === "entry_comment")
  1820. entryId = sectionEntry.__vue__.item.parent.id;
  1821.  
  1822. // TODO ZNALEZISKA
  1823. let apiURL = `https://wykop.pl/api/v3/entries/${entryId}/comments`;
  1824. const method = "POST";
  1825. const body = {
  1826. data: {
  1827. "content": `@${authorUsername} [+](https://greasyfork.org/en/scripts/489949)1`,
  1828. "adult": false
  1829. }
  1830. }
  1831. /*
  1832. "data":
  1833. {
  1834. "content": "**foobar** __foobar__ [lorem](https://www.wykop.pl) impsum!!! #nsfw #wykop",
  1835. "embed": "1fde707843ss3fbe9cb4eed0asdfsdfc64ab9a4df6084199b39d2",
  1836. "photo": "e07843ss3fbe9cb4saeed0asdfsdfc64b9a4df6084199b39d2",
  1837. "adult": false
  1838. }
  1839. }
  1840. */
  1841.  
  1842. return new Promise(async (resolve, reject) =>
  1843. {
  1844. await fetch(apiURL, {
  1845. method: method,
  1846. headers: {
  1847. "Content-Type": "application/json",
  1848. Authorization: "Bearer " + window.localStorage.getItem("token"),
  1849. },
  1850. body: JSON.stringify(body)
  1851. })
  1852. .then((response) =>
  1853. {
  1854. if (!response.ok)
  1855. {
  1856. if (dev) console.log("HTTP error! status: ${response.status}");
  1857. // throw new Error(`HTTP error! status: ${response.status}`);
  1858. }
  1859. return response.json();
  1860. })
  1861. .then(async (responseJSON) =>
  1862. {
  1863. resolve(responseJSON.data);
  1864.  
  1865. }).catch((error) =>
  1866. {
  1867. if (error instanceof TypeError)
  1868. {
  1869. console.error('Network error:', error); // AWARIA SERWERA WYPOKU
  1870. } else
  1871. {
  1872. console.error('Other error:', error);
  1873. }
  1874. reject(error);
  1875. });
  1876. });
  1877. }
  1878.  
  1879. // li.more click
  1880. document.addEventListener("click", async function (e)
  1881. {
  1882. if (e.target.closest("div.buttons button.plus"))
  1883. {
  1884. const sectionEntry = e.target.closest("section.entry[id]");
  1885. if (sectionEntry.__vue__?.item?.voted == 1)
  1886. {
  1887. // if (settings.addCommentPlusWhenVotingOnEntry && sectionEntry && sectionEntry.__vue__?.item?.resource == "entry")
  1888. // {
  1889. // postCommentPlus1ToAPI(sectionEntry);
  1890. // }
  1891. // else if (settings.addCommentPlusWhenVotingOnComment && sectionEntry && sectionEntry.__vue__?.item?.resource == "entry_comment")
  1892. // {
  1893. // postCommentPlus1ToAPI(sectionEntry);
  1894. // }
  1895. }
  1896. }
  1897.  
  1898. if (e.target.matches("li.more span"))
  1899. {
  1900. e.preventDefault();
  1901.  
  1902. let sectionEntry = e.target.closest("section.entry");
  1903. const entryId = e.target.dataset.entryId;
  1904. const commentId = e.target.dataset.commentId;
  1905. if (dev) console.log(`Wykop XS pobiera listę ${e.target.dataset.votesUp} plusujących`);
  1906.  
  1907. e.target.closest("section.entry-voters").innerHTML = `<span>(Wykop X: wczytywanie ${e.target.dataset.votesUp} plusujących...)</span>`;
  1908.  
  1909. let voters = await fetchAllVotersFromAPI(entryId, commentId);
  1910.  
  1911. appendVotersToEntry(sectionEntry, voters);
  1912. return;
  1913. }
  1914.  
  1915. if (e.target.matches("span.favouriteButton"))
  1916. {
  1917. e.preventDefault();
  1918. if (e.target.dataset.isFavourite == "true")
  1919. {
  1920. if (e.target.dataset.commentId) postFavouriteToAPI(false, "entry_comment", e.target.dataset.commentId);
  1921. else postFavouriteToAPI(false, "entry", e.target.dataset.entryId);
  1922. e.target.parentElement.classList.remove("active");
  1923. e.target.dataset.isFavourite = "false";
  1924.  
  1925. }
  1926. else if (e.target.dataset.isFavourite == "false")
  1927. {
  1928. if (e.target.dataset.commentId) postFavouriteToAPI(true, "entry_comment", e.target.dataset.commentId);
  1929. else postFavouriteToAPI(true, "entry", e.target.dataset.entryId);
  1930. e.target.parentElement.classList.add("active");
  1931. e.target.dataset.isFavourite = "true";
  1932. }
  1933. return;
  1934. }
  1935. }, false);
  1936.  
  1937.  
  1938.  
  1939.  
  1940.  
  1941.  
  1942. /* CSS WYKOP XS MIKROCZAT */
  1943. if (settings?.hideShareButton) CSS += `section.actions ul li.sharing { display: none!important; }`;
  1944.  
  1945.  
  1946. /* Wykop X Style 3.0 */
  1947. CSS += `
  1948. :root
  1949. {
  1950. --kolorBananowy1: rgba(255, 185, 0, 1);
  1951. --tagChannelColor: rgba(0, 183, 255, 1);
  1952. --pmChannelColor: rgba(255, 89, 23, 1);
  1953. --smallBorderRadius: 4px;
  1954. }
  1955. div[data-modal="entryVoters"] section.entry-voters::after {content: none!important;} /* Wykop X Style PROMO */
  1956. `;
  1957.  
  1958. /* LISTA PLUSUJĄCYCH CSS, PRZYCISK DODAJ DO ULUBIONYCH */
  1959. if (settings?.entryVotersListEnable)
  1960. {
  1961. CSS += `
  1962. /* Chrome 109, Firefox 115 */
  1963. @supports not (display: block flex)
  1964. {
  1965. section.entry-voters ul
  1966. {
  1967. display: flex;
  1968. }
  1969. }
  1970.  
  1971. section.entry-voters ul
  1972. {
  1973. display: block flex;
  1974. row-gap: 0px;
  1975. flex-wrap: wrap;
  1976. align-items: baseline;
  1977. padding: 0 0 0 0;
  1978. margin: 0;
  1979. margin-top: 8px;
  1980. list-style-type: none;
  1981. position: relative;
  1982. }
  1983.  
  1984. section.entry-voters ul,
  1985. section.entry-voters > span
  1986. {
  1987. font-size: var(--entryVotersTextFontSize, 12px);
  1988. color: var(--gullGray);
  1989. }
  1990.  
  1991. section.entry-voters ul::before
  1992. {
  1993. content: "Plusujący: ";
  1994. margin-right: 0.2em;
  1995. }
  1996.  
  1997. section.entry-voters ul li.more
  1998. {
  1999. cursor: pointer;
  2000. font-weight: 700;
  2001. text-transform: uppercase;
  2002. }
  2003.  
  2004. section.entry-voters ul li::after
  2005. {
  2006. content: " • ";
  2007. margin: 0px 0.2em 0px 0em;
  2008. }
  2009.  
  2010. section.entry-voters ul li.more::after,
  2011. section.entry-voters ul li:only-child::after
  2012. { content: none; }
  2013.  
  2014. section.entry-voters ul li a.username span
  2015. {
  2016. font-weight: normal;
  2017. }
  2018.  
  2019. section.entry-voters ul li a.username i { display: none; font-size: 0.8em; font-style: normal; bottom: 0px; position: relative; }
  2020. section.entry-voters ul li a.username i:has(+span) { margin-right: 1px; }
  2021. section.entry-voters ul li a.username i.follow-true,
  2022. section.entry-voters ul li a.username i.blacklist-true,
  2023. section.entry-voters ul li a.username i.banned ,
  2024. section.entry-voters ul li a.username i.suspended,
  2025. section.entry-voters ul li a.username i.removed,
  2026. section.entry-voters ul li a.username i.f-gender,
  2027. section.entry-voters ul li a.username i.m-gender
  2028. { display: inline flex;}
  2029. section.entry-voters ul li a.username i.follow-true::before { content: '🔔'; }
  2030. section.entry-voters ul li a.username i.blacklist-true::before { content: '⛔'; }
  2031. section.entry-voters ul li a.username i.banned::before { content: '🍌'; }
  2032. section.entry-voters ul li a.username i.suspended::before { content: '✖'; }
  2033. section.entry-voters ul li a.username i.removed::before { content: '❌'; }
  2034. section.entry-voters ul li a.username i.f-gender::before { content: '🟣'; font-size: 0.7em; bottom: 3px; }
  2035. section.entry-voters ul li:has(a.username) { order: 6; }
  2036. section.entry-voters ul li.more { order: 100; }
  2037. `;
  2038.  
  2039. if (settings?.votersFollowFirst) CSS += `section.entry-voters ul li:has(a.username.follow-true) { order: 1; }`;
  2040. if (settings?.votersBlackFirst) CSS += `section.entry-voters ul li:has(a.username.burgundy-profile) { order: 3; }`;
  2041. if (settings?.votersOrangeFirst) CSS += `section.entry-voters ul li:has(a.username.orange-profile) { order: 4; }`;
  2042. if (settings?.votersGreenFirst) CSS += `section.entry-voters ul li:has(a.username.green-profile) { order: 5; }`;
  2043.  
  2044. if (settings?.votersBlacklistLast) CSS += `section.entry-voters ul li:has(a.username.blacklist-true) { order: 7; }`;
  2045. if (settings?.votersBannedLast) CSS += `section.entry-voters ul li:has(a.username.banned) { order: 8; }`;
  2046. if (settings?.votersSuspendedLast) CSS += `section.entry-voters ul li:has(a.username.banned) { order: 9; }`;
  2047. if (settings?.votersRemovedLast) CSS += `section.entry-voters ul li:has(a.username.removed) { order: 10; }`;
  2048.  
  2049. if (!settings?.votersColorOrange) CSS += `section.entry-voters ul li a.username.orange-profile { color: var(--gullGray); }`;
  2050. if (!settings?.votersColorGreen) CSS += `section.entry-voters ul li a.username.green-profile { color: var(--gullGray); }`;
  2051. if (!settings?.votersColorBurgundy) CSS += `section.entry-voters ul li a.username.burgundy-profile { color: var(--gullGray); }`;
  2052.  
  2053. CSS += `
  2054. section.entry-voters ul li a.username.banned:not(.removed) span { color: var(--kolorBananowy1); };
  2055. section.entry-voters ul li a.username.suspended:not(.removed) span { color: var(--heather); }
  2056. section.entry-voters ul li a.username.removed span { color: var(--heather); }
  2057. [data-night-mode] section.entry-voters ul li a.username.removed span { background-color: rgba(255, 255, 255, 0.1); padding-left: 5px; padding-right: 5px; }
  2058. `;
  2059. }
  2060.  
  2061. /* ULUBIONE */
  2062. CSS += `
  2063. section.actions > ul > li.favourite
  2064. {
  2065. cursor: pointer;
  2066. user-select: none;
  2067. color: var(--gullGray);
  2068. font-size: 14px;
  2069. padding-left: 26px;
  2070. transition: color .2s ease, opacity .2s ease;
  2071. }
  2072.  
  2073. .actions li.favourite span::before
  2074. {
  2075. content: '';
  2076. width: 18px;
  2077. height: 18px;
  2078. display: block;
  2079. position: absolute;
  2080. left: 0;
  2081. background: var(--gullGray);
  2082. transition: background .2s ease;
  2083.  
  2084. -webkit-mask-size: 18px 18px;
  2085. mask-size: 18px 18px;
  2086. -webkit-mask: url(/static/img/svg/favourite.svg) no-repeat center;
  2087. mask-image: url(/static/img/svg/favourite.svg);
  2088. }
  2089. .actions li.favourite.active span::before
  2090. {
  2091. background: var(--orange);
  2092. -webkit-mask: url(/static/img/svg/favourite-filled.svg) no-repeat center;
  2093. mask-image: url(/static/img/svg/favourite-filled.svg);
  2094. }
  2095. `;
  2096.  
  2097.  
  2098. /* HIDE ADS ALWAYS */
  2099. if (settings.hideAds) { CSS += `.pub-slot-wrapper { display: none!important; }`; }
  2100.  
  2101. /* HIDE WYKOP XS PROMO FROM STYLUS */
  2102. CSS += `.wykopxs, body div.main-content[class] section > section.sidebar::after { display: none!important; }`;
  2103.  
  2104. styleElement.textContent = CSS;
  2105. document.head.appendChild(styleElement);
  2106. })();
  2107.