├── Wykop X Bookmarklets ├── README.md ├── dodaj-strone-www-jako-nowe-znalezisko.js ├── wykopx.js └── odcenzuruj.js ├── .gitignore ├── .github └── FUNDING.yml ├── Wykop XS ├── wykop_xs_przycisk_do_usuwania_obserwowanych_dyskusji.js ├── wykop_xs_obrazki.js ├── stylus.styl ├── wykop----pagination.js ├── wykop_xs_banned.user.js ├── wykop_xs_ungroup_notifications.user.js ├── wykop_xs_xhr_blocker.user.js └── wykop_xs_all_comments.user.js ├── Wykop X Style ├── wykop_x_blank - HEADER.txt ├── wykop_x_style_ad_blocker.user.css ├── dummy_classes.css └── wykop_x_style_ikonki_powiadomien.user.css ├── README.md ├── Wykop XS - skrypty do konsoli ├── wykop_xs_czyszczenie_listy_obserwowanych_dyskusji.min.js └── wykop_xs_czyszczenie_listy_obserwowanych_dyskusji.js └── Twitter X Style └── twitter_x_style.user.css /Wykop X Bookmarklets/README.md: -------------------------------------------------------------------------------- 1 | Pierwsza wersja bookmarklet's 2 | żeby korzystanie z Wykopu było szybsze i łatwiejsze ( ͡° ͜ʖ ͡°) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | Wykop XS/vue item.jsonc 3 | Wykop XS/API examples.jsonc 4 | Wykop XS/odmiana.js 5 | /.vscode 6 | Wykop XS/.vscode/settings.json 7 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: ["https://buycoffee.to/wykopx"] 14 | 15 | -------------------------------------------------------------------------------- /Wykop XS/wykop_xs_przycisk_do_usuwania_obserwowanych_dyskusji.js: -------------------------------------------------------------------------------- 1 | /* 2 | ----- Zapraszam na tag #wykopx ----- 3 | 4 | SKRYPT DO WYCZYSZCZENIA LISTY OBSERWOWANYCH DYSKUSJI 5 | 6 | Skrypt został przeniesiony do osobnego folderu: 7 | https://github.com/wykopx/WykopX/tree/main/Wykop%20XS%20-%20skrypty%20do%20konsoli 8 | 9 | Wersja zminimalizowana tego skryptu gotowa do wklejenia= w konsoli: 10 | https://raw.githubusercontent.com/wykopx/WykopX/refs/heads/main/Wykop%20XS%20-%20skrypty%20do%20konsoli/wykop_xs_czyszczenie_listy_obserwowanych_dyskusji.min.js 11 | 12 | Pełna wersja tego skryptu tutaj: 13 | https://github.com/wykopx/WykopX/blob/main/Wykop%20XS%20-%20skrypty%20do%20konsoli/wykop_xs_czyszczenie_listy_obserwowanych_dyskusji.js 14 | 15 | 16 | Chcesz wesprzeć projekt Wykop X? Postaw kawę: 17 | 18 | @contributionURL https://buycoffee.to/wykopx 19 | @author Wykop X 20 | 21 | ----- Zapraszam na tag #wykopx ----- 22 | */ 23 | -------------------------------------------------------------------------------- /Wykop X Style/wykop_x_blank - HEADER.txt: -------------------------------------------------------------------------------- 1 | /* ==UserStyle== 2 | @name Wykop X Style 3 Blank 3 | @version 3.1.0 4 | 5 | @description Niniejsza wersja to wersja BLANK, w której wszystkie funkcje są wyłączone. 6 | @description https://styl.wykopx.pl 7 | 8 | 9 | Chcesz zostać patronem projektu Wykop X? 10 | Doborowolne wsparcie na stronie: https://buycoffee.to/wykopx 11 | 12 | 13 | --- Wykop X Style --- 14 | 15 | Jeśli nie chcesz poświęcać czasu na konfigurowanie, skorzystaj z wersji głównej Wykop X Style 16 | 17 | >>> https://styl.wykopx.pl 18 | 19 | 20 | 21 | 22 | --- Wykop X XS --- 23 | 24 | Zainstaluj teź pomocniczy skrypt Wykop XS, który 25 | dodaje ponad 100 nowych funkcji oznaczonych jako ❎ 26 | 27 | >>> https://skrypt.wykopx.pl 28 | 29 | 30 | 31 | 32 | 33 | 34 | @description ---- WYKOP X ---- 35 | @description http://wiki.wykopx.pl 36 | @description https://userstyles.world/style/8174/wykop-x-style-3 37 | 38 | 39 | 40 | ---- AUTOR ---- 41 | 42 | @author Wykop X | wiki.wykopx.pl 43 | @homepageURL http://wiki.wykopx.pl 44 | @supportURL http://wiki.wykopx.pl 45 | 46 | ---- AUTOR ---- 47 | -------------------------------------------------------------------------------- /Wykop X Bookmarklets/dodaj-strone-www-jako-nowe-znalezisko.js: -------------------------------------------------------------------------------- 1 | javascript: (function () 2 | { 3 | var url = new URL(location.href); 4 | if (url.hostname === "wykop.pl") 5 | { 6 | if (url.pathname.startsWith("/wpis/")) 7 | { 8 | window.open(url.href.replace(/wykop\.pl/g, 'wykopx.pl')); 9 | } 10 | else if (url.pathname.startsWith("/tag/")) 11 | { 12 | window.open("https://mikroczat.pl/czat/" + url.pathname.split("/tag/")[1]); 13 | } 14 | else if (url.pathname.startsWith("/ludzie/") && url.pathname.length > 8) 15 | { 16 | window.open("https://mikroczat.pl/pm/@" + url.pathname.split("/ludzie/")[1]); 17 | } 18 | } 19 | else if (url.hostname === "mikroczat.pl") 20 | { 21 | 22 | } 23 | else 24 | { 25 | window.open(`https://wykop.pl/dodaj-link?url=${location.href}`); 26 | } 27 | })(); 28 | /* 29 | v.1.0.1 30 | 1. Skopiuj cały kod tego skryptu 31 | 2. Wciśnij na dowolnej stronie CTRL+D aby otworzyć okno dodawania Ulubionej/Zakładki/Bookmark 32 | 3. W polu adresu URL usuń adres strony na której jesteś i wklej skopiowany powyżej kod 33 | 4. Ustaw dowolną nazwą np. 'Dodaj na Wykop' 34 | 4. Gotowe. 35 | 36 | Aby skorzystać z Bookmarklet Wykop X po prostu kliknij jego ikonę 37 | - na dowolnej stronie -> otworzysz okno dodawania nowego znaleziska 38 | */ 39 | -------------------------------------------------------------------------------- /Wykop X Bookmarklets/wykopx.js: -------------------------------------------------------------------------------- 1 | javascript: (function () 2 | { 3 | var url = new URL(location.href); 4 | if (url.hostname === "wykop.pl") 5 | { 6 | if (url.pathname.startsWith("/wpis/")) 7 | { 8 | window.open(url.href.replace(/wykop\.pl/g, 'wykopx.pl')); 9 | } 10 | else if (url.pathname.startsWith("/tag/")) 11 | { 12 | window.open("https://mikroczat.pl/czat/" + url.pathname.split("/tag/")[1]); 13 | } 14 | else if (url.pathname.startsWith("/ludzie/") && url.pathname.length > 8) 15 | { 16 | window.open("https://mikroczat.pl/pm/@" + url.pathname.split("/ludzie/")[1]); 17 | } 18 | } 19 | else if (url.hostname === "mikroczat.pl") 20 | { 21 | 22 | } 23 | else 24 | { 25 | window.open("https://wykopx.pl/m"); 26 | } 27 | })(); 28 | /* 29 | v.1.0.1 30 | 31 | 1. Skopiuj cały kod tego skryptu 32 | 2. Wciśnij na dowolnej stronie CTRL+D aby otworzyć okno dodawania Ulubionej/Zakładki/Bookmark 33 | 3. W polu adresu URL usuń adres strony na której jesteś i wklej skopiowany powyżej kod 34 | 4. Ustaw dowolną nazwą np. 'Wykop' albo 'WX' 35 | 4. Gotowe. 36 | 37 | Aby skorzystać z Bookmarklet Wykop X po prostu kliknij jego ikonę 38 | - na stronie dowolnego tagu -> otworzysz kanał na Mikroczacie 39 | - na dowolnej stronie -> otworzysz Mikroblog 40 | - na stronie wpisu -> otworzysz Archiwum X z oryginalną treścią wpisu 41 | */ 42 | // Kliknij, aby zobaczyć treść usuniętego wpisu z Archiwum X 43 | -------------------------------------------------------------------------------- /Wykop X Style/wykop_x_style_ad_blocker.user.css: -------------------------------------------------------------------------------- 1 | /* ==UserStyle== 2 | @name Wykop X - blokowanie reklam 3 | @version 1.1.1 4 | @description Blokowanie reklam i znalezisk Sponsorowanych na wykop.pl 5 | 6 | 7 | @author SebastianDosiadlgo | www.wykopx.pl 8 | 9 | @homepageURL http://www.wykopx.pl 10 | @supportURL http://issues.wykopx.pl 11 | 12 | @preprocessor stylus 13 | @namespace userstyles.world/user/wykopchanger 14 | @license No License (YOU CAN USE THIS CODE ONLY IN STYLUS EXTENSIONS. You are not allowed to: copy any part of the code, share, and use it anywhere) 15 | 16 | 17 | 18 | -- http://www.WykopX.pl 19 | 20 | -- https://wykop.pl/tag/wykopwnowymstylu 21 | 22 | 23 | Changelog 24 | 25 | 1.1.1 [2023-02-26] 26 | - możliwość włączenia/wyłączenia całkowitego ukrywania reklam 27 | - możliwość włączenia/wyłączenia ukrywania znalezisk sponsorowanych "Wykop Sponsorowany" 28 | - możliwość włączenia/wyłączenia ukrywania znalezisk polecanych "Wykop Poleca" 29 | 30 | 1.1.0 [2023-01-22] 31 | - uproszczenie ukrywania reklam 32 | - ukrywanie także wpisów sponsorowanych 33 | 34 | 35 | 36 | 37 | @var checkbox hideAds ` Usuń reklamy` 1 38 | @var checkbox hideRecommendedLinks ` Ukryj znaleziska "Wykop Poleca"` 1 39 | @var checkbox hideSponsoredLinks ` Ukryj znaleziska "Wykop Sponsorowany"` 1 40 | ==/UserStyle== */ 41 | 42 | @-moz-document domain("wykop.pl") 43 | { 44 | if(hideAds) 45 | { 46 | .pub-slot-wrapper { display: none!important; } 47 | .pub-slot-wrapper:has(section.premium-pub.link-block) { display: flex!important; } 48 | } 49 | if(hideSponsoredLinks) 50 | { 51 | .pub-slot-wrapper:has(section.premium-pub.link-block) { display: none!important; } 52 | } 53 | if(hideRecommendedLinks) 54 | { 55 | section.stream section.link-block:has(li.recommend-label) { display: none!important; } 56 | } 57 | } 58 | 59 | 60 | -------------------------------------------------------------------------------- /Wykop XS/wykop_xs_obrazki.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name Wykop XS - Obrazki+ 3 | // @name:pl Wykop XS - Obrazki+ 4 | // @name:en Wykop XS - Images+ 5 | 6 | // @version 3.0.81 7 | 8 | // @description Otwiera obrazki z wykopu poprzez www.wykopx.pl - z dodatkowymi funkcjami. Otwórz dowolny obrazek na wykopie i zamień w adresie URL 'wykop.pl' na 'wykopx.pl'. Obrazek możesz obrócić, odbić lustrzanie, udostępnić, skopiować, zapisać, włączyć pełny ekran. Oprócz przycisków masz też wygodne skróty klawiaturowe do każdej z tych akcji. | Wejdź na Mikroczat: https://mikroczat.pl Projekt Wykop X: https://wykopx.pl Wiki projektu Wykop X: https://wiki.wykopx.pl 9 | // @description:en Otwiera obrazki z wykopu poprzez www.wykopx.pl - z dodatkowymi funkcjami. Otwórz dowolny obrazek na wykopie i zamień w adresie URL 'wykop.pl' na 'wykopx.pl'. Obrazek możesz obrócić, odbić lustrzanie, udostępnić, skopiować, zapisać, włączyć pełny ekran. Oprócz przycisków masz też wygodne skróty klawiaturowe do każdej z tych akcji. | Wykop Live Chat: https://mikroczat.pl | Wykop X Project: https://wykopx.pl | Wiki: https://wiki.wykopx.pl 10 | 11 | 12 | // Chcesz wesprzeć projekt Wykop X? Postaw kawkę: 13 | // @contributionURL https://buycoffee.to/wykopx 14 | 15 | // @author Wykop X 16 | 17 | 18 | 19 | 20 | 21 | 22 | // @run-at document-start 23 | 24 | // @match https://wykop.pl/cdn/* 25 | // @supportURL http://wykop.pl/tag/wykopx 26 | // @namespace Violentmonkey Scripts 27 | // @compatible chrome, firefox, opera, safari, edge 28 | // @license No License 29 | // @icon https://www.google.com/s2/favicons?sz=64&domain=wykop.pl 30 | 31 | 32 | // @inject-into page 33 | // ==/UserScript== 34 | document.documentElement.style.backgroundColor = "rgb(18, 18, 20)"; 35 | document.documentElement.style.borderTop = "48px solid rgb(60, 60, 60)"; 36 | 37 | const body = document.querySelector("body"); 38 | if (body) 39 | { 40 | const img = body.querySelector("img"); 41 | img.style.display = "none"; 42 | img.style.opacity = "0"; 43 | body.style.backgroundColor = "rgb(18, 18, 20)"; 44 | body.style.overflow = "hidden"; 45 | } 46 | if (unsafeWindow.location.href.startsWith("https://wykop.pl/cdn/")) 47 | { 48 | unsafeWindow.location.replace(unsafeWindow.location.href.replace("https://wykop.pl", "https://wykopx.pl")); 49 | } 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Wykop X 2 | 3 | 17 | 18 | **Wykop X** to połączenie kilku dodatków - arkuszy stylów CSS **Wykop X Style** oraz skryptów JavaScript **Wykop XS** 19 | 20 | **Wykop X** dodaje aż kilkaset usprawnień dla strony wykop.pl - nowe funkcje, naprawianie Wykopowych błędów, zmiana intefejsu czy kolorystyki. 21 | Zerknij na listę wszystkich funkcji: 22 | https://github.com/wykopx/WykopX/wiki/Lista-funkcji 23 | 24 | Informacje takie jak: 25 | - instrukcja dotycząca instalacji i działania stylu **Wykop X Style** oraz skryptu **Wykop XS** 26 | - lista wszystkich funkcji 27 | - opis działania wybranych, najciekawszych funkcji 28 | - changelog 29 | 30 | ...dostępne są w Wiki projektu: 31 | - https://github.com/wykopx/WykopX/wiki 32 | 33 | Lista wykopowych aplikacji, skryptów i botów: 34 | - https://github.com/wykopx/Aplikacje-wykopowe/wiki/Aplikacje 35 | 36 | 37 | *** 38 | Chcesz wesprzeć i wysłać kilka złotych za dobrą robotę? 39 | 💲 Możesz postawić mi kawkę ☕ na [https://buycoffee.to/wykopx](https://buycoffee.to/wykopx) 💲 40 | *** 41 | 42 | 43 | Skrypty JavaScript 44 | - **Wykop XS** https://greasyfork.org/en/scripts/458860-wykop-xs 45 | - **Wykop XS - XHR Blocker** https://greasyfork.org/en/scripts/486722-wykop-xs-xhr-blocker 46 | 47 | Style CSS: 48 | - **Wykop X Style**: https://userstyles.world/style/8174/wykop-x-style 49 | 50 | - **Wykop X Blank** https://userstyles.world/style/8419/wykop-x-blank 51 | 52 | 53 | 54 | 55 | 56 | Propozycje nowych funkcji można zgłaszać tutaj: 57 | [Wykop X Project Dashboard](https://github.com/users/wykopx/projects/1/views/1?filterQuery=-status%3A%22%E2%9C%85+Done%22++-status%3A%22%E2%9B%94+No%2C+no%2C+no%22+&groupedBy%5BcolumnId%5D=Status) 58 | 59 | 60 | Możesz też tu zobaczyć nad czym obecnie pracuję i co pojawi się w przyszłych wersjach Wykop X 61 | 62 | 63 | Autorski tag dotyczący Wykop X: 64 | http://wykop.pl/tag/wykopwnowymstylu 65 | -------------------------------------------------------------------------------- /Wykop X Style/dummy_classes.css: -------------------------------------------------------------------------------- 1 | /* dummyClass - https://github.com/openstyles/stylus/issues/1719 */ 2 | 3 | /* WPISY - przypiete na stronie głównej */ 4 | main.main > section > div.content > section.home-page > section.home > section.stream > div.content > section.entry 5 | /* WPISY */ 6 | main.main > section > div.content > section.bucket-page > section.microblog > section.stream > div.content > section.entry, 7 | main.main > section > div.content > section.category-page > section.microblog > section.stream > div.content > section.entry, 8 | main.main > section > div.content > section.search-page > section.search > section > section.stream > div.content > section.entry, 9 | main.main > section > div.content > section.favourites-page > section.favourites > section.stream > div.content > section.entry, 10 | main.main > section > div.content > section.observed-page > section.observed > section.stream > div.content > section.entry, 11 | main.main > section > div.content > section.profile-page > section.profile > section > section.stream > div.content > section.entry, 12 | main.main > section > div.content > section.tag-page > section.stream > article > section.stream > div.content > section.entry, 13 | 14 | main.main > section > div.content > section.microblog-page > section.microblog > section.stream > div.content > section.entry 15 | /* WPISY :is() */ 16 | main.main > section > div.content > section:is(.bucket-page, .category-page, .favourites-page, .home-page, .observed-page, .profile-page, .tag-page, .microblog-page) > section section.stream > div.content > section.entry main.main > section > div.content > section:is(.bucket-page, .category-page, .favourites-page, .home-page, .observed-page, .profile-page, .tag-page, .microblog-page) > section section.stream > div.content > section.entry:not(.own) main.main > section > div.content > section.search-page > section section.stream > div.content section.entry:not(.own) 17 | /* przy uzywaniu dwoch selektorow jeden po drugim, dodac .dummyClassX - https://github.com/openstyles/stylus/issues/1719 */ 18 | 19 | /* WPISY W SIDEBARZE: */ 20 | main.main > section > section.sidebar > section.custom-sidebar > div.content > section.entries > section.entry 21 | /* ZNALEZISKA */ 22 | main.main > section > div.content > section.bucket-page > section.bucket > section.stream > div.content > section.link-block, 23 | main.main > section > div.content > section.category-page > section.category > section.stream > div.content > section.link-block, 24 | main.main > section > div.content > section.search-page > section.search > section > section.stream > div.content > section.link-block, 25 | main.main > section > div.content > section.favourites-page > section.favourites > section.stream > div.content > section.link-block, 26 | main.main > section > div.content > section.observed-page > section.observed > section.stream > div.content > section.link-block, 27 | main.main > section > div.content > section.profile-page > section.profile > section > section.stream > div.content > section.link-block, 28 | main.main > section > div.content > section.tag-page > section.stream > article > section.stream > div.content > section.link-block, 29 | main.main > section > div.content > section.home-page > section.home > section.stream > div.content > section.link-block, 30 | main.main > section > div.content > section.hits-page > section.hits > section.stream > div.content > section.link-block, 31 | main.main > section > div.content > section.upcoming-page > section.upcoming > section.stream > div.content > section.link-block, 32 | 33 | main.main > section > div.content > section:is(.bucket-page, .search-page, .category-page, .favourites-page, .home-page, .observed-page, .profile-page, .tag-page, .hits-page, .upcoming-page) > section section.stream > div.content > section.link-block 34 | {} -------------------------------------------------------------------------------- /Wykop XS/stylus.styl: -------------------------------------------------------------------------------- 1 | section > nav.mobile-navbar 2 | { 3 | padding: 0!important; 4 | } 5 | body > section:not(.is-mobile) main.main 6 | { 7 | width: 100% !important; 8 | max-width: unset !important; 9 | } 10 | 11 | 12 | section > nav.mobile-navbar > ul 13 | { 14 | border-radius: 0!important; 15 | display: flex!important; 16 | } 17 | section > nav.mobile-navbar > ul > li 18 | { 19 | background: var(--mobileNavbarButtonBackgroundColorInactive)!important; 20 | width: 100%!important; 21 | opacity: 0.6!important; 22 | border-top: 3px solid transparent!important; 23 | } 24 | 25 | section > nav.mobile-navbar > ul > li:hover 26 | { 27 | opacity: 1!important; 28 | } 29 | [data-night-mode] section > nav.mobile-navbar:hover > ul > li 30 | { 31 | background-color: rgb(60, 60, 60); 32 | } 33 | section > nav.mobile-navbar > ul > li:hover span:before 34 | { 35 | background: unset!important; 36 | } 37 | section > nav.mobile-navbar > ul > li.active 38 | { 39 | opacity: 1!important; 40 | border-color: var(--mobileNavbarButtonColorActive)!important; 41 | background: var(--mobileNavbarButtonBackgroundColorActive)!important; 42 | } 43 | section > nav.mobile-navbar > ul > li > a 44 | { 45 | display: block!important; 46 | height: 100%!important; 47 | width: 100%!important; 48 | color: white!important; 49 | } 50 | 51 | 52 | /* dodatkowe przyciski */ 53 | section > nav.mobile-navbar > ul > li > a > figure, 54 | section > nav.mobile-navbar > ul > li > a > span 55 | { 56 | display: block!important; 57 | height: 100%!important; 58 | width: 100%!important; 59 | background-repeat: no-repeat; 60 | background-position: 50% 50%; 61 | color: transparent!important; 62 | } 63 | section > nav.mobile-navbar > ul > li > a > figure 64 | { 65 | display: block!important; 66 | height: 100%!important; 67 | width: 100%!important; 68 | background-repeat: no-repeat!important; 69 | background-position: 50% 50%!important; 70 | } 71 | 72 | section > nav.mobile-navbar > ul > li > a > span 73 | { 74 | height: 100%!important; 75 | width: 100%!important; 76 | color: transparent!important; 77 | } 78 | section > nav.mobile-navbar > ul > li > a > span:hover 79 | { 80 | color: transparent!important; 81 | } 82 | 83 | section.is-mobile > nav.mobile-navbar > ul > li > a > span:before 84 | { 85 | width:100%!important; 86 | height: 100%!important; 87 | border-radius:0!important; 88 | } 89 | section.is-mobile > nav.mobile-navbar > ul > li > a > span:after 90 | { 91 | display: none!important; 92 | } 93 | section > nav.mobile-navbar > ul > li > a > span > i 94 | { 95 | display: none!important; 96 | } 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | /* BELKA MOBILNA - WIADOMOŚCI */ 105 | if(mobileNavBarMessagesButton == 1) 106 | { 107 | 108 | 109 | } 110 | 111 | 112 | /* BELKA MOBILNA - STRONA GŁÓWNA */ 113 | section > nav.mobile-navbar > ul > li.home > a > span 114 | { 115 | background-image: url('https://i.imgur.com/UQamDsQ.png'); 116 | } 117 | 118 | [data-night-mode] section > nav.mobile-navbar > ul > li.home > a > span 119 | { 120 | background-image: url('https://i.imgur.com/4wpzWuo.png'); 121 | } 122 | 123 | /* BELKA MOBILNA - WYKOPALISKO */ 124 | section > nav.mobile-navbar > ul > li.upcoming > a > span 125 | { 126 | background-image: url('https://i.imgur.com/UQamDsQ.png'); 127 | background-image: url('https://i.imgur.com/tYQMm7Q.png'); 128 | } 129 | 130 | [data-night-mode] section > nav.mobile-navbar > ul > li.upcoming > a > span 131 | { 132 | background-image: url('https://i.imgur.com/IeIwCWa.png'); 133 | } 134 | 135 | /* BELKA MOBILNA - MIKROBLOG */ 136 | section > nav.mobile-navbar > ul > li.microblog > a > span 137 | { 138 | background-image: url('https://i.imgur.com/OcgW9zq.png'); 139 | } 140 | 141 | [data-night-mode] section > nav.mobile-navbar > ul > li.microblog > a > span 142 | { 143 | background-image: url('https://i.imgur.com/DRyLFtj.png'); 144 | } -------------------------------------------------------------------------------- /Wykop XS/wykop----pagination.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | local_limit = 60; 10 | backend_limit = 50; 11 | total = 1000; 12 | 13 | 14 | 15 | 16 | local = 70 17 | 1 1 - 70[1, 2] 2(1 + 1) 18 | 2 71 - 140[2, 3] 19 | 3 141 - 210[3, 4] 20 | 21 | local - 120 22 | 1 1 - 120[1, 3] 3(1 + 2) 23 | 2 121 - 240[3, 5] 24 | 3 241 - 360[5, 8] 25 | 26 | 27 | local = 240 28 | 1 1 - 240[1, 5]-- 5(1 + 4) 29 | 2 241 - 480[5, 10] 6(1 + 5) 30 | 3 481 - 720[10, 15] 6(1 + 5) 31 | 32 | 33 | local = 250 34 | 1 1 - 250[1, 5]-- 5(1 + 4) 35 | 2 251 - 500[6, 10] 36 | 3 501 - 750[11, 15] 37 | 38 | 39 | 40 | backend - 50 41 | 42 | 1 1 - 50 43 | 2 51 - 100 44 | 3 101 - 150 45 | 4 151 - 200 46 | 5 201 - 250 47 | 6 251 - 300 48 | 7 301 - 350 49 | 8 351 - 400 50 | 9 401 - 450 51 | 10 450 - 500 52 | 11 501 - 550 53 | 12 551 - 600 54 | 13 601 - 650 55 | 14 651 - 700 56 | 15 701 - 750 57 | 58 | // x = n * (per_page / 50) - 1 59 | 60 | x = (n - 1 * 3) + 1 61 | n 62 | 1 1 1 - 50 51 - 100 101 - 150 63 | 2 151 4 151 - 200 201 - 250 251 - 300 64 | 3 301 7 301 65 | 4 450 10 66 | 67 | 68 | 100 50 69 | 70 | // x = n * (per_page / 50) - 1 71 | 72 | n 73 | 1 1 74 | 2 3 75 | 3 5 76 | 4 7 77 | 5 9 78 | 6 11 79 | 80 | 81 | 20 50 82 | 1 1 - 20 1 83 | 2 21 - 40 1 84 | 3 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | // local_limit = 100 94 | // local.page=1 => backend.page=1 95 | // local.items.first = 1 => backend.items.firs = 1 96 | // local.items.last = 100 => backend.items.last = 50 97 | 98 | // local.page=1 => backend.page=2 99 | // local.items.first = 1 => backend.items.firs = 51 100 | // local.items.last = 100 => backend.items.last = 100 101 | 102 | // local.page=2 => backend.page=3 103 | // local.items.first = 101 => backend.items.firs = 101 104 | // local.items.last = 200 => backend.items.last = 150 105 | 106 | // local.page = 2 => backend.page = 4 107 | // local.items.first = 101 => backend.items.firs = 151 108 | // local.items.last = 200 => backend.items.last = 200 109 | 110 | // local.page = 3 => backend.page = 5 111 | // local.items.first = 201 => backend.items.firs = 201 112 | // local.items.last = 300 => backend.items.last = 250 113 | 114 | 115 | // local.page = 4 => backend.page = 7 116 | // local.items.first = 301 => backend.items.firs = 301 117 | // local.items.last = 400 => backend.items.last = 350 118 | 119 | 120 | 121 | 122 | // local_limit = 60 123 | // local.page=1 => backend.page=1 124 | // local.items.first = 1 => backend.items.firs = 1 125 | // local.items.last = 60 => backend.items.last = 50 126 | 127 | // local.page=1 => backend.page=2 128 | // local.items.first = 1 => backend.items.firs = 51 129 | // local.items.last = 60 => backend.items.last = 100 130 | 131 | // local.page=2 => backend.page=3 132 | // local.items.first = 61 => backend.items.firs = 101 133 | // local.items.last = 120 => backend.items.last = 150 134 | 135 | // local.page = 2 => backend.page = 4 136 | // local.items.first = 101 => backend.items.firs = 151 137 | // local.items.last = 200 => backend.items.last = 200 138 | 139 | // local.page = 3 => backend.page = 5 140 | // local.items.first = 201 => backend.items.firs = 201 141 | // local.items.last = 300 => backend.items.last = 250 142 | 143 | function returnLocalFromBackend(backend) 144 | { 145 | const local = 146 | { 147 | page: Math.ceil(backend.page / (local_limit / backend_limit)), 148 | 149 | item: 150 | { 151 | first: (local.page - 1) * local_limit + 1, 152 | last: Math.min(local.page * local_limit, total) 153 | } 154 | } 155 | 156 | return local; 157 | } 158 | 159 | 160 | function returnBackendFromLocal(local) 161 | { 162 | const backend = { 163 | page: Math.ceil(local.page * (local_limit / backend_limit)), 164 | item: { 165 | first: (backend.page - 1) * backend_limit + 1, 166 | last: Math.min(backend.page * backend_limit, total) 167 | } 168 | }; 169 | 170 | return backend; 171 | } 172 | 173 | 174 | -------------------------------------------------------------------------------- /Wykop X Bookmarklets/odcenzuruj.js: -------------------------------------------------------------------------------- 1 | javascript: (function () 2 | { 3 | var url = new URL(location.href); 4 | if (url.hostname === "wykop.pl") 5 | { 6 | function replaceCensoredWords(text, censoredMap) 7 | { 8 | for (let [key, value] of censoredMap) 9 | { 10 | text = text.replace(new RegExp(key, 'gi'), value); 11 | } 12 | return text; 13 | } 14 | 15 | let censored = new Map(); 16 | censored.set("a-----l", "alkohol"); 17 | censored.set("a--------a", "amfetamina"); 18 | censored.set("a--------y", "amfetaminy"); 19 | censored.set("b--m", "bdsm"); 20 | censored.set("b---t", "biust"); 21 | censored.set("b-----b", "blowjob"); 22 | censored.set("b---a", "bomba"); 23 | censored.set("b---ę", "bombę"); 24 | censored.set("b---e", "bombe"); 25 | censored.set("b---y", "bomby"); 26 | censored.set("b---s", "boobs"); 27 | censored.set("b--ń", "broń"); 28 | censored.set("b----l", "burdel"); 29 | censored.set("b----c", "bzykac"); 30 | censored.set("b----ć", "bzykać"); 31 | censored.set("b------o", "bzykanko"); 32 | censored.set("c-d", "cbd"); 33 | censored.set("c--j", "chój"); 34 | censored.set("c--j", "chuj"); 35 | censored.set("c--a", "cipa"); 36 | censored.set("c------a", "cipeczka"); 37 | censored.set("c---a", "cipka"); 38 | censored.set("c-c", "cyc"); 39 | censored.set("c--e", "cyce"); 40 | censored.set("c---i", "cycki"); 41 | censored.set("c------i", "cycuszki"); 42 | censored.set("d--------e", "dieselgate"); 43 | censored.set("d---o", "dildo"); 44 | censored.set("d----s", "donbas"); 45 | censored.set("d-------e", "dopalacze"); 46 | censored.set("d---i", "dragi"); 47 | censored.set("d---s", "drags"); 48 | censored.set("d--a", "dupa"); 49 | censored.set("d----a", "dupcia"); 50 | censored.set("d------a", "dupeczka"); 51 | censored.set("d------i", "dupeczki"); 52 | censored.set("d--y", "dupy"); 53 | censored.set("d----a", "dziwka"); 54 | censored.set("e-----y", "ecstasy"); 55 | censored.set("e-------e", "erotyczne"); 56 | censored.set("e-------y", "erotyczny"); 57 | censored.set("e--------m", "erotycznym"); 58 | censored.set("e-----a", "erotyka"); 59 | censored.set("f-----m", "faszyzm"); 60 | censored.set("f----z", "fetysz"); 61 | censored.set("g------a", "gówniana"); 62 | censored.set("g---o", "gówno"); 63 | censored.set("g--------l", "gwałciciel"); 64 | censored.set("g---t", "gwałt"); 65 | censored.set("h-----z", "haszysz"); 66 | censored.set("h------u", "haszyszu"); 67 | censored.set("h----d", "hazard"); 68 | censored.set("h-----a", "heroina"); 69 | censored.set("h-----y", "heroiny"); 70 | censored.set("h-j", "huj"); 71 | censored.set("j---a", "jądra"); 72 | censored.set("j---a", "jajca"); 73 | censored.set("j---ć", "jebać"); 74 | censored.set("j---c", "jebac"); 75 | censored.set("j-----e", "jebanie"); 76 | censored.set("j----y", "jebany"); 77 | censored.set("j-----m", "jebanym"); 78 | censored.set("k--------m", "kanibalizm"); 79 | censored.set("k-----a", "kokaina"); 80 | censored.set("k-----y", "kokainy"); 81 | censored.set("k--s", "koks"); 82 | censored.set("k------z", "koksiarz"); 83 | censored.set("k----m", "kondom"); 84 | censored.set("k---a", "kórwa"); 85 | censored.set("k-----a", "kurewka"); 86 | censored.set("k---a", "kurwa"); 87 | censored.set("k---y", "kurwy"); 88 | censored.set("m-------a", "marihuana"); 89 | censored.set("m------n", "mefedron"); 90 | censored.set("m-------u", "mefedronu"); 91 | censored.set("m--f", "milf"); 92 | censored.set("m----n", "murzyn"); 93 | censored.set("n-----c", "najebac"); 94 | censored.set("n-----ć", "najebać"); 95 | censored.set("n------e", "najebane"); 96 | censored.set("n------i", "najebani"); 97 | censored.set("n---d", "naked"); 98 | censored.set("n------n", "narkoman"); 99 | censored.set("n-------a", "narkomana"); 100 | censored.set("n--------a", "narkomanka"); 101 | censored.set("n--------ę", "narkomankę"); 102 | censored.set("n------k", "narkotyk"); 103 | censored.set("n-------i", "narkotyki"); 104 | censored.set("n-------m", "neonazizm"); 105 | censored.set("n--e", "nude"); 106 | censored.set("o----m", "orgazm"); 107 | censored.set("p-------y", "papierosy"); 108 | censored.set("p-----l", "pedofil"); 109 | censored.set("p-------a", "pedofilia"); 110 | censored.set("p-------w", "pedofilów"); 111 | censored.set("p---s", "penis"); 112 | censored.set("p-----m", "penisem"); 113 | censored.set("p----i", "piersi"); 114 | censored.set("p--o", "piwo"); 115 | censored.set("p-----y", "playboy"); 116 | censored.set("p------y", "pojebany"); 117 | censored.set("p---r", "poker"); 118 | censored.set("p-----b", "pornhub"); 119 | censored.set("p---o", "porno"); 120 | censored.set("p----------a", "prezerwatywa"); 121 | censored.set("p----------y", "prezerwatywy"); 122 | censored.set("p---------a", "prostytucja"); 123 | censored.set("p-------a", "prostytutka"); 124 | censored.set("p-----c", "przemoc"); 125 | censored.set("p--a", "pupa"); 126 | censored.set("p----e", "pupcie"); 127 | censored.set("p--y", "pupy"); 128 | censored.set("r----c", "ruchac"); 129 | censored.set("r----ć", "ruchać"); 130 | censored.set("r------o", "ruchanko"); 131 | censored.set("r--ź", "rzeź"); 132 | censored.set("s-----a", "sadysta"); 133 | censored.set("s-------a", "samobójca"); 134 | censored.set("s---------o", "samobójstwo"); 135 | censored.set("s--s", "seks"); 136 | censored.set("s-x", "sex"); 137 | censored.set("s-------n", "skurwysyn"); 138 | censored.set("s----a", "sperma"); 139 | censored.set("s-------ć", "spieprzyć"); 140 | censored.set("s--------i", "spieprzyli"); 141 | censored.set("s---------m", "spieprzyłam"); 142 | censored.set("s---------m", "spieprzyłem"); 143 | censored.set("s---------a", "strzelanina"); 144 | censored.set("t------i", "tyłeczki"); 145 | censored.set("t----k", "tyłek"); 146 | censored.set("u----i", "używki"); 147 | censored.set("w----a", "wagina"); 148 | censored.set("w----ę", "waginę"); 149 | censored.set("w-----y", "whiskey"); 150 | censored.set("w----y", "whisky"); 151 | censored.set("w------r", "wibrator"); 152 | censored.set("w---a", "wódka"); 153 | censored.set("t---k", "tyłek"); 154 | censored.set("z----l", "zoofil"); 155 | censored.set("z------a", "zoofilia"); 156 | 157 | const wrappers = document.querySelectorAll('div.wrapper'); 158 | wrappers.forEach(wrapper => 159 | { 160 | wrapper.innerHTML = replaceCensoredWords(wrapper.innerHTML, censored); 161 | }); 162 | } 163 | else if (url.hostname === "mikroczat.pl") 164 | { 165 | 166 | } 167 | else 168 | { 169 | window.open("https://wykopx.pl/m"); 170 | } 171 | })(); 172 | /* 173 | v.1.0.1 174 | 175 | 1. Skopiuj cały kod tego skryptu 176 | 2. Wciśnij na dowolnej stronie CTRL+D aby otworzyć okno dodawania Ulubionej/Zakładki/Bookmark 177 | 3. W polu adresu URL usuń adres strony na której jesteś i wklej cały skopiowany powyżej kod 178 | 4. Ustaw dowolną nazwą np. 'Wykop' albo 'WX' 179 | 4. Gotowe. 180 | 181 | Aby skorzystać z Bookmarklet Wykop X po prostu kliknij 182 | - na dowolnej stronie wykopu z ocenzurowanymi wpisami i komentarzami 183 | */ 184 | // Bookmarklet Wykop X odcenzoruje wszystkie wpisy i komentarze 185 | -------------------------------------------------------------------------------- /Wykop XS - skrypty do konsoli/wykop_xs_czyszczenie_listy_obserwowanych_dyskusji.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | ----- Zapraszam na tag #wykopx ----- 3 | 4 | TEN SKRYPT SŁUŻY DO WYCZYSZCZENIA LISTY OBSERWOWANYCH DYSKUSJI 5 | Jeśli nie wiesz jak z niego skorzystać, przeczytaj instrukcję poniżej. 6 | 7 | UWAGA! TEN SKRYPT NIE JEST SKRYPTEM DO ViolentMonkey/TamperMonkey 8 | KOD TEGO SKRYPTU NALEŻY WKLEIĆ GO DO KONSOLI [CTRL + SHIFT + C] 9 | 10 | INSTRUKCJA: 11 | 1. wejdź na dowolną stronę wykop.pl 12 | 13 | 2. otwórz konsolę skrótem [CTRL + SHIFT + C] lub klawiszem [F12] 14 | 15 | 3. wpisz w konsoli `allow-pasting` (razem z cudzysłowami ` `) i wciśnij [ENTER] 16 | 17 | 4. wklej CAŁY poniższy kod i wciśnij [ENTER] 18 | 19 | 5. Na górnej belce Wykopu pojawi się nowy przycisk, który po kliknięciu: 20 | 21 | - sprawdzi ile dyskusji obserwujesz 22 | - w kilku krokach pozwoli ci wybrać czy chcesz usunąć obserwowane wpisy/znaleziska/komentarze 23 | - zdecydujesz czy chcesz również usuwać dyskusje, które dodałeś do Ulubionych 24 | (jeśli chcesz, aby niektóre obserwowane dyskusje nie były usunięte - dodaj je wcześniej do ulubionych) 25 | - w ostatnim kroku masz możliwość rezygnacji - nic nie zostanie wtedy usunięte 26 | 27 | - w trakcie usuwania pasek postępu pokazywany jest w adresie URL na przykład: 28 | https://wykop.pl/tag/wykopx/#--usunięto: 178/180 (99%) 29 | 30 | 31 | Lista dyskusji, które obserwujesz znajduje się tutaj: 32 | https://wykop.pl/obserwowane/dyskusje 33 | 34 | Wersja zminimalizowana tego skryptu gotowa do wklejenia= w konsoli: 35 | https://raw.githubusercontent.com/wykopx/WykopX/refs/heads/main/Wykop%20XS%20-%20skrypty%20do%20konsoli/wykop_xs_czyszczenie_listy_obserwowanych_dyskusji.min.js 36 | 37 | Pełna wersja tego skryptu tutaj: 38 | https://github.com/wykopx/WykopX/blob/main/Wykop%20XS%20-%20skrypty%20do%20konsoli/wykop_xs_czyszczenie_listy_obserwowanych_dyskusji.js 39 | 40 | Chcesz wesprzeć projekt Wykop X? Postaw kawę: 41 | 42 | @contributionURL https://buycoffee.to/wykopx 43 | 44 | @author Wykop X 45 | @License No License 46 | @version 1.0.2 47 | 48 | ----- Zapraszam na tag #wykopx ----- 49 | */ 50 | let observedLinks = 0, observedLinksFavourited = 0, observedEntries = 0, observedEntriesFavourited = 0, observedLinkComments = 0, observedLinkCommentsFavourited = 0, deleteEntries = !0, deleteLinks = !0, deleteLinkComments = !0, dontDeleteFavourites = !0, totalToDelete = 0; async function fetchObservedDiscussionData() { const e = localStorage.getItem("token"); if (!e) return new Map; const o = new Map; async function n(n = "") { const t = "https://wykop.pl/api/v3/observed/discussions" + (n ? `?page=${n}` : ""), s = await fetch(t, { headers: { Authorization: `Bearer ${e}` } }); if (!s.ok) return null; const i = await s.json(); return i.data.forEach((e => { o.set(e.object.id, e), "entry" == e.object.resource ? (observedEntries++, e.object.favourite && observedEntriesFavourited++) : "link" == e.object.resource ? (observedLinks++, e.object.favourite && observedLinksFavourited++) : "link_comment" == e.object.resource && (observedLinkComments++, e.object.favourite && observedLinkCommentsFavourited++) })), i.pagination.next } let t = await n(); for (let e = 0; t; e++)t = await n(t), await delay(100); return o } function delay(e) { return new Promise((o => setTimeout(o, e))) } async function deleteSelectedFromMap(e) { const o = localStorage.getItem("token"); if (!o) return; const n = new URL(window.location.href); n.pathname = "/tag/wykopx", window.history.pushState({}, "", n); let t = 0; for (const [n, s] of e) { let e = ""; if ("entry" == s.object.resource && deleteEntries ? e = `https://wykop.pl/api/v3/entries/${s.object.id}/observed-discussions` : "link" == s.object.resource && deleteLinks ? e = `https://wykop.pl/api/v3/links/${s.object.id}/observed-discussions` : "link_comment" == s.object.resource && deleteLinkComments && (e = `https://wykop.pl/api/v3/links/${s.object.parent.id}/comments/${s.object.id}/observed-discussions`), s.object.favourite && dontDeleteFavourites && (e = ""), "" !== e) { t++; await fetch(e, { method: "DELETE", headers: { Authorization: `Bearer ${o}` } }); await delay(170) } 0; const n = `--usunieto:${t}/${totalToDelete}_(${Math.ceil(100 * t / totalToDelete)}%)`; window.location.hash = n } } async function wykopx() { observedLinks = 0, observedLinksFavourited = 0, observedEntries = 0, observedEntriesFavourited = 0, observedLinkComments = 0, observedLinkCommentsFavourited = 0, deleteEntries = !1, deleteLinks = !1, deleteLinkComments = !1, dontDeleteFavourites = !0, totalToDelete = 0; let e = 0, o = 7; alert(`KROK ${++e}/7\nWykop X przeanalizuje teraz obserwowane przez Ciebie dyskusje \n\n> Kliknij [OK] i poczekaj kilka sekund.\n\nSpokojnie, jeszcze nie usuwamy obserwowanych dyskusji.\nPrzejdziemy do tego w następnych krokach.`), fetchObservedDiscussionData().then((n => { if (0 === n.size) o = 1, alert(`KROK ${++e}/${o}\n\nWykop X przeanalizował Twoje obserwowane:\n- Nie obserwujesz żadnych dyskusji`); else { 0 == observedEntries && o--, 0 == observedLinks && o--, 0 == observedLinkComments && o--, alert(`KROK ${++e}/${o}\n- Obserwujesz łącznie: (${n.size}) dyskusji\n- Limit obserwowanych dyskusji na wykopie wynosi (1000)\n\nObserwujesz:\n- (${observedEntries}) wpisów na mikroblogu w tym (${observedEntriesFavourited}) wpisów ⭐ Ulubionych\n- (${observedLinks}) znalezisk w tym (${observedLinksFavourited}) znalezisk ⭐ Ulubionych\n- (${observedLinkComments}) komentarzy w znaleziskach w tym (${observedLinkCommentsFavourited}) komentarzy ⭐ Ulubionych\n\n> Kliknij [OK] aby kontynuować`), dontDeleteFavourites = confirm(`KROK ${++e}/${o}\nMożesz teraz wybrać czy chcesz, POMINĄĆ usuwanie dyskusji, które masz oznaczone jako "⭐ Ulubione"\n\n> [OK] jeśli chcesz, żeby 🌟 Ulubione dyskusje NIE ZOSTAŁY USUNIĘTE\n\n> [Anuluj] jeśli CHCESZ USUNĄĆ również 🌟 Ulubione dyskusje`); let t = dontDeleteFavourites ? observedEntries - observedEntriesFavourited : observedEntries, s = dontDeleteFavourites ? observedLinks - observedLinksFavourited : observedLinks, i = dontDeleteFavourites ? observedLinkComments - observedLinkCommentsFavourited : observedLinkComments; t > 0 && (deleteEntries = confirm(`KROK ${++e}/${o}\nCzy chcesz usunąć (${t}) obserwowanych WPISÓW NA MIKROBLOGU?\n\n> [OK] jeśli chcesz, żeby WPISY zostały usunięte z obserwowanych\n\n> [Anuluj] jeśli nie chcesz usuwać obserwowanych WPISÓW`)), s > 0 && (deleteLinks = confirm(`KROK ${++e}/${o}\nCzy chcesz usunąć (${s}) obserwowanych ZNALEZISK?\n\n> [OK] jeśli chcesz, żeby ZNALEZISKA zostały usunięte z obserwowanych\n\n> [Anuluj] jeśli nie chcesz usuwać obserwowanych ZNALEZISK`)), i > 0 && (deleteLinkComments = confirm(`KROK ${++e}/${o}\nCzy chcesz usunąć (${i}) obserwowanych KOMENTARZY W ZNALEZISKACH?\n\n> [OK] jeśli chcesz, żeby KOMENTARZE W ZNALEZISKACH zostały usunięte z obserwowanych\n\n> [Anuluj] jeśli nie chcesz usuwać obserwowanych KOMENTARZY W ZNALEZISKACH`)), deleteEntries || (t = 0), deleteLinks || (s = 0), deleteLinkComments || (i = 0), totalToDelete = t + s + i; let r = `⚠ KROK ${++e}/${o} - USUWANIE ⚠ \nPo kliknięciu w [OK] ROZPOCZNIE SIĘ USUWANIE!\n\nWykop X usunie:`; if (t > 0 && (r += `\n- (${t}) obserwowanych wpisów ${dontDeleteFavourites ? "(bez ulubionych)" : "w tym także ulubione"}`), s > 0 && (r += `\n- (${s}) obserwowanych znalezisk ${dontDeleteFavourites ? "(bez ulubionych)" : "w tym także ulubione"}`), i > 0 && (r += `\n- (${i}) obserwowanych komentarzy w znaleziskach ${dontDeleteFavourites ? "(bez ulubionych)" : "w tym także ulubione"}`), r += `\n\nŁącznie usuniemy (${totalToDelete}) z (${n.size}) obserwowanych dyskusji.\n\n> [OK] aby USUNĄĆ (${totalToDelete}) obserwowanych dyskusji\n> [Anuluj] aby PRZERWAĆ proces usuwania.\n`, totalToDelete > 0) confirm(r) && deleteSelectedFromMap(n).then((() => { alert("Wszystkie wybrane dyskusje zostały usunięte."), window.location.hash = `(づ•﹏•)づ__usunięto_${totalToDelete}_z_${n.size}_obserwowanych_dyskusji` })); else { const e = new URL(window.location.href); e.pathname = "/tag/wykopx", window.history.pushState({}, "", e), window.location.hash = "(づ•﹏•)づ", confirm("⚠ KROK 21/37 ⚠\n\n\nNie to nie ( ͡° ͜ʖ ͡°)") } } })) } console.clear(); const button = document.createElement("button"); button.setAttribute("style", "position: fixed; top: 5px; left: 50%; z-index: 999; display: flex; color: rgb(255 255 255 / 0.6); border: 1px solid rgb(0 0 0 / 0.3); background-color: rgb(0 0 0 / 0.2); padding: 10px;"), button.textContent = "Usuń obserwowane dyskusje", document.body.insertBefore(button, document.body.firstChild), button.addEventListener("click", (async () => { await wykopx() })); 51 | /* Upewnij się, że zaznaczasz i kopiujesz cały kod skryptu */ -------------------------------------------------------------------------------- /Wykop X Style/wykop_x_style_ikonki_powiadomien.user.css: -------------------------------------------------------------------------------- 1 | /* ==UserStyle== 2 | @name Wykop X Style - ikonki powiadomień na wykopie 3 | @version 3.0.54 4 | 5 | 6 | @description Wykop X Style 7 | @description Ten styl to 900 różnych funkcji zmieniających wykop 8 | description https://styl.wykopx.pl 9 | 10 | 11 | @description Wykop X Style Blank 12 | @description W wersji BLANK wszystkie opcje są wyłączone 13 | @description https://blank.wykopx.pl 14 | 15 | 16 | @description Wykop XS 17 | @description Pomocniczy skrypt Wykop XS z dodatkowymi funkcjami 18 | @description https://skrypt.wykopx.pl 19 | 20 | @description ---- WYKOP X ---- 21 | @description http://wiki.wykopx.pl 22 | @description https://userstyles.world/style/8174/wykop-x-style-3 23 | 24 | 25 | 26 | ---- AUTOR WYKOP X ---- 27 | 28 | @author Wykop X | wiki.wykopx.pl 29 | @homepageURL http://wiki.wykopx.pl 30 | @supportURL http://wiki.wykopx.pl 31 | 32 | ---- AUTOR WYKOP X ---- 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | @preprocessor stylus 57 | @namespace userstyles.world/user/wykopchanger 58 | @license No License (YOU CAN USE THIS CODE ONLY IN STYLUS EXTENSIONS. You are NOT ALLOWED TO copy, share and use any part of this code anywhere else without author's written permission) 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | ==/UserStyle== */ 67 | 68 | 69 | 70 | 71 | 72 | @-moz-document url-prefix("https://wykop.pl") 73 | { 74 | hideAds = 1; 75 | hideSponsoredLinks = 1; 76 | 77 | if(hideAds == 1) 78 | { 79 | .pub-slot-wrapper { display: none!important; } 80 | .pub-slot-wrapper:has(section.premium-pub.link-block) { display: flex!important; } 81 | } 82 | if(hideSponsoredLinks == 1) 83 | { 84 | .pub-slot-wrapper:has(section.premium-pub.link-block) { display: none!important; } 85 | } 86 | 87 | :root 88 | { 89 | --userCustomColorAccent: rgb(57, 131, 175); /* Kolor wiodący */ 90 | 91 | /* POWIADOMIENIA */ 92 | --notificationIconActiveColor: var(--userCustomColorAccent); /* ikonka powiadomienia ✉ 🕭 #, która została kliknięta */ 93 | --notificationIconActiveBackgroundColor: rgba(255, 255, 255, 0.3); /* tło ikonki powiadomienia, która została kliknięta */ 94 | 95 | --inactiveButtonBackground: rgba(255, 255, 255, 0.4); 96 | /* ikonka z nowymi powiaodmieniami */ 97 | --notificationIconWithUnreadNotificationsColor: rgba(255, 255, 255, 0.8); /* ikonka powiadomienia ✉ 🕭 #, jesli sa nieprzeczytane */ 98 | --notificationIconWithUnreadNotificationsBackgroundColor: rgba(255, 255, 255, 0); /* tło powiadomienia ✉ 🕭 #, jesli sa nieprzeczytane */ 99 | --notificationIconWithUnreadNotificationsHoverColor: rgba(255, 255, 255, 1); 100 | --notificationIconWithUnreadNotificationsHoverBackgroundColor: rgba(255, 255, 255, 0.2); 101 | --notificationIconWithUnreadNotificationsActiveColor: rgba(255, 255, 255, 1); 102 | --notificationIconWithUnreadNotificationsActiveBackgroundColor: rgba(255, 255, 255, 0.3); 103 | 104 | /* powiadomienia */ 105 | --notificationIconWithoutUnreadNotificationsColor: rgba(255, 255, 255, 0.2); /* ikonka powiadomienia ✉ 🕭 #, jesli nie ma nowych powiadomien */ 106 | --notificationIconWithoutUnreadNotificationsBackgroundColor: rgba(255, 255, 255, 0); /* tło powiadomienia ✉ 🕭 #, jesli nie ma nowych powiadomien */ 107 | --notificationIconWithoutUnreadNotificationsHoverColor: rgba(255, 255, 255, 0.6); 108 | --notificationIconWithoutUnreadNotificationsHoverBackgroundColor: rgba(255, 255, 255, 0.2); 109 | --notificationIconWithoutUnreadNotificationsActiveColor: rgba(255, 255, 255, 0.6); 110 | --notificationIconWithoutUnreadNotificationsActiveBackgroundColor: rgba(255, 255, 255, 0.3); 111 | } 112 | 113 | 114 | if(fixNotificationBadgeBug == 1) 115 | { 116 | /* ukrycie badge z liczbą powiadomien jeśli wszystkie powiadomienia w okienku są przeczytane */ 117 | body > section:not(.is-mobile) > header.header div.right > nav ul li.notifications:not(:has( > section.dropdown-body > section.notifications > section.stream > div.content > section.notify:not(.read))) > a:after, 118 | body > section:not(.is-mobile) > header.header div.right > nav ul li.notifications:not(:has( > section.dropdown-body > section.notifications > section.stream > div.content > section.notify:not(.read))) > a:before, 119 | body > section:not(.is-mobile) > header.header div.right > nav ul li.pm:not(:has( > section.dropdown-body > section.stream > div.content > section.item.unread)) > a.new:after, 120 | body > section:not(.is-mobile) > header.header div.right > nav ul li.pm:not(:has( > section.dropdown-body > section.stream > div.content > section.item.unread)) > a.new:before 121 | { 122 | display: none!important; 123 | } 124 | /* naprawienie kolorów ikonek - brak nieprzeczytanych */ 125 | body > section:not(.is-mobile) > header.header div.right > nav ul li.notifications:not(:has( > section.dropdown-body > section.notifications > section.stream > div.content > section.notify:not(.read))) > a > div.svg-inline > svg, 126 | body > section:not(.is-mobile) > header.header div.right > nav ul li.pm:not(:has( > section.dropdown-body > section.stream > div.content > section.item.unread)) > a > div.svg-inline > svg 127 | { 128 | fill: var(--notificationIconWithoutUnreadNotificationsColor) !important; 129 | } 130 | body > section:not(.is-mobile) > header.header div.right > nav ul li.notifications:not(:has( > section.dropdown-body > section.notifications > section.stream > div.content > section.notify:not(.read))) > a, 131 | body > section:not(.is-mobile) > header.header div.right > nav ul li.pm:not(:has( > section.dropdown-body > section.stream > div.content > section.item.unread)) > a 132 | { 133 | background-color: var(--notificationIconWithoutUnreadNotificationsBackgroundColor) !important; 134 | } 135 | /* :hover */ 136 | body > section:not(.is-mobile) > header.header div.right > nav ul li.notifications:not(:has( > section.dropdown-body > section.notifications > section.stream > div.content > section.notify:not(.read))) > a:hover > div.svg-inline > svg, 137 | body > section:not(.is-mobile) > header.header div.right > nav ul li.pm:not(:has( > section.dropdown-body > section.stream > div.content > section.item.unread)) > a:hover > div.svg-inline > svg 138 | { 139 | fill: var(--notificationIconWithoutUnreadNotificationsHoverColor) !important; 140 | } 141 | body > section:not(.is-mobile) > header.header div.right > nav ul li.notifications:not(:has( > section.dropdown-body > section.notifications > section.stream > div.content > section.notify:not(.read))) > a:hover, 142 | body > section:not(.is-mobile) > header.header div.right > nav ul li.pm:not(:has( > section.dropdown-body > section.stream > div.content > section.item.unread)) > a:hover 143 | { 144 | background-color: var(--notificationIconWithoutUnreadNotificationsHoverBackgroundColor) !important; 145 | } 146 | /* otwarte menu */ 147 | body > section:not(.is-mobile) > header.header div.right > nav ul li.notifications.dropdown.active:not(:has( > section.dropdown-body > section.notifications > section.stream > div.content > section.notify:not(.read))) > a > div.svg-inline > svg, 148 | body > section:not(.is-mobile) > header.header div.right > nav ul li.pm.dropdown.active:not(:has( > section.dropdown-body > section.stream > div.content > section.item.unread)) > a > div.svg-inline > svg 149 | { 150 | fill: var(--notificationIconWithoutUnreadNotificationsActiveColor) !important; 151 | } 152 | body > section:not(.is-mobile) > header.header div.right > nav ul li.notifications.dropdown.active:not(:has( > section.dropdown-body > section.notifications > section.stream > div.content > section.notify:not(.read))) > a, 153 | body > section:not(.is-mobile) > header.header div.right > nav ul li.pm.dropdown.active:not(:has( > section.dropdown-body > section.stream > div.content > section.item.unread)) > a 154 | { 155 | background-color: var(--notificationIconWithoutUnreadNotificationsActiveBackgroundColor) !important; 156 | } 157 | } 158 | 159 | 160 | 161 | 162 | 163 | 164 | } -------------------------------------------------------------------------------- /Wykop XS/wykop_xs_banned.user.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name Wykop XS - Ban Info - Informacje o banach 3 | // @name:pl Wykop XS - Ban Info - Informacje o banach 4 | // @name:en Wykop XS - Ban Info 5 | 6 | // @version 3.0.81 7 | 8 | // @description Wykop XS - Informacje o banach na profilach zbanowanych użytkowników. Wykop X Style znajdziesz na: http://styl.wykopx.pl 9 | // @description:en Wykop XS - Shows precise info about banned users on Wykop.pl. Check out Wykop X Style here: http://styl.wykopx.pl 10 | 11 | 12 | // Chcesz wesprzeć projekt Wykop X? Postaw kawkę: 13 | // @contributionURL https://buycoffee.to/wykopx 14 | 15 | // @author Wykop X 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://cdn.jsdelivr.net/npm/dayjs@1.11.10/dayjs.min.js 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | // ==/UserScript== 42 | 43 | (async function () 44 | { 45 | 'use strict'; 46 | 47 | const currentVersion = "3.0.80"; 48 | let dev = false; 49 | 50 | const promoString = " - Wykop XS / #wykopx"; 51 | 52 | const root = document.documentElement; 53 | const head = document.head; 54 | const body = document.body; 55 | const bodySection = body.querySelector("section"); 56 | const wykopxSettings = getComputedStyle(head); 57 | const settings = {}; 58 | 59 | const styleElement = document.createElement('style'); 60 | styleElement.id = "wykopxs_ban_info"; 61 | let CSS = ""; 62 | 63 | function setSettingsValueFromCSSProperty(settingName, defaultValueForWykopXS = true, propertyValueInsteadOfBoolean = false) 64 | { 65 | if (propertyValueInsteadOfBoolean) settings[settingName] = wykopxSettings.getPropertyValue(`--${settingName}`) ? wykopxSettings.getPropertyValue(`--${settingName}`).trim() : defaultValueForWykopXS; 66 | else settings[settingName] = wykopxSettings.getPropertyValue(`--${settingName}`) ? wykopxSettings.getPropertyValue(`--${settingName}`).trim() === '1' : defaultValueForWykopXS; 67 | } 68 | 69 | setSettingsValueFromCSSProperty("WykopXSEnabled"); 70 | if (settings.WykopXSEnabled == false) return; 71 | /* WYKOP XS HEADER */ 72 | 73 | 74 | setSettingsValueFromCSSProperty("hideAds"); // blokuje wszystkie reklamy na wykopie 75 | 76 | 77 | let loadTime = dayjs(); 78 | 79 | // wykop_xs_banned.user.js - START - 1 80 | setSettingsValueFromCSSProperty("infoboxUserBannedInfoOnProfilePage"); 81 | // wykop_xs_banned.user.js - END - 1 82 | 83 | // wykop_xs_banned.user.js - START - 2 84 | if (settings.infoboxUserBannedInfoOnProfilePage) 85 | { 86 | waitForKeyElements("aside.profile-top:has(aside.info-box.red)", bannedUserProfileAside, false); 87 | 88 | // DODAJEMY INFO NA STRONIE PROFILOWEJ O SZCZEGÓŁACH BANA 89 | function bannedUserProfileAside(element) 90 | { 91 | const bannedUserObject = element?.__vue__?.user; 92 | 93 | if (!bannedUserObject) return; 94 | 95 | if (bannedUserObject.status == "banned" || bannedUserObject.status == "suspended") 96 | { 97 | bannedUserObject.banned.wxs_reason_lowercase = bannedUserObject.banned.reason.toLowerCase(); 98 | 99 | bannedUserObject.banned.wxs_ban_end_date_string = bannedUserObject.banned.expired; // "2024-01-04 17:22:31" / null 100 | if (bannedUserObject.banned.wxs_ban_end_date_string != null) 101 | { 102 | bannedUserObject.banned.wxs_ban_end_date_object = dayjs(bannedUserObject.banned.wxs_ban_end_date_string); 103 | bannedUserObject.banned.wxs_ban_end_in_years = bannedUserObject.banned.wxs_ban_end_date_object.diff(loadTime, 'year'); // 5 > koniec bana za "5" lat 104 | bannedUserObject.banned.wxs_ban_end_in_months = bannedUserObject.banned.wxs_ban_end_date_object.diff(loadTime, 'month'); // 3 > koniec bana za: "3" miesiące 105 | bannedUserObject.banned.wxs_ban_end_in_days = bannedUserObject.banned.wxs_ban_end_date_object.diff(loadTime, 'day'); // 31 > koniec bana za 31 dni 106 | bannedUserObject.banned.wxs_ban_end_in_days = bannedUserObject.banned.wxs_ban_end_date_object.diff(loadTime, 'day'); // 31 > koniec bana za 31 dni 107 | // banEndDateDuration = banEndDateObject.toNow() 108 | 109 | } 110 | 111 | 112 | 113 | const bannedRedBox = element.querySelector("aside.info-box.red p"); 114 | let bannedRedBoxInnerHTML = `To konto jest ${bannedUserObject.status == "suspended" ? "w trakcie usuwania" : "zbanowane"}.

Informacja z Wykop X - Ban Info:
`; 115 | 116 | // Ban permanentny 117 | if (bannedUserObject.status == "banned" && (bannedUserObject.banned.wxs_ban_end_date_string == null || bannedUserObject.banned.wxs_ban_end_in_years > 100)) 118 | { 119 | bannedRedBoxInnerHTML = `To konto jest zbanowane permanentnie.

Wykop XS Ban Info:
`; 120 | } 121 | 122 | 123 | // "Użytkowniczka @NadiaFrance dsotała bana za naruszenie regulaminu" 124 | if (bannedUserObject.status == "suspended") 125 | { 126 | bannedRedBoxInnerHTML += `${bannedUserObject.gender == "f" ? "Użytkowniczka @" + bannedUserObject.username + " rozpoczęła usuwanie konta" : "Użytkownik @" + bannedUserObject.username + " rozpoczął usuwanie konta"}`; 127 | } 128 | else 129 | { 130 | bannedRedBoxInnerHTML += `${bannedUserObject.gender == "f" ? "Użytkowniczka @" + bannedUserObject.username + " dostała" : "Użytkownik @" + bannedUserObject.username + " dostał"} bana za ${bannedUserObject.banned.wxs_reason_lowercase}`; 131 | } 132 | 133 | // Ban permanentny 134 | if (bannedUserObject.banned.wxs_ban_end_date_string == null || bannedUserObject.banned.wxs_ban_end_in_years > 100) 135 | { 136 | // Ban permanentny na 999 lat 137 | bannedRedBoxInnerHTML += `
Ban permanentny. Śpij słodko aniołku [*] `; 138 | } 139 | else 140 | { 141 | // "Koniec bana za 14 dni" 142 | bannedRedBoxInnerHTML += `
143 | Koniec bana ${bannedUserObject.banned.wxs_ban_end_in_years > 1 ? "za " + bannedUserObject.banned.wxs_ban_end_in_years + " lat(a)" : bannedUserObject.banned.wxs_ban_end_in_months > 1 ? "za " + bannedUserObject.banned.wxs_ban_end_in_months + " miesiące(ęcy)" : bannedUserObject.banned.wxs_ban_end_in_days > 1 ? "za " + bannedUserObject.banned.wxs_ban_end_in_days + " dni" : bannedUserObject.banned.wxs_ban_end_date_object.isSame(loadTime, 'day') == true ? " już dzisiaj! " : " jutro"}
`; 144 | // "Ban trwa do 2024-12-12 23:59:59" 145 | bannedRedBoxInnerHTML += `Ban trwa do ${bannedUserObject.banned.wxs_ban_end_date_string}
`; 146 | } 147 | 148 | bannedRedBox.innerHTML = bannedRedBoxInnerHTML; 149 | } 150 | } 151 | } 152 | // wykop_xs_banned.user.js - END - 2 153 | 154 | 155 | 156 | 157 | /* HIDE ADS ALWAYS */ 158 | if (settings.hideAds) { CSS += `.pub-slot-wrapper { display: none!important; }`; } 159 | 160 | /* HIDE WYKOP XS PROMO FROM STYLUS */ 161 | CSS += `.wykopxs, body div.main-content[class] section > section.sidebar::after { display: none!important; }`; 162 | 163 | styleElement.textContent = CSS; 164 | document.head.appendChild(styleElement); 165 | })(); 166 | 167 | 168 | // https://cdn.jsdelivr.net/gh/CoeJoder/waitForKeyElements.js@latest/waitForKeyElements.js 169 | /** 170 | * A utility function for userscripts that detects and handles AJAXed content. 171 | * 172 | * @example 173 | * waitForKeyElements("div.comments", (element) => { 174 | * element.innerHTML = "This text inserted by waitForKeyElements()."; 175 | * }); 176 | * 177 | * waitForKeyElements(() => { 178 | * const iframe = document.querySelector('iframe'); 179 | * if (iframe) { 180 | * const iframeDoc = iframe.contentDocument || iframe.contentWindow.document; 181 | * return iframeDoc.querySelectorAll("div.comments"); 182 | * } 183 | * return null; 184 | * }, callbackFunc); 185 | * 186 | * @param {(string|function)} selectorOrFunction - The selector string or function. 187 | * @param {function} callback - The callback function; takes a single DOM element as parameter. 188 | * If returns true, element will be processed again on subsequent iterations. 189 | * @param {boolean} [waitOnce=true] - Whether to stop after the first elements are found. 190 | * @param {number} [interval=300] - The time (ms) to wait between iterations. 191 | * @param {number} [maxIntervals=-1] - The max number of intervals to run (negative number for unlimited). 192 | */ 193 | function waitForKeyElements(selectorOrFunction, callback, waitOnce, interval, maxIntervals) 194 | { 195 | if (typeof waitOnce === "undefined") 196 | { 197 | waitOnce = true; 198 | } 199 | if (typeof interval === "undefined") 200 | { 201 | interval = 300; 202 | } 203 | if (typeof maxIntervals === "undefined") 204 | { 205 | maxIntervals = -1; 206 | } 207 | if (typeof waitForKeyElements.namespace === "undefined") 208 | { 209 | waitForKeyElements.namespace = Date.now().toString(); 210 | } 211 | var targetNodes = (typeof selectorOrFunction === "function") 212 | ? selectorOrFunction() 213 | : document.querySelectorAll(selectorOrFunction); 214 | 215 | var targetsFound = targetNodes && targetNodes.length > 0; 216 | if (targetsFound) 217 | { 218 | targetNodes.forEach(function (targetNode) 219 | { 220 | var attrAlreadyFound = `data-userscript-${waitForKeyElements.namespace}-alreadyFound`; 221 | var alreadyFound = targetNode.getAttribute(attrAlreadyFound) || false; 222 | if (!alreadyFound) 223 | { 224 | var cancelFound = callback(targetNode); 225 | if (cancelFound) 226 | { 227 | targetsFound = false; 228 | } 229 | else 230 | { 231 | targetNode.setAttribute(attrAlreadyFound, true); 232 | } 233 | } 234 | }); 235 | } 236 | 237 | if (maxIntervals !== 0 && !(targetsFound && waitOnce)) 238 | { 239 | maxIntervals -= 1; 240 | setTimeout(function () 241 | { 242 | waitForKeyElements(selectorOrFunction, callback, waitOnce, interval, maxIntervals); 243 | }, interval); 244 | } 245 | } -------------------------------------------------------------------------------- /Wykop XS/wykop_xs_ungroup_notifications.user.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name Wykop XS - Rozgrupuj powiadomienia 3 | // @name:pl Wykop XS - Rozgrupuj powiadomienia 4 | // @name:en Wykop XS - Ungroup notifications 5 | 6 | // @version 3.0.82 7 | 8 | // @description Wykop XS - Rozgrupuj powiadomienia | Wejdź na Mikroczat: https://mikroczat.pl Projekt Wykop X: https://wykopx.pl Wiki projektu Wykop X: https://wiki.wykopx.pl 9 | // @description:en Wykop XS - Ungroup notiications | Wykop Live Chat: https://mikroczat.pl | Wykop X Project: https://wykopx.pl | Wiki: https://wiki.wykopx.pl 10 | 11 | 12 | // Chcesz wesprzeć projekt Wykop X? Postaw kawkę: 13 | // @contributionURL https://buycoffee.to/wykopx 14 | 15 | // @author Wykop X 16 | 17 | 18 | 19 | // @match https://wykop.pl/* 20 | // @supportURL http://wykop.pl/tag/wykopx 21 | // @namespace Violentmonkey Scripts 22 | // @compatible chrome, firefox, opera, safari, edge 23 | // @license No License 24 | // @icon https://www.google.com/s2/favicons?sz=64&domain=wykop.pl 25 | 26 | 27 | 28 | 29 | // ==/UserScript== 30 | (async function () 31 | { 32 | 'use strict'; 33 | const currentVersion = "3.0.82"; 34 | let dev = false; 35 | const promoString = " - Wykop XS / #wykopx"; 36 | 37 | let xhook = null; 38 | //XHook - v1.6.2 - https://github.com/jpillora/xhook | Jaime Pillora - MIT Copyright 2023 39 | xhook = function () { "use strict"; const e = (e, t) => Array.prototype.slice.call(e, t); let t = null; "undefined" != typeof WorkerGlobalScope && self instanceof WorkerGlobalScope ? t = self : "undefined" != typeof global ? t = global : window && (t = window); const n = t, o = t.document, r = ["load", "loadend", "loadstart"], s = ["progress", "abort", "error", "timeout"], a = e => ["returnValue", "totalSize", "position"].includes(e), i = function (e, t) { for (let n in e) { if (a(n)) continue; const o = e[n]; try { t[n] = o } catch (e) { } } return t }, c = function (e, t, n) { const o = e => function (o) { const r = {}; for (let e in o) { if (a(e)) continue; const s = o[e]; r[e] = s === t ? n : s } return n.dispatchEvent(e, r) }; for (let r of Array.from(e)) n._has(r) && (t[`on${r}`] = o(r)) }, u = function (e) { if (o && null != o.createEventObject) { const t = o.createEventObject(); return t.type = e, t } try { return new Event(e) } catch (t) { return { type: e } } }, l = function (t) { let n = {}; const o = e => n[e] || [], r = { addEventListener: function (e, t, r) { n[e] = o(e), n[e].indexOf(t) >= 0 || (r = void 0 === r ? n[e].length : r, n[e].splice(r, 0, t)) }, removeEventListener: function (e, t) { if (void 0 === e) return void (n = {}); void 0 === t && (n[e] = []); const r = o(e).indexOf(t); -1 !== r && o(e).splice(r, 1) }, dispatchEvent: function () { const n = e(arguments), s = n.shift(); t || (n[0] = i(n[0], u(s)), Object.defineProperty(n[0], "target", { writable: !1, value: this })); const a = r[`on${s}`]; a && a.apply(r, n); const c = o(s).concat(o("*")); for (let e = 0; e < c.length; e++) { c[e].apply(r, n) } }, _has: e => !(!n[e] && !r[`on${e}`]) }; return t && (r.listeners = t => e(o(t)), r.on = r.addEventListener, r.off = r.removeEventListener, r.fire = r.dispatchEvent, r.once = function (e, t) { var n = function () { return r.off(e, n), t.apply(null, arguments) }; return r.on(e, n) }, r.destroy = () => n = {}), r }; var f = function (e, t) { switch (typeof e) { case "object": return n = e, Object.entries(n).map((([e, t]) => `${e.toLowerCase()}: ${t}`)).join("\r\n"); case "string": return function (e, t) { const n = e.split("\r\n"); null == t && (t = {}); for (let e of n) if (/([^:]+):\s*(.+)/.test(e)) { const e = null != RegExp.$1 ? RegExp.$1.toLowerCase() : void 0, n = RegExp.$2; null == t[e] && (t[e] = n) } return t }(e, t) }var n; return [] }; const d = l(!0), p = e => void 0 === e ? null : e, h = n.XMLHttpRequest, y = function () { const e = new h, t = {}; let n, o, a, u = null; var y = 0; const v = function () { if (a.status = u || e.status, -1 !== u && (a.statusText = e.statusText), -1 === u); else { const t = f(e.getAllResponseHeaders()); for (let e in t) { const n = t[e]; if (!a.headers[e]) { const t = e.toLowerCase(); a.headers[t] = n } } } }, b = function () { x.status = a.status, x.statusText = a.statusText }, g = function () { n || x.dispatchEvent("load", {}), x.dispatchEvent("loadend", {}), n && (x.readyState = 0) }, E = function (e) { for (; e > y && y < 4;)x.readyState = ++y, 1 === y && x.dispatchEvent("loadstart", {}), 2 === y && b(), 4 === y && (b(), "text" in a && (x.responseText = a.text), "xml" in a && (x.responseXML = a.xml), "data" in a && (x.response = a.data), "finalUrl" in a && (x.responseURL = a.finalUrl)), x.dispatchEvent("readystatechange", {}), 4 === y && (!1 === t.async ? g() : setTimeout(g, 0)) }, m = function (e) { if (4 !== e) return void E(e); const n = d.listeners("after"); var o = function () { if (n.length > 0) { const e = n.shift(); 2 === e.length ? (e(t, a), o()) : 3 === e.length && t.async ? e(t, a, o) : o() } else E(4) }; o() }; var x = l(); t.xhr = x, e.onreadystatechange = function (t) { try { 2 === e.readyState && v() } catch (e) { } 4 === e.readyState && (o = !1, v(), function () { if (e.responseType && "text" !== e.responseType) "document" === e.responseType ? (a.xml = e.responseXML, a.data = e.responseXML) : a.data = e.response; else { a.text = e.responseText, a.data = e.responseText; try { a.xml = e.responseXML } catch (e) { } } "responseURL" in e && (a.finalUrl = e.responseURL) }()), m(e.readyState) }; const w = function () { n = !0 }; x.addEventListener("error", w), x.addEventListener("timeout", w), x.addEventListener("abort", w), x.addEventListener("progress", (function (t) { y < 3 ? m(3) : e.readyState <= 3 && x.dispatchEvent("readystatechange", {}) })), "withCredentials" in e && (x.withCredentials = !1), x.status = 0; for (let e of Array.from(s.concat(r))) x[`on${e}`] = null; if (x.open = function (e, r, s, i, c) { y = 0, n = !1, o = !1, t.headers = {}, t.headerNames = {}, t.status = 0, t.method = e, t.url = r, t.async = !1 !== s, t.user = i, t.pass = c, a = {}, a.headers = {}, m(1) }, x.send = function (n) { let u, l; for (u of ["type", "timeout", "withCredentials"]) l = "type" === u ? "responseType" : u, l in x && (t[u] = x[l]); t.body = n; const f = d.listeners("before"); var p = function () { if (!f.length) return function () { for (u of (c(s, e, x), x.upload && c(s.concat(r), e.upload, x.upload), o = !0, e.open(t.method, t.url, t.async, t.user, t.pass), ["type", "timeout", "withCredentials"])) l = "type" === u ? "responseType" : u, u in t && (e[l] = t[u]); for (let n in t.headers) { const o = t.headers[n]; n && e.setRequestHeader(n, o) } e.send(t.body) }(); const n = function (e) { if ("object" == typeof e && ("number" == typeof e.status || "number" == typeof a.status)) return i(e, a), "data" in e || (e.data = e.response || e.text), void m(4); p() }; n.head = function (e) { i(e, a), m(2) }, n.progress = function (e) { i(e, a), m(3) }; const d = f.shift(); 1 === d.length ? n(d(t)) : 2 === d.length && t.async ? d(t, n) : n() }; p() }, x.abort = function () { u = -1, o ? e.abort() : x.dispatchEvent("abort", {}) }, x.setRequestHeader = function (e, n) { const o = null != e ? e.toLowerCase() : void 0, r = t.headerNames[o] = t.headerNames[o] || e; t.headers[r] && (n = t.headers[r] + ", " + n), t.headers[r] = n }, x.getResponseHeader = e => p(a.headers[e ? e.toLowerCase() : void 0]), x.getAllResponseHeaders = () => p(f(a.headers)), e.overrideMimeType && (x.overrideMimeType = function () { e.overrideMimeType.apply(e, arguments) }), e.upload) { let e = l(); x.upload = e, t.upload = e } return x.UNSENT = 0, x.OPENED = 1, x.HEADERS_RECEIVED = 2, x.LOADING = 3, x.DONE = 4, x.response = "", x.responseText = "", x.responseXML = null, x.readyState = 0, x.statusText = "", x }; y.UNSENT = 0, y.OPENED = 1, y.HEADERS_RECEIVED = 2, y.LOADING = 3, y.DONE = 4; var v = { patch() { h && (n.XMLHttpRequest = y) }, unpatch() { h && (n.XMLHttpRequest = h) }, Native: h, Xhook: y }; function b(e, t, n, o) { return new (n || (n = Promise))((function (r, s) { function a(e) { try { c(o.next(e)) } catch (e) { s(e) } } function i(e) { try { c(o.throw(e)) } catch (e) { s(e) } } function c(e) { var t; e.done ? r(e.value) : (t = e.value, t instanceof n ? t : new n((function (e) { e(t) }))).then(a, i) } c((o = o.apply(e, t || [])).next()) })) } const g = n.fetch; function E(e) { return e instanceof Headers ? m([...e.entries()]) : Array.isArray(e) ? m(e) : e } function m(e) { return e.reduce(((e, [t, n]) => (e[t] = n, e)), {}) } const x = function (e, t = { headers: {} }) { let n = Object.assign(Object.assign({}, t), { isFetch: !0 }); if (e instanceof Request) { const o = function (e) { let t = {}; return ["method", "headers", "body", "mode", "credentials", "cache", "redirect", "referrer", "referrerPolicy", "integrity", "keepalive", "signal", "url"].forEach((n => t[n] = e[n])), t }(e), r = Object.assign(Object.assign({}, E(o.headers)), E(n.headers)); n = Object.assign(Object.assign(Object.assign({}, o), t), { headers: r, acceptedRequest: !0 }) } else n.url = e; const o = d.listeners("before"), r = d.listeners("after"); return new Promise((function (t, s) { let a = t; const i = function (e) { if (!r.length) return a(e); const t = r.shift(); return 2 === t.length ? (t(n, e), i(e)) : 3 === t.length ? t(n, e, i) : i(e) }, c = function (e) { if (void 0 !== e) { const n = new Response(e.body || e.text, e); return t(n), void i(n) } u() }, u = function () { if (!o.length) return void l(); const e = o.shift(); return 1 === e.length ? c(e(n)) : 2 === e.length ? e(n, c) : void 0 }, l = () => b(this, void 0, void 0, (function* () { const { url: t, isFetch: o, acceptedRequest: r } = n, c = function (e, t) { var n = {}; for (var o in e) Object.prototype.hasOwnProperty.call(e, o) && t.indexOf(o) < 0 && (n[o] = e[o]); if (null != e && "function" == typeof Object.getOwnPropertySymbols) { var r = 0; for (o = Object.getOwnPropertySymbols(e); r < o.length; r++)t.indexOf(o[r]) < 0 && Object.prototype.propertyIsEnumerable.call(e, o[r]) && (n[o[r]] = e[o[r]]) } return n }(n, ["url", "isFetch", "acceptedRequest"]); return e instanceof Request && c.body instanceof ReadableStream && (c.body = yield new Response(c.body).text()), g(t, c).then((e => i(e))).catch((function (e) { return a = s, i(e), s(e) })) })); u() })) }; var w = { patch() { g && (n.fetch = x) }, unpatch() { g && (n.fetch = g) }, Native: g, Xhook: x }; const O = d; return O.EventEmitter = l, O.before = function (e, t) { if (e.length < 1 || e.length > 2) throw "invalid hook"; return O.on("before", e, t) }, O.after = function (e, t) { if (e.length < 2 || e.length > 3) throw "invalid hook"; return O.on("after", e, t) }, O.enable = function () { v.patch(), w.patch() }, O.disable = function () { v.unpatch(), w.unpatch() }, O.XMLHttpRequest = v.Native, O.fetch = w.Native, O.headers = f, O.enable(), O }(); 40 | 41 | xhook.before((request, callback) => 42 | { 43 | if (['https://wykop.pl/api/v3/notifications/tags', 'https://wykop.pl/api/v3/notifications/entries', 'https://wykop.pl/api/v3/notifications/observed-discussions'].some(baseURL => new RegExp(`^${baseURL}\\?page=\\d+&show_grouped=1$`).test(request.url))) request.url = request.url.replace('show_grouped=1', 'show_grouped=0'); 44 | callback(); 45 | }); 46 | } 47 | )(); -------------------------------------------------------------------------------- /Wykop XS - skrypty do konsoli/wykop_xs_czyszczenie_listy_obserwowanych_dyskusji.js: -------------------------------------------------------------------------------- 1 | /* 2 | ----- Zapraszam na tag #wykopx ----- 3 | 4 | TEN SKRYPT SŁUŻY DO WYCZYSZCZENIA LISTY OBSERWOWANYCH DYSKUSJI 5 | Jeśli nie wiesz jak z niego skorzystać, przeczytaj instrukcję poniżej. 6 | 7 | UWAGA! TEN SKRYPT NIE JEST SKRYPTEM DO ViolentMonkey/TamperMonkey 8 | KOD TEGO SKRYPTU NALEŻY WKLEIĆ GO DO KONSOLI [CTRL + SHIFT + C] 9 | 10 | INSTRUKCJA: 11 | 1. wejdź na dowolną stronę wykop.pl 12 | 13 | 2. otwórz konsolę skrótem [CTRL + SHIFT + C] lub klawiszem [F12] 14 | 15 | 3. wpisz w konsoli `allow-pasting` (razem z cudzysłowami ` `) i wciśnij [ENTER] 16 | 17 | 4. wklej CAŁY poniższy kod i wciśnij [ENTER] 18 | 19 | 5. Na górnej belce Wykopu pojawi się nowy przycisk, który po kliknięciu: 20 | 21 | - sprawdzi ile dyskusji obserwujesz 22 | - w kilku krokach pozwoli ci wybrać czy chcesz usunąć obserwowane wpisy/znaleziska/komentarze 23 | - zdecydujesz czy chcesz również usuwać dyskusje, które dodałeś do Ulubionych 24 | (jeśli chcesz, aby niektóre obserwowane dyskusje nie były usunięte - dodaj je wcześniej do ulubionych) 25 | - w ostatnim kroku masz możliwość rezygnacji - nic nie zostanie wtedy usunięte 26 | 27 | - w trakcie usuwania pasek postępu pokazywany jest w adresie URL na przykład: 28 | https://wykop.pl/tag/wykopx/#--usunięto: 178/180 (99%) 29 | 30 | 31 | Lista dyskusji, które obserwujesz znajduje się tutaj: 32 | https://wykop.pl/obserwowane/dyskusje 33 | 34 | Wersja zminimalizowana tego skryptu gotowa do wklejenia= w konsoli: 35 | https://raw.githubusercontent.com/wykopx/WykopX/refs/heads/main/Wykop%20XS%20-%20skrypty%20do%20konsoli/wykop_xs_czyszczenie_listy_obserwowanych_dyskusji.min.js 36 | 37 | Pełna wersja tego skryptu tutaj: 38 | https://github.com/wykopx/WykopX/blob/main/Wykop%20XS%20-%20skrypty%20do%20konsoli/wykop_xs_czyszczenie_listy_obserwowanych_dyskusji.js 39 | 40 | Chcesz wesprzeć projekt Wykop X? Postaw kawę: 41 | 42 | @contributionURL https://buycoffee.to/wykopx 43 | 44 | @author Wykop X 45 | @License No License 46 | @version 1.0.2 47 | 48 | ----- Zapraszam na tag #wykopx ----- 49 | */ 50 | 51 | let observedLinks = 0; 52 | let observedLinksFavourited = 0; 53 | let observedEntries = 0; 54 | let observedEntriesFavourited = 0; 55 | let observedLinkComments = 0; 56 | let observedLinkCommentsFavourited = 0; 57 | let deleteEntries = true; 58 | let deleteLinks = true; 59 | let deleteLinkComments = true; 60 | let dontDeleteFavourites = true; 61 | let totalToDelete = 0; 62 | console.clear(); 63 | 64 | async function fetchObservedDiscussionData() 65 | { 66 | const token = localStorage.getItem('token'); 67 | if (!token) { return new Map(); } 68 | const dataMap = new Map(); 69 | 70 | 71 | async function getData(page = '') 72 | { 73 | const url = `https://wykop.pl/api/v3/observed/discussions${page ? `?page=${page}` : ''}`; 74 | const response = await fetch(url, { 75 | headers: { 76 | 'Authorization': `Bearer ${token}` 77 | } 78 | }); 79 | 80 | if (!response.ok) { return null; } 81 | const result = await response.json(); 82 | 83 | result.data.forEach(item => 84 | { 85 | dataMap.set(item.object.id, item); 86 | if (item.object.resource == "entry") 87 | { 88 | observedEntries++; 89 | if (item.object.favourite) observedEntriesFavourited++; 90 | } 91 | else if (item.object.resource == "link") 92 | { 93 | observedLinks++; 94 | if (item.object.favourite) observedLinksFavourited++; 95 | } 96 | else if (item.object.resource == "link_comment") 97 | { 98 | observedLinkComments++; 99 | if (item.object.favourite) observedLinkCommentsFavourited++; 100 | } 101 | }); 102 | return result.pagination.next; 103 | } 104 | 105 | let nextPage = await getData(); 106 | 107 | // for (let i = 0; i < 3 && nextPage; i++) 108 | for (let i = 0; nextPage; i++) 109 | { 110 | nextPage = await getData(nextPage); 111 | await delay(100); 112 | } 113 | return dataMap; 114 | } 115 | 116 | function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } 117 | 118 | async function deleteSelectedFromMap(dataMap) 119 | { 120 | const token = localStorage.getItem('token'); 121 | if (!token) { return; } 122 | 123 | const progressURL = new URL(window.location.href) 124 | const basePathName = `/tag/wykopx`; 125 | progressURL.pathname = basePathName; 126 | window.history.pushState({}, '', progressURL); 127 | 128 | let i = 0; 129 | let deleted = 0; 130 | 131 | for (const [id, item] of dataMap) 132 | { 133 | let apiURL = ""; 134 | 135 | if (item.object.resource == "entry" && deleteEntries) 136 | { 137 | apiURL = `https://wykop.pl/api/v3/entries/${item.object.id}/observed-discussions`; 138 | } 139 | else if (item.object.resource == "link" && deleteLinks) 140 | { 141 | apiURL = `https://wykop.pl/api/v3/links/${item.object.id}/observed-discussions`; 142 | } 143 | else if (item.object.resource == "link_comment" && deleteLinkComments) 144 | { 145 | apiURL = `https://wykop.pl/api/v3/links/${item.object.parent.id}/comments/${item.object.id}/observed-discussions`; 146 | } 147 | 148 | if (item.object.favourite && dontDeleteFavourites) apiURL = ""; 149 | 150 | if (apiURL !== "") 151 | { 152 | deleted++; 153 | 154 | const response = await fetch(apiURL, { 155 | method: 'DELETE', 156 | headers: { 157 | 'Authorization': `Bearer ${token}` 158 | } 159 | }); 160 | 161 | await delay(170); 162 | } 163 | 164 | 165 | i++; 166 | const newHash = `--usunieto:${deleted}/${totalToDelete}_(${Math.ceil((deleted * 100 / totalToDelete))}%)`; // __przeanalizowano:${i}/${dataMap.size}`; 167 | window.location.hash = newHash; 168 | } 169 | } 170 | 171 | async function wykopx() 172 | { 173 | observedLinks = 0; 174 | observedLinksFavourited = 0; 175 | observedEntries = 0; 176 | observedEntriesFavourited = 0; 177 | observedLinkComments = 0; 178 | observedLinkCommentsFavourited = 0; 179 | deleteEntries = false; 180 | deleteLinks = false; 181 | deleteLinkComments = false; 182 | dontDeleteFavourites = true; 183 | totalToDelete = 0; 184 | 185 | let step = 0; 186 | let totalSteps = 7; 187 | alert(`KROK ${++step}/7\nWykop X przeanalizuje teraz obserwowane przez Ciebie dyskusje \n\n> Kliknij [OK] i poczekaj kilka sekund.\n\nSpokojnie, jeszcze nie usuwamy obserwowanych dyskusji.\nPrzejdziemy do tego w następnych krokach.`) 188 | 189 | fetchObservedDiscussionData().then(dataMap => 190 | { 191 | if (dataMap.size === 0) 192 | { 193 | totalSteps = 1; 194 | alert(`KROK ${++step}/${totalSteps}\n\nWykop X przeanalizował Twoje obserwowane:\n- Nie obserwujesz żadnych dyskusji`); 195 | } 196 | else 197 | { 198 | if (observedEntries == 0) totalSteps--; 199 | if (observedLinks == 0) totalSteps--; 200 | if (observedLinkComments == 0) totalSteps--; 201 | 202 | alert(`KROK ${++step}/${totalSteps}\n- Obserwujesz łącznie: (${dataMap.size}) dyskusji\n- Limit obserwowanych dyskusji na wykopie wynosi (1000)\n\nObserwujesz:\n- (${observedEntries}) wpisów na mikroblogu w tym (${observedEntriesFavourited}) wpisów ⭐ Ulubionych\n- (${observedLinks}) znalezisk w tym (${observedLinksFavourited}) znalezisk ⭐ Ulubionych\n- (${observedLinkComments}) komentarzy w znaleziskach w tym (${observedLinkCommentsFavourited}) komentarzy ⭐ Ulubionych\n\n> Kliknij [OK] aby kontynuować`); 203 | dontDeleteFavourites = confirm(`KROK ${++step}/${totalSteps}\nMożesz teraz wybrać czy chcesz, POMINĄĆ usuwanie dyskusji, które masz oznaczone jako "⭐ Ulubione"\n\n> [OK] jeśli chcesz, żeby 🌟 Ulubione dyskusje NIE ZOSTAŁY USUNIĘTE\n\n> [Anuluj] jeśli CHCESZ USUNĄĆ również 🌟 Ulubione dyskusje`); 204 | 205 | 206 | let entriesToDelete = dontDeleteFavourites ? observedEntries - observedEntriesFavourited : observedEntries; 207 | let linksToDelete = dontDeleteFavourites ? observedLinks - observedLinksFavourited : observedLinks; 208 | let linkCommentsToDelete = dontDeleteFavourites ? observedLinkComments - observedLinkCommentsFavourited : observedLinkComments; 209 | 210 | if (entriesToDelete > 0) deleteEntries = confirm(`KROK ${++step}/${totalSteps}\nCzy chcesz usunąć (${entriesToDelete}) obserwowanych WPISÓW NA MIKROBLOGU?\n\n> [OK] jeśli chcesz, żeby WPISY zostały usunięte z obserwowanych\n\n> [Anuluj] jeśli nie chcesz usuwać obserwowanych WPISÓW`); 211 | if (linksToDelete > 0) deleteLinks = confirm(`KROK ${++step}/${totalSteps}\nCzy chcesz usunąć (${linksToDelete}) obserwowanych ZNALEZISK?\n\n> [OK] jeśli chcesz, żeby ZNALEZISKA zostały usunięte z obserwowanych\n\n> [Anuluj] jeśli nie chcesz usuwać obserwowanych ZNALEZISK`); 212 | if (linkCommentsToDelete > 0) deleteLinkComments = confirm(`KROK ${++step}/${totalSteps}\nCzy chcesz usunąć (${linkCommentsToDelete}) obserwowanych KOMENTARZY W ZNALEZISKACH?\n\n> [OK] jeśli chcesz, żeby KOMENTARZE W ZNALEZISKACH zostały usunięte z obserwowanych\n\n> [Anuluj] jeśli nie chcesz usuwać obserwowanych KOMENTARZY W ZNALEZISKACH`); 213 | 214 | 215 | if (!deleteEntries) entriesToDelete = 0; 216 | if (!deleteLinks) linksToDelete = 0; 217 | if (!deleteLinkComments) linkCommentsToDelete = 0; 218 | 219 | totalToDelete = entriesToDelete + linksToDelete + linkCommentsToDelete; 220 | 221 | let lastStepText = `⚠ KROK ${++step}/${totalSteps} - USUWANIE ⚠ \nPo kliknięciu w [OK] ROZPOCZNIE SIĘ USUWANIE!\n\nWykop X usunie:`; 222 | entriesToDelete > 0 ? lastStepText += `\n- (${entriesToDelete}) obserwowanych wpisów ${dontDeleteFavourites ? "(bez ulubionych)" : "w tym także ulubione"}` : ""; 223 | linksToDelete > 0 ? lastStepText += `\n- (${linksToDelete}) obserwowanych znalezisk ${dontDeleteFavourites ? "(bez ulubionych)" : "w tym także ulubione"}` : ""; 224 | linkCommentsToDelete > 0 ? lastStepText += `\n- (${linkCommentsToDelete}) obserwowanych komentarzy w znaleziskach ${dontDeleteFavourites ? "(bez ulubionych)" : "w tym także ulubione"}` : ""; 225 | 226 | lastStepText += `\n\nŁącznie usuniemy (${totalToDelete}) z (${dataMap.size}) obserwowanych dyskusji.\n\n> [OK] aby USUNĄĆ (${totalToDelete}) obserwowanych dyskusji\n> [Anuluj] aby PRZERWAĆ proces usuwania. 227 | ` 228 | if (totalToDelete > 0) 229 | { 230 | if (confirm(lastStepText)) 231 | { 232 | deleteSelectedFromMap(dataMap).then(() => 233 | { 234 | alert('Wszystkie wybrane dyskusje zostały usunięte.'); 235 | window.location.hash = `(づ•﹏•)づ__usunięto_${totalToDelete}_z_${dataMap.size}_obserwowanych_dyskusji`; 236 | }); 237 | } 238 | } 239 | else 240 | { 241 | const progressURL = new URL(window.location.href) 242 | progressURL.pathname = `/tag/wykopx`; 243 | window.history.pushState({}, '', progressURL); 244 | window.location.hash = "(づ•﹏•)づ"; 245 | confirm(`⚠ KROK 21/37 ⚠\n\n\nNie to nie ( ͡° ͜ʖ ͡°)`); 246 | } 247 | } 248 | }); 249 | } 250 | 251 | const button = document.createElement('button'); 252 | button.setAttribute("style", "position: fixed; top: 5px; left: 50%; z-index: 999; display: flex; color: rgb(255 255 255 / 0.6); border: 1px solid rgb(0 0 0 / 0.3); background-color: rgb(0 0 0 / 0.2); padding: 10px;") 253 | button.textContent = 'Usuń obserwowane dyskusje'; 254 | document.body.insertBefore(button, document.body.firstChild); 255 | button.addEventListener('click', async () => { await wykopx(); }); -------------------------------------------------------------------------------- /Wykop XS/wykop_xs_xhr_blocker.user.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name Wykop XS - XHR blocker 3 | // @name:pl Wykop XS - XHR blocker 4 | // @name:en Wykop XS - XHR blocker 5 | 6 | // @version 3.0.81 7 | 8 | // @description Wykop XS - XHR Blocker | Wykop X Style znajdziesz na: http://style.wykopx.pl 9 | // @description:en Wykop XS - XHR Blocker | Check out also: http://style.wykopx.pl 10 | 11 | 12 | // Chcesz wesprzeć projekt Wykop X? Postaw kawkę: 13 | // @contributionURL https://buycoffee.to/wykopx 14 | 15 | // @author Wykop X 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 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | // ==/UserScript== 42 | 43 | (async function () 44 | { 45 | 'use strict'; 46 | 47 | const currentVersion = "3.0.80"; 48 | let dev = false; 49 | 50 | const promoString = " - Wykop XHR Blocker / #wykopx"; 51 | 52 | const root = document.documentElement; 53 | const head = document.head; 54 | const body = document.body; 55 | const bodySection = body.querySelector("section"); 56 | const wykopxSettings = getComputedStyle(head); 57 | const settings = {}; 58 | 59 | const styleElement = document.createElement('style'); 60 | styleElement.id = "wykopxs_xhr_blocker"; 61 | let CSS = ""; 62 | 63 | function setSettingsValueFromCSSProperty(settingName, defaultValueForWykopXS = true, propertyValueInsteadOfBoolean = false) 64 | { 65 | if (propertyValueInsteadOfBoolean) settings[settingName] = wykopxSettings.getPropertyValue(`--${settingName}`) ? wykopxSettings.getPropertyValue(`--${settingName}`).trim() : defaultValueForWykopXS; 66 | else settings[settingName] = wykopxSettings.getPropertyValue(`--${settingName}`) ? wykopxSettings.getPropertyValue(`--${settingName}`).trim() === '1' : defaultValueForWykopXS; 67 | } 68 | 69 | setSettingsValueFromCSSProperty("WykopXSEnabled"); 70 | if (settings.WykopXSEnabled == false) return; 71 | /* WYKOP XS HEADER */ 72 | 73 | 74 | setSettingsValueFromCSSProperty("hideAds"); // blokuje wszystkie reklamy na wykopie 75 | 76 | 77 | setSettingsValueFromCSSProperty("infiniteScrollEntriesEnabled"); 78 | setSettingsValueFromCSSProperty("infiniteScrollLinksEnabled"); 79 | 80 | // Wykop XS - XHR Blocker 81 | // https://greasyfork.org/en/scripts/486722-wykop-xs-xhr-blocker 82 | setSettingsValueFromCSSProperty("wxsBlockXHREnable"); 83 | if (settings.wxsBlockXHREnable) 84 | { 85 | setSettingsValueFromCSSProperty("wxsBlockXHRExternal"); 86 | setSettingsValueFromCSSProperty("wxsBlockXHRInternalAds"); 87 | // setSettingsValueFromCSSProperty("wxsBlockXHRConsoleLogAllowed", false); 88 | // setSettingsValueFromCSSProperty("wxsBlockXHRConsoleLogBlocked", false); 89 | // setSettingsValueFromCSSProperty("rightSidebarHidePopularTags", false); 90 | // setSettingsValueFromCSSProperty("rightSidebarHideRelatedTags", false); 91 | // setSettingsValueFromCSSProperty("rightSidebarHideHits", false); 92 | // setSettingsValueFromCSSProperty("rightSidebarHideEntriesHot", false); 93 | // setSettingsValueFromCSSProperty("rightSidebarHideEntriesActive", false); 94 | // setSettingsValueFromCSSProperty("rightSidebarHideEntriesPopular", false); 95 | // setSettingsValueFromCSSProperty("rightSidebarHideUpcomingActive", false); 96 | // setSettingsValueFromCSSProperty("rightSidebarHideLinksNewest", false); 97 | // setSettingsValueFromCSSProperty("rightSidebarHideLinksActive", false); 98 | // setSettingsValueFromCSSProperty("rightSidebarHideLinksPopular", false); 99 | } 100 | 101 | 102 | 103 | let xhook = null; 104 | if (settings.infiniteScrollEntriesEnabled || settings.infiniteScrollLinksEnabled || settings.wxsBlockXHRExternal || settings.wxsBlockXHRInternalAds) 105 | { 106 | //XHook - v1.6.2 - https://github.com/jpillora/xhook | Jaime Pillora - MIT Copyright 2023 107 | xhook = function () { "use strict"; const e = (e, t) => Array.prototype.slice.call(e, t); let t = null; "undefined" != typeof WorkerGlobalScope && self instanceof WorkerGlobalScope ? t = self : "undefined" != typeof global ? t = global : window && (t = window); const n = t, o = t.document, r = ["load", "loadend", "loadstart"], s = ["progress", "abort", "error", "timeout"], a = e => ["returnValue", "totalSize", "position"].includes(e), i = function (e, t) { for (let n in e) { if (a(n)) continue; const o = e[n]; try { t[n] = o } catch (e) { } } return t }, c = function (e, t, n) { const o = e => function (o) { const r = {}; for (let e in o) { if (a(e)) continue; const s = o[e]; r[e] = s === t ? n : s } return n.dispatchEvent(e, r) }; for (let r of Array.from(e)) n._has(r) && (t[`on${r}`] = o(r)) }, u = function (e) { if (o && null != o.createEventObject) { const t = o.createEventObject(); return t.type = e, t } try { return new Event(e) } catch (t) { return { type: e } } }, l = function (t) { let n = {}; const o = e => n[e] || [], r = { addEventListener: function (e, t, r) { n[e] = o(e), n[e].indexOf(t) >= 0 || (r = void 0 === r ? n[e].length : r, n[e].splice(r, 0, t)) }, removeEventListener: function (e, t) { if (void 0 === e) return void (n = {}); void 0 === t && (n[e] = []); const r = o(e).indexOf(t); -1 !== r && o(e).splice(r, 1) }, dispatchEvent: function () { const n = e(arguments), s = n.shift(); t || (n[0] = i(n[0], u(s)), Object.defineProperty(n[0], "target", { writable: !1, value: this })); const a = r[`on${s}`]; a && a.apply(r, n); const c = o(s).concat(o("*")); for (let e = 0; e < c.length; e++) { c[e].apply(r, n) } }, _has: e => !(!n[e] && !r[`on${e}`]) }; return t && (r.listeners = t => e(o(t)), r.on = r.addEventListener, r.off = r.removeEventListener, r.fire = r.dispatchEvent, r.once = function (e, t) { var n = function () { return r.off(e, n), t.apply(null, arguments) }; return r.on(e, n) }, r.destroy = () => n = {}), r }; var f = function (e, t) { switch (typeof e) { case "object": return n = e, Object.entries(n).map((([e, t]) => `${e.toLowerCase()}: ${t}`)).join("\r\n"); case "string": return function (e, t) { const n = e.split("\r\n"); null == t && (t = {}); for (let e of n) if (/([^:]+):\s*(.+)/.test(e)) { const e = null != RegExp.$1 ? RegExp.$1.toLowerCase() : void 0, n = RegExp.$2; null == t[e] && (t[e] = n) } return t }(e, t) }var n; return [] }; const d = l(!0), p = e => void 0 === e ? null : e, h = n.XMLHttpRequest, y = function () { const e = new h, t = {}; let n, o, a, u = null; var y = 0; const v = function () { if (a.status = u || e.status, -1 !== u && (a.statusText = e.statusText), -1 === u); else { const t = f(e.getAllResponseHeaders()); for (let e in t) { const n = t[e]; if (!a.headers[e]) { const t = e.toLowerCase(); a.headers[t] = n } } } }, b = function () { x.status = a.status, x.statusText = a.statusText }, g = function () { n || x.dispatchEvent("load", {}), x.dispatchEvent("loadend", {}), n && (x.readyState = 0) }, E = function (e) { for (; e > y && y < 4;)x.readyState = ++y, 1 === y && x.dispatchEvent("loadstart", {}), 2 === y && b(), 4 === y && (b(), "text" in a && (x.responseText = a.text), "xml" in a && (x.responseXML = a.xml), "data" in a && (x.response = a.data), "finalUrl" in a && (x.responseURL = a.finalUrl)), x.dispatchEvent("readystatechange", {}), 4 === y && (!1 === t.async ? g() : setTimeout(g, 0)) }, m = function (e) { if (4 !== e) return void E(e); const n = d.listeners("after"); var o = function () { if (n.length > 0) { const e = n.shift(); 2 === e.length ? (e(t, a), o()) : 3 === e.length && t.async ? e(t, a, o) : o() } else E(4) }; o() }; var x = l(); t.xhr = x, e.onreadystatechange = function (t) { try { 2 === e.readyState && v() } catch (e) { } 4 === e.readyState && (o = !1, v(), function () { if (e.responseType && "text" !== e.responseType) "document" === e.responseType ? (a.xml = e.responseXML, a.data = e.responseXML) : a.data = e.response; else { a.text = e.responseText, a.data = e.responseText; try { a.xml = e.responseXML } catch (e) { } } "responseURL" in e && (a.finalUrl = e.responseURL) }()), m(e.readyState) }; const w = function () { n = !0 }; x.addEventListener("error", w), x.addEventListener("timeout", w), x.addEventListener("abort", w), x.addEventListener("progress", (function (t) { y < 3 ? m(3) : e.readyState <= 3 && x.dispatchEvent("readystatechange", {}) })), "withCredentials" in e && (x.withCredentials = !1), x.status = 0; for (let e of Array.from(s.concat(r))) x[`on${e}`] = null; if (x.open = function (e, r, s, i, c) { y = 0, n = !1, o = !1, t.headers = {}, t.headerNames = {}, t.status = 0, t.method = e, t.url = r, t.async = !1 !== s, t.user = i, t.pass = c, a = {}, a.headers = {}, m(1) }, x.send = function (n) { let u, l; for (u of ["type", "timeout", "withCredentials"]) l = "type" === u ? "responseType" : u, l in x && (t[u] = x[l]); t.body = n; const f = d.listeners("before"); var p = function () { if (!f.length) return function () { for (u of (c(s, e, x), x.upload && c(s.concat(r), e.upload, x.upload), o = !0, e.open(t.method, t.url, t.async, t.user, t.pass), ["type", "timeout", "withCredentials"])) l = "type" === u ? "responseType" : u, u in t && (e[l] = t[u]); for (let n in t.headers) { const o = t.headers[n]; n && e.setRequestHeader(n, o) } e.send(t.body) }(); const n = function (e) { if ("object" == typeof e && ("number" == typeof e.status || "number" == typeof a.status)) return i(e, a), "data" in e || (e.data = e.response || e.text), void m(4); p() }; n.head = function (e) { i(e, a), m(2) }, n.progress = function (e) { i(e, a), m(3) }; const d = f.shift(); 1 === d.length ? n(d(t)) : 2 === d.length && t.async ? d(t, n) : n() }; p() }, x.abort = function () { u = -1, o ? e.abort() : x.dispatchEvent("abort", {}) }, x.setRequestHeader = function (e, n) { const o = null != e ? e.toLowerCase() : void 0, r = t.headerNames[o] = t.headerNames[o] || e; t.headers[r] && (n = t.headers[r] + ", " + n), t.headers[r] = n }, x.getResponseHeader = e => p(a.headers[e ? e.toLowerCase() : void 0]), x.getAllResponseHeaders = () => p(f(a.headers)), e.overrideMimeType && (x.overrideMimeType = function () { e.overrideMimeType.apply(e, arguments) }), e.upload) { let e = l(); x.upload = e, t.upload = e } return x.UNSENT = 0, x.OPENED = 1, x.HEADERS_RECEIVED = 2, x.LOADING = 3, x.DONE = 4, x.response = "", x.responseText = "", x.responseXML = null, x.readyState = 0, x.statusText = "", x }; y.UNSENT = 0, y.OPENED = 1, y.HEADERS_RECEIVED = 2, y.LOADING = 3, y.DONE = 4; var v = { patch() { h && (n.XMLHttpRequest = y) }, unpatch() { h && (n.XMLHttpRequest = h) }, Native: h, Xhook: y }; function b(e, t, n, o) { return new (n || (n = Promise))((function (r, s) { function a(e) { try { c(o.next(e)) } catch (e) { s(e) } } function i(e) { try { c(o.throw(e)) } catch (e) { s(e) } } function c(e) { var t; e.done ? r(e.value) : (t = e.value, t instanceof n ? t : new n((function (e) { e(t) }))).then(a, i) } c((o = o.apply(e, t || [])).next()) })) } const g = n.fetch; function E(e) { return e instanceof Headers ? m([...e.entries()]) : Array.isArray(e) ? m(e) : e } function m(e) { return e.reduce(((e, [t, n]) => (e[t] = n, e)), {}) } const x = function (e, t = { headers: {} }) { let n = Object.assign(Object.assign({}, t), { isFetch: !0 }); if (e instanceof Request) { const o = function (e) { let t = {}; return ["method", "headers", "body", "mode", "credentials", "cache", "redirect", "referrer", "referrerPolicy", "integrity", "keepalive", "signal", "url"].forEach((n => t[n] = e[n])), t }(e), r = Object.assign(Object.assign({}, E(o.headers)), E(n.headers)); n = Object.assign(Object.assign(Object.assign({}, o), t), { headers: r, acceptedRequest: !0 }) } else n.url = e; const o = d.listeners("before"), r = d.listeners("after"); return new Promise((function (t, s) { let a = t; const i = function (e) { if (!r.length) return a(e); const t = r.shift(); return 2 === t.length ? (t(n, e), i(e)) : 3 === t.length ? t(n, e, i) : i(e) }, c = function (e) { if (void 0 !== e) { const n = new Response(e.body || e.text, e); return t(n), void i(n) } u() }, u = function () { if (!o.length) return void l(); const e = o.shift(); return 1 === e.length ? c(e(n)) : 2 === e.length ? e(n, c) : void 0 }, l = () => b(this, void 0, void 0, (function* () { const { url: t, isFetch: o, acceptedRequest: r } = n, c = function (e, t) { var n = {}; for (var o in e) Object.prototype.hasOwnProperty.call(e, o) && t.indexOf(o) < 0 && (n[o] = e[o]); if (null != e && "function" == typeof Object.getOwnPropertySymbols) { var r = 0; for (o = Object.getOwnPropertySymbols(e); r < o.length; r++)t.indexOf(o[r]) < 0 && Object.prototype.propertyIsEnumerable.call(e, o[r]) && (n[o[r]] = e[o[r]]) } return n }(n, ["url", "isFetch", "acceptedRequest"]); return e instanceof Request && c.body instanceof ReadableStream && (c.body = yield new Response(c.body).text()), g(t, c).then((e => i(e))).catch((function (e) { return a = s, i(e), s(e) })) })); u() })) }; var w = { patch() { g && (n.fetch = x) }, unpatch() { g && (n.fetch = g) }, Native: g, Xhook: x }; const O = d; return O.EventEmitter = l, O.before = function (e, t) { if (e.length < 1 || e.length > 2) throw "invalid hook"; return O.on("before", e, t) }, O.after = function (e, t) { if (e.length < 2 || e.length > 3) throw "invalid hook"; return O.on("after", e, t) }, O.enable = function () { v.patch(), w.patch() }, O.disable = function () { v.unpatch(), w.unpatch() }, O.XMLHttpRequest = v.Native, O.fetch = w.Native, O.headers = f, O.enable(), O }(); 108 | } 109 | 110 | 111 | 112 | if (xhook != null && (settings.wxsBlockXHRExternal || settings.wxsBlockXHRInternalAds)) 113 | { 114 | if (!dev) dev = setSettingsValueFromCSSProperty("wxsDev", false); 115 | 116 | const allowed = []; 117 | if (settings.wxsBlockXHRExternal) allowed.push('https://wykop.pl/api/', 'https://raw.githubusercontent.com/wykopx/', 'wykopx.pl'); 118 | 119 | const prohibited = []; 120 | if (settings.wxsBlockXHRInternalAds) prohibited.push("https://wykop.pl/api/v3/ads"); 121 | // prohibited.push("https://wykop.pl/api/v3/links?type=homepage&sort=active&sidebar=true"); 122 | // prohibited.push("https://wykop.pl/api/v3/tags/popular?sidebar=true"); 123 | // prohibited.push("https://wykop.pl/api/v3/entries?sort=active&sidebar=true"); 124 | // prohibited.push("https://wykop.pl/api/v3/links?type=homepage&sort=newest&sidebar=true"); 125 | // prohibited.push("https://wykop.pl/api/v3/links?type=upcoming&sort=active&sidebar=true"); 126 | // prohibited.push("https://wykop.pl/api/v3/hits/links?sort=day&sidebar=true"); 127 | // prohibited.push("https://wykop.pl/api/v3/entries?sort=hot&last_update=24&sidebar=true"); 128 | // prohibited.push("https://wykop.pl/api/v3/entries?sort=hot&last_update=12&sidebar=true"); 129 | // prohibited.push("https://wykop.pl/api/v3/links?type=upcoming&sort=newest&sidebar=true"); 130 | // prohibited.push("https://wykop.pl/api/v3/hits/links?sort=week&sidebar=true"); 131 | // prohibited.push("https://wykop.pl/api/v3/search/links?sort=popular&bucket=17c344d6871fcac52893&sidebar=true"); 132 | // prohibited.push("https://wykop.pl/api/v3/search/entries?sort=popular&bucket=17c344d6871fcac52893&sidebar=true"); 133 | // prohibited.push("https://wykop.pl/api/v3/tags/polska/related?sidebar=true"); 134 | // prohibited.push("https://wykop.pl/api/v3/buckets/status"); 135 | // prohibited.push("https://wykop.pl/api/v3/links/stats/upcoming"); 136 | // prohibited.push("https://wykop.pl/api/v3/notifications/status"); 137 | // prohibited.push("https://wykop.pl/api/v3/notifications/tags?page=1"); 138 | // prohibited.push("https://wykop.pl/api/v3/notifications/entries?page=1"); 139 | // prohibited.push("https://wykop.pl/api/v3/pm/conversations"); 140 | 141 | xhook.before((request, callback) => 142 | { 143 | 144 | if (allowed.some(str => request.url.includes(str)) && !prohibited.some(str => request.url.includes(str))) 145 | { 146 | if (dev) console.log("Wykop XS - XHR Blocker | XHR: 🌍 " + request.url + " (ALLOWED)"); 147 | callback(); 148 | } 149 | else 150 | { 151 | if (dev) console.log("Wykop XS - XHR Blocker | XHR: ⛔ " + request.url + " (BLOCKED)"); 152 | } 153 | }); 154 | } 155 | 156 | 157 | /* HIDE ADS ALWAYS */ 158 | if (settings.hideAds) { CSS += `.pub-slot-wrapper { display: none!important; }`; } 159 | 160 | /* HIDE WYKOP XS PROMO FROM STYLUS */ 161 | CSS += `.wykopxs, body div.main-content[class] section > section.sidebar::after { display: none!important; }`; 162 | 163 | styleElement.textContent = CSS; 164 | document.head.appendChild(styleElement); 165 | })(); -------------------------------------------------------------------------------- /Wykop XS/wykop_xs_all_comments.user.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name Wykop XS - OnePage Komentarze i Notatki 3 | // @name:pl Wykop XS - OnePage Komentarze i Notatki 4 | // @name:en Wykop XS - OnePage Komentarze i Notatki 5 | 6 | // @version 3.0.83 7 | 8 | // @description Wykop XS - OnePage Komentarze i Notatki | Wejdź na Mikroczat: https://mikroczat.pl Projekt Wykop X: https://wykopx.pl Wiki projektu Wykop X: https://wiki.wykopx.pl 9 | // @description:en Wykop XS - OnePage Komentarze i Notatki | Wykop Live Chat: https://mikroczat.pl | Wykop X Project: https://wykopx.pl | Wiki: https://wiki.wykopx.pl 10 | 11 | 12 | // Chcesz wesprzeć projekt Wykop X? Postaw kawkę: 13 | // @contributionURL https://buycoffee.to/wykopx 14 | 15 | // @author Wykop X 16 | 17 | 18 | 19 | // @match https://wykop.pl/* 20 | // @supportURL http://wykop.pl/tag/wykopx 21 | // @namespace Violentmonkey Scripts 22 | // @compatible chrome, firefox, opera, safari, edge 23 | // @license No License 24 | // @icon https://www.google.com/s2/favicons?sz=64&domain=wykop.pl 25 | 26 | 27 | 28 | 29 | // ==/UserScript== 30 | (async function () 31 | { 32 | /* USTAWIENIA START */ 33 | // - 34 | // - poniższe ustawienia można zmieniać według uznania 35 | // - 36 | 37 | // USTAWIENIE LICZBY KOMENTARZY WYŚWIETLANYCH NA JEDNEJ STRONIE 38 | let SHOW_ALL_COMMENTS_IN_ONE_PAGE_WITHOUT_ANY_LIMIT = true; // czy chcemy wyświetlać wszystkie komentarze na jednej stronie 39 | let LIMIT_MAXIMUM_COMMENTS_IN_ONE_PAGE = 5000; // ZABEZPIECZENIE PRZED WPISAMI Z BARDZO DUŻĄ LICZBĄ KOMENTARZY https://wykop.pl/wpis/57976055/wpis 40 | // LIMIT KOMENTARZY NA STRONĘ jeśli SHOW_ALL_COMMENTS_IN_ONE_PAGE_WITHOUT_ANY_LIMIT = false 41 | // 1 | 10 | 20 | 100 - tyle ile użytkownik chce, żeby się wyświetlało - dowolna liczba (domyślnie wykop wyświetla 50 komentarzy dla użytkownika zalogowanego i 25 dla niezalogowanego) 42 | let LOCAL_LIMIT_COMMENTS = 500; 43 | 44 | 45 | // STRONA TWOJEGO PROFILU 46 | // https://wykop.pl/ludzie/TwojLogin 47 | // ile najnowszych notatek wyświetlać na stronie profilu: 48 | // Domyślnie na stronie profilu pokazują się 3 najnowsze notatki, a w jednym requeście może być 50, a jeśli chcemy, to więcej requestów np. dla 100 czy 200 49 | let LIMIT_NOTES_ON_PROFILE_PAGES = 50; 50 | 51 | 52 | 53 | // STRONA NOTATEK NA TWOIM PROFILU 54 | // https://wykop.pl/ludzie/TwojLogin/notatki 55 | let SHOW_ALL_NOTES_IN_ONE_PAGE_WITHOUT_ANY_LIMIT = true; // czy chcemy wyświetlić wszystkie notatki 56 | let LIMIT_MAXIMUM_NOTES_IN_ONE_PAGE = 10000; // ZABEZPIECZENIE PRZED OGROMNĄ LICZBĄ NOTATEK 57 | 58 | // LIMIT NOTATEK NA STRONĘ jeśli SHOW_ALL_NOTES_IN_ONE_PAGE_WITHOUT_ANY_LIMIT = false 59 | // 1 | 10 | 20 | 100 - tyle ile użytkownik chce, żeby się wyświetlało, dowolna liczba (domyślnie wykop wyświetla 50 notatek) 60 | let LOCAL_LIMIT_NOTES = 500; 61 | // - 62 | // - 63 | /* USTAWIENIA END */ 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | const currentVersion = "3.0.83"; 72 | let dev = false; 73 | 74 | const AWAIT_MILLISECONDS = 400; 75 | const BACKEND_LIMIT_COMMENTS = 50; // limit backendu do faktycznego pobierania 1-50 76 | const BACKEND_LIMIT_NOTES = 50; // limit backendu do faktycznego pobierania 1-50, wykop wysyła /notes?limit=100 ale i tak pobierane jest 50 77 | let per_page_comments = BACKEND_LIMIT_COMMENTS; 78 | let per_page_notes = BACKEND_LIMIT_NOTES; 79 | // wyliczamy backend limit jako mniejszą liczbę z obecnego limitu 50 albo mniejszą wybraną przez użytkownika 80 | // np. gdy uzytkownik chce miec 20 komentarzy/notatek na stronie zamiast domyslnych 50 81 | if (!SHOW_ALL_COMMENTS_IN_ONE_PAGE_WITHOUT_ANY_LIMIT) per_page_comments = Math.min(BACKEND_LIMIT_COMMENTS, LOCAL_LIMIT_COMMENTS); 82 | if (!SHOW_ALL_NOTES_IN_ONE_PAGE_WITHOUT_ANY_LIMIT) per_page_notes = Math.min(BACKEND_LIMIT_NOTES, LOCAL_LIMIT_NOTES); 83 | 84 | 85 | // unused yet 86 | function getLocalFromPage(pageNumber) 87 | { 88 | const local = 89 | { 90 | page: pageNumber, 91 | 92 | item: 93 | { 94 | first: ((pageNumber - 1) * LOCAL_LIMIT_COMMENTS) + 1, 95 | last: ((pageNumber - 1) * LOCAL_LIMIT_COMMENTS) + LOCAL_LIMIT_COMMENTS + 1, 96 | } 97 | } 98 | 99 | return local; 100 | } 101 | 102 | 103 | function getBackendFromBackendPage(pageStart, pageEnd = pageStart) 104 | { 105 | const backend = 106 | { 107 | pageStart: pageStart, 108 | pageEnd: pageEnd, 109 | 110 | item: 111 | { 112 | first: ((pageStart - 1) * BACKEND_LIMIT_COMMENTS) + 1, 113 | last: ((pageStart - 1) * BACKEND_LIMIT_COMMENTS) + BACKEND_LIMIT_COMMENTS + 1, 114 | } 115 | } 116 | 117 | return backend; 118 | } 119 | 120 | function getPageParam(urlString) 121 | { 122 | const params = new URL(urlString).searchParams; 123 | const pageValue = params.get('page'); // Returns `null` if missing 124 | const pageNumber = parseInt(pageValue || 1); // Default to `1` if missing/invalid 125 | return isNaN(pageNumber) ? 1 : pageNumber; // Force `1` for non-integer values 126 | } 127 | 128 | 129 | function extractPageNumber(url) 130 | { 131 | const pattern = /\/strona\/(\d+)/; 132 | const match = url.match(pattern); 133 | if (match) 134 | { 135 | return parseInt(match[1], 10); // Convert the captured group to a number 136 | } 137 | return 1; 138 | } 139 | 140 | function getBackendPagesFromLocal(local) 141 | { 142 | 143 | if (dev) console.log(`getFirstBackendPageFromLocal() local.page: [${local.page}] | local_limit: [${LOCAL_LIMIT_COMMENTS}] | backend_limit: [${BACKEND_LIMIT_COMMENTS}]`); 144 | 145 | let backend = 146 | { 147 | // f(x) = ax - (a - 1) 148 | // f(x) = a(x-1) + 1 149 | pageStart: (Math.floor(LOCAL_LIMIT_COMMENTS / BACKEND_LIMIT_COMMENTS) * (local.page - 1) + 1), 150 | // pageEnd: 151 | 152 | }; 153 | 154 | backend = getBackendFromBackendPage(backend.pageStart, backend.pageEnd); 155 | 156 | if (dev) console.log("getFirstBackendPageFromLocal() local: ", local); 157 | if (dev) console.log("getFirstBackendPageFromLocal() backend: ", backend); 158 | if (dev) console.log(`getFirstBackendPageFromLocal() local.page: ${local.page} | backend.pageStart: ${backend.pageStart}`) 159 | 160 | return backend; 161 | } 162 | 163 | 164 | 165 | 166 | 167 | let xhook = null; 168 | //XHook - v1.6.2 - https://github.com/jpillora/xhook | Jaime Pillora - MIT Copyright 2023 169 | xhook = function () { "use strict"; const e = (e, t) => Array.prototype.slice.call(e, t); let t = null; "undefined" != typeof WorkerGlobalScope && self instanceof WorkerGlobalScope ? t = self : "undefined" != typeof global ? t = global : window && (t = window); const n = t, o = t.document, r = ["load", "loadend", "loadstart"], s = ["progress", "abort", "error", "timeout"], a = e => ["returnValue", "totalSize", "position"].includes(e), i = function (e, t) { for (let n in e) { if (a(n)) continue; const o = e[n]; try { t[n] = o } catch (e) { } } return t }, c = function (e, t, n) { const o = e => function (o) { const r = {}; for (let e in o) { if (a(e)) continue; const s = o[e]; r[e] = s === t ? n : s } return n.dispatchEvent(e, r) }; for (let r of Array.from(e)) n._has(r) && (t[`on${r}`] = o(r)) }, u = function (e) { if (o && null != o.createEventObject) { const t = o.createEventObject(); return t.type = e, t } try { return new Event(e) } catch (t) { return { type: e } } }, l = function (t) { let n = {}; const o = e => n[e] || [], r = { addEventListener: function (e, t, r) { n[e] = o(e), n[e].indexOf(t) >= 0 || (r = void 0 === r ? n[e].length : r, n[e].splice(r, 0, t)) }, removeEventListener: function (e, t) { if (void 0 === e) return void (n = {}); void 0 === t && (n[e] = []); const r = o(e).indexOf(t); -1 !== r && o(e).splice(r, 1) }, dispatchEvent: function () { const n = e(arguments), s = n.shift(); t || (n[0] = i(n[0], u(s)), Object.defineProperty(n[0], "target", { writable: !1, value: this })); const a = r[`on${s}`]; a && a.apply(r, n); const c = o(s).concat(o("*")); for (let e = 0; e < c.length; e++) { c[e].apply(r, n) } }, _has: e => !(!n[e] && !r[`on${e}`]) }; return t && (r.listeners = t => e(o(t)), r.on = r.addEventListener, r.off = r.removeEventListener, r.fire = r.dispatchEvent, r.once = function (e, t) { var n = function () { return r.off(e, n), t.apply(null, arguments) }; return r.on(e, n) }, r.destroy = () => n = {}), r }; var f = function (e, t) { switch (typeof e) { case "object": return n = e, Object.entries(n).map((([e, t]) => `${e.toLowerCase()}: ${t}`)).join("\r\n"); case "string": return function (e, t) { const n = e.split("\r\n"); null == t && (t = {}); for (let e of n) if (/([^:]+):\s*(.+)/.test(e)) { const e = null != RegExp.$1 ? RegExp.$1.toLowerCase() : void 0, n = RegExp.$2; null == t[e] && (t[e] = n) } return t }(e, t) }var n; return [] }; const d = l(!0), p = e => void 0 === e ? null : e, h = n.XMLHttpRequest, y = function () { const e = new h, t = {}; let n, o, a, u = null; var y = 0; const v = function () { if (a.status = u || e.status, -1 !== u && (a.statusText = e.statusText), -1 === u); else { const t = f(e.getAllResponseHeaders()); for (let e in t) { const n = t[e]; if (!a.headers[e]) { const t = e.toLowerCase(); a.headers[t] = n } } } }, b = function () { x.status = a.status, x.statusText = a.statusText }, g = function () { n || x.dispatchEvent("load", {}), x.dispatchEvent("loadend", {}), n && (x.readyState = 0) }, E = function (e) { for (; e > y && y < 4;)x.readyState = ++y, 1 === y && x.dispatchEvent("loadstart", {}), 2 === y && b(), 4 === y && (b(), "text" in a && (x.responseText = a.text), "xml" in a && (x.responseXML = a.xml), "data" in a && (x.response = a.data), "finalUrl" in a && (x.responseURL = a.finalUrl)), x.dispatchEvent("readystatechange", {}), 4 === y && (!1 === t.async ? g() : setTimeout(g, 0)) }, m = function (e) { if (4 !== e) return void E(e); const n = d.listeners("after"); var o = function () { if (n.length > 0) { const e = n.shift(); 2 === e.length ? (e(t, a), o()) : 3 === e.length && t.async ? e(t, a, o) : o() } else E(4) }; o() }; var x = l(); t.xhr = x, e.onreadystatechange = function (t) { try { 2 === e.readyState && v() } catch (e) { } 4 === e.readyState && (o = !1, v(), function () { if (e.responseType && "text" !== e.responseType) "document" === e.responseType ? (a.xml = e.responseXML, a.data = e.responseXML) : a.data = e.response; else { a.text = e.responseText, a.data = e.responseText; try { a.xml = e.responseXML } catch (e) { } } "responseURL" in e && (a.finalUrl = e.responseURL) }()), m(e.readyState) }; const w = function () { n = !0 }; x.addEventListener("error", w), x.addEventListener("timeout", w), x.addEventListener("abort", w), x.addEventListener("progress", (function (t) { y < 3 ? m(3) : e.readyState <= 3 && x.dispatchEvent("readystatechange", {}) })), "withCredentials" in e && (x.withCredentials = !1), x.status = 0; for (let e of Array.from(s.concat(r))) x[`on${e}`] = null; if (x.open = function (e, r, s, i, c) { y = 0, n = !1, o = !1, t.headers = {}, t.headerNames = {}, t.status = 0, t.method = e, t.url = r, t.async = !1 !== s, t.user = i, t.pass = c, a = {}, a.headers = {}, m(1) }, x.send = function (n) { let u, l; for (u of ["type", "timeout", "withCredentials"]) l = "type" === u ? "responseType" : u, l in x && (t[u] = x[l]); t.body = n; const f = d.listeners("before"); var p = function () { if (!f.length) return function () { for (u of (c(s, e, x), x.upload && c(s.concat(r), e.upload, x.upload), o = !0, e.open(t.method, t.url, t.async, t.user, t.pass), ["type", "timeout", "withCredentials"])) l = "type" === u ? "responseType" : u, u in t && (e[l] = t[u]); for (let n in t.headers) { const o = t.headers[n]; n && e.setRequestHeader(n, o) } e.send(t.body) }(); const n = function (e) { if ("object" == typeof e && ("number" == typeof e.status || "number" == typeof a.status)) return i(e, a), "data" in e || (e.data = e.response || e.text), void m(4); p() }; n.head = function (e) { i(e, a), m(2) }, n.progress = function (e) { i(e, a), m(3) }; const d = f.shift(); 1 === d.length ? n(d(t)) : 2 === d.length && t.async ? d(t, n) : n() }; p() }, x.abort = function () { u = -1, o ? e.abort() : x.dispatchEvent("abort", {}) }, x.setRequestHeader = function (e, n) { const o = null != e ? e.toLowerCase() : void 0, r = t.headerNames[o] = t.headerNames[o] || e; t.headers[r] && (n = t.headers[r] + ", " + n), t.headers[r] = n }, x.getResponseHeader = e => p(a.headers[e ? e.toLowerCase() : void 0]), x.getAllResponseHeaders = () => p(f(a.headers)), e.overrideMimeType && (x.overrideMimeType = function () { e.overrideMimeType.apply(e, arguments) }), e.upload) { let e = l(); x.upload = e, t.upload = e } return x.UNSENT = 0, x.OPENED = 1, x.HEADERS_RECEIVED = 2, x.LOADING = 3, x.DONE = 4, x.response = "", x.responseText = "", x.responseXML = null, x.readyState = 0, x.statusText = "", x }; y.UNSENT = 0, y.OPENED = 1, y.HEADERS_RECEIVED = 2, y.LOADING = 3, y.DONE = 4; var v = { patch() { h && (n.XMLHttpRequest = y) }, unpatch() { h && (n.XMLHttpRequest = h) }, Native: h, Xhook: y }; function b(e, t, n, o) { return new (n || (n = Promise))((function (r, s) { function a(e) { try { c(o.next(e)) } catch (e) { s(e) } } function i(e) { try { c(o.throw(e)) } catch (e) { s(e) } } function c(e) { var t; e.done ? r(e.value) : (t = e.value, t instanceof n ? t : new n((function (e) { e(t) }))).then(a, i) } c((o = o.apply(e, t || [])).next()) })) } const g = n.fetch; function E(e) { return e instanceof Headers ? m([...e.entries()]) : Array.isArray(e) ? m(e) : e } function m(e) { return e.reduce(((e, [t, n]) => (e[t] = n, e)), {}) } const x = function (e, t = { headers: {} }) { let n = Object.assign(Object.assign({}, t), { isFetch: !0 }); if (e instanceof Request) { const o = function (e) { let t = {}; return ["method", "headers", "body", "mode", "credentials", "cache", "redirect", "referrer", "referrerPolicy", "integrity", "keepalive", "signal", "url"].forEach((n => t[n] = e[n])), t }(e), r = Object.assign(Object.assign({}, E(o.headers)), E(n.headers)); n = Object.assign(Object.assign(Object.assign({}, o), t), { headers: r, acceptedRequest: !0 }) } else n.url = e; const o = d.listeners("before"), r = d.listeners("after"); return new Promise((function (t, s) { let a = t; const i = function (e) { if (!r.length) return a(e); const t = r.shift(); return 2 === t.length ? (t(n, e), i(e)) : 3 === t.length ? t(n, e, i) : i(e) }, c = function (e) { if (void 0 !== e) { const n = new Response(e.body || e.text, e); return t(n), void i(n) } u() }, u = function () { if (!o.length) return void l(); const e = o.shift(); return 1 === e.length ? c(e(n)) : 2 === e.length ? e(n, c) : void 0 }, l = () => b(this, void 0, void 0, (function* () { const { url: t, isFetch: o, acceptedRequest: r } = n, c = function (e, t) { var n = {}; for (var o in e) Object.prototype.hasOwnProperty.call(e, o) && t.indexOf(o) < 0 && (n[o] = e[o]); if (null != e && "function" == typeof Object.getOwnPropertySymbols) { var r = 0; for (o = Object.getOwnPropertySymbols(e); r < o.length; r++)t.indexOf(o[r]) < 0 && Object.prototype.propertyIsEnumerable.call(e, o[r]) && (n[o[r]] = e[o[r]]) } return n }(n, ["url", "isFetch", "acceptedRequest"]); return e instanceof Request && c.body instanceof ReadableStream && (c.body = yield new Response(c.body).text()), g(t, c).then((e => i(e))).catch((function (e) { return a = s, i(e), s(e) })) })); u() })) }; var w = { patch() { g && (n.fetch = x) }, unpatch() { g && (n.fetch = g) }, Native: g, Xhook: x }; const O = d; return O.EventEmitter = l, O.before = function (e, t) { if (e.length < 1 || e.length > 2) throw "invalid hook"; return O.on("before", e, t) }, O.after = function (e, t) { if (e.length < 2 || e.length > 3) throw "invalid hook"; return O.on("after", e, t) }, O.enable = function () { v.patch(), w.patch() }, O.disable = function () { v.unpatch(), w.unpatch() }, O.XMLHttpRequest = v.Native, O.fetch = w.Native, O.headers = f, O.enable(), O }(); 170 | 171 | 172 | xhook.before((request, callback) => 173 | { 174 | /* ADBLOCK XHR START */ 175 | const prohibitedUrls = [ 176 | // "btloader.com", 177 | // "btmessage.com", 178 | // "4dex.io", 179 | // "a-mo.net", 180 | // "adform.net", 181 | // "adnxs-simple.com", 182 | // "connectad.io", 183 | // "creativecdn.com", 184 | // "criteo.com", 185 | // "dns-finder.com", 186 | // "pubmatic.com", 187 | // "r2b2.cz", 188 | // "rubiconproject.com", 189 | // "smilewanted.com", 190 | // "smartadserver.com", 191 | // "spolecznosci.net/", 192 | // "teads.tv", 193 | "https://ssp.wp.pl", 194 | "std.wpcdn.pl", 195 | "https://wykop.pl/api/v3/ads", 196 | ]; 197 | 198 | 199 | // if (dev) console.log(request.url); 200 | if (prohibitedUrls.some((url) => request.url.includes(url))) return; 201 | /* ADBLOCK XHR END */ 202 | 203 | 204 | let PAGETYPE = null; 205 | 206 | if ((request.url.includes("links") || request.url.includes("entries")) && request.url.includes("comments") && request.url.includes("page=")) 207 | { 208 | PAGETYPE = "comments"; 209 | } 210 | else if (request.url.startsWith("https://wykop.pl/api/v3/notes?") && window.location.href.includes("https://wykop.pl/ludzie/")) 211 | { 212 | // 'https://wykop.pl/api/v3/notes/username' - unikaj PUT i GET pobierania pojedynczego użytkownika / zapisywania edycji notatki 213 | if (!request.url.includes("page=")) request.url += "&page=1"; 214 | 215 | if (window.location.href.includes("/notatki")) 216 | { 217 | // strona wyświetlania notatek na profilu np. https://wykop.pl/ludzie/TwojLogin/notatki 218 | PAGETYPE = "notes"; 219 | } 220 | else 221 | { 222 | // strona własnego profilu np. https://wykop.pl/ludzie/TwojLogin 223 | if (request.url.includes("limit=3")) 224 | { 225 | // domyślnie na stronie profilu pobierane są 3 notatki w 1 requeście. Możemy pobrać w jednym requeście maksymalnie 50 226 | request.url = request.url.replace("limit=3", `limit=${Math.min(LIMIT_NOTES_ON_PROFILE_PAGES, BACKEND_LIMIT_NOTES)}`); 227 | } 228 | 229 | if (LIMIT_NOTES_ON_PROFILE_PAGES > BACKEND_LIMIT_NOTES) 230 | { 231 | // jeśli chcemy na stronie profilu więcej notatek niż 5-, to będziemy pobierać je w pętli przez xhook.after() 232 | PAGETYPE = "notes"; 233 | } 234 | 235 | if (request.url.includes("limit=100")) request.url = request.url.replace("limit=100", `limit=${BACKEND_LIMIT_NOTES}`); 236 | } 237 | } 238 | 239 | 240 | if (PAGETYPE != null) 241 | { 242 | if (dev) console.log(`xhook.before, PAGETYPE: ${PAGETYPE} | request.url: ${request.url}`); 243 | 244 | if (dev) console.log(request); 245 | if (dev) console.log(request.url); 246 | 247 | if (dev) console.log(`BEFORE - request o URL: request.url - ${request.url}`); 248 | 249 | const local = {}; 250 | local.item = { first: {} } 251 | 252 | if (request.url.includes("page=")) 253 | { 254 | [, local.page] = request.url.match(/page=(\d+)/) || [null, 1]; 255 | } 256 | else 257 | { 258 | local.page = 1; // na wszelki wypadek przy pobieraniu pierwszej strony https://wykop.pl/ludzie/uzytkownik/notatki URL do API nie ma ?page=1 259 | } 260 | 261 | 262 | // WSZYSTKIE KOMENTARZE NA JEDNEJ STRONIE - START 263 | if (PAGETYPE == "comments" && SHOW_ALL_COMMENTS_IN_ONE_PAGE_WITHOUT_ANY_LIMIT == true) 264 | { 265 | // ZA DUŻO KOMENTARZY, PONAD LIMITEM 5000, WIĘC JEDNAK I TAK BĘDZIEMY DZIELIĆ NA STRONY PO 500, ale działa tylko gdy przechodzi się na ?page=12 a nie na ?page=1 266 | if (local.page * 50 > LIMIT_MAXIMUM_COMMENTS_IN_ONE_PAGE) 267 | { 268 | if (dev) console.log(`BEFORE - chcialismy wyswietlic wszystkie komentarze na jednej stronie, ale jest ich za dużo, więc dzielimy je na podstrony po ${LIMIT_MAXIMUM_COMMENTS_IN_ONE_PAGE} sztuk`); 269 | SHOW_ALL_COMMENTS_IN_ONE_PAGE_WITHOUT_ANY_LIMIT = false; 270 | LOCAL_LIMIT_COMMENTS = LIMIT_MAXIMUM_COMMENTS_IN_ONE_PAGE; 271 | } 272 | else 273 | { 274 | // jeśli chcemy wszystkie komentarze na jednej stronie nawet gdy jest ich bardzo dużo, kazdy request ?page=8 (wejście fizycznie na stronę 8) zamieniamy na page=1 a potem obslugujemy wszystkie page=1 -> page=8 w xhook.after(); 275 | request.url = request.url.replace(/page=\d+/, 'page=1'); 276 | } 277 | } 278 | 279 | // WSZYSTKIE NOTATKI NA JEDNEJ STRONIE - START 280 | if (PAGETYPE == "notes" && SHOW_ALL_NOTES_IN_ONE_PAGE_WITHOUT_ANY_LIMIT == true) 281 | { 282 | // ZA DUŻO NOTATEK, PONAD LIMITEM 5000, WIĘC JEDNAK I TAK BĘDZIEMY DZIELIĆ NA STRONY PO 500, ale działa tylko gdy przechodzi się na ?page=12 a nie na ?page=1 283 | if (local.page * 50 > LIMIT_MAXIMUM_NOTES_IN_ONE_PAGE) 284 | { 285 | if (dev) console.log(`BEFORE - chcialismy wyswietlic wszystkie komentarze na jednej stronie, ale jest ich za dużo, więc dzielimy je na podstrony po ${LIMIT_MAXIMUM_COMMENTS_IN_ONE_PAGE} sztuk`); 286 | SHOW_ALL_COMMENTS_IN_ONE_PAGE_WITHOUT_ANY_LIMIT = false; 287 | LOCAL_LIMIT_NOTES = LIMIT_MAXIMUM_NOTES_IN_ONE_PAGE; 288 | } 289 | else 290 | { 291 | // jeśli chcemy wszystkie notatki na jednej stronie nawet gdy jest ich bardzo dużo, kazdy request ?page=8 (wejście fizycznie na stronę 8) zamieniamy na page=1 a potem obslugujemy wszystkie page=1 -> page=8 w xhook.after(); 292 | request.url = request.url.replace(/page=\d+/, 'page=1'); 293 | } 294 | } 295 | 296 | 297 | 298 | 299 | 300 | // ZMIENIAMY LICZBĘ KOMENTARZY NA PODSTRONACH z 50 na użytkownika 301 | if (PAGETYPE == "comments" && SHOW_ALL_COMMENTS_IN_ONE_PAGE_WITHOUT_ANY_LIMIT == false 302 | || PAGETYPE == "notest" && SHOW_ALL_NOTES_IN_ONE_PAGE_WITHOUT_ANY_LIMIT == false) 303 | { 304 | // jeśli chcemy mieć paginację Z INNĄ LICZBĄ NIŻ 50 KOMENTARZAMI, musimy obliczyć, którą stronę (backend.pageStart) faktycznie chcemy dostać na podstawie strony, którą użytkownik zażądał (local.page) 305 | if (PAGETYPE == "comments" && LOCAL_LIMIT_COMMENTS < BACKEND_LIMIT_COMMENTS 306 | || PAGETYPE == "notes" && LOCAL_LIMIT_NOTES < BACKEND_LIMIT_NOTES) 307 | { 308 | // chcemy mieć na stronie mniej niż 50 komentarzy więc zwyczajnie wybieramy 309 | // page= mniejszą niż 50 i ustawiamy limit dla backendu API odpowiedni do local_limit 310 | request.url = request.url.replace(/page=\d+/, `page=${local.page}`); 311 | } 312 | else if (PAGETYPE == "comments" && LOCAL_LIMIT_COMMENTS > BACKEND_LIMIT_COMMENTS 313 | || PAGETYPE == "notes" && LOCAL_LIMIT_NOTES > BACKEND_LIMIT_NOTES) 314 | { 315 | 316 | if (dev && PAGETYPE == "comments") console.log(`local_limit > BACKEND_LIMIT -> ${LOCAL_LIMIT_COMMENTS} > ${BACKEND_LIMIT_COMMENTS}`); 317 | if (dev && PAGETYPE == "notest") console.log(`local_limit > BACKEND_LIMIT -> ${LOCAL_LIMIT_NOTES} > ${BACKEND_LIMIT_NOTES}`); 318 | // chcemy mieć na stronie więcej niż 50 komentarzy, więc otwieramy w backendzie 319 | // pierwszą stronę, która zawiera aktualne wpisy 320 | // czyli np. gdy local_limit wynosi 70, a chcemy 2 stronę, czyli wpisy 71-140 321 | // to bedziemy chcieli faktycznie od backendu stronę 2 ponieważ komentarz 71 jest na 2. stronie po 50 wpisów (51-100) 322 | // więć otrzymamy wpisy 51-100 i wybierzemy wpisy od 71-100 323 | // natomiast potem xhook.after będzie pobierał stronę 3, żeby pobrać wpisy 101-140 324 | let backend = { pageStart: local.page }; 325 | backend = getBackendPagesFromLocal(local); 326 | request.url = request.url.replace(/page=\d+/, `page=${backend.pageStart}`); 327 | } 328 | 329 | // ILE KOMENTARZY NA STRONIE ma być pobranych z backendu (max 50) 330 | if (request.url.includes("limit=")) request.url = request.url.replace(/limit=\d+/, `limit=${per_page_comments}`); // min(x, 50) limit => per_page 331 | else { request.url += `&limit=${per_page_comments}`; } 332 | } 333 | 334 | if (dev) console.log("REQUEST WYSŁANY: ", request.url); 335 | } 336 | 337 | callback(); 338 | }); 339 | 340 | 341 | 342 | 343 | xhook.after((request, response) => 344 | { 345 | 346 | let PAGETYPE = null; 347 | if (response.status !== 200 || !response.finalUrl) return; 348 | 349 | // https://wykop.pl/api/v3/entries/80073681/comments?page=1 350 | 351 | // https://wykop.pl/api/v3/notes?limit=100 352 | // https://wykop.pl/api/v3/notes?page=3&limit=100 353 | if (!response.finalUrl.includes("comments") && !response.finalUrl.includes("notes")) return; 354 | 355 | 356 | // if ((response.finalUrl.includes("links") || response.finalUrl.includes("entries")) && response.finalUrl.includes("comments") && response.finalUrl.includes("page=")) 357 | if (response.finalUrl.includes("comments")) 358 | { 359 | PAGETYPE = "comments"; 360 | } 361 | else if (request.url.startsWith("https://wykop.pl/api/v3/notes?") && window.location.href.includes("https://wykop.pl/ludzie/")) 362 | { 363 | // 'https://wykop.pl/api/v3/notes/username' - unikaj PUT i GET pobierania pojedynczego użytkownika / zapisywania edycji notatki 364 | 365 | if (!request.url.includes("page=")) request.url += "&page=1"; 366 | 367 | if (window.location.href.includes("/notatki")) 368 | { 369 | // strona wyświetlania notatek na profilu np. https://wykop.pl/ludzie/TwojLogin/notatki 370 | PAGETYPE = "notes"; 371 | } 372 | else 373 | { 374 | // strona własnego profilu np. https://wykop.pl/ludzie/TwojLogin 375 | if (request.url.includes("limit=3")) 376 | { 377 | // domyślnie na stronie profilu pobierane są 3 notatki w 1 requeście. Możemy pobrać w jednym requeście maksymalnie 50 378 | request.url = request.url.replace("limit=3", `limit=${Math.min(LIMIT_NOTES_ON_PROFILE_PAGES, BACKEND_LIMIT_NOTES)}`); 379 | } 380 | 381 | if (LIMIT_NOTES_ON_PROFILE_PAGES > BACKEND_LIMIT_NOTES) 382 | { 383 | // jeśli chcemy na stronie profilu więcej notatek niż 5-, to będziemy pobierać je w pętli przez xhook.after() 384 | PAGETYPE = "notes"; 385 | } 386 | 387 | if (request.url.includes("limit=100")) request.url = request.url.replace("limit=100", `limit=${BACKEND_LIMIT_NOTES}`); 388 | } 389 | } 390 | 391 | if (dev) console.log("PAGETYPE", PAGETYPE); 392 | if (dev) console.log("xhook.after: ", response.finalUrl) 393 | 394 | 395 | 396 | 397 | if (PAGETYPE == "comments") 398 | { 399 | if (!response.finalUrl.startsWith("https://wykop.pl/api/v3/entries/") && !response.finalUrl.startsWith("https://wykop.pl/api/v3/links/")) return; 400 | if (!response.finalUrl.includes("page=")) return; // dla notatek domyslnie nie ma page= na pierwszej stronie :/ :/ 401 | } 402 | 403 | 404 | if (dev) console.log(`AFTER - response.finalUrl - ${response.finalUrl}`); 405 | if (dev) console.log("AFTER: response: ", response); 406 | 407 | let json = JSON.parse(response.text) 408 | 409 | if (dev) console.log("AFTER -- json", json) 410 | if (dev) console.log("AFTER -- json.pagination: ", json.pagination); 411 | 412 | 413 | // WSZYSTKIE KOMENTARZE NA JEDNEJ STRONIE - START 414 | if ((PAGETYPE == "comments" && SHOW_ALL_COMMENTS_IN_ONE_PAGE_WITHOUT_ANY_LIMIT == false)) 415 | { 416 | // ZA DUŻO KOMENTARZY, PONAD LIMITEM np. 500, WIĘC JEDNAK BĘDZIEMY DZIELIĆ NA STRONY PO 500 417 | if (json.pagination.total > LIMIT_MAXIMUM_COMMENTS_IN_ONE_PAGE) 418 | { 419 | if (dev) console.log(`AFTER - chcielismy wyswietlic wszystkie komentarze na jednej stronie, ale jest ich za dużo, więc JEDNAK dzielimy je na podstrony`); 420 | SHOW_ALL_COMMENTS_IN_ONE_PAGE_WITHOUT_ANY_LIMIT = false; 421 | LOCAL_LIMIT_COMMENTS = LIMIT_MAXIMUM_COMMENTS_IN_ONE_PAGE; 422 | } 423 | } 424 | if ((PAGETYPE == "notes" && SHOW_ALL_NOTES_IN_ONE_PAGE_WITHOUT_ANY_LIMIT == false)) 425 | { 426 | // ZA DUŻO NOTATEK, PONAD LIMITEM np. 500, WIĘC JEDNAK BĘDZIEMY DZIELIĆ NA STRONY PO 500 427 | if (json.pagination.total > LIMIT_MAXIMUM_NOTES_IN_ONE_PAGE) 428 | { 429 | if (dev) console.log(`AFTER - chcielismy wyswietlic wszystkie komentarze na jednej stronie, ale jest ich za dużo, więc JEDNAK dzielimy je na podstrony`); 430 | SHOW_ALL_COMMENTS_IN_ONE_PAGE_WITHOUT_ANY_LIMIT = false; 431 | LOCAL_LIMIT_COMMENTS = LIMIT_MAXIMUM_COMMENTS_IN_ONE_PAGE; 432 | } 433 | } 434 | 435 | // NIE MODYFIKUJEMY PODCZAS POBIERANIA KOLEJNYCH STRON page=2 ... DLA SHOW_ALL_COMMENTS_IN_ONE_PAGE, obsługujemy tylko page=1 436 | if (PAGETYPE == "comments" && SHOW_ALL_COMMENTS_IN_ONE_PAGE_WITHOUT_ANY_LIMIT == true && getPageParam(response.finalUrl) != 1) return; 437 | if (PAGETYPE == "notes" && SHOW_ALL_NOTES_IN_ONE_PAGE_WITHOUT_ANY_LIMIT == true && getPageParam(response.finalUrl) != 1) return; 438 | 439 | 440 | // https://wykop.pl/api/v3/entries/79760717/comments?page=1 441 | // https://wykop.pl/api/v3/links/7627183/comments?page=1&sort=best&ama=true 442 | // https://wykop.pl/api/v3/notes?limit=100&page=1 443 | 444 | 445 | const url = new URL(response.finalUrl); 446 | if (dev) console.log("AFTER: url ", url); 447 | if (dev) console.log("AFTER: url.pathname", url.pathname); 448 | 449 | let searchParams = new URLSearchParams(url.searchParams) 450 | let requestPage = parseInt(searchParams.get('page')); 451 | 452 | if (dev) console.log("AFTER: url.searchParams: "); 453 | if (dev) console.log(`AFTER: pageRequested = searchParams.get('page'): `, requestPage) 454 | 455 | // id wpisu/znaleziska 456 | let id = null; 457 | if (PAGETYPE == "comments") 458 | { 459 | id = (response.finalUrl.match(/\/links\/(\d+)|\/entries\/(\d+)/) || []).slice(1).find(Boolean); 460 | if (dev) console.log("AFTER: ID from URL: ", id); 461 | } 462 | 463 | if (dev) console.log("local_limit", LOCAL_LIMIT_COMMENTS) 464 | if (dev) console.log("json.data.length", json.data.length) 465 | if (dev) console.log("json.pagination.per_page", json.pagination.per_page) 466 | if (dev) console.log("json.pagination.total", json.pagination.total) 467 | 468 | 469 | 470 | 471 | // chcemy wyświetlić wszystkie na jednej stronie 472 | if (PAGETYPE == "comments" && SHOW_ALL_COMMENTS_IN_ONE_PAGE_WITHOUT_ANY_LIMIT 473 | || PAGETYPE == "notes" && SHOW_ALL_NOTES_IN_ONE_PAGE_WITHOUT_ANY_LIMIT) 474 | { 475 | const totalPages = Math.ceil(json.pagination.total / json.pagination.per_page); 476 | 477 | if (dev) console.log("for loop start ---------- SHOW ALL IN ONE PAGE"); 478 | if (dev) console.log("totalPages: ", totalPages); 479 | if (dev) console.log("urlPath: ", url.pathname) 480 | 481 | 482 | // POBIERAMY ELEMENTY Z WYBRANYCH STRON 483 | for (let page = 2; page <= totalPages; ++page) 484 | { 485 | // 429 too many requests fix 486 | 487 | if (page % 5 === 0) 488 | { 489 | const start = Date.now(); 490 | while (Date.now() - start < AWAIT_MILLISECONDS) 491 | { 492 | // Busy-wait loop to create delay 493 | } 494 | } 495 | 496 | searchParams.set('page', `${page}`); 497 | 498 | 499 | if (dev) console.log("url.pathname", url.pathname); 500 | if (dev) console.log("✔ xhook url.searchParams: ", searchParams); 501 | 502 | /* REQUEST */ 503 | const req = new XMLHttpRequest(); 504 | req.open('GET', `${url.pathname}?${searchParams.toString()}`, false); 505 | 506 | for (let key in request.headers) 507 | { 508 | if (request.headers.hasOwnProperty(key)) req.setRequestHeader(key, request.headers[key]); 509 | } 510 | 511 | req.send(null) 512 | 513 | if (req.status !== 200) 514 | { 515 | break; 516 | } 517 | /* REQUEST END */ 518 | 519 | let data = JSON.parse(req.responseText).data; 520 | if (dev) console.log("for loop - data: ", data) 521 | if (dev) console.log("for loop - json: ", json) 522 | if (data.length === 0) break; 523 | json.data = json.data.concat(data); 524 | if (dev) console.log("for loop - json2: ", json) 525 | } 526 | 527 | 528 | 529 | 530 | // zamiast "234" wyświetlamy 1.234 żeby nie wyświetlała się paginacja 531 | if (PAGETYPE == "comments" && json.data.length > BACKEND_LIMIT_COMMENTS 532 | || PAGETYPE == "notes" && json.data.length > BACKEND_LIMIT_NOTES) 533 | { 534 | json.pagination.total = parseFloat(`1.${json.data.length}`); 535 | } 536 | 537 | 538 | if (PAGETYPE == "notes") 539 | { 540 | // kod z mikroczat.pl / webworker.ts 541 | // sortowanie notatek od uzytkownikow 542 | if (json.data.length > 0) 543 | { 544 | json.data.sort((a, b) => 545 | { 546 | if (a.user.username && b.user.username) return a.user.username.localeCompare(b.user.username); 547 | return 0; 548 | }); 549 | 550 | // separate users and group them 551 | const regularUsers = []; 552 | const removedUsers = []; 553 | const bannedUsers = []; 554 | 555 | const removedUsernameIncludes = "....."; 556 | 557 | json.data.forEach(u => 558 | { 559 | // u = { content: "Treść notatki", user: UserObject } 560 | if (u.user.username.includes(removedUsernameIncludes)) 561 | { 562 | removedUsers.push(u); 563 | } 564 | else if (u.user.status === "banned") 565 | { 566 | bannedUsers.push(u); 567 | } 568 | else 569 | { 570 | regularUsers.push(u); 571 | } 572 | }); 573 | 574 | json.data = [...regularUsers, ...bannedUsers, ...removedUsers]; 575 | } 576 | } 577 | 578 | 579 | 580 | 581 | if (dev) console.log("json.data: ", json.data); 582 | 583 | 584 | 585 | 586 | 587 | response.text = JSON.stringify(json); 588 | 589 | return; 590 | } 591 | 592 | 593 | // uzytkownik chce wyswietlic wiecej niż 50 elementów, a jest więcej niż 50 elementów 594 | if (PAGETYPE == "comments" && (LOCAL_LIMIT_COMMENTS > json.data.length && LOCAL_LIMIT_COMMENTS > json.pagination.per_page) 595 | || PAGETYPE == "notes" && (LOCAL_LIMIT_NOTES > json.data.length && LOCAL_LIMIT_NOTES > json.pagination.per_page)) 596 | { 597 | if (dev && PAGETYPE == "comments") console.log(`AFTER: local_limit [${LOCAL_LIMIT_COMMENTS}] > json.data.length [${json.data.length}] && local_limit > json.pagination.per_page [${json.pagination.per_page}]`); 598 | if (dev && PAGETYPE == "notes") console.log(`AFTER: local_limit [${LOCAL_LIMIT_NOTES}] > json.data.length [${json.data.length}] && local_limit > json.pagination.per_page [${json.pagination.per_page}]`); 599 | 600 | 601 | if (dev) console.log("window.location.href", window.location.href) 602 | const openedCurrentPageNumber = extractPageNumber(window.location.href); 603 | if (dev) console.log(`NUMER STRONY OTWARTEJ Z URL:`, openedCurrentPageNumber); 604 | 605 | 606 | // TODO zrobic sprawdzenie czy obecna strona to np. strona/2 strona/3 i pobierac odpowiednio dalsze grupy 607 | // bazujac na backend page i local_page 608 | 609 | // TYLKO JEŚLI REQUEST JEST DO page=3 na stronie której jesteśmy /strona/3 (nawet pomijając więcej wpisów) 610 | if (requestPage == openedCurrentPageNumber) 611 | { 612 | // pobraliśmy już 50 komentarzy z aktalnej strony requestPage więc teraz bedziemy pobierać kolejne 50 z następnej 613 | let nextPage = requestPage + 1; 614 | 615 | // sprawdzić nextPage czy jest z local/backend, ale chyba jest ok z requestu 616 | 617 | 618 | let itemsFetchedInFirstRequest = json.data.length; // ile pobralismy w pierwszym requeście 619 | // let remainingComments = json.pagination.total - json.data.length; // local_limit - BACKEND_LIMIT; 620 | let remainingItemsToFetch = null; 621 | if (PAGETYPE == "comments") remainingItemsToFetch = LOCAL_LIMIT_COMMENTS - itemsFetchedInFirstRequest; // ile jeszcze do pobrania 622 | else if (PAGETYPE == "notes") remainingItemsToFetch = LOCAL_LIMIT_NOTES - itemsFetchedInFirstRequest; // ile jeszcze do pobrania 623 | 624 | const totalPagesToFetch = Math.ceil(remainingItemsToFetch / json.pagination.per_page); 625 | 626 | if (dev) console.log("requestPage", requestPage) 627 | if (dev) console.log("nextPage", nextPage) 628 | if (dev) console.log("itemsFetchedInFirstRequest", itemsFetchedInFirstRequest) 629 | if (dev) console.log("remainingItemsToFetch", remainingItemsToFetch) 630 | if (dev) console.log("totalPagesToFetch", totalPagesToFetch) 631 | 632 | let i = 1; 633 | 634 | if (dev) console.log(`--- while START: `); 635 | 636 | while (i <= totalPagesToFetch) 637 | { 638 | // 429 too many requests fix 639 | // await new Promise(resolve => setTimeout(resolve, AWAIT_MILLISECONDS)); 640 | 641 | if (dev) console.log(`--- while --- page: ${nextPage} START | i: ${i}`); 642 | 643 | searchParams.set('page', `${nextPage}`); 644 | 645 | /* REQUEST */ 646 | let req = new XMLHttpRequest(); 647 | req.open('GET', `${url.pathname}?${searchParams.toString()}`, false) 648 | 649 | for (let key in request.headers) 650 | { 651 | if (request.headers.hasOwnProperty(key)) req.setRequestHeader(key, request.headers[key]); 652 | } 653 | req.send(null); 654 | 655 | if (req.status !== 200) break; 656 | /* REQUEST END */ 657 | 658 | let data = JSON.parse(req.responseText).data; 659 | if (data.length === 0) break; 660 | 661 | json.data = json.data.concat(data); 662 | 663 | itemsFetchedInFirstRequest += data.length; 664 | remainingItemsToFetch -= itemsFetchedInFirstRequest; 665 | nextPage++; 666 | i++; 667 | if (dev) console.log("while - i: ", i) 668 | if (dev) console.log("while - nextPage: ", nextPage) 669 | if (dev) console.log("while - itemsFetchedInFirstRequest: ", itemsFetchedInFirstRequest) 670 | if (dev) console.log("while - remainingItemsToFetch: ", remainingItemsToFetch) 671 | if (dev) console.log(`while - Fetched [${data.length}] comments on page [${nextPage - 1}] and got JSON `, data); 672 | 673 | } 674 | 675 | if (PAGETYPE == "comments") 676 | { 677 | if (itemsFetchedInFirstRequest > LOCAL_LIMIT_COMMENTS) 678 | { 679 | if (dev) console.log(`Successfully fetched [${itemsFetchedInFirstRequest}] comments. Slicing to [${LOCAL_LIMIT_COMMENTS}]`); 680 | json.data = json.data.slice(0, LOCAL_LIMIT_COMMENTS); // dla pewnosci 681 | } 682 | else 683 | { 684 | if (dev) console.log(`Only [${itemsFetchedInFirstRequest}] comments available in total.`); 685 | } 686 | 687 | json.pagination.total = LOCAL_LIMIT_COMMENTS; // tu zmienić wyswietlanie na 1.123 688 | } 689 | 690 | 691 | else if (PAGETYPE == "notes") 692 | { 693 | if (itemsFetchedInFirstRequest > LOCAL_LIMIT_NOTES) 694 | { 695 | if (dev) console.log(`Successfully fetched [${itemsFetchedInFirstRequest}] notes. Slicing to [${LOCAL_LIMIT_NOTES}]`); 696 | json.data = json.data.slice(0, LOCAL_LIMIT_NOTES); // dla pewnosci 697 | } 698 | else 699 | { 700 | if (dev) console.log(`Only [${itemsFetchedInFirstRequest}] notes available in total.`); 701 | } 702 | json.pagination.total = LOCAL_LIMIT_NOTES; // tu zmienić wyswietlanie na 1.123 703 | } 704 | 705 | response.text = JSON.stringify(json); 706 | } 707 | 708 | } 709 | }); 710 | })(); -------------------------------------------------------------------------------- /Twitter X Style/twitter_x_style.user.css: -------------------------------------------------------------------------------- 1 | /* ==UserStyle== 2 | @name Twitter X Ads Blocker 3 | @version 1.0.6 4 | 5 | @description Best AdBlock for X.com / Twitter.com Blocks and removes all ads, sponsored tweets. You can customise and remove irrelevant panels like Subscribe Premium or Who to Follow. adblock, adsblock. uBlock. Remove ads. Block hide remove advertisements and adverts. 6 | @description https://wiki.wykopx.pl 7 | 8 | 9 | Support and buy a small coffee https://buycoffee.to/wykopx 10 | 11 | 12 | ---- AUTHOR ---- 13 | 14 | @author Wykop X | wiki.wykopx.pl 15 | @homepageURL http://wiki.wykopx.pl 16 | @supportURL https://buycoffee.to/wykopx 17 | 18 | ---- AUTHOR ---- 19 | 20 | 21 | @var range HR_AD_blocker `AD BLOCKER` [0, 0, 99900, 1, 'mm'] 22 | 23 | @var select adsRemoval `⛔ Block Ads` { 24 | "Show ads":"disabled", 25 | "Block & remove ads*":"enabled", 26 | } 27 | 28 | @var select sponsoredRemoval `⛔ Sponsored tweets` { 29 | "Show sponsored tweets":"disabled", 30 | "Block & remove sponsored tweets*":"enabled", 31 | } 32 | 33 | @var range HR_SHOW_ADS_PREFERENCES `SHOWING ADs PREFERENCES` [0, 0, 99900, 1, 'mm'] 34 | 35 | @var checkbox adsStylingOpacity `Ads semi-transparent` 1 36 | @var checkbox adsStylingGrayedOut `Ads in grayscale` 1 37 | @var checkbox adsStylingBluredOut `Ads blurred` 1 38 | @var checkbox adsMarkerShow `Show info marker on every ad` 1 39 | 40 | 41 | @var range HR_HIDE_STREAM `HIDE STREAM ELEMENTS` [0, 0, 99900, 1, 'mm'] 42 | 43 | @var checkbox removeTimelineSubscribePremium `⛔ Hide "Subscribe Premium" announcement` 1 44 | @var checkbox removeTimelineAnnouncements `⛔ Hide X announcements on Home stream` 0 45 | var checkbox removeTimelineCreatorsForYou `⛔ Hide "Creators For You"` 1 46 | var checkbox removeTimelineDiscoverNewCommunities `⛔ Hide "Discover new Communities"` 1 47 | @var checkbox removeTimelineWhoToFollow `⛔ Hide "Who to follow"` 1 48 | 49 | 50 | @var range HR_HIDE_LEFT_MENU `HIDE LEFT MENU ITEMS` [0, 0, 99900, 1, 'mm'] 51 | @var checkbox removeLeftHome `⛔ Hide "Home"` 0 52 | @var checkbox removeLeftExplore `⛔ Hide "Explore"` 0 53 | @var checkbox removeLeftNotifications `⛔ Hide "Notifications"` 0 54 | @var checkbox removeLeftMessages `⛔ Hide "Messages" 🔹` 0 55 | @var checkbox removeLeftBookmarks `⛔ Hide "Bookmarks"` 1 56 | @var checkbox removeLeftJobs `⛔ Hide "Jobs"` 1 57 | @var checkbox removeLeftCommunities `⛔ Hide "Communities"` 0 58 | @var checkbox removeLeftPremium `⛔ Hide "Premium"` 1 59 | @var checkbox removeLeftVerified `⛔ Hide "Verified Orgs"` 1 60 | @var checkbox removeLeftProfile `⛔ Hide "Profile"` 0 61 | @var checkbox removeLeftMore `⛔ Hide "More..."` 0 62 | @var checkbox removeReadonlyPostButton `⛔ Hide "Post" button in left menu 🔸` 0 63 | 64 | @var range HR_HIDE_STREAM `HIDE SIDEBAR ELEMENTS` [0, 0, 99900, 1, 'mm'] 65 | @var checkbox removeSidebarSubscribePremium `⛔ Hide "Subscribe Premium"` 1 66 | @var checkbox removeSidebarBlockWhoToFollow `⛔ Hide "Who to follow"` 1 67 | @var checkbox removeSidebarBlockTrends `⛔ Hide "Trends"` 0 68 | @var checkbox removeSidebarTOSFooter `⛔ Hide sidebar Footer` 1 69 | 70 | @var range HR_HIDE_TWEET_ELEMENTS `HIDE TWEET ELEMENTS` [0, 0, 99900, 1, 'mm'] 71 | @var checkbox removeReadonlyShareButton `⛔ Hide share button 🔸` 0 72 | 73 | @var range HR_HIDE_READONLY `TURN OFF POSTING - READ-ONLY MODE 🔸` [0, 0, 99900, 1, 'mm'] 74 | @var checkbox removeReadonlyPreset `[PRESET 🔸] Enable read-only mode` 0 75 | @var checkbox removeReadonlyNewEntry `⛔ Hide new entry textbox 🔸` 0 76 | @var checkbox removeReadonlyNewCommentTextbox `⛔ Hide new comment textboxes 🔸` 0 77 | @var checkbox removeReadonlyNewCommentModal `⛔ Hide new comment modal 🔸` 0 78 | 79 | 80 | 81 | @var range HR_HIDE_OTHER_ELEMENTS `TURN OFF MESSAGING` [0, 0, 99900, 1, 'mm'] 82 | @var checkbox removeMessagesPreset `[PRESET 🔹] Turn off Messaging (DMs)` 0 83 | @var checkbox removeMessagesBox `⛔ Hide "Messages" box 🔹` 0 84 | @var checkbox removeMessageButton `⛔ Hide "Message" button on user profile 🔹` 0 85 | 86 | @var range HR_EXTRA_FEATURES `EXTRA FEATURES` [0, 0, 99900, 1, 'mm'] 87 | @var checkbox tweetsShowDateTime `⌚ Date & time in tweets (e.g. 2024-12-31 23:59:59)` 1 88 | 89 | 90 | @var range HR_TESTING `DEBUGGING` [0, 0, 99900, 1, 'mm'] 91 | @var checkbox dev `Show and mark blocked/hidden elements` 0 92 | 93 | 94 | @preprocessor stylus 95 | @namespace userstyles.world/user/wykopchanger 96 | @license No License (YOU CAN USE THIS CODE ONLY IN STYLUS EXTENSIONS. You are NOT ALLOWED TO copy, share and use any part of this code anywhere else without author's written permission) 97 | 98 | 99 | 100 | ==/UserStyle== */ 101 | 102 | @-moz-document domain("x.com"), domain("twitter.com") 103 | { 104 | i = !important; 105 | 106 | 107 | 108 | if(removeReadonlyPreset == 1) 109 | { 110 | removeReadonlyPostButton = 1; 111 | removeReadonlyNewEntry = 1; 112 | removeReadonlyNewCommentTextbox = 1; 113 | removeReadonlyNewCommentModal = 1; 114 | removeReadonlyShareButton = 1; 115 | } 116 | 117 | if(removeMessagesPreset == 1) 118 | { 119 | removeLeftMessages = 1; 120 | removeMessagesBox = 1; 121 | removeMessageButton = 1; 122 | } 123 | if(removeMessagesBox == 1) 124 | { 125 | div.r-12vffkv > div > div[data-testid="DMDrawer"] 126 | { 127 | if(dev) { border: 10px solid #004eff i; } 128 | else { display: none i; } 129 | } 130 | } 131 | if(removeMessageButton == 1) 132 | { 133 | div[data-testid="primaryColumn"] div[data-testid^="UserAvatar"] + div > button[data-testid="sendDMFromProfile"] 134 | { 135 | if(dev) { border: 3px solid #004eff i; } 136 | else { display: none i; } 137 | } 138 | } 139 | 140 | 141 | div[data-testid="cellInnerDiv"]:has(div.r-1kkk96v span) 142 | { 143 | /* border: 3px solid red i; */ 144 | } 145 | 146 | 147 | 148 | if(sponsoredRemoval == "enabled") 149 | { 150 | div[data-testid="cellInnerDiv"]:has(path[d="M19.498 3h-15c-1.381 0-2.5 1.12-2.5 2.5v13c0 1.38 1.119 2.5 2.5 2.5h15c1.381 0 2.5-1.12 2.5-2.5v-13c0-1.38-1.119-2.5-2.5-2.5zm-3.502 12h-2v-3.59l-5.293 5.3-1.414-1.42L12.581 10H8.996V8h7v7z"]) 151 | { 152 | if(dev) { border: 10px solid #d1e123 i; } 153 | else { display: none i; } 154 | } 155 | /* div[data-testid="cellInnerDiv"]:has(svg + div > span) 156 | { 157 | outline: 3px solid white i; 158 | } */ 159 | } 160 | 161 | 162 | 163 | 164 | if(adsRemoval == "enabled") 165 | { 166 | /* div.r-1kkk96v - right aligned top post */ 167 | div[data-testid="cellInnerDiv"]:has(div.r-1kkk96v > div > div > span) 168 | { 169 | if(dev) { border: 10px solid #1ed940 i; } 170 | else { display: none i; } 171 | } 172 | } 173 | else 174 | { 175 | div[data-testid="cellInnerDiv"]:has(div.r-1kkk96v span):not(:hover) 176 | { 177 | transition: all 0.2s; 178 | display: flex i; 179 | position: absolute i; 180 | 181 | if(adsStylingOpacity == 1) 182 | { 183 | opacity: 0.3 i; 184 | } 185 | 186 | if(adsStylingGrayedOut == 1) 187 | { 188 | filter: grayscale(1) i; 189 | 190 | if(adsStylingBluredOut == 1) 191 | { 192 | filter: grayscale(1) blur(3px) i; 193 | } 194 | } 195 | else if(adsStylingBluredOut == 1) 196 | { 197 | filter: blur(3px) i; 198 | } 199 | } 200 | if(adsMarkerShow == 1) 201 | { 202 | div[data-testid="cellInnerDiv"] div.r-1kkk96v span 203 | { 204 | display: none i; 205 | } 206 | div[data-testid="cellInnerDiv"]:has(div.r-1kkk96v span):before 207 | { 208 | display: flex; 209 | position: fixed; 210 | z-index: 999999; 211 | right: 0px; 212 | top: 150px; 213 | width: 20%; 214 | content: "Advertisement"; 215 | font-family: TwitterChirp, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; 216 | padding: 13px 13px 13px 20px; 217 | font-size: 0.9rem; 218 | font-weight: 600; 219 | color: rgba(220, 220, 220, 1); 220 | background-color: rgba(40, 40, 40, 0.9); 221 | border-radius: 6px 0px 0px 6px; 222 | border: 1px solid rgba(220, 220, 220, 0.1); 223 | border-right: none; 224 | box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); 225 | } 226 | } 227 | } 228 | 229 | if(removeTimelineSubscribePremium == 1) 230 | { 231 | div[data-testid="primaryColumn"] div[data-testid="cellInnerDiv"]:has(a[href^="/i/premium_sign_up"]) 232 | { 233 | if(dev) { border: 10px solid #6dfd68 i; } 234 | else { display: none i; } 235 | } 236 | } 237 | if(removeTimelineAnnouncements == 1) 238 | { 239 | div[data-testid="primaryColumn"] div[data-testid="cellInnerDiv"]:has(h1[role="heading"]):has(a[href]) 240 | { 241 | if(dev) { border: 10px solid #f00 i; } 242 | else { display: none i; } 243 | } 244 | } 245 | 246 | 247 | 248 | if(removeTimelineCreatorsForYou == 1) 249 | { 250 | div[data-testid="primaryColumn"] div[data-testid="cellInnerDiv"] div.css-175oi2r div div span 251 | { 252 | /* border: 3px solid red i; */ 253 | } 254 | } 255 | if(removeTimelineDiscoverNewCommunities == 1) 256 | { 257 | div[data-testid="primaryColumn"] div[data-testid="cellInnerDiv"] 258 | { 259 | /* border: 3px solid red i; */ 260 | } 261 | } 262 | 263 | if(removeTimelineWhoToFollow == 1) 264 | { 265 | main[role="main"] > div.css-175oi2r.r-150rngu.r-16y2uox.r-1wbh5a2.r-113js5t > div.css-175oi2r.r-aqfbo4.r-16y2uox > div.css-175oi2r.r-1oszu61.r-1niwhzg.r-18u37iz.r-16y2uox.r-2llsf.r-13qz1uu.r-1wtj0ep > div.css-175oi2r.r-yfoy6g.r-18bvks7.r-1ua6aaf.r-th6na.r-1phboty.r-16y2uox.r-184en5c.r-1c4cdxw.r-1t251xo.r-f8sm7e.r-13qz1uu.r-1ye8kvj[data-testid="primaryColumn"] > div.css-175oi2r > div.css-175oi2r > div.css-175oi2r.r-16y2uox div[data-testid="cellInnerDiv"]:has(> div.css-175oi2r.r-1adg3ll.r-1ny4l3l > div.css-175oi2r > div.css-175oi2r.r-1wtj0ep.r-1mmae3n.r-3pj75a.r-1ny4l3l > h2.css-175oi2r.r-18u37iz.r-7cikom > div.css-175oi2r.r-1kihuf0.r-18u37iz.r-16y2uox.r-17s6mgv.r-1ez5h0i), 266 | main[role="main"] > div.css-175oi2r.r-150rngu.r-16y2uox.r-1wbh5a2.r-113js5t > div.css-175oi2r.r-aqfbo4.r-16y2uox > div.css-175oi2r.r-1oszu61.r-1niwhzg.r-18u37iz.r-16y2uox.r-2llsf.r-13qz1uu.r-1wtj0ep > div.css-175oi2r.r-yfoy6g.r-18bvks7.r-1ua6aaf.r-th6na.r-1phboty.r-16y2uox.r-184en5c.r-1c4cdxw.r-1t251xo.r-f8sm7e.r-13qz1uu.r-1ye8kvj[data-testid="primaryColumn"] > div.css-175oi2r > div.css-175oi2r > div.css-175oi2r.r-16y2uox div[data-testid="cellInnerDiv"]:has(> div.css-175oi2r.r-1adg3ll.r-1ny4l3l > div.css-175oi2r > div.css-175oi2r.r-1wtj0ep.r-1mmae3n.r-3pj75a.r-1ny4l3l > h2.css-175oi2r.r-18u37iz.r-7cikom > div.css-175oi2r.r-1kihuf0.r-18u37iz.r-16y2uox.r-17s6mgv.r-1ez5h0i) + div, 267 | main[role="main"] > div.css-175oi2r.r-150rngu.r-16y2uox.r-1wbh5a2.r-113js5t > div.css-175oi2r.r-aqfbo4.r-16y2uox > div.css-175oi2r.r-1oszu61.r-1niwhzg.r-18u37iz.r-16y2uox.r-2llsf.r-13qz1uu.r-1wtj0ep > div.css-175oi2r.r-yfoy6g.r-18bvks7.r-1ua6aaf.r-th6na.r-1phboty.r-16y2uox.r-184en5c.r-1c4cdxw.r-1t251xo.r-f8sm7e.r-13qz1uu.r-1ye8kvj[data-testid="primaryColumn"] > div.css-175oi2r > div.css-175oi2r > div.css-175oi2r.r-16y2uox div[data-testid="cellInnerDiv"]:has(> div.css-175oi2r.r-1adg3ll.r-1ny4l3l > div.css-175oi2r > div.css-175oi2r.r-1wtj0ep.r-1mmae3n.r-3pj75a.r-1ny4l3l > h2.css-175oi2r.r-18u37iz.r-7cikom > div.css-175oi2r.r-1kihuf0.r-18u37iz.r-16y2uox.r-17s6mgv.r-1ez5h0i) + div + div, 268 | main[role="main"] > div.css-175oi2r.r-150rngu.r-16y2uox.r-1wbh5a2.r-113js5t > div.css-175oi2r.r-aqfbo4.r-16y2uox > div.css-175oi2r.r-1oszu61.r-1niwhzg.r-18u37iz.r-16y2uox.r-2llsf.r-13qz1uu.r-1wtj0ep > div.css-175oi2r.r-yfoy6g.r-18bvks7.r-1ua6aaf.r-th6na.r-1phboty.r-16y2uox.r-184en5c.r-1c4cdxw.r-1t251xo.r-f8sm7e.r-13qz1uu.r-1ye8kvj[data-testid="primaryColumn"] > div.css-175oi2r > div.css-175oi2r > div.css-175oi2r.r-16y2uox div[data-testid="cellInnerDiv"]:has(> div.css-175oi2r.r-1adg3ll.r-1ny4l3l > div.css-175oi2r > div.css-175oi2r.r-1wtj0ep.r-1mmae3n.r-3pj75a.r-1ny4l3l > h2.css-175oi2r.r-18u37iz.r-7cikom > div.css-175oi2r.r-1kihuf0.r-18u37iz.r-16y2uox.r-17s6mgv.r-1ez5h0i) + div + div + div, 269 | main[role="main"] > div.css-175oi2r.r-150rngu.r-16y2uox.r-1wbh5a2.r-113js5t > div.css-175oi2r.r-aqfbo4.r-16y2uox > div.css-175oi2r.r-1oszu61.r-1niwhzg.r-18u37iz.r-16y2uox.r-2llsf.r-13qz1uu.r-1wtj0ep > div.css-175oi2r.r-yfoy6g.r-18bvks7.r-1ua6aaf.r-th6na.r-1phboty.r-16y2uox.r-184en5c.r-1c4cdxw.r-1t251xo.r-f8sm7e.r-13qz1uu.r-1ye8kvj[data-testid="primaryColumn"] > div.css-175oi2r > div.css-175oi2r > div.css-175oi2r.r-16y2uox div[data-testid="cellInnerDiv"]:has(> div.css-175oi2r.r-1adg3ll.r-1ny4l3l > div.css-175oi2r > div.css-175oi2r.r-1wtj0ep.r-1mmae3n.r-3pj75a.r-1ny4l3l > h2.css-175oi2r.r-18u37iz.r-7cikom > div.css-175oi2r.r-1kihuf0.r-18u37iz.r-16y2uox.r-17s6mgv.r-1ez5h0i) + div + div + div + div, 270 | { 271 | if(dev) { border: 10px solid #252bee i; } 272 | else { display: none i; } 273 | } 274 | } 275 | 276 | 277 | 278 | 279 | if(removeSidebarBlockWhoToFollow == 1) 280 | { 281 | div[data-testid="sidebarColumn"] div.r-1ifxtd0:has(aside > div > h2) 282 | { 283 | if(dev) { border: 10px solid #5cdf8c i; } 284 | else { display: none i; } 285 | } 286 | } 287 | 288 | if(removeSidebarBlockTrends == 1) 289 | { 290 | div[data-testid="sidebarColumn"] div.r-1ifxtd0:has(div > section) 291 | { 292 | if(dev) { border: 10px solid #3c5123 i; } 293 | else { display: none i; } 294 | } 295 | } 296 | if(removeSidebarTOSFooter == 1) 297 | { 298 | div[data-testid="sidebarColumn"] div.r-1yadl64 299 | { 300 | if(dev) { border: 10px solid #5c3030 i; } 301 | else { display: none i; } 302 | } 303 | } 304 | if(removeSidebarSubscribePremium == 1) 305 | { 306 | div[data-testid="sidebarColumn"] > div > div > div > div > div > div:has(aside > a[href^="/i/premium_sign_up"]), 307 | div[data-testid="sidebarColumn"] > div.css-175oi2r:has(> div.css-175oi2r.r-yfoy6g.r-18bvks7.r-1867qdf.r-1phboty.r-rs99b7.r-1ifxtd0.r-1udh08x a[href^="/i/premium_sign_up"]) 308 | { 309 | if(dev) { border: 10px solid #6a00ff i; } 310 | else { display: none i; } 311 | } 312 | } 313 | 314 | 315 | 316 | if(removeReadonlyShareButton == 1) 317 | { 318 | article[data-testid="tweet"] div.css-175oi2r div.css-175oi2r[role="group"] > div.css-175oi2r:not(.r-18u37iz) 319 | { 320 | if(dev) { border: 2px solid #c70 i; } 321 | else { display: none i; } 322 | } 323 | } 324 | if(removeReadonlyPostButton == 1) 325 | { 326 | header[role="banner"] div.css-175oi2r.r-e7q0ms.r-12kyg2d:has(a[href="/compose/post"]) 327 | { 328 | if(dev) { border: 10px solid #c70 i; } 329 | else { display: none i; } 330 | } 331 | } 332 | if(removeReadonlyNewEntry == 1) 333 | { 334 | main[role="main"] div[data-testid="primaryColumn"] > div > div.css-175oi2r.r-yfoy6g.r-184en5c 335 | { 336 | if(dev) { border: 10px solid #c70 i; } 337 | else { display: none i; } 338 | } 339 | } 340 | if(removeReadonlyNewCommentTextbox == 1) 341 | { 342 | div[data-testid="cellInnerDiv"] div[data-testid="inline_reply_offscreen"] 343 | { 344 | if(dev) { border: 10px solid #c70 i; } 345 | else { display: none i; } 346 | } 347 | } 348 | /* if(removeReadonlyNewCommentModal == 1) 349 | { 350 | div#react-root div#layers > div.r-12vffkv:has(div[data-testid="tweetTextarea_0_label"]) 351 | { 352 | if(dev) { border: 10px solid #c70 i; } 353 | else { display: none i; } 354 | } 355 | } */ 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | if(tweetsShowDateTime == 1) 366 | { 367 | 368 | div[data-testid="cellInnerDiv"] time 369 | { 370 | display: block flex; 371 | overflow: hidden; 372 | width: 171px; 373 | } 374 | 375 | div[data-testid="cellInnerDiv"] time:after 376 | { 377 | display: block; 378 | content: attr(datetime); 379 | font-family: monospace; 380 | font-size: 13px; 381 | font-weight: 600; 382 | opacity: 1; 383 | margin-left: 10px; 384 | 385 | background: -webkit-linear-gradient(360deg, rgb(128, 128, 128) 71px, transparent 71px, transparent 71px, transparent 71px, transparent 78px, rgb(128, 128, 128) 78px, rgb(128, 128, 128) 158px, transparent 156px); 386 | -webkit-background-clip: text; 387 | -webkit-text-fill-color: transparent; 388 | 389 | width: 171px; 390 | } 391 | } 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | if(removeLeftHome == 1) 401 | { 402 | nav[role="navigation"] a[href="/home"] 403 | { 404 | if(dev) { border: 4px solid #ff0008 i; } 405 | else { display: none i; } 406 | } 407 | } 408 | if(removeLeftExplore == 1) 409 | { 410 | nav[role="navigation"] a[href="/explore"] 411 | { 412 | if(dev) { border: 4px solid #ff0008 i; } 413 | else { display: none i; } 414 | } 415 | } 416 | if(removeLeftNotifications == 1) 417 | { 418 | nav[role="navigation"] a[href="/notifications"] 419 | { 420 | if(dev) { border: 4px solid #ff0008 i; } 421 | else { display: none i; } 422 | } 423 | } 424 | if(removeLeftMessages == 1) 425 | { 426 | nav[role="navigation"] a[href^="/messages"] 427 | { 428 | if(dev) { border: 4px solid blue i; } 429 | else { display: none i; } 430 | } 431 | } 432 | if(removeLeftBookmarks == 1) 433 | { 434 | nav[role="navigation"] a[href="/i/bookmarks"] 435 | { 436 | if(dev) { border: 4px solid #ff0008 i; } 437 | else { display: none i; } 438 | } 439 | } 440 | if(removeLeftJobs == 1) 441 | { 442 | nav[role="navigation"] a[href="/jobs"] 443 | { 444 | if(dev) { border: 4px solid #ff0008 i; } 445 | else { display: none i; } 446 | } 447 | } 448 | if(removeLeftCommunities == 1) 449 | { 450 | nav[role="navigation"] a[href$="/communities"] 451 | { 452 | if(dev) { border: 4px solid #ff0008 i; } 453 | else { display: none i; } 454 | } 455 | } 456 | if(removeLeftPremium == 1) 457 | { 458 | nav[role="navigation"] a[href="/i/premium_sign_up"] 459 | { 460 | if(dev) { border: 4px solid #ff0008 i; } 461 | else { display: none i; } 462 | } 463 | } 464 | if(removeLeftVerified == 1) 465 | { 466 | nav[role="navigation"] a[href="/i/verified-orgs-signup"] 467 | { 468 | if(dev) { border: 4px solid #ff0008 i; } 469 | else { display: none i; } 470 | } 471 | } 472 | if(removeLeftMore == 1) 473 | { 474 | nav[role="navigation"] button[aria-haspopup="menu"] 475 | { 476 | if(dev) { border: 4px solid #ff0008 i; } 477 | else { display: none i; } 478 | } 479 | } 480 | } 481 | 482 | 483 | @-moz-document url-prefix("moz-extension://"), url-prefix("chrome-extension://") 484 | { 485 | body#stylus-manage 486 | { 487 | display: grid!important; 488 | } 489 | 490 | body#stylus-manage > div#message-box 491 | { 492 | justify-self: center !important; 493 | 494 | border: 1px solid var(--accent-2); 495 | box-shadow: 1px 0px 10px 13px rgba(0, 0, 0, 0.3); 496 | //margin: 10px; 497 | 498 | left: unset!important; 499 | right: unset!important; 500 | top: 20px; 501 | bottom: 20px; 502 | 503 | width: 30%; 504 | min-width: 800px; 505 | max-width: 2000px; 506 | 507 | position: fixed; 508 | } 509 | 510 | @media screen and (max-width: 840px) 511 | { 512 | body#stylus-manage > div#message-box 513 | { 514 | left: 5px!important; 515 | right: 5px!important; 516 | top: 5px!important; 517 | bottom: 5px!important; 518 | 519 | width: calc(100% - 10px); 520 | min-width: unset; 521 | max-width: unset; 522 | } 523 | } 524 | body#stylus-manage > div#message-box > div 525 | { 526 | left: unset!important; 527 | right: 0px!important; 528 | position: sticky!important; 529 | width: 100%!important; 530 | } 531 | 532 | /* for screenshot */ 533 | /* 534 | body#stylus-manage 535 | { 536 | background-color: rgb(13, 17, 23); 537 | } 538 | body#stylus-manage > div#message-box 539 | { 540 | position: relative!important; 541 | width: 100%; 542 | min-width: 700px; 543 | max-width: 2000px; 544 | margin: 60px!important; 545 | } 546 | body#stylus-manage > div#message-box > div 547 | { 548 | position: sticky!important; 549 | width: 100%!important; 550 | } 551 | */ 552 | 553 | 554 | 555 | 556 | body#stylus-manage > div#installed > div.entry:has(> h2 > a[href*="wykopx.pl"]) 557 | { 558 | order: -888; 559 | } 560 | body#stylus-manage > div#installed > div.entry.disabled:has(> h2 > a[href*="wykopx.pl"]) > h2.style-name > a.style-name-link 561 | { 562 | color: var(--accent-2)!important; 563 | } 564 | body#stylus-manage > div#installed > div.entry.enabled:has(> h2 > a[href*="wykopx.pl"]) 565 | { 566 | order: -999; 567 | background-color: var(--accent-3)!important; 568 | } 569 | body#stylus-manage > div#installed > div.entry:has(> h2 > a[href*="wykopx.pl"]) > p > a.configure-usercss > i::after 570 | { 571 | color: var(--c00); 572 | font-size: 22px; 573 | } 574 | body#stylus-manage > div#installed > div.entry:has(> h2 > a[href*="wykopx.pl"]) > p > a.configure-usercss > i:hover::after 575 | { 576 | color: var(--accent-1); 577 | } 578 | body#stylus-manage 579 | { 580 | height: max-content!important; 581 | } 582 | 583 | 584 | 585 | #message-box > div > #message-box-contents::-webkit-scrollbar 586 | { 587 | width: 24px!important; 588 | } 589 | #message-box > div > #message-box-contents::-webkit-scrollbar-button 590 | { 591 | display: none!important; 592 | } 593 | 594 | #message-box > div > #message-box-contents::-webkit-scrollbar-thumb 595 | { 596 | height: 100px!important; 597 | background: #111!important; 598 | background: linear-gradient(#1b1b1b, #111)!important; 599 | border: 1px solid #000!important; 600 | box-shadow: inset 0 0 0 1px #272727!important; 601 | border-radius: 6px!important; 602 | transition: background 0.3s linear; 603 | } 604 | #message-box > div > #message-box-contents::-webkit-scrollbar-thumb:hover 605 | { 606 | background: linear-gradient(rgba(32, 44, 34, 1), #111)!important; 607 | background: linear-gradient(rgba(56, 148, 148, 0.21) 0%, #111 60%)!important; 608 | } 609 | #message-box > div > #message-box-contents::-webkit-scrollbar-thumb:active 610 | { 611 | background: linear-gradient(rgba(32, 44, 34, 1), #111)!important; 612 | background: linear-gradient(rgba(56, 148, 148, 0.61) 25%, #111 75%)!important; 613 | } 614 | #message-box > div > #message-box-contents::-webkit-scrollbar-track-piece 615 | { 616 | background-color: var(--bg)!important; 617 | } 618 | 619 | /* 620 | ::-webkit-scrollbar — the entire scrollbar. 621 | ::-webkit-scrollbar-button — the buttons on the scrollbar (arrows pointing upwards and downwards that scroll one line at a time). 622 | ::-webkit-scrollbar:horizontal{} — the horizontal scrollbar. 623 | ::-webkit-scrollbar-thumb — the draggable scrolling handle. 624 | ::-webkit-scrollbar-track — the track (progress bar) of the scrollbar, where there is a gray bar on top of a white bar. 625 | ::-webkit-scrollbar-track-piece — the part of the track (progress bar) not covered by the handle. 626 | ::-webkit-scrollbar:vertical{} — the vertical scrollbar. 627 | ::-webkit-scrollbar-corner — the bottom corner of the scrollbar, where both horizontal and vertical scrollbars meet. This is often the bottom-right corner of the browser window. 628 | ::-webkit-resizer — the draggable resizing handle that appears at the bottom corner of some elements. 629 | */ 630 | 631 | 632 | 633 | 634 | #message-box > div 635 | { 636 | max-width: 100%!important; 637 | max-height: 100%!important; 638 | top: 0px!important; 639 | } 640 | 641 | /* Closing setting box */ 642 | #message-box > div > #message-box-close-icon 643 | { 644 | position: absolute; 645 | right: 11px; 646 | top: 10px; 647 | transition: all 0.1s ease-in-out; 648 | 649 | } 650 | #message-box > div > #message-box-close-icon i 651 | { 652 | display: none; 653 | } 654 | #message-box > div > #message-box-close-icon:before 655 | { 656 | width: 20px; height: 20px; 657 | content: "❌"; 658 | font-size: 16px; 659 | } 660 | #message-box > div > #message-box-close-icon:hover 661 | { 662 | scale: 1.4; 663 | } 664 | 665 | 666 | 667 | 668 | .config-body .select-wrapper 669 | { 670 | max-width: 100%; 671 | } 672 | #message-box.config-dialog .config-body 673 | { 674 | position: relative; 675 | display: flex; 676 | flex-direction: column; 677 | } 678 | #message-box.config-dialog .config-body input[type="text"], 679 | #message-box.config-dialog .config-body .select-resizer, 680 | #message-box.config-dialog .config-body select, 681 | #message-box.config-dialog .config-body input[type="range"], 682 | #message-box.config-dialog .config-body label.config-select > div 683 | { 684 | min-width: 210px; 685 | } 686 | 687 | 688 | #message-box-contents div.config-heading a[href$="wykopx.pl"] 689 | { 690 | font-size: 0; 691 | text-decoration: none; 692 | } 693 | #message-box-contents div.config-heading a[href$="wykopx.pl"]:before 694 | #message-box-contents div.config-heading a[href$="wykopx.pl"]:after 695 | { 696 | font-size: 13px; 697 | } 698 | 699 | 700 | #message-box-contents div.config-heading a[href$="wykopx.pl"]:hover:after 701 | { 702 | text-decoration: underline; 703 | } 704 | 705 | 706 | #message-box-contents div.config-heading 707 | { 708 | text-align: center; 709 | 710 | a[href$="wykopx.pl"] 711 | { 712 | } 713 | a[href$="wykopx.pl"]:before, 714 | a[href$="wykopx.pl"]:after 715 | { 716 | font-size: 16px 717 | display: block; 718 | cursor: default 719 | color: rgba(255, 255, 255, 0.6); 720 | } 721 | a[href$="wykopx.pl"]:before, 722 | { 723 | margin-top: 30px!important 724 | } 725 | a[href$="wykopx.pl"]:hover 726 | { 727 | 728 | } 729 | } 730 | 731 | [data-ui-theme="light"] #message-box-contents div.config-heading a[href$="wykopx.pl"]:after, 732 | [data-ui-theme="light"] #message-box-contents div.config-heading a[href$="wykopx.pl"]:before 733 | { 734 | color: rgba(0, 0, 0, 0.6); 735 | } 736 | 737 | /* tylko komputer przy wąskim okienku Stylusa */ 738 | @media (pointer: fine) and (max-width: 519px) 739 | { 740 | #message-box-contents div.config-heading a[href$="wykopx.pl"]:before 741 | { 742 | color: #df2c2c; 743 | content: "Go into Stylus Settings '⚙' and in section 'Popup' in field 'Popup width (in pixels)' set value between 𝟲𝟬𝟬 and 𝟴𝟬𝟬 "!important; 744 | } 745 | } 746 | /* telefon lub komputer z rozszerzonym okienkiem Stylusa */ 747 | @media (pointer: none), (min-width: 520px) 748 | { 749 | #message-box-contents div.config-heading a[href$="wykopx.pl"]:before 750 | { 751 | content: "Zaobserwuj tag #wykopx ▫ Do funkcji oznaczonych emoji: ❎ zainstaluj 𝗪𝘆𝗸𝗼𝗽 𝗫𝗦 Szczegóły na xs.wykopx.pl ▫ Opis najciekawszych funkcji 𝗪𝘆𝗸𝗼𝗽 𝗫 na stronie "; 752 | text-decoration: none; 753 | } 754 | #message-box-contents div.config-heading a[href$="wykopx.pl"]:after 755 | { 756 | content: "wiki.wykopx.pl" 757 | } 758 | #message-box-contents div.config-heading a[href$="wykopx.pl"]:hover:after 759 | { 760 | cursor: pointer; 761 | color: rgba(255, 255, 255, 1); 762 | } 763 | [data-ui-theme="light"] #message-box-contents div.config-heading a[href$="wykopx.pl"]:hover:after 764 | { 765 | color: rgba(0, 0, 0, 1); 766 | } 767 | } 768 | 769 | 770 | .config-body > label 771 | { 772 | padding: 7px 0px 7px 15px; 773 | font-size: 13px; 774 | display: flex; 775 | } 776 | 777 | [data-ui-theme="light"] .config-body > label{color: rgba(0, 0, 0, 1); } 778 | [data-ui-theme="dark"] .config-body > label{color: rgba(255, 255, 255, 1); } 779 | 780 | [data-ui-theme="light"] .config-body > label:has(.onoffswitch) { color: rgba(0, 0, 0, 0.5); } 781 | [data-ui-theme="light"] .config-body > label:has(.onoffswitch input:checked) { color: rgba(0, 0, 0, 1); } 782 | [data-ui-theme="dark"] .config-body > label:has(.onoffswitch) { color: rgba(255, 255, 255, 0.5); } 783 | [data-ui-theme="dark"] .config-body > label:has(.onoffswitch input:checked) { color: rgba(255, 255, 255, 1); } 784 | 785 | 786 | 787 | /* NAZWA SEKCJI */ 788 | [data-ui-theme="light"] label.config-range:has(input[type="range"][max="99900"]) 789 | { 790 | border-top: 1px solid rgba(128,128,128,1); 791 | background: #cfcfcf; 792 | background: linear-gradient(#ffffff, #dfdfdf); 793 | border: 1px solid #fff; 794 | box-shadow: inset 0 0 0 1px #c7c7c7; 795 | } 796 | [data-ui-theme="dark"] label.config-range:has(input[type="range"][max="99900"]) 797 | { 798 | border-top: 1px solid rgba(128,128,128,1); 799 | background: #111; 800 | background: linear-gradient(#1b1b1b, #111); 801 | border: 1px solid #000; 802 | box-shadow: inset 0 0 0 1px #272727; 803 | } 804 | label.config-range:has(input[type="range"][max="99900"]) 805 | { 806 | display: flex!important; 807 | padding: 10px!important; 808 | 809 | margin-top: 40px; 810 | 811 | margin-bottom: 10px; 812 | border-radius: 5px; 813 | z-index: 1; 814 | 815 | & + label 816 | { 817 | border-top: none; 818 | } 819 | span.config-name 820 | { 821 | text-align: center; 822 | text-align: left; 823 | padding-left: 10px; 824 | 825 | font-weight: 300; 826 | font-family: system-ui; 827 | font-size: 15px; 828 | letter-spacing: 1px; 829 | text-shadow: 1px 1px 2px rgba(0,0,0,0.3); 830 | text-wrap: pretty; 831 | } 832 | 833 | input[type="range"][max="99900"], span.current-value, a.config-reset-icon 834 | { 835 | display: none!important; 836 | } 837 | } 838 | 839 | /* NAZWA PODSEKCJI */ 840 | [data-ui-theme="light"] label.config-range:has(input[type="range"][max="99999"]) 841 | { 842 | border-top: 1px solid rgba(128,128,128,1); 843 | background: #cfcfcf; 844 | //background: linear-gradient(#ffffff, #dfdfdf); 845 | border: 1px solid #fff; 846 | box-shadow: inset 0 0 0 1px #c7c7c7; 847 | 848 | align-self: center; 849 | } 850 | [data-ui-theme="dark"] label.config-range:has(input[type="range"][max="99999"]) 851 | { 852 | border-top: 1px solid rgba(128,128,128,1); 853 | background: #111; 854 | //background: linear-gradient(#1b1b1b, #111); 855 | border: 1px solid #000; 856 | box-shadow: inset 0 0 0 1px #272727; 857 | } 858 | label.config-range:has(input[type="range"][max="99999"]) 859 | { 860 | display: flex!important; 861 | align-self: center; 862 | //align-self: start; 863 | margin-top: 15px; // 864 | padding: 4px!important; // 865 | margin-bottom: 10px; 866 | border-radius: 5px; 867 | z-index: 1; 868 | 869 | width: 70%; // 870 | 871 | & + label 872 | { 873 | border-top: none; 874 | } 875 | span.config-name 876 | { 877 | text-align: center; 878 | //text-align: left; 879 | padding-left: 10px; 880 | font-weight: 300; 881 | font-family: system-ui; 882 | font-size: 14px; 883 | letter-spacing: 1px; 884 | text-shadow: 1px 1px 2px rgba(0,0,0,0.3); 885 | text-wrap: pretty; 886 | } 887 | 888 | input[type="range"][max="99999"], span.current-value, a.config-reset-icon 889 | { 890 | display: none!important; 891 | } 892 | } 893 | 894 | 895 | 896 | 897 | 898 | 899 | 900 | 901 | /* border NAD elementem opcji */ 902 | .config-body label:not(:first-child) 903 | { 904 | border-top: 1px dotted var(--c80); 905 | } 906 | 907 | // WŁĄCZONY/WYŁĄCZONY CHECKBOX PONIŻEJ 908 | label.config-range:has(input[type="range"][max="111100"]), 909 | label.config-range:has(input[type="range"][max="100000"]) 910 | { 911 | display: none; 912 | border-top: none!important; 913 | 914 | input[type="range"][max="111100"], 915 | input[type="range"][max="100000"], 916 | span.current-value, 917 | a.config-reset-icon 918 | { 919 | display: none!important; 920 | } 921 | } 922 | 923 | // INFO WŁĄCZONY 924 | label.config-range:has(input[type="range"][max="111100"]):has(+ label.config-checkbox input.slider:checked) 925 | { 926 | display: block; 927 | background-color: rgba(0, 128, 30, .09); 928 | color: #7ab37a; 929 | } 930 | label.config-range:has(input[type="range"][max="100000"]):has(+ label.config-range + label.config-checkbox input.slider:not(:checked)), 931 | label.config-range:has(input[type="range"][max="100000"]):has(+ label.config-checkbox input.slider:not(:checked)) 932 | { 933 | display: block; 934 | background-color: rgba(128, 0, 30, .09); 935 | color: #b37a7e; 936 | } 937 | label.config-range:has(input[type="range"][max="111100"]) + label.config-checkbox:has(input.slider:checked), 938 | label.config-range:has(input[type="range"][max="100000"]) + label.config-range + label.config-checkbox:has(input.slider:not(:checked)) 939 | { 940 | border-top: none!important; 941 | } 942 | 943 | 944 | 945 | 946 | 947 | // OPIS INFO DLA POPRZEDNIEJ FUNKCJI 948 | div.config-body label:has(+ label.config-range input[type="range"][max="88800"]):before 949 | { 950 | content: "🛈"; //❔ 951 | position: absolute; 952 | font-size: 14px; 953 | width: 20px; 954 | translate: -10px -8px; 955 | } 956 | label.config-range:has(input[type="range"][max="88800"]) 957 | { 958 | transition-property: border-bottom, opacity, display, height, font-size; 959 | transition-duration: 1s, 1s, 1s, 0.1s, 1s; 960 | transition-behavior: allow-discrete; 961 | 962 | @starting-style 963 | { 964 | opacity: 0; 965 | font-size: 0px; 966 | height: 0px; 967 | } 968 | 969 | opacity: 1; 970 | display: block; 971 | font-size: 0px; 972 | height: 0px; 973 | padding: 0px; 974 | border: transparent; 975 | padding: 0px 0px 2px 15px; 976 | 977 | color: var(--c60); 978 | 979 | input[type="range"][max="88800"], span.current-value, a.config-reset-icon 980 | { 981 | display: none!important; 982 | } 983 | } 984 | div.config-body label:hover + label.config-range:has(input[type="range"][max="88800"]) 985 | { 986 | transition-property: border-bottom, opacity, display, height, font-size; 987 | transition-duration: 0.2s, 0.2s, 0.2s, 0.1s, 0.2s; 988 | transition-behavior: allow-discrete; 989 | transition-delay: 1.2s; 990 | 991 | @starting-style 992 | { 993 | opacity: 1; 994 | display: block; 995 | height: 20px; 996 | font-size: 11px; 997 | } 998 | 999 | opacity: 1; 1000 | display: block; 1001 | height: max-content; 1002 | min-height: max-content; 1003 | max-height: max-content; 1004 | font-size: 11px; 1005 | 1006 | border-bottom: 1px solid var(--accent-3); 1007 | 1008 | border-top: 0px dashed var(--c90); 1009 | } 1010 | 1011 | /* Ikonka resetowania do wartosci domyslnej przy Checkboxie na wąskim ekranie */ 1012 | #message-box-contents div.config-body label a.config-reset-icon 1013 | { 1014 | translate: 22px; 1015 | } 1016 | #message-box-contents div.config-body label a.config-reset-icon:hover i 1017 | { 1018 | color: var(--accent-1); 1019 | } 1020 | 1021 | @media (max-width: 600px) 1022 | { 1023 | #message-box-contents div.config-body label 1024 | { 1025 | margin-bottom: 10px; 1026 | } 1027 | #message-box-contents div.config-body label > span.config-name 1028 | { 1029 | line-height: 21px; 1030 | } 1031 | 1032 | /* TYTUL SEKCJI */ 1033 | #message-box-contents div.config-body label.config-range:has(input[type="range"][max="99900"]) span.config-name 1034 | { 1035 | font-size: 15px!important; 1036 | } 1037 | 1038 | #message-box-contents div.config-body label.config-checkbox, 1039 | #message-box-contents div.config-body label.config-select, 1040 | #message-box-contents div.config-body label.config-range, 1041 | #message-box-contents div.config-body label.config-text 1042 | { 1043 | display: grid; 1044 | row-gap: 10px; 1045 | } 1046 | 1047 | // CHECKBOX 1048 | #message-box-contents div.config-body label.config-checkbox, 1049 | { 1050 | grid-template-columns: 1fr 30px 30px; 1051 | grid-template-rows: 1fr; 1052 | width: 100%; 1053 | row-gap: 0px; 1054 | } 1055 | #message-box-contents div.config-body label.config-checkbox span.config-name, 1056 | { 1057 | display: flex; 1058 | grid-column-start: 1; 1059 | grid-column-end: 2; 1060 | 1061 | text-wrap: pretty; 1062 | } 1063 | #message-box-contents div.config-body label.config-checkbox input.config-value, 1064 | { 1065 | display: flex; 1066 | grid-column-start: 2; 1067 | grid-column-end: 3; 1068 | 1069 | align-self: start; 1070 | } 1071 | 1072 | /* Ikonka resetowania do wartosci domyslnej przy Checkboxie na wąskim ekranie */ 1073 | #message-box-contents div.config-body label.config-checkbox a.config-reset-icon 1074 | { 1075 | display: flex; 1076 | grid-column-start: 3; 1077 | grid-column-end: 4; 1078 | 1079 | align-self: start; 1080 | } 1081 | // SELECT 1082 | #message-box-contents div.config-body label.config-select, 1083 | #message-box-contents div.config-body label.config-text 1084 | { 1085 | grid-template-columns: auto 10px; 1086 | grid-template-rows: 1fr 1fr; 1087 | width: 100%; 1088 | } 1089 | #message-box-contents div.config-body label.config-select span.config-name, 1090 | #message-box-contents div.config-body label.config-text span.config-name 1091 | { 1092 | display: flex; 1093 | grid-column-start: 1; 1094 | grid-column-end: 3; 1095 | grid-row-start: 1; 1096 | grid-row-end: 2; 1097 | } 1098 | #message-box-contents div.config-body label.config-select div.config-value, 1099 | #message-box-contents div.config-body label.config-text input.config-value 1100 | { 1101 | display: flex; 1102 | grid-column-start: 1; 1103 | grid-column-end: 2; 1104 | grid-row-start: 2; 1105 | grid-row-end: 3; 1106 | 1107 | margin-top: 2px; 1108 | } 1109 | #message-box-contents div.config-body label.config-select div.config-value > select, 1110 | #message-box-contents div.config-body label.config-text input.config-value 1111 | { 1112 | min-width: 90%; 1113 | height: 27px; 1114 | } 1115 | 1116 | #message-box-contents div.config-body label.config-select div.config-value > select > option 1117 | { 1118 | font-size: 12px; 1119 | border: 1px solid #f00!important; 1120 | } 1121 | 1122 | #message-box-contents div.config-body label.config-select div.config-value::after 1123 | { 1124 | position: relative; 1125 | left: 4px; 1126 | } 1127 | #message-box-contents div.config-body label.config-select a.config-reset-icon, 1128 | #message-box-contents div.config-body label.config-text a.config-reset-icon 1129 | { 1130 | display: flex; 1131 | grid-column-start: 2; 1132 | grid-column-end: 3; 1133 | grid-row-start: 2; 1134 | grid-row-end: 3; 1135 | position: relative; 1136 | top: 0px; 1137 | } 1138 | 1139 | 1140 | // RANGE 1141 | #message-box-contents div.config-body label.config-range 1142 | { 1143 | grid-template-columns: auto auto 0px; 1144 | grid-template-rows: 1fr 1fr; 1145 | width: 100%; 1146 | } 1147 | 1148 | 1149 | #message-box-contents div.config-body label.config-range span.config-name 1150 | { 1151 | display: flex; 1152 | grid-column-start: 1; 1153 | grid-column-end: 2; 1154 | grid-row-start: 1; 1155 | grid-row-end: 2; 1156 | } 1157 | #message-box-contents div.config-body label.config-range span.current-value 1158 | { 1159 | display: flex; 1160 | grid-column-start: 3; 1161 | grid-column-end: 4; 1162 | grid-row-start: 1; 1163 | grid-row-end: 2; 1164 | position: relative; 1165 | top: 0px; 1166 | left: -100px; 1167 | width: 20px; 1168 | justify-content: end; 1169 | } 1170 | #message-box-contents div.config-body label.config-range a.config-reset-icon 1171 | { 1172 | display: flex; 1173 | grid-column-start: 3; 1174 | grid-column-end: 4; 1175 | grid-row-start: 2; 1176 | grid-row-end: 3; 1177 | position: relative; 1178 | top: 0px; 1179 | left: -20px; 1180 | width: 20px; 1181 | } 1182 | #message-box-contents div.config-body label.config-range input.config-value 1183 | { 1184 | display: flex; 1185 | width: 90%; 1186 | grid-column-start: 1; 1187 | grid-column-end: 3; 1188 | grid-row-start: 2; 1189 | grid-row-end: 3; 1190 | } 1191 | } 1192 | } 1193 | 1194 | 1195 | 1196 | --------------------------------------------------------------------------------