您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Leitet mytischtennis.de/click-tt/... früh auf click-tt.de um; fängt normale Klicks ab; funktioniert auch bei SPA-Navigation; für RTTVR-Gruppen 500207–500216 wird targetFed=RTTVR & championship=suedl.WW-RL 25/26 erzwungen.
// ==UserScript== // @name myTT->clickTT // @namespace https://greasyfork.org/de/users/1521935-rr247 // @version 0.1.1 // @description Leitet mytischtennis.de/click-tt/... früh auf click-tt.de um; fängt normale Klicks ab; funktioniert auch bei SPA-Navigation; für RTTVR-Gruppen 500207–500216 wird targetFed=RTTVR & championship=suedl.WW-RL 25/26 erzwungen. // @author RR // @license MIT // @match https://www.mytischtennis.de/* // @match https://mytischtennis.de/* // @run-at document-start // @noframes // @grant none // ==/UserScript== (function () { "use strict"; // ===== Konfiguration ===== const CLICKTT_SEG_RE = /\/(click-tt|clicktt)\//i; // Sonderlogik (wie von dir gewünscht) const SPECIAL_MIN = 500207; const SPECIAL_MAX = 500216; const SPECIAL_FED = "RTTVR"; // targetFed const SPECIAL_LABEL = "suedl.WW-RL"; // championship-Präfix (vor " 25/26") // Verbandscode-Normalisierung für click-tt Subdomänen function normalizeAssoc(s) { const x = (s || "").toLowerCase(); if (x === "byttv") return "bttv"; if (x === "hettv") return "httv"; if (x === "sbttv" || x === "battv") return "ttvbw"; return x; } // "25--26" -> "25/26" function prettySeason(raw) { return (raw || "").replace(/--/g, "/"); } function isMyTT(hostname) { const h = (hostname || "").replace(/^www\./i, "").toLowerCase(); return h === "mytischtennis.de"; } // Kern: baue Ziel-URL aus einem myTT-/click-tt/-Pfad function buildTargetFromPath(pathname) { if (!CLICKTT_SEG_RE.test(pathname)) return null; const parts = pathname.split("/").filter(Boolean); const idx = parts.findIndex(p => p === "click-tt" || p === "clicktt"); if (idx < 0 || parts.length < idx + 3) return null; const assocRaw = parts[idx + 1] || ""; // z.B. RTTVR const assoc = normalizeAssoc(assocRaw); // z.B. rttvr const assocUC = assocRaw.toUpperCase(); // RTTVR const season = prettySeason(parts[idx + 2] || ""); // 25/26 const base = `https://${assoc}.click-tt.de/cgi-bin/WebObjects/nuLigaTTDE.woa/wa/`; const mMeeting = pathname.match(/\/spielbericht\/(\d+)/i); const mGroup = pathname.match(/\/gruppe\/(\d+)/i); const mClubT = pathname.match(/\/verein\/(\d+)\/mannschaften/i); const mClubP = pathname.match(/\/verein\/(\d+)\/mannschaftsmeldungen/i); function groupQuery(idStr) { const gid = parseInt(idStr, 10); if (!isNaN(gid) && gid >= SPECIAL_MIN && gid <= SPECIAL_MAX) { return `targetFed=${encodeURIComponent(SPECIAL_FED)}&championship=${encodeURIComponent(SPECIAL_LABEL + " " + season)}&group=${gid}`; // Ergebnis z.B.: targetFed=RTTVR&championship=suedl.WW-RL+25%2F26&group=500209 } // Standard: "RTTVR 25/26" return `championship=${encodeURIComponent(assocUC + " " + season)}&group=${gid}`; } if (mMeeting) { return `${base}meetingReport?championship=${encodeURIComponent(assocUC + " " + season)}&meeting=${mMeeting[1]}`; } if (mGroup) { return `${base}groupPage?${groupQuery(mGroup[1])}`; } if (mClubT) { return `${base}clubTeams?championship=${encodeURIComponent(assocUC + " " + season)}&club=${mClubT[1]}`; } if (mClubP) { return `${base}clubPools?championship=${encodeURIComponent(assocUC + " " + season)}&club=${mClubP[1]}`; } return null; } // 1) Sofort-Redirect bei direktem Aufruf von .../click-tt/... function tryRedirectFromLocation() { if (!CLICKTT_SEG_RE.test(location.pathname)) return; const target = buildTargetFromPath(location.pathname); if (target && target !== location.href) { location.replace(target); } } tryRedirectFromLocation(); // 2) Normale Klicks abfangen (auch Touch/Pointer), vor Seitenskripten function onPossibleClick(e) { const el = e.target && e.target.closest ? e.target.closest("a[href]") : null; if (!el) return; let href = el.getAttribute("href"); if (!href) return; let abs; try { abs = new URL(href, location.href); } catch { return; } if (!isMyTT(abs.hostname)) return; if (!CLICKTT_SEG_RE.test(abs.pathname)) return; const target = buildTargetFromPath(abs.pathname); if (target) { e.preventDefault(); e.stopImmediatePropagation(); location.href = target; // same-tab } } ["click", "pointerup", "touchend"].forEach(type => { document.addEventListener(type, onPossibleClick, { capture: true, passive: false }); }); // 3) Alle (auch dynamisch eingefügten) Links im DOM auf direkte click-tt-URLs umschreiben function rewriteAnchor(a) { if (!a || a._nomytt_done) return; const href = a.getAttribute("href"); if (!href) return; let abs; try { abs = new URL(href, location.href); } catch { return; } if (!isMyTT(abs.hostname)) return; if (!CLICKTT_SEG_RE.test(abs.pathname)) return; const target = buildTargetFromPath(abs.pathname); if (target) { a.removeAttribute("target"); a.setAttribute("href", target); a._nomytt_done = true; } } function rewriteAll() { document.querySelectorAll("a[href]").forEach(rewriteAnchor); } if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", rewriteAll, { once: true }); } else { rewriteAll(); } const mo = new MutationObserver(muts => { for (const m of muts) { if (m.type === "childList") { m.addedNodes && m.addedNodes.forEach(node => { if (node.nodeType === 1) { if (node.tagName === "A") rewriteAnchor(node); node.querySelectorAll && node.querySelectorAll("a[href]").forEach(rewriteAnchor); } }); } else if (m.type === "attributes" && m.target.tagName === "A" && m.attributeName === "href") { rewriteAnchor(m.target); } } }); mo.observe(document.documentElement, { childList: true, subtree: true, attributes: true, attributeFilter: ["href"] }); // 4) SPA-Navigation abfangen (pushState/replaceState/popstate) function maybeRedirectURL(urlLike) { let urlStr; if (typeof urlLike === "string") urlStr = urlLike; else if (urlLike && urlLike.href) urlStr = urlLike.href; else return; try { const u = new URL(urlStr, location.href); if (isMyTT(u.hostname) && CLICKTT_SEG_RE.test(u.pathname)) { const t = buildTargetFromPath(u.pathname); if (t && t !== location.href) location.replace(t); } } catch {} } const _ps = history.pushState; history.pushState = function (s, t, url) { maybeRedirectURL(url); return _ps.apply(this, arguments); }; const _rs = history.replaceState; history.replaceState = function (s, t, url) { maybeRedirectURL(url); return _rs.apply(this, arguments); }; window.addEventListener("popstate", () => tryRedirectFromLocation(), { capture: true }); })();