AccountRefresh.top

Adds a floating button to retrieve and inject new account information using a paid credit system.

설치하기 전에, Greasy Fork는 이 스크립트에 사용자가 아닌 스크립트 작성자의 이익을 위한 기능인 역기능이 포함되어 있음을 알려드립니다.

결제를 완료해야 스크립트의 모든 기능을 사용할 수 있습니다. Greasy Fork는 결제 과정에 관여하지 않으므로, 유료 기능의 가치를 보증하거나 환불을 도와드릴 수 없습니다.

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램을 설치해야 합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

// ==UserScript==
// @name         AccountRefresh.top
// @namespace    accountrefresh.top
// @author       Armoire
// @version      1.2
// @description  Adds a floating button to retrieve and inject new account information using a paid credit system.
// @license      GNU AGPLv3
// @match        *://*.ome.tv/*
// @match        *://*.ometv.chat/*
// @match        *://*.minichat.com/*
// @match        *://*.chatalternative.com/*
// @connect      accountrefresh.top
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_xmlhttpRequest
// @grant        GM_openInTab
// @grant        GM_addStyle
// @run-at       document-end
// @antifeature  payment
// ==/UserScript==

(function () {
  "use strict";

  const BASE_URL = "https://accountrefresh.top/api";
  const LANDING_URL = "https://accountrefresh.top";
  const SYNC_TOKEN = "75e92b318d3748e7b877c7a127ecdaf1";

  const ICON_SHIELD_BLACK = `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230f172a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z'/%3E%3C/svg%3E")`;
  const ICON_SHIELD_WHITE = `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z'/%3E%3C/svg%3E")`;

  let popupChecker = null;

  if (window.top !== window.self) return;

  const existingOverlay = document.getElementById("mm-overlay-container");
  if (existingOverlay) existingOverlay.remove();

  const cssStyles = `
      #mm-overlay-container {
        position: fixed;
        top: 0;
        left: 0;
        width: 0;
        height: 0;
        z-index: 2147483647;
        pointer-events: none;

        --mm-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica,
          Arial, sans-serif;
        --mm-bg: #f8fafc;
        --mm-card-bg: #ffffff;
        --mm-text: #0f172a;
        --mm-text-muted: #64748b;
        --mm-border: #e2e8f0;
        --mm-primary: #3b82f6;
        --mm-primary-hover: #2563eb;
        --mm-danger: #ef4444;
        --mm-success: #10b981;
      }

      #mm-overlay-container.dark-mode {
        --mm-bg: #1a1a1a;
        --mm-card-bg: #2a2a2a;
        --mm-text: #f1f5f9;
        --mm-text-muted: #94a3b8;
        --mm-border: #334155;
        --mm-primary: #60a5fa;
        --mm-primary-hover: #3b82f6;
      }

      #mm-overlay-container ::-webkit-scrollbar {
        width: 8px;
        height: 8px;
      }

      #mm-overlay-container ::-webkit-scrollbar-track {
        background: transparent;
      }

      #mm-overlay-container ::-webkit-scrollbar-thumb {
        background: #c4c4c4;
        border-radius: 4px;
      }

      #mm-overlay-container ::-webkit-scrollbar-thumb:hover {
        background: #333333;
      }

      #mm-overlay-container.dark-mode ::-webkit-scrollbar-thumb:hover {
        background: #ffffff;
      }

      #mm-overlay-container * {
        all: unset;
        box-sizing: border-box;
        font-family: var(--mm-font);
        line-height: 1.5;
        -webkit-font-smoothing: antialiased;
      }

      #mm-overlay-container div {
        display: block;
      }
      #mm-overlay-container button {
        display: inline-block;
        cursor: pointer;
        text-align: center;
      }
      #mm-overlay-container span {
        display: inline;
      }
      #mm-overlay-container input {
        display: inline-block;
      }
      #mm-overlay-container ul {
        display: block;
      }
      #mm-overlay-container li {
        display: block;
      }

      #mm-overlay-container #mm-floating-btn {
        position: fixed;
        top: 20px;
        right: 20px;
        bottom: auto;
        left: auto;
        width: 50px;
        height: 50px;
        background-color: var(--mm-bg);
        border-radius: 50%;
        display: flex;
        align-items: center;
        justify-content: center;
        box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
        pointer-events: auto;
        cursor: pointer;
        z-index: 2147483647;
        padding: 12px;
        transition: transform 0.1s;
      }
      #mm-overlay-container #mm-floating-btn .mm-icon {
        display: block;
        width: 100%;
        height: 100%;
        background-position: center;
        background-repeat: no-repeat;
        background-size: contain;
        background-image: ${ICON_SHIELD_BLACK};
      }
      #mm-overlay-container.dark-mode #mm-floating-btn .mm-icon {
        background-image: ${ICON_SHIELD_WHITE};
      }
      #mm-overlay-container #mm-floating-btn:active {
        transform: scale(0.95);
      }
      #mm-overlay-container #mm-floating-btn:hover {
        filter: brightness(1.1);
      }

      #mm-overlay-container .mm-window {
        position: fixed;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 380px;
        max-height: 80vh;
        background-color: var(--mm-bg);
        border: 1px solid var(--mm-border);
        border-radius: 12px;
        box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
        display: none !important;
        flex-direction: column;
        overflow: hidden;
        pointer-events: auto;
        color: var(--mm-text);
      }
      #mm-overlay-container.open .mm-window {
        display: flex !important;
      }

      #mm-overlay-container .mm-view {
        padding: 16px;
        display: flex;
        flex-direction: column;
        gap: 16px;
        height: 100%;
        overflow-y: auto;
      }
      #mm-overlay-container .hidden {
        display: none !important;
      }

      #mm-overlay-container .mm-header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        margin-bottom: 8px;
      }
      #mm-overlay-container .mm-header-actions {
        display: flex;
        gap: 6px;
        align-items: center;
        user-select: none;
        -webkit-user-select: none;
      }

      #mm-overlay-container .mm-title {
        font-size: 16px;
        font-weight: 700;
        display: flex;
        align-items: center;
        gap: 8px;
        color: var(--mm-text);
        -webkit-user-select: none;
        user-select: none;
      }

      #mm-overlay-container .mm-inline-logo {
        width: 20px;
        height: 20px;
        background-size: contain;
        background-repeat: no-repeat;
        background-position: center;
        background-image: ${ICON_SHIELD_BLACK};
      }

      #mm-overlay-container.dark-mode .mm-inline-logo {
        width: 20px;
        height: 20px;
        background-size: contain;
        background-repeat: no-repeat;
        background-position: center;
        background-image: ${ICON_SHIELD_WHITE};
      }

      #mm-overlay-container .mm-card {
        background-color: var(--mm-card-bg);
        border: 1px solid var(--mm-border);
        border-radius: 8px;
        padding: 12px;
        display: flex;
        flex-direction: column;
        gap: 8px;
      }

      #mm-overlay-container .mm-btn {
        width: 100%;
        padding: 10px;
        border-radius: 6px;
        font-weight: 600;
        font-size: 14px;
        display: flex;
        justify-content: center;
        align-items: center;
        gap: 6px;
        border: none;
        transition: opacity 0.2s;
      }
      #mm-overlay-container .mm-btn:hover {
        opacity: 0.9;
      }

      #mm-overlay-container .mm-btn-primary {
        background-color: var(--mm-primary);
        color: #ffffff;
      }
      #mm-overlay-container .mm-btn-secondary {
        background-color: var(--mm-card-bg);
        border: 1px solid var(--mm-border);
        color: var(--mm-text);
      }
      #mm-overlay-container .mm-btn-ghost {
        background: transparent;
        color: var(--mm-text-muted);
        width: auto;
        padding: 6px;
        border-radius: 6px;
        min-width: 28px;
      }
      #mm-overlay-container .mm-btn-ghost:hover {
        background: var(--mm-border);
        color: var(--mm-text);
      }
      #mm-overlay-container .mm-btn-close:hover {
        background: var(--mm-danger) !important;
        color: #ffffff !important;
      }
      #mm-overlay-container .mm-btn-link {
        background: none;
        color: var(--mm-primary);
        display: inline-block;
        font-size: 12px;
        font-weight: 600;
        border: none;
        padding: 4px;
      }

      #mm-overlay-container .mm-pos-grid {
        display: grid;
        grid-template-columns: 1fr 1fr 1fr 1fr;
        gap: 8px;
        margin-top: 4px;
      }
      #mm-overlay-container .mm-pos-btn {
        padding: 8px;
        background: var(--mm-card-bg);
        border: 1px solid var(--mm-border);
        border-radius: 6px;
        color: var(--mm-text-muted);
        font-size: 18px;
      }
      #mm-overlay-container .mm-pos-btn:hover {
        border-color: var(--mm-primary);
        color: var(--mm-primary);
      }
      #mm-overlay-container .mm-pos-btn.active {
        background: rgba(59, 130, 246, 0.1);
        border-color: var(--mm-primary);
        color: var(--mm-primary);
      }

      #mm-overlay-container .mm-input-group {
        margin-bottom: 8px;
      }
      #mm-overlay-container .mm-label {
        font-size: 11px;
        font-weight: 700;
        text-transform: uppercase;
        color: var(--mm-text-muted);
        margin-bottom: 4px;
        display: block;
        pointer-events: none;
        -webkit-user-select: none;
        user-select: none;
      }
      #mm-overlay-container .mm-input-wrapper {
        position: relative;
        display: flex;
        align-items: center;
      }
      #mm-overlay-container .mm-input {
        width: 100%;
        padding: 8px 32px 8px 10px;
        border-radius: 6px;
        border: 1px solid var(--mm-border);
        background-color: var(--mm-card-bg);
        color: var(--mm-text);
        font-size: 13px;
        font-family: monospace;
      }
      #mm-overlay-container .mm-input:focus {
        outline: 2px solid var(--mm-primary);
        border-color: transparent;
      }
      #mm-overlay-container .mm-copy-btn {
        position: absolute;
        right: 4px;
        background: transparent;
        border: none;
        cursor: pointer;
        padding: 4px;
        font-size: 14px;
        opacity: 0.6;
        transition: opacity 0.2s;
      }
      #mm-overlay-container .mm-copy-btn:hover {
        opacity: 1;
        background: var(--mm-border);
        border-radius: 4px;
      }

      #mm-overlay-container .mm-list {
        list-style: none;
        border: 1px solid var(--mm-border);
        border-radius: 6px;
        background: var(--mm-card-bg);
        max-height: 150px;
        overflow-y: auto;
      }
      #mm-overlay-container .mm-list-item {
        padding: 8px 12px;
        border-bottom: 1px solid var(--mm-border);
        font-size: 12px;
        display: flex;
        justify-content: space-between;
        color: var(--mm-text);
        cursor: pointer;
      }
      #mm-overlay-container .mm-list-item:hover {
        background-color: var(--mm-bg);
      }
      #mm-overlay-container .mm-time {
        color: var(--mm-text-muted);
        font-size: 11px;
      }

      #mm-overlay-container .mm-grid {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 8px;
      }
      #mm-overlay-container .mm-price-card {
        border: 1px solid var(--mm-border);
        border-radius: 8px;
        padding: 10px;
        background: var(--mm-card-bg);
        cursor: pointer;
        text-align: left;
        position: relative;
        display: block;
      }
      #mm-overlay-container .mm-price-card:hover {
        border-color: var(--mm-primary);
      }
      #mm-overlay-container .mm-price-main {
        font-size: 18px;
        font-weight: 800;
        color: var(--mm-text);
        display: block;
      }
      #mm-overlay-container .mm-price-sub {
        font-size: 12px;
        color: var(--mm-text-muted);
        display: block;
      }
      #mm-overlay-container .mm-badge {
        font-size: 10px;
        font-weight: 700;
        padding: 2px 6px;
        border-radius: 4px;
        background: rgba(59, 130, 246, 0.1);
        color: var(--mm-primary);
        display: inline-block;
        margin-top: 4px;
        pointer-events: none;
        -webkit-user-select: none;
        user-select: none;
      }

      #mm-overlay-container .mm-switch-row {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 4px 0;
      }
      #mm-overlay-container .mm-switch {
        position: relative;
        display: inline-block;
        width: 36px;
        height: 20px;
      }
      #mm-overlay-container .mm-switch input {
        opacity: 0;
        width: 0;
        height: 0;
      }
      #mm-overlay-container .mm-slider {
        position: absolute;
        cursor: pointer;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background-color: var(--mm-border);
        transition: 0.4s;
        border-radius: 34px;
      }
      #mm-overlay-container .mm-slider:before {
        position: absolute;
        content: "";
        height: 14px;
        width: 14px;
        left: 3px;
        bottom: 3px;
        background-color: white;
        transition: 0.4s;
        border-radius: 50%;
      }
      #mm-overlay-container input:checked + .mm-slider {
        background-color: var(--mm-primary);
      }
      #mm-overlay-container input:checked + .mm-slider:before {
        transform: translateX(16px);
      }

      #mm-overlay-container .mm-modal-bg {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background: rgba(0, 0, 0, 0.5);
        z-index: 2147483647;
        pointer-events: auto;
        display: flex;
        align-items: center;
        justify-content: center;
      }
      #mm-overlay-container .mm-modal {
        width: 280px;
        background: var(--mm-card-bg);
        padding: 20px;
        border-radius: 12px;
        border: 1px solid var(--mm-border);
        text-align: center;
        color: var(--mm-text);
      }
      #mm-overlay-container .mm-modal-actions {
        display: flex;
        gap: 10px;
        margin-top: 16px;
      }
  `;

  GM_addStyle(cssStyles);

  const container = document.createElement("div");
  container.id = "mm-overlay-container";
  container.innerHTML = `
      <div id="mm-floating-btn" title="Open Menu">
        <div class="mm-icon"></div>
      </div>

      <div class="mm-window">
        <div id="view-main" class="mm-view">
          <div class="mm-header">
            <div class="mm-title">
              <div class="mm-inline-logo"></div>
              AccountRefresh.top
            </div>
            <div class="mm-header-actions">
              <button class="mm-btn-ghost theme-toggle" title="Toggle Theme">
                🌙
              </button>
              <button
                id="btn-close"
                class="mm-btn-ghost mm-btn-close"
                title="Close Window"
              >
                ✕
              </button>
            </div>
          </div>
          <div class="mm-card">
            <button
              id="btn-refresh"
              class="mm-btn mm-btn-primary"
              title="Refresh Account"
            >
              <span>↻</span> Refresh Account
            </button>
            <button
              id="btn-settings"
              class="mm-btn mm-btn-secondary"
              title="Open Settings Menu"
            >
              <span>⚙️</span> Settings
            </button>
            <div
              id="msg-main"
              style="
                text-align: center;
                font-size: 11px;
                color: var(--mm-danger);
                min-height: 14px;
              "
            ></div>
          </div>
          <div style="flex-grow: 1; display: flex; flex-direction: column">
            <div class="mm-header">
              <span class="mm-label">Recent Accounts</span>
              <span
                class="mm-badge"
                style="
                  background: var(--mm-border);
                  color: var(--mm-text-muted);
                  padding: 2px 6px;
                  border-radius: 4px;
                  font-size: 10px;
                "
                >Last 10 Accounts</span
              >
            </div>
            <ul id="list-history" class="mm-list"></ul>
          </div>
        </div>

        <div id="view-settings" class="mm-view hidden">
          <div class="mm-header">
            <div class="mm-title">
              <button id="nav-back-main" class="mm-btn-ghost" title="Go Back">
                ←
              </button>
              Settings
            </div>
            <div class="mm-header-actions">
              <button class="mm-btn-ghost theme-toggle">🌙</button>
              <button
                id="btn-close"
                class="mm-btn-ghost mm-btn-close"
                title="Close Window"
              >
                ✕
              </button>
            </div>
          </div>

          <div class="mm-card">
            <div class="mm-switch-row">
              <span class="mm-label" style="margin: 0; font-size: 12px"
                >Auto-Refresh on Ban</span
              >
              <label class="mm-switch">
                <input type="checkbox" id="inp-autorefresh" />
                <span class="mm-slider"></span>
              </label>
            </div>
          </div>

          <div class="mm-card">
            <span class="mm-label">Button Position</span>
            <div class="mm-pos-grid">
              <button class="mm-pos-btn" data-pos="TL" title="Top Left">↖</button>
              <button class="mm-pos-btn" data-pos="TR" title="Top Right">↗</button>
              <button class="mm-pos-btn" data-pos="BL" title="Bottom Left">↙</button>
              <button class="mm-pos-btn" data-pos="BR" title="Bottom Right">↘</button>
            </div>
          </div>

          <div class="mm-card" style="align-items: center; text-align: center">
            <div
              style="
                display: flex;
                flex-direction: row;
                justify-content: space-between;
                align-items: center;
                width: 100%;
              "
            >
              <span class="mm-label">Credits Balance</span>
              <button
                id="btn-refresh-credits"
                class="mm-btn-ghost"
                style="font-size: 20px; width: 40px; height: 40px"
                title="Refresh Balance"
              >
                ↻
              </button>
            </div>
            <div
              id="val-credits"
              style="font-size: 24px; font-weight: 800; color: var(--mm-text)"
            >
              --
            </div>
            <button
              id="nav-topup"
              class="mm-btn-link"
              title="Open Top Up Credits Menu"
            >
              Top Up Credits ↗
            </button>
          </div>

          <div class="mm-card">
            <form onsubmit="return false;">
              <div class="mm-input-group">
                <label class="mm-label">User ID</label>
                <div class="mm-input-wrapper">
                  <input
                    id="inp-userid"
                    type="password"
                    class="mm-input"
                    autocomplete=""
                    readonly
                  />
                  <button
                    id="btn-copy-userid"
                    class="mm-copy-btn"
                    title="Copy User ID"
                    type="button"
                  >
                    📋
                  </button>
                </div>
              </div>
              <div class="mm-input-group">
                <label class="mm-label">API Key</label>
                <div class="mm-input-wrapper">
                  <input
                    id="inp-key"
                    type="password"
                    class="mm-input"
                    placeholder="sk-..."
                    autocomplete=""
                  />
                  <button
                    id="btn-copy-key"
                    class="mm-copy-btn"
                    title="Copy API Key"
                    type="button"
                  >
                    📋
                  </button>
                </div>
              </div>
              <div style="display: flex; gap: 8px">
                <button
                  id="btn-gen-key"
                  class="mm-btn mm-btn-secondary"
                  title="Generate New API Key"
                  type="button"
                >
                  Generate
                </button>
                <button
                  id="btn-save"
                  class="mm-btn mm-btn-primary"
                  title="Save API Key"
                  type="button"
                >
                  Save Key
                </button>
              </div>
            </form>
          </div>
        </div>

        <div id="view-topup" class="mm-view hidden">
          <div class="mm-header">
            <div class="mm-title">
              <button id="nav-back-settings" class="mm-btn-ghost" title="Go Back">
                ←
              </button>
              Add Credits
            </div>
            <div class="mm-header-actions">
              <button class="mm-btn-ghost theme-toggle">🌙</button>
              <button
                id="btn-close"
                class="mm-btn-ghost mm-btn-close"
                title="Close Window"
              >
                ✕
              </button>
            </div>
          </div>
          <div class="mm-grid">
            <button
              class="mm-price-card charge-btn"
              data-amt="1"
              title="Get 2 Credits for $1"
            >
              <div class="mm-price-main">$1</div>
              <div class="mm-price-sub">2 Credits</div>
            </button>
            <button
              class="mm-price-card charge-btn"
              data-amt="5"
              title="Get 15 Credits for $5"
            >
              <div class="mm-price-main">$5</div>
              <div class="mm-price-sub">15 Credits</div>
              <div class="mm-badge">+50% Value</div>
            </button>
            <button
              class="mm-price-card charge-btn"
              data-amt="10"
              title="Get 35 Credits for $10"
              style="
                border-color: var(--mm-primary);
                background: rgba(59, 130, 246, 0.05);
              "
            >
              <div class="mm-price-main">$10</div>
              <div class="mm-price-sub">35 Credits</div>
              <div class="mm-badge">+75% Value</div>
            </button>
            <button
              class="mm-price-card charge-btn"
              data-amt="20"
              title="Get 75 Credits for $20"
            >
              <div class="mm-price-main">$20</div>
              <div class="mm-price-sub">75 Credits</div>
              <div class="mm-badge">+88% Value</div>
            </button>
            <button
              class="mm-price-card charge-btn"
              data-amt="50"
              title="Get 200 Credits for $50"
            >
              <div class="mm-price-main">$50</div>
              <div class="mm-price-sub">200 Credits</div>
              <div class="mm-badge">DOUBLE CREDITS (+100%)</div>
            </button>
          </div>
          <div
            id="msg-topup"
            style="
              text-align: center;
              font-size: 11px;
              margin-top: 10px;
              color: var(--mm-text-muted);
            "
          ></div>
        </div>

        <div id="mm-modal" class="mm-modal-bg hidden">
          <div class="mm-modal">
            <h3
              id="modal-title"
              style="
                font-size: 16px;
                font-weight: 700;
                margin-bottom: 8px;
                display: block;
              "
            >
              Confirm
            </h3>
            <p
              id="modal-msg"
              style="
                font-size: 13px;
                color: var(--mm-text-muted);
                margin-bottom: 16px;
                display: block;
              "
            >
              Sure?
            </p>
            <div class="mm-modal-actions">
              <button
                id="modal-cancel"
                class="mm-btn mm-btn-secondary"
                title="Cancel Action"
              >
                Cancel
              </button>
              <button
                id="modal-confirm"
                class="mm-btn mm-btn-primary"
                title="Confirm Action"
              >
                Confirm
              </button>
            </div>
          </div>
        </div>
      </div>

  `;
  document.body.appendChild(container);

  const getEl = (id) => container.querySelector(`#${id}`);
  const getEls = (sel) => container.querySelectorAll(sel);

  const showView = (id) => {
    getEls(".mm-view").forEach((v) => v.classList.add("hidden"));
    getEl(id).classList.remove("hidden");
  };

  function setBtnPos(code) {
    const el = getEl("mm-floating-btn");
    const pad = "20px";
    const auto = "auto";

    el.style.top = auto;
    el.style.bottom = auto;
    el.style.left = auto;
    el.style.right = auto;

    switch (code) {
      case "TL":
        el.style.top = pad;
        el.style.left = pad;
        break;
      case "BL":
        el.style.bottom = pad;
        el.style.left = pad;
        break;
      case "BR":
      default:
        el.style.bottom = pad;
        el.style.right = pad;
        break;
      case "TR":
        el.style.top = pad;
        el.style.right = pad;
        break;
    }
    GM_setValue("btnPosCode", code);

    getEls(".mm-pos-btn").forEach((btn) => {
      btn.classList.toggle("active", btn.dataset.pos === code);
    });
  }

  setBtnPos(GM_getValue("btnPosCode", "TR"));

  getEls(".mm-pos-btn").forEach((btn) => {
    btn.onclick = () => setBtnPos(btn.dataset.pos);
  });

  getEl("mm-floating-btn").onclick = () => {
    showView("view-main");
    container.classList.toggle("open");
  };

  function checkBanStatus() {
    const iframe = document.getElementById("videochat");
    let doc = null;
    if (iframe) {
      doc = iframe.contentDocument || iframe.contentWindow?.document;
    } else {
      doc = document;
    }

    if (!doc) return;

    const banPopup = doc.getElementById("BanPopup");
    const mobileBanPopup = doc.querySelector(".ban-popup.overlay.visible");

    if ((banPopup && banPopup.style.display === "block") || mobileBanPopup) {
      performAccountRefresh(true);
    }
  }

  function startMonitoring() {
    if (popupChecker) return;
    checkBanStatus();
    popupChecker = setInterval(checkBanStatus, 1000);
  }

  function stopMonitoring() {
    if (popupChecker) {
      clearInterval(popupChecker);
      popupChecker = null;
    }
  }

  const autoToggle = getEl("inp-autorefresh");
  autoToggle.onchange = () => {
    const isEnabled = autoToggle.checked;
    GM_setValue("autoRefresh", isEnabled);

    if (isEnabled) {
      startMonitoring();
    } else {
      stopMonitoring();
    }
  };

  function apiRequest(endpoint, method = "GET", body = null, apiKey = null) {
    return new Promise((resolve, reject) => {
      const headers = {
        "ngrok-skip-browser-warning": "true",
        "Content-Type": "application/json",
      };
      if (apiKey) headers["X-Api-Key"] = apiKey;
      GM_xmlhttpRequest({
        method,
        url: `${BASE_URL}${endpoint}`,
        headers,
        data: body ? JSON.stringify(body) : null,
        onload: (res) => {
          if (res.status >= 200 && res.status < 300) {
            try {
              resolve(JSON.parse(res.responseText));
            } catch {
              reject("Bad JSON");
            }
          } else {
            try {
              reject(new Error(JSON.parse(res.responseText).detail || "Error"));
            } catch {
              reject(new Error("Status: " + res.status));
            }
          }
        },
        onerror: () => reject(new Error("Network Error")),
      });
    });
  }

  async function fetchInfo() {
    const k = GM_getValue("userApiKey", "");
    if (!k) return { credits: -1, user_id: null };
    try {
      return await apiRequest("/balance", "GET", null, k);
    } catch {
      return { credits: -1, user_id: null };
    }
  }

  function renderHistory() {
    const list = GM_getValue("accountHistory", []);
    const ul = getEl("list-history");
    ul.innerHTML = "";
    list.forEach((item) => {
      const li = document.createElement("li");
      li.className = "mm-list-item";
      li.innerHTML = `<span class="mm-time" title="Restore Account Generated at ${item.timestamp}">${item.timestamp}</span>`;
      li.onclick = async () => {
        const isAutoRefreshEnabled = getEl("inp-autorefresh").checked;
        if (isAutoRefreshEnabled) {
          if (
            await confirmAction(
              "WARNING: Auto Refresh Enabled",
              "If this account is banned, you will immediately spend a credit to refresh. Restore anyway?"
            )
          ) {
            clearSiteData(item.account, scrapeSettings());
          }
        } else {
          if (
            await confirmAction("Restore?", "Restore this account session?")
          ) {
            clearSiteData(item.account, scrapeSettings());
          }
        }
      };
      ul.appendChild(li);
    });
  }

  function clearSiteData(account, settings) {
    window.postMessage(
      {
        type: "RESET_SESSION_CONTEXT",
        token: SYNC_TOKEN,
        account,
        settings,
      },
      "*"
    );
  }

  window.addEventListener("message", (e) => {
    if (
      e.data?.type === "SESSION_RESET_COMPLETE" &&
      e.data.token === SYNC_TOKEN
    ) {
      const s = e.data.settings;
      localStorage.setItem("snid", e.data.account);
      if (s) {
        localStorage.setItem("selected_country", s.selected_country);
        localStorage.setItem("gender", s.gender);
        localStorage.setItem("language", s.language);
        localStorage.setItem("translate_messages", s.translate_messages);
      }
      location.reload();
    }
  });

  function scrapeSettings() {
    return {
      selected_country: localStorage.getItem("selected_country") || "ZZ",
      gender: localStorage.getItem("gender") || "0",
      language: localStorage.getItem("language") || "en",
      translate_messages: localStorage.getItem("translate_messages") === "true",
    };
  }

  const applyTheme = (isDark) => {
    isDark
      ? container.classList.add("dark-mode")
      : container.classList.remove("dark-mode");
    getEls(".theme-toggle").forEach(
      (b) => (b.textContent = isDark ? "☀️" : "🌙")
    );
  };
  getEls(".theme-toggle").forEach(
    (b) =>
      (b.onclick = () => {
        const d = !container.classList.contains("dark-mode");
        GM_setValue("darkMode", d);
        applyTheme(d);
      })
  );

  getEl("btn-settings").onclick = () => showView("view-settings");
  getEl("nav-back-main").onclick = () => showView("view-main");
  getEl("nav-topup").onclick = () => showView("view-topup");
  getEl("nav-back-settings").onclick = () => showView("view-settings");
  getEls(".mm-btn-close").forEach(
    (b) => (b.onclick = () => container.classList.remove("open"))
  );
  getEl("btn-refresh-credits").onclick = async () => {
    const info = await fetchInfo();
    getEl("val-credits").textContent = info.credits >= 0 ? info.credits : "--";
    getEl("inp-userid").value = info.user_id || "";
  };

  getEl("btn-copy-userid").onclick = () =>
    navigator.clipboard.writeText(getEl("inp-userid").value);
  getEl("btn-copy-key").onclick = () =>
    navigator.clipboard.writeText(getEl("inp-key").value);

  function confirmAction(title, msg) {
    return new Promise((resolve) => {
      const m = getEl("mm-modal");
      getEl("modal-title").textContent = title;
      getEl("modal-msg").textContent = msg;
      m.classList.remove("hidden");
      getEl("modal-confirm").onclick = () => {
        m.classList.add("hidden");
        resolve(true);
      };
      getEl("modal-cancel").onclick = () => {
        m.classList.add("hidden");
        resolve(false);
      };
    });
  }

  getEl("btn-gen-key").onclick = async () => {
    const k = GM_getValue("userApiKey", "");
    if (
      !k ||
      (await confirmAction(
        "Existing API Key Detected",
        "This will replace your existing API key and reset your credits to 0. Are you sure?"
      ))
    ) {
      try {
        getEl("btn-gen-key").textContent = "...";
        const d = await apiRequest("/register", "POST");
        GM_setValue("userApiKey", d.api_key);
        init();
      } catch (e) {
        alert(e.message);
      }
      getEl("btn-gen-key").textContent = "Generate";
    }
  };

  getEl("btn-save").onclick = async () => {
    const k = GM_getValue("userApiKey", "");
    const isSameKey = k === getEl("inp-key");
    if (
      !isSameKey &&
      (!k ||
        (await confirmAction(
          "Save API Key?",
          "Do you want to overwrite your current key and lose access to any existing credits?"
        )))
    ) {
      GM_setValue("userApiKey", getEl("inp-key").value);
      init();
    }
  };

  async function performAccountRefresh(isAuto = false) {
    if (!isAuto) {
      const confirmed = await confirmAction(
        "Refresh?",
        "This will spend 1 credit to generate new account data and clear your current cookies."
      );
      if (!confirmed) return;
    }

    stopMonitoring();

    const btn = getEl("btn-refresh");
    if (btn) {
      btn.disabled = true;
      btn.innerHTML = "Working...";
    }

    try {
      const d = await apiRequest(
        "/refresh",
        "POST",
        {},
        GM_getValue("userApiKey")
      );
      const h = GM_getValue("accountHistory", []);
      h.unshift({
        timestamp: new Date().toLocaleString(),
        account: d.account,
      });
      GM_setValue("accountHistory", h.slice(0, 10));

      clearSiteData(d.account, scrapeSettings());
    } catch (e) {
      const msgEl = getEl("msg-main");
      if (msgEl) msgEl.textContent = e.message;

      if (btn) {
        btn.disabled = false;
        btn.innerHTML = "<span>↻</span> Refresh Account";
      }

      const isAuto = getEl("inp-autorefresh").checked;
      if (isAuto) startMonitoring();
    }
  }

  getEl("btn-refresh").onclick = async () => performAccountRefresh(false);

  getEls(".charge-btn").forEach((btn) => {
    btn.onclick = async () => {
      const amt = btn.dataset.amt;
      if (
        await confirmAction("Charge?", `Generate a payment link for $${amt}?`)
      ) {
        try {
          getEl("msg-topup").textContent = "Opening...";
          const d = await apiRequest(
            "/create-charge",
            "POST",
            { amount_usd: parseInt(amt) },
            GM_getValue("userApiKey")
          );
          const url = d.data?.hosted_url || d.url;
          if (url) {
            GM_openInTab(url, { active: true });
            getEl("msg-topup").textContent = "Opened tab.";
          }
        } catch (e) {
          getEl("msg-topup").textContent = e.message;
        }
      }
    };
  });

  async function init() {
    applyTheme(GM_getValue("darkMode", false));
    const k = GM_getValue("userApiKey", "");
    if (k) getEl("inp-key").value = k;

    const info = await fetchInfo();
    getEl("val-credits").textContent = info.credits >= 0 ? info.credits : "--";
    getEl("inp-userid").value = info.user_id || "";

    renderHistory();

    const savedAutoRefresh = GM_getValue("autoRefresh", false);
    autoToggle.checked = savedAutoRefresh;
    if (savedAutoRefresh) {
      startMonitoring();
    }

    const firstRunComplete = GM_getValue("firstRunComplete", false);
    if (!firstRunComplete) {
      GM_openInTab(LANDING_URL, { active: true });
      GM_setValue("firstRunComplete", true);
    }
  }
  init();
})();