Listy plusujących + MirkoCzat

Wykop X - Mikroczat.pl / Mirkoczat oraz dodanie usuniętej listy plusujących

当前为 2024-04-26 提交的版本,查看 最新版本

// ==UserScript==
// @name        Listy plusujących + MirkoCzat
// @name:pl     Listy plusujących + MirkoCzat
// @name:en     Listy plusujących + MirkoCzat
// @version     3.0.22


// @supportURL  		http://wykop.pl/tag/wykopwnowymstylu
// @contributionURL  	https://buycoffee.to/wykopx


// @author      Wykop X <[email protected]>
// @namespace   Violentmonkey Scripts
// @match       https://wykop.pl/*


// @description Wykop X - Mikroczat.pl / Mirkoczat oraz dodanie usuniętej listy plusujących
// @description:en Wykop X - Mikroczat.pl / Mirkoczat and list of entry/comment voters


// @require https://unpkg.com/[email protected]/dist/localforage.min.js
// @require https://cdn.jsdelivr.net/npm/dayjs@1/dayjs.min.js


// @compatible  chrome, firefox, opera, safari, edge
// @license     No License

// ==/UserScript==


const promoString = "- Wykop X";
const head = document.head;
const styleElement = document.createElement('style');
let CSS = "";
let dev = false;



/*  --- ZMIANA USTAWIEŃ ---
jeśli chcesz zmienić domyślne ustawienia nie zmieniaj ich w tym kodzie.
Zmień je w przeglądarce w następujący sposób:

1. Wejdź na Wykop
2. Otwórz panel narzędzi deweloperskich klawiszem *F12* lub skrótem klawiaturowym *CTRL* + *SHIFT* + *C*
3. Przejdź na zakładkę "Aplikacja"
4. w panelu po lewej w sekcji "Pamięć" wybierz "Pamięć lokalna" i znajdź na liście https://wykop.pl
5. w głównym okienku pojawi się lista kilku wartości. Znajdź opcję "wykopx/settings/settings"
6. zmień wybraną opcję na true (aby ją włączyć) lub false (aby wyłączyć)


Domyślne wartości wyglądają tak:

{"votersFollow":true,"votersBlacklist":true,"votersBanned":true,"votersSuspended":true,"votersRemoved":true,"votersGenderF":false,"votersGenderM":false,"votersColorGreen":true,"votersColorOrange":false,"votersColorBurgundy":true}

*/





// DEFAULT SETTINGS - nie zmieniaj tych wartości
const settings =
{
	votersFollow: true,				// pokazuje 🔔 przed użytkownikami, których obserwujesz
	votersBlacklist: true,			// pokazuje 🚯 przed użytkownikami, których blokujesz
	votersBanned: true,				// pokazuje użytkowników z aktywnym banem w kolorze i z ikonką 🍌
	votersSuspended: true,			// pokazuje ✖ przed kontami, które są w trakcie usuwania
	votersRemoved: true,			// pokazuje ✖ przed kontami, które są usunięte
	votersGenderF: false,			// pokazuje różową kropkę przed kobietami
	votersGenderM: false,			// pokazuje niebieską kropkę przed mężczyznami
	votersColorGreen: true,			// pokazuje zielonki w kolorze
	votersColorOrange: false,
	votersColorBurgundy: true,		// pokazuje użytkowników bordo w kolorze
};



(async function ()
{
	// MIKROCZAT XS -- START
	let wykopDomain = "https://wykop.pl";
	let wxDomain = "https://wykopx.pl";
	const mikroczatDomain = "https://mikroczat.pl";
	const mikroczatPath = "/chat";
	let mikroczatChannel = "/";
	let mikroczatWindow = null;



	// LOCALSTORAGE
	localStorageSettings = localforage.createInstance({
		driver: localforage.LOCALSTORAGE,
		name: "wykopx",
		storeName: "settings",
	});

	// Try to get the settings from local storage
	await localStorageSettings.getItem('settings').then(async (localSettings) =>
	{
		if (localSettings)
		{
			mergeSettings(localSettings, settings);
		} else
		{
			localStorageSettings.setItem('settings', settings);
		}
		await localStorageSettings.setItem('settings', settings);
	}).catch((err) =>
	{
		console.error('An error occurred: ', err);
	});


	document.addEventListener("mousedown", (event) =>
	{
		if (!event.target.closest(".wykopx_open_mikroczat")) return;
		event.preventDefault();
		let windowOptions = "";
		let mikroczatURL = `${mikroczatDomain}`;

		if (event.shiftKey || event.ctrlKey || event.altKey || event.button === 2)
		{
			windowOptions = "popup";
		}

		// WykopXS unique
		const pathnameArray = new URL(document.URL).pathname.split("/");
		if (pathnameArray[1] == "tag")
		{
			mikroczatChannel = "/" + pathnameArray[2]; // nazwatagu
			mikroczatURL += `${mikroczatPath}${mikroczatChannel}`;
		}


		mikroczatWindow = window.open(mikroczatURL, 'mikroczat', windowOptions);
	});


	document.addEventListener("click", (event) =>
	{
		if (!event.target.closest(".wykopx_open_mikroczat")) return;
		event.preventDefault();
	});



	// WIADOMOŚCI OD MIKROCZAT
	window.addEventListener('message', function (event)
	{
		if (event.origin !== mikroczatDomain) return;
		console.log('Wiadomość z mikroczat.pl', event.data);
		//if (event.data == "MikroCzatOpened") mikroczatWindow.postMessage({ type: "token", token: window.localStorage.getItem("token") }, mikroczatDomain);
		if (event.data == "MikroCzatOpened") mikroczatWindow.postMessage({ type: "TokensObject", token: window.localStorage.getItem("token"), userKeep: window.localStorage.getItem("userKeep") }, mikroczatDomain);


		if (event.data == "MikroCzatLoggedIn") bodySection.dataset.mikroczatLogged = true;
		if (event.data == "MikroCzatClosed")
		{
			bodySection.dataset.mikroczatLogged = false;
			mikroczatWindow = null;
		}
	}, false);

	CSS += `body > section[data-mikroczat-logged="true"] li.wykopx_open_mikroczat_li:after
	{
		content: "🗯";
		color: white;
		position: absolute;
		top: -2px;
		right: -2px;
	}
	body > section[data-mikroczat-logged="false"] li.wykopx_open_mikroczat_li:after
	{
		content: "⊗";
		color: rgb(255, 255, 255, 0.3);
		position: absolute;
		top: -2px;
		right: -2px;
	}`;


	createNewNavBarButton({
		position: "left",
		// text: "Mikro<strong>czat</strong>",
		text: "Czat",
		title: `Otwórz wykopowy MikroCzat`,
		class: "open_mikroczat", // wykopx_open_mikroczat_li
		hideWithoutXStyle: false,
		url: mikroczatDomain,
		target: "mikroczat",
		icon: "https://i.imgur.com/9PvHlaA.png",
		number: null,
	})






	const debounce = (fn, time) =>
	{
		let timeoutHandler;
		return (...args) =>
		{
			clearTimeout(timeoutHandler);
			timeoutHandler = setTimeout(() =>
			{
				fn(...args)
			}, time);
		}
	}
	let debounceAddVotersList = debounce((target) => addVotersList(target), 1000);

	let parentNode = document.body;
	let observer = new MutationObserver((mutations) =>
	{
		mutations.forEach((mutation) =>
		{
			if (mutation.target && mutation.target.tagName === "SECTION")
			{
				// console.log(" ------------- ");
				// console.log(" mutation.addedNodes: " + mutation.addedNodes);
				// console.log(mutation.addedNodes);
				// console.log(" mutation.attributeName: " + mutation.attributeName);
				// console.log(mutation.attributeName);
				// console.log(" mutation.attributeNamespace: " + mutation.attributeNamespace);
				// console.log(mutation.attributeNamespace);
				// console.log(" mutation.nextSibling: " + mutation.nextSibling);
				// console.log(mutation.nextSibling);
				// console.log(" mutation.oldValue: " + mutation.oldValue);
				// console.log(mutation.oldValue);
				// console.log(" mutation.previousSibling: " + mutation.previousSibling);
				// console.log(mutation.previousSibling);
				// console.log(" mutation.removedNodes: " + mutation.removedNodes);
				// console.log(mutation.removedNodes);
				// console.log(" mutation.target: " + mutation.target);
				// console.log(mutation.target);
				// console.log(" mutation.type: " + mutation.type);

				if (mutation.target.matches("section.entry"))
				{
					addVotersList(mutation.target);

					let sectionEntryArray = mutation.target.querySelectorAll('section.entry');
					if (sectionEntryArray)
					{
						sectionEntryArray.forEach((el) =>
						{
							addVotersList(el);
						})
					}
				}
				else if (mutation.target.matches("section.stream.microblog"))
				{
					let sectionEntryArray = mutation.target.querySelectorAll('section.entry');
					if (sectionEntryArray)
					{
						sectionEntryArray.forEach((el) =>
						{
							addVotersList(el);
						})
					}
				}
			}
		});
	});

	let config = { childList: true, subtree: true };
	observer.observe(parentNode, config);









	CSS += `
	section.entry-voters
	{
		ul
		{
			display: block flex;
			column-gap: 0.5em;
			row-gap: 5px;
			
			align-items: baseline;
			flex-wrap: wrap;

			padding: 0 0 0 0;
			margin: 0;
			list-style-type: none;
			position: relative;
			font-size: 12px;
			color: var(--gullGray);

			
			&::before
			{
				content: "Plusujący: ";
			}

			li
			{
				a.username
				{
					
					span
					{

					}

					&.banned, &.suspended
					{
						color: 
					}
				}

				&.more
				{
					cursor: pointer;
					font-weight: 700;
					text-transform: uppercase;
				}
			}
		}
	}

	section.entry-voters ul li a.username i { display: none; font-size: 0.8em; font-style: normal; bottom: 1px; position: relative; }
	section.entry-voters ul li a.username i:has(+span) { margin-right: 1px; }
	section.entry-voters ul li a.username i.follow-true,
	section.entry-voters ul li a.username i.blacklist-true,
	section.entry-voters ul li a.username i.banned ,
	section.entry-voters ul li a.username i.suspended,
	section.entry-voters ul li a.username i.removed,
	section.entry-voters ul li a.username i.f-gender,
	section.entry-voters ul li a.username i.m-gender
	{ display: inline flex;} 
	
	section.entry-voters ul li a.username i.follow-true::before { content: '🔔'; }
	section.entry-voters ul li a.username i.blacklist-true::before { content: '🚯'; }
	section.entry-voters ul li a.username i.banned::before { content: '🍌'; }
	section.entry-voters ul li a.username i.suspended::before { content: '✖'; }
	section.entry-voters ul li a.username i.removed::before { content: '✖'; }
	section.entry-voters ul li a.username i.f-gender::before { content: '🟣'; font-size: 0.7em; bottom: 3px; }
	section.entry-voters ul li:has(a.username.burgundy-profile) { order: 1; }
	section.entry-voters ul li:has(a.username.green-profile) { order: 3; }
	section.entry-voters ul li:has(a.username.orange-profile) { order: 3; }
	section.entry-voters ul li.more { order: 10; }
	`;

	if (!settings?.votersColorOrange) CSS += `section.entry-voters ul li a.username.orange-profile { color: var(--gullGray); }`;
	if (!settings?.votersColorGreen) CSS += `section.entry-voters ul li a.username.green-profile { color: var(--gullGray); }`;
	if (!settings?.votersColorBurgundy) CSS += `section.entry-voters ul li a.username.burgundy-profile { color: var(--gullGray); }`;

	/* Wykop X Style 3.0 */
	CSS += `
	:root { --kolorBananowy1: rgba(255, 185, 0, 1); }
	section.entry-voters ul li a.username:is(.banned, .suspended):not(.removed) span  { color: var(--kolorBananowy1);
	section.entry-voters ul li a.username.removed { color: rgb(0, 0, 0) }
	[data-night-mode] section.entry-voters ul li a.username.removed { background-color: rgba(255, 255, 255, 0.3); padding-left: 5rem; padding-right: 5rem;
	`

	styleElement.textContent = CSS;
	document.head.appendChild(styleElement);



	function getListItemForUser(voter)
	{
		let userHTML = `<li data-v-6e6ed6ee="">
				<a data-v-ed9f6c56="" data-v-6e6ed6ee="" href="/ludzie/${voter.username}" class="username`;

		userHTML += ` ${voter.color}-profile`; 		// orange-profile green-profile burgundy-profile
		userHTML += ` ${voter.status}`;				// active banned suspended removed
		userHTML += ` follow-${voter.follow}`;		// follow-true  follow-false
		userHTML += ` verified-${voter.verified}`;	// verified-false
		userHTML += ` blacklist-${voter.blacklist}`;// blacklist-true blacklist-false
		userHTML += ` online-${voter.online}`;		// online-true online-false

		userHTML += ` ${voter.gender}-gender`;		// m-gender, f-gender, null-gender
		if (voter.gender == "m") userHTML += ` male`;
		else if (voter.gender == "f") userHTML += ` female`;
		userHTML += `">`;


		if (settings?.votersFollow && voter.follow) userHTML += `<i class="follow-true" title="Obserwujesz tego użytkownika"></i>`;
		if (settings?.votersVerified && voter.verified) userHTML += `<i class="verified-true" title="Ten użytkownik jest zweryfikowany"></i>`;
		if (settings?.votersBlacklist && voter.blacklist) userHTML += `<i class="blacklist-true" title="Ten użytkownik jest na Twojej czarnej liście"></i>`;
		if (settings?.votersOffline && !voter.online) userHTML += `<i class="online-false" title="Ten uzytkownik jest teraz offline"></i>`;
		if (settings?.votersOnline && voter.online) userHTML += `<i class="online-true" title="Ten uzytkownik jest teraz online"></i>`;
		if (settings?.votersBanned && voter.status == "banned") userHTML += `<i class="banned" title="Użytkownik dostał bana. Z dodatkiem Wykop XS - Ban Info możesz szybko sprawdzić przyczynę i długość trwania bana."></i>`;
		if (settings?.votersSuspended && voter.status == "suspended") userHTML += `<i class="suspended" title="To konto jest w trakcie usuwania."></i>`;
		if (settings?.votersRemoved && voter.status == "removed") userHTML += `<i class="removed" title="Konto usunięte"></i>`;
		if (settings?.votersGenderM && voter.gender == "m") userHTML += `<i class="${voter.gender}-gender" title="Wpis od niebieskiego"></i>`;
		if (settings?.votersGenderF && voter.gender == "f") userHTML += `<i class="${voter.gender}-gender" title="Plus od różowej"></i>`;

		userHTML += `<span data-v-ed9f6c56="">${voter.username}</span>
				</a>
			</li>`;

		return userHTML;
	}


	function appendVotersToEntry(sectionEntry, voters)
	{

		const fiveVoters = voters;

		if (!fiveVoters || fiveVoters.length < 1) return false;

		let sectionEntryVotersHTML = `<ul data-v-6e6ed6ee="">`;

		fiveVoters.forEach(voter =>
		{
			sectionEntryVotersHTML += getListItemForUser(voter);
		});

		if (sectionEntry?.__vue__?.item?.votes.up > 5 && voters.length <= 5)
		{
			sectionEntryVotersHTML += `
				<li data-v-6e6ed6ee="" data-no-bubble="" class="more">
					<span data-v-6e6ed6ee="" `;

			if (sectionEntry?.__vue__?.item.resource == "entry") 
			{
				sectionEntryVotersHTML += `data-entry-id="${sectionEntry?.__vue__?.item.id}"`;
			}
			else if (sectionEntry?.__vue__?.item.resource == "entry_comment") 
			{
				sectionEntryVotersHTML += `data-entry-id="${sectionEntry?.__vue__?.item.parent.id}"`;
				sectionEntryVotersHTML += `data-comment-id="${sectionEntry?.__vue__?.item.id}"`;
			}

			sectionEntryVotersHTML += `>+${sectionEntry?.__vue__?.item?.votes.up - 5} innych</span></li>`;
		}


		sectionEntryVotersHTML += `</ul>`;
		const sectionEntryVoters = document.createElement("section");
		sectionEntryVoters.classList.add("entry-voters");
		sectionEntryVoters.setAttribute('data-v-6e6ed6ee', '');
		sectionEntryVoters.setAttribute('data-v-2aacfeb5', '');
		sectionEntryVoters.innerHTML = sectionEntryVotersHTML;

		const sectionEntryVotersElement = sectionEntry.querySelector('section.entry-voters');
		if (sectionEntryVotersElement)
		{
			let parentElement = sectionEntryVotersElement.parentNode;
			parentElement.replaceChild(sectionEntryVoters, sectionEntryVotersElement);
		}
		else
		{
			const editWrapper = sectionEntry.querySelector(".edit-wrapper");
			if (editWrapper) editWrapper.appendChild(sectionEntryVoters);
		}
	}


	/*
	<section data-v-6e6ed6ee="" data-v-2aacfeb5="" class="entry-voters">
		<ul data-v-6e6ed6ee="">
			<li data-v-6e6ed6ee="" class="">
				<a data-v-ed9f6c56="" data-v-6e6ed6ee="" href="/ludzie/NaczelnyAgnostyk" class="username orange-profile active">
					<span data-v-ed9f6c56="">
						NaczelnyAgnostyk<!---->
					</span>
				</a>
			</li>
			<li data-v-6e6ed6ee="" data-no-bubble="" class="more">
				<span data-v-6e6ed6ee="">+5 innych</span>
			</li>
		</ul>
	</section>
	*/

	function fetchAllVotersFromAPI(entryId, commentId)
	{
		let apiURL = `https://wykop.pl/api/v3/entries/${entryId}/votes?page=1`
		if (commentId) apiURL = `https://wykop.pl/api/v3/entries/${entryId}/comments/${commentId}/votes`;

		return new Promise(async (resolve, reject) =>
		{
			await fetch(apiURL, {
				method: "GET",
				headers: {
					"Content-Type": "application/json",
					Authorization: "Bearer " + window.localStorage.getItem("token"),
				},
			})
				.then((response) =>
				{
					if (!response.ok)
					{
						if (dev) console.log("HTTP error! status: ${response.status}");
						// throw new Error(`HTTP error! status: ${response.status}`);
					}
					return response.json();
				})
				.then(async (responseJSON) =>
				{
					resolve(responseJSON.data);

				}).catch((error) =>
				{
					if (error instanceof TypeError)
					{
						console.error('Network error:', error); // AWARIA SERWERA WYPOKU
					} else
					{
						console.error('Other error:', error);
					}
					reject(error);
				});
		});
	}







	function createNewNavBarButton(options)
	{

		let nav_ul;

		if (options.position == "left") nav_ul = document.querySelector("body header div.left nav.main ul");
		else if (options.position == "center") nav_ul = document.querySelector("body header div.right nav aside"); // doodle
		else nav_ul = document.querySelector("body header div.right nav ul"); // brak na wersji mobilnej

		if (nav_ul) 
		{
			let nav_ul_li;  // ! = nav_ul.querySelector(`li.wykopx_${options.class}_li`);

			if (!nav_ul_li)
			{
				nav_ul_li = document.createElement("li");

				if (options.data) nav_ul_li.setAttribute(options.data, null);
				if (options.hideWithoutXStyle == true) nav_ul_li.classList.add("wykopxs");
				addWykopXSClassesToElement(nav_ul_li, options.class, "li") // class="wykopx_aaaaaa_li"

				let nav_ul_li_a = document.createElement("a");
				nav_ul_li.dataset["v-5182b5f6"] = "";
				nav_ul_li_a.dataset["v-5182b5f6"] = "";

				if (options.url) nav_ul_li_a.setAttribute("href", options.url);
				if (options.href) nav_ul_li_a.setAttribute("href", options.href);
				if (options.target) nav_ul_li_a.setAttribute("target", options.target);
				if (options.title) nav_ul_li_a.setAttribute("title", options.title);
				if (options.data) nav_ul_li_a.setAttribute(options.data, null);

				nav_ul_li_a.classList.add("hybrid");
				if (options.class) addWykopXSClassesToElement(nav_ul_li_a, options.class);

				let nav_ul_li_a_span = document.createElement("span");
				nav_ul_li_a_span.innerHTML = options.text;

				nav_ul_li_a.appendChild(nav_ul_li_a_span);
				nav_ul_li.appendChild(nav_ul_li_a);

				if (options.insertAfter != null)
				{
					let section = nav_ul.querySelector(options.insertAfter);
					section.insertAdjacentElement('afterend', nav_ul_li);
				}
				else
				{
					nav_ul.appendChild(nav_ul_li);
				}
			}
		}
	}


	function addWykopXSClassesToElement(element, inputClassOrArray, suffix = null)
	{
		if (inputClassOrArray)
		{
			if (typeof inputClassOrArray === 'string')
			{
				element.classList.add(`wykopx_${inputClassOrArray}${suffix != null ? "_" + suffix : ""}`);
			}
			else if (Array.isArray(inputClassOrArray) && inputClassOrArray.every(item => typeof item === 'string'))
			{
				inputClassOrArray.map(item =>
				{
					element.classList.add(`wykopx_${item}${suffix != null ? "_" + suffix : ""}`);
				});
			}
		}
	}



	function addVotersList(sectionEntry)
	{
		if (sectionEntry && sectionEntry?.__vue__ && sectionEntry?.__vue__.item.votes.up > 0)
		{
			appendVotersToEntry(sectionEntry, sectionEntry?.__vue__?.item?.votes?.users)
		}

	}





	// Function to merge settings with default settings
	function mergeSettings(localSettings, defaultSettings)
	{
		for (let key in defaultSettings)
		{
			if (localSettings[key])
			{
				settings[key] = localSettings[key];
			}

			else if (!localSettings[key])
			{
				settings[key] = defaultSettings[key];
			}

		}
	}


	document.addEventListener('click', async function (event)
	{
		if (!event.target.matches('li.more span')) return;
		event.preventDefault();
		let voters = await fetchAllVotersFromAPI(event.target.dataset.entryId, event.target.dataset.commentId);
		let entry = event.target.closest(`section.entry`);
		appendVotersToEntry(entry, voters);

	}, false);


})();








QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址