// ==UserScript==
// @name Twitch OAuth Token Kopierer
// @namespace https://gf.qytechs.cn/de/users/1492193-foschbaa
// @version 1.8
// @description Kopiert den Twitch OAuth Token per Klick in die Zwischenablage
// @author Foschbaa
// @match https://www.twitch.tv/*
// @icon https://static.twitchcdn.net/assets/favicon-32-e29e246c157142c94346.png
// @homepageURL https://gf.qytechs.cn/de/users/1492193-foschbaa
// @supportURL https://gf.qytechs.cn/de/users/1492193-foschbaa
// @license MIT
// @run-at document-end
// ==/UserScript==
(function() {
'use strict';
// === KONSTANTEN ===
const AUTO_REMOVE_TIMEOUT = 5000;
const TOAST_TIMEOUT = 1500;
const COLOR_SUCCESS = "#9147ff";
const COLOR_SUCCESS_HOVER = "#772ce8";
const COLOR_ERROR = "#ff3860";
const COLOR_ERROR_HOVER = "#e02d4b";
const COLOR_TOAST_SUCCESS = "#23272a";
const COLOR_TOAST_ERROR = "#ff3860";
// === LOKALISIERUNG ===
const LANGUAGES = {
de: {
BTN_COPY: "OAuth-Token kopieren",
BTN_ERROR: "Kein OAuth-Token gefunden – bitte einloggen!",
TOAST_COPIED: "Der OAuth-Token wurde erfolgreich in die Zwischenablage kopiert.",
TOAST_COPY_FAILED: "Das Kopieren des Tokens ist fehlgeschlagen.",
TOAST_LOGIN: "Bitte logge dich auf Twitch ein, damit dein OAuth-Token ausgelesen werden kann."
},
en: {
BTN_COPY: "Copy OAuth token",
BTN_ERROR: "No OAuth token found – please log in!",
TOAST_COPIED: "OAuth token has been copied to clipboard.",
TOAST_COPY_FAILED: "Copying the token failed.",
TOAST_LOGIN: "Please log in to Twitch so your OAuth token can be read."
}
// Weitere Sprachen können hier ergänzt werden
};
// Automatische Sprachwahl (Browser-Sprache, fallback: Deutsch)
const BROWSER_LANG = navigator.language.slice(0,2);
const TEXT = LANGUAGES[BROWSER_LANG] || LANGUAGES["de"];
const BTN_STYLE = {
position: "fixed",
top: "20px",
right: "20px",
zIndex: 9999,
padding: "12px 18px",
fontSize: "16px",
fontWeight: "bold",
border: "none",
borderRadius: "8px",
boxShadow: "0 2px 8px rgba(0,0,0,0.15)",
cursor: "pointer",
transition: "background 0.2s"
};
const TOAST_STYLE = {
position: "fixed",
top: "80px",
right: "30px",
padding: "14px 24px",
color: "#fff",
fontSize: "16px",
fontWeight: "bold",
borderRadius: "8px",
boxShadow: "0 2px 12px rgba(0,0,0,0.18)",
zIndex: 10000,
opacity: "0",
transition: "opacity 0.5s, transform 0.5s",
transform: "translateY(-20px)",
pointerEvents: "none"
};
function applyStyles(element, styles) {
for (const key in styles) {
element.style[key] = styles[key];
}
}
function removeButton(btn) {
if (btn && btn.parentNode) {
btn.parentNode.removeChild(btn);
}
}
function showToast(message, error = false, callback, duration = TOAST_TIMEOUT) {
// Entferne alten Toast, falls noch sichtbar
const oldToast = document.getElementById("twitch-oauth-toast");
if (oldToast && oldToast.parentNode) oldToast.parentNode.removeChild(oldToast);
const toast = document.createElement("div");
toast.id = "twitch-oauth-toast";
toast.textContent = message;
applyStyles(toast, TOAST_STYLE);
toast.style.background = error ? COLOR_TOAST_ERROR : COLOR_TOAST_SUCCESS;
document.body.appendChild(toast);
setTimeout(() => {
toast.style.opacity = "1";
toast.style.transform = "translateY(0)";
}, 50);
setTimeout(() => {
toast.style.opacity = "0";
toast.style.transform = "translateY(-20px)";
setTimeout(() => {
if (toast.parentNode) toast.parentNode.removeChild(toast);
if (typeof callback === "function") callback();
}, 500);
}, duration);
}
const token = document.cookie.split("; ").find(item => item.startsWith("auth-token="))?.split("=")[1];
const btn = document.createElement("button");
applyStyles(btn, BTN_STYLE);
let removeTimeout;
if (token) {
btn.textContent = TEXT.BTN_COPY;
btn.style.background = COLOR_SUCCESS;
btn.style.color = "#fff";
btn.onmouseover = () => btn.style.background = COLOR_SUCCESS_HOVER;
btn.onmouseout = () => btn.style.background = COLOR_SUCCESS;
btn.onclick = async () => {
clearTimeout(removeTimeout);
try {
await navigator.clipboard.writeText(token);
showToast(TEXT.TOAST_COPIED, false, () => removeButton(btn), TOAST_TIMEOUT);
} catch (e) {
showToast(TEXT.TOAST_COPY_FAILED, true, () => removeButton(btn), TOAST_TIMEOUT);
}
};
} else {
btn.textContent = TEXT.BTN_ERROR;
btn.style.background = COLOR_ERROR;
btn.style.color = "#fff";
btn.onmouseover = () => btn.style.background = COLOR_ERROR_HOVER;
btn.onmouseout = () => btn.style.background = COLOR_ERROR;
btn.onclick = () => {
clearTimeout(removeTimeout);
showToast(TEXT.TOAST_LOGIN, true, () => removeButton(btn), TOAST_TIMEOUT);
};
}
document.body.appendChild(btn);
removeTimeout = setTimeout(() => {
removeButton(btn);
}, AUTO_REMOVE_TIMEOUT);
})();