linux.do.level

Linux.Do 查看用户信任级别以及升级条件,数据来源于 https://connect.linux.do

À partir de 2024-03-29. Voir la dernière version.

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name         linux.do.level
// @namespace    https://linux.do/u/io.oi/s/level
// @version      1.1.1
// @author       LINUX.DO
// @description  Linux.Do 查看用户信任级别以及升级条件,数据来源于 https://connect.linux.do
// @icon         https://cdn.linux.do/uploads/default/original/1X/de7ee26820e897b6a07350126411ebc489f62202.png
// @match        https://linux.do/*
// @grant        GM.xmlHttpRequest
// @grant        GM_addStyle
// ==/UserScript==

(e=>{if(typeof GM_addStyle=="function"){GM_addStyle(e);return}const o=document.createElement("style");o.textContent=e,document.head.append(o)})(" .level-window{position:fixed;bottom:0;background:var(--secondary);z-index:999;padding:.5em;color:var(--primary);box-shadow:0 0 4px #00000020;border:1px solid var(--primary-low)}.level-window .title .close{width:30px;height:30px;color:#fff;background:red;display:inline-block;text-align:center;line-height:30px;float:right;cursor:pointer;border-radius:4px}.level-window .bg-white{background-color:var(--primary-50);border-radius:.5em;padding:.5em;margin-top:.5em}.level-window h1{color:var(--primary);font-size:1.3rem}.level-window h2{font-size:1.25rem}.mb-4 table tr:nth-child(2n){background-color:var(--tertiary-400)}.level-window .text-red-500{color:#ef4444}.level-window .text-green-500{color:#10b981}.level-window .mb-4 table tr td{padding:4px 8px} ");

(function () {
  'use strict';

  var _GM = /* @__PURE__ */ (() => typeof GM != "undefined" ? GM : void 0)();
  async function getLevelFromConnect() {
    return await new Promise((resolve, reject) => {
      _GM.xmlHttpRequest({
        method: "GET",
        url: "https://connect.linux.do",
        onload: (response) => {
          let regx = /<body[^>]*>([\s\S]+?)<\/body>/i;
          let contents = regx.exec(response.responseText);
          if (contents) {
            const content = contents[1].replace('<a href="/logout" target="_self" class="text-blue-500 hover:underline" title="LINUX DO登录也会退出">退出</a>', "");
            resolve({
              status: true,
              content,
              error: ""
            });
          }
        },
        onerror: (e) => {
          reject({ status: false, error: e.error, content: "" });
        }
      });
    });
  }
  let levelWindow = void 0;
  function createLevelButton() {
    const loadingHTML = `
        <div class="widget-component-connector">
          <a class="icon btn-flat" tabindex="2" title="查看我的等级">
            <svg xmlns="http://www.w3.org/2000/svg" width="60px" height="60px" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid" class="lds-ring">
              <circle cx="50" cy="50" r="30" stroke="#B3B5B4" stroke-width="10" fill="none"/>
              <circle cx="50" cy="50" r="30" stroke="#808281" stroke-width="10" fill="none" transform="rotate(144 50 50)">
                <animateTransform attributeName="transform" type="rotate" calcMode="linear" values="0 50 50;360 50 50" keyTimes="0;1" dur="1s" begin="0s" repeatCount="indefinite"/>
                <animate attributeName="stroke-dasharray" calcMode="linear" values="18.84955592153876 169.64600329384882;94.2477796076938 94.24777960769377;18.84955592153876 169.64600329384882" keyTimes="0;0.5;1" dur="1" begin="0s" repeatCount="indefinite"/>
              </circle> 
            </svg>
          </a>
        </div>`;
    const defaultHTML = `
        <div class="widget-component-connector">
          <a class="icon btn-flat" tabindex="2" title="查看我的等级">
            <svg class="fa d-icon d-icon-d-chat svg-icon svg-string" xmlns="http://www.w3.org/2000/svg"><use href="#discourse-sparkles"></use></svg>
          </a>
        </div>`;
    let li = document.createElement("li");
    li.className = "header-dropdown-toggle chat-header-icon";
    li.setAttribute("id", "level-button");
    li.innerHTML = `
        <div class="widget-component-connector">
            <a class="icon btn-flat" tabindex="2" title="查看我的等级">
                <svg class="fa d-icon d-icon-d-chat svg-icon svg-string" xmlns="http://www.w3.org/2000/svg"><use href="#discourse-sparkles"></use></svg>
            </a>
        </div>
    `;
    let loading = false;
    li.addEventListener("click", async () => {
      if (!loading && !levelWindow) {
        loading = true;
        li.innerHTML = loadingHTML;
        let result = await getLevelFromConnect();
        loading = false;
        li.innerHTML = defaultHTML;
        if (result.status) {
          levelWindow = createWindow(result.content);
          document.body.appendChild(levelWindow);
        } else {
          console.error(result.error);
        }
      } else if (levelWindow && !loading) {
        levelWindow.remove();
        levelWindow = void 0;
      }
    });
    return li;
  }
  function createWindow(content) {
    let root = document.createElement("div");
    root.setAttribute("id", "level-window");
    root.className = "level-window";
    root.style.right = document.querySelector("div.chat-drawer.is-expanded") ? "430px" : "15px";
    root.innerHTML = `
     <div class="title">
         <span class="close" id="close-button">
              <svg class="fa d-icon d-icon-times svg-icon svg-string" xmlns="http://www.w3.org/2000/svg">
                  <use href="#times"></use>
              </svg>
         </span>
         <div id="content" class="content"></div>
     </div>`;
    let container = root.querySelector("div#content");
    if (container) {
      container.innerHTML = content;
    }
    let close = root.querySelector("span#close-button");
    if (close) {
      close.addEventListener("click", () => {
        root.remove();
        levelWindow = void 0;
      });
    }
    let chatContainer = document.querySelector("div.chat-drawer-outlet-container");
    if (chatContainer) {
      let observer = new MutationObserver((_) => {
        let chat = document.querySelector("div.chat-drawer.is-expanded");
        root.style.right = chat ? "430px" : "15px";
      });
      observer.observe(chatContainer, { childList: true });
    }
    return root;
  }
  (() => {
    let headerObserver = void 0;
    function fixSearchButton(titleBar) {
      let search = titleBar.childNodes[1];
      if (search) {
        titleBar.removeChild(search);
        titleBar.prepend(search);
      }
      titleBar.prepend(createLevelButton());
    }
    function fixPeopleButton(titleBar) {
      if (titleBar.lastChild) {
        titleBar.lastChild.addEventListener("click", () => {
          if (titleBar.parentElement && titleBar.parentElement.lastChild) {
            if (titleBar.parentElement.lastChild.nodeName === "DIV") {
              titleBar.parentElement.removeChild(titleBar.parentElement.lastChild);
            }
          }
        });
      }
    }
    function addLevelButtonToTitleBar(header) {
      let titleBar = header.querySelector("header div div div.panel ul.icons.d-header-icons");
      if (titleBar) {
        if (titleBar.querySelector("li#level-button")) {
          return;
        }
        fixSearchButton(titleBar);
        fixPeopleButton(titleBar);
      } else {
        console.warn("query title bar fail.");
      }
    }
    function addHeaderObserver(header) {
      if (headerObserver) {
        headerObserver.disconnect();
      }
      headerObserver = new MutationObserver((_) => {
        addLevelButtonToTitleBar(header);
      });
      headerObserver.observe(header, { childList: true });
      addLevelButtonToTitleBar(header);
    }
    function init() {
      window.addEventListener("load", () => {
        let header = document.querySelector("body section div div.d-header-wrap.drop-down-mode.ember-view");
        if (header) {
          addHeaderObserver(header);
        } else {
          let section = document.querySelector("section.ember-application");
          if (section) {
            let mainObserver = new MutationObserver((_) => {
              addHeaderObserver(section.querySelector("body section div div.d-header-wrap.drop-down-mode.ember-view"));
              mainObserver.disconnect();
            });
            mainObserver.observe(section, { childList: true });
          }
        }
      });
      window.addEventListener("unload", () => {
        if (headerObserver) {
          headerObserver.disconnect();
        }
      });
    }
    init();
  })();

})();