Event - Los z obsługą linków graficznych w polach tekstowych
// ==UserScript==
// @name Menelgame - LOS
// @namespace https://greasyfork.org/pl/scripts/588953-menelgame-los
// @version 2.1.6
// @description Event - Los z obsługą linków graficznych w polach tekstowych
// @author Arctos + Gemini
// @match *://*.menelgame.online/*
// @match *://*.menelwars.pl/*
// @grant GM.xmlHttpRequest
// @connect docs.google.com
// @connect googleusercontent.com
// @connect *.googleusercontent.com
// @license MIT
// ==/UserScript==
(function() {
'use strict';
console.log("%c[MG-LOS] Skrypt wystartował (Wersja 2.0.15 - Inteligentne łączenie wierszy)!", "color: #10b981; font-weight: bold; font-size: 14px;");
let cachedRows = null;
let cacheTimestamp = 0;
const CACHE_TTL = 5 * 60 * 1000;
const SHEET_JSON_URL = "https://docs.google.com/spreadsheets/d/1l-Tpk_olCJOy1qa8PbYKaZC2LJHwXBOXcH4N9fFmDqc/gviz/tq?tqx=out:json&gid=5017211";
const SLOWNIK_IKON = {
"zbieractwo": "https://menelgame.online/images/kosz.png",
"zebranie": "https://menelgame.online/images/zebractwo.png",
"puszki": "https://menelgame.online/images/icons/puszka.png",
"menelpower": "https://menelgame.online/images/icons/mpower.png",
"mp": "https://menelgame.online/images/icons/mpower.png",
"kombinowanie": "https://images.menelgame.online/images/hustling/gambler.png",
"nauka": "https://menelgame.online/images/rozwoj.png"
};
const SLOWNIK_IKON_ZAMIEN_PO = {
"zł": "https://menelgame.online/images/icons/kasa.png",
"zl": "https://menelgame.online/images/icons/kasa.png",
"z": "https://menelgame.online/images/icons/kasa.png"
};
function getStoredState(key, defaultValue) {
const val = localStorage.getItem(key);
return val !== null ? val === 'true' : defaultValue;
}
const stanyModulow = {
globalny: getStoredState('MG_los_globalny', false)
};
let ostatnioPrzetworzonyTytul = null;
function czyJestCooldown() {
const cooldownDo = localStorage.getItem('mg_los_cooldown');
if (!cooldownDo) return false;
const terazAktualnyCzas = Math.floor(Date.now() / 1000);
if (terazAktualnyCzas < parseInt(cooldownDo, 10)) {
return true;
} else {
localStorage.removeItem('mg_los_cooldown');
return false;
}
}
function przechwycAPI() {
const originalFetch = window.fetch;
window.fetch = async function(...args) {
const response = await originalFetch.apply(this, args);
try {
const clone = response.clone();
const data = await clone.json();
if (data && data.nextMainEventAt) {
localStorage.setItem('mg_los_cooldown', data.nextMainEventAt);
}
} catch (e) {}
return response;
};
}
przechwycAPI();
function normalizujTekst(tekst) {
if (!tekst) return "";
return tekst
.toLowerCase()
.normalize("NFD")
.replace(/[\u0300-\u036f]/g, "")
.replace(/[^\w\s-]/gi, ' ')
.replace(/\s+/g, " ")
.trim();
}
function czyToLink(tekst) {
try {
let url = new URL(tekst);
return url.protocol === "http:" || url.protocol === "https:";
} catch (_) {
return false;
}
}
function parseGvizJson(responseText) {
try {
let startIndex = responseText.indexOf('{');
let endIndex = responseText.lastIndexOf('}');
if (startIndex === -1 || endIndex === -1 || endIndex <= startIndex) return [];
let jsonString = responseText.substring(startIndex, endIndex + 1);
let data = JSON.parse(jsonString);
let table = data.table;
if (!table || !table.rows) return [];
let rows = [];
table.rows.forEach(r => {
let rowData = [];
if (r.c) {
r.c.forEach(cell => {
if (!cell) {
rowData.push('');
return;
}
let val = cell.v !== null && cell.v !== undefined ? String(cell.v) : '';
let formattedVal = cell.f !== null && cell.f !== undefined ? String(cell.f) : val;
rowData.push(formattedVal !== "" ? formattedVal : val);
});
}
rows.push(rowData);
});
return rows;
} catch (e) {
console.error("[MG-LOS] Błąd parsowania odpowiedzi JSON gviz:", e);
return [];
}
}
async function pobierzDaneZArkusza() {
const teraz = Date.now();
if (cachedRows && (teraz - cacheTimestamp < CACHE_TTL)) {
return cachedRows;
}
return new Promise((resolve) => {
GM.xmlHttpRequest({
method: "GET",
url: SHEET_JSON_URL,
onload: function(response) {
if (response.status >= 200 && response.status < 300) {
cachedRows = parseGvizJson(response.responseText);
cacheTimestamp = teraz;
console.log(`%c[MG-LOS] Pobrano i sparsowano dane z arkusza (Wierszy: ${cachedRows.length})`, "color: #3b82f6; font-weight: bold;");
resolve(cachedRows);
} else {
console.warn(`[MG-LOS] Błąd pobierania danych gviz, status: ${response.status}`);
resolve(null);
}
},
onerror: function(err) {
console.error("[MG-LOS] Błąd połączenia z gviz:", err);
resolve(null);
}
});
});
}
async function przetworzEventLos() {
if (typeof stanyModulow !== 'undefined' && stanyModulow.globalny === false) {
return;
}
if (czyJestCooldown()) return;
const klatkaEventu = document.querySelector('.karmic-card');
if (!klatkaEventu) {
if (ostatnioPrzetworzonyTytul !== null) {
ostatnioPrzetworzonyTytul = null;
}
return;
}
const tytulElement = klatkaEventu.querySelector('.karmic-title');
if (!tytulElement) return;
const eventTitle = tytulElement.textContent.trim();
if (!eventTitle) return;
if (ostatnioPrzetworzonyTytul === eventTitle) return;
ostatnioPrzetworzonyTytul = eventTitle;
console.log(`%c[MG-LOS] Wykryto event: "${eventTitle}"`, "color: #ec4899; font-weight: bold;");
const przyciskiWybboru = klatkaEventu.querySelectorAll('.karmic-choices button.karmic-choice');
const rows = await pobierzDaneZArkusza();
if (!rows) return;
let znormalizowanySzukany = normalizujTekst(eventTitle);
let matchedRows = [];
for (let i = 0; i < rows.length; i++) {
let row = rows[i];
if (!row[2]) continue;
let kolumnaCTitle = row[2];
if (normalizujTekst(kolumnaCTitle) === znormalizowanySzukany) {
matchedRows.push(row);
}
}
if (matchedRows.length === 0) {
console.warn(`[MG-LOS] Nie znaleziono dopasowania w arkuszu dla: "${eventTitle}"`);
przyciskiWybboru.forEach((przycisk) => {
if (przycisk.querySelector('.mg-nagroda-custom')) return;
const infoDiv = document.createElement('div');
infoDiv.className = 'mg-nagroda-custom';
infoDiv.style.cssText = `font-size: 12px; color: #ffffff; background-color: rgba(250,80,80,0.2); padding: 2px 4px; margin-top: 6px; border-radius: 4px; font-weight: bold; text-align: center; border: 1px solid rgba(255, 255, 255, 0.2); display: flex; align-items: center; justify-content: center; gap: 6px;`;
infoDiv.innerHTML = `<span>❌</span><span>Brak zadania na liście</span>`;
przycisk.appendChild(infoDiv);
});
return;
}
const zakresyKonfiguracja = [
{ cols: [3, 4, 5, 6, 7, 8, 9] },
{ cols: [10, 11, 12, 13, 14, 15, 16] },
{ cols: [17, 18, 19, 20, 21, 22, 23] },
{ cols: [24, 25, 26, 27, 28, 29, 30] }
];
przyciskiWybboru.forEach((przycisk, index) => {
if (przycisk.querySelector('.mg-nagroda-custom')) return;
const config = zakresyKonfiguracja[index];
if (!config) return;
const infoDiv = document.createElement('div');
infoDiv.className = 'mg-nagroda-custom';
infoDiv.style.cssText = `font-size: 12px; color: #ffffff; padding: 2px 4px; margin-top: 6px; border-radius: 4px; font-weight: bold; text-align: center; border: 1px solid rgba(201,164,92,0.2); box-shadow: 0 2px 4px rgba(0,0,0,0.3); display: flex; flex-direction: column; gap: 3px;`;
// Sprawdzamy najpierw, czy ten przycisk ma gdziekolwiek jakiekolwiek dane we wszystkich pasujących wierszach
let maJakiekolwiekDane = false;
matchedRows.forEach((matchedRow) => {
let wycinekSprawdzenie = [];
for (let i = 0; i < config.cols.length; i++) {
let cIdx = config.cols[i];
if (matchedRow[cIdx] !== undefined && matchedRow[cIdx].trim() !== "") {
wycinekSprawdzenie.push(matchedRow[cIdx].trim());
}
}
if (wycinekSprawdzenie.length > 0) {
maJakiekolwiekDane = true;
}
});
matchedRows.forEach((matchedRow) => {
let wycinekTekstow = [];
for (let i = 0; i < config.cols.length; i++) {
let cIdx = config.cols[i];
if (matchedRow[cIdx] !== undefined && matchedRow[cIdx].trim() !== "") {
wycinekTekstow.push(matchedRow[cIdx].trim());
}
}
const tekstNagrody = wycinekTekstow.length > 0 ? wycinekTekstow.join(" | ") : "Brak danych w arkuszu";
const brakDanych = wycinekTekstow.length === 0;
// Jeśli są jakiekolwiek dane dla tego przycisku w innych wierszach, pomijamy renderowanie wiersza "Brak danych w arkuszu"
if (brakDanych && maJakiekolwiekDane) {
return;
}
let jestNegatywna = false;
if (brakDanych) {
jestNegatywna = true;
} else {
for (let k = 0; k < wycinekTekstow.length; k++) {
if (wycinekTekstow[k].includes('-')) {
jestNegatywna = true;
break;
}
}
}
const wierszNagrodyDiv = document.createElement('div');
wierszNagrodyDiv.style.cssText = `background-color: ${jestNegatywna ? "rgba(250,80,80,0.2)" : "rgba(46,125,50,0.2)"}; padding: 3px 3px; border-radius: 3px; display: flex; align-items: center; justify-content: center; gap: 4px; flex-wrap: wrap;`;
const spanIcon = document.createElement('span');
spanIcon.textContent = jestNegatywna ? "❌" : "✔️";
spanIcon.style.marginRight = "4px";
wierszNagrodyDiv.appendChild(spanIcon);
if (brakDanych) {
const spanText = document.createElement('span');
spanText.textContent = tekstNagrody;
wierszNagrodyDiv.appendChild(spanText);
} else {
let czesciNagrody = tekstNagrody.split(" | ");
czesciNagrody.forEach((czesc, cIdx) => {
if (cIdx > 0) {
const separatorSpan = document.createElement('span');
separatorSpan.textContent = " | ";
separatorSpan.style.opacity = "0.6";
wierszNagrodyDiv.appendChild(separatorSpan);
}
let czystyCzc = czesc.trim();
if (czyToLink(czystyCzc)) {
const imgNagroda = document.createElement('img');
imgNagroda.loading = 'lazy';
imgNagroda.referrerPolicy = 'no-referrer';
imgNagroda.src = czystyCzc;
imgNagroda.style.width = '18px';
imgNagroda.style.height = '18px';
imgNagroda.style.objectFit = 'contain';
imgNagroda.style.verticalAlign = 'middle';
imgNagroda.style.marginLeft = '2px';
imgNagroda.style.marginRight = '2px';
wierszNagrodyDiv.appendChild(imgNagroda);
return;
}
let slowaWpisu = czesc.split(" ");
for (let sIdx = 0; sIdx < slowaWpisu.length; sIdx++) {
let slowo = slowaWpisu[sIdx];
if (czyToLink(slowo)) {
const imgSlowo = document.createElement('img');
imgSlowo.loading = 'lazy';
imgSlowo.referrerPolicy = 'no-referrer';
imgSlowo.src = slowo;
imgSlowo.style.width = '16px';
imgSlowo.style.height = '16px';
imgSlowo.style.objectFit = 'contain';
imgSlowo.style.verticalAlign = 'middle';
imgSlowo.style.marginLeft = (sIdx > 0 ? '3px' : '0px');
imgSlowo.style.marginRight = '2px';
wierszNagrodyDiv.appendChild(imgSlowo);
continue;
}
let slowoNorm = normalizujTekst(slowo);
let znalezionyUrlPrzed = null;
let urlZastepczyPo = null;
for (let klucz in SLOWNIK_IKON) {
if (slowoNorm === klucz || slowoNorm.includes(klucz)) {
znalezionyUrlPrzed = SLOWNIK_IKON[klucz];
break;
}
}
for (let kluczZamien in SLOWNIK_IKON_ZAMIEN_PO) {
let kluczNorm = normalizujTekst(kluczZamien);
if (slowoNorm === kluczNorm) {
urlZastepczyPo = SLOWNIK_IKON_ZAMIEN_PO[kluczZamien];
slowo = "";
break;
} else if (slowoNorm.endsWith(kluczNorm) && slowoNorm.length > kluczNorm.length) {
urlZastepczyPo = SLOWNIK_IKON_ZAMIEN_PO[kluczZamien];
let regex = new RegExp(kluczZamien + '$', 'i');
slowo = slowo.replace(regex, '').trim();
break;
}
}
if (znalezionyUrlPrzed) {
const imgPrzed = document.createElement('img');
imgPrzed.loading = 'lazy';
imgPrzed.referrerPolicy = 'no-referrer';
imgPrzed.src = znalezionyUrlPrzed;
imgPrzed.style.width = '15px';
imgPrzed.style.height = '15px';
imgPrzed.style.objectFit = 'contain';
imgPrzed.style.verticalAlign = 'middle';
imgPrzed.style.marginRight = '2px';
imgPrzed.style.marginLeft = (sIdx > 0 ? '3px' : '0px');
wierszNagrodyDiv.appendChild(imgPrzed);
}
if (slowo !== "") {
const spanSlowo = document.createElement('span');
spanSlowo.textContent = (sIdx > 0 && !znalezionyUrlPrzed ? " " : "") + (sIdx > 0 && znalezionyUrlPrzed ? " " : "") + slowo;
wierszNagrodyDiv.appendChild(spanSlowo);
}
if (urlZastepczyPo) {
const imgZastepcza = document.createElement('img');
imgZastepcza.loading = 'lazy';
imgZastepcza.referrerPolicy = 'no-referrer';
imgZastepcza.src = urlZastepczyPo;
imgZastepcza.style.width = '15px';
imgZastepcza.style.height = '15px';
imgZastepcza.style.objectFit = 'contain';
imgZastepcza.style.verticalAlign = 'middle';
imgZastepcza.style.marginLeft = '2px';
wierszNagrodyDiv.appendChild(imgZastepcza);
}
}
});
}
infoDiv.appendChild(wierszNagrodyDiv);
});
przycisk.appendChild(infoDiv);
});
}
setInterval(przetworzEventLos, 1000);
function pingPanel() {
const wersja = (typeof GM_info !== 'undefined') ? GM_info.script.version : '1.0.0';
window.dispatchEvent(new CustomEvent('scriptPingFromSub', { detail: { scriptId: 'MG_los', version: wersja }}));
}
window.addEventListener('scriptPingFromPanel', pingPanel);
window.addEventListener('scriptStateChanged', (e) => {
const { scriptId, enabled } = e.detail;
if (scriptId === 'MG_los' || scriptId.includes('MG_los_')) {
if (scriptId === 'MG_los' || scriptId === 'MG_los_globalny') {
stanyModulow.globalny = enabled;
} else {}
}
});
setTimeout(pingPanel, 500);
})();