Nyako LIB

Common library for Tampermonkey/ViolentMonkey scripts

Este script não deve ser instalado diretamente. Este script é uma biblioteca de outros scripts para incluir com o diretório meta // @require https://update.greasyfork.org/scripts/586977/1875787/Nyako%20LIB.js

Você precisará instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Você precisará instalar uma extensão como o Tampermonkey para instalar este script.

Você precisará instalar um gerenciador de scripts de usuário para instalar este script.

(Eu já tenho um gerenciador de scripts de usuário, me deixe instalá-lo!)

Advertisement:

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

(Eu já possuo um gerenciador de estilos de usuário, me deixar fazer a instalação!)

Advertisement:

// ==UserScript==
// @name         Nyako LIB
// @version      0.5.0
// @description  Common library for Tampermonkey scripts
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_registerMenuCommand
// @license     Apache License 2.0
// @author      https://t.me/Nyako_TW
// @compatible   tampermonkey
// @compatible   violentmonkey
// @incompatible greasemonkey
// ==/UserScript==

var NyakoLib = {};
 
 
// Вспомогательные утилиты
NyakoLib.getPlatform = function() {
  var ua = navigator.userAgent.toLowerCase();
  if (/android/.test(ua)) {
    return "android";
  }
  if (/iphone|ipad|ipod/.test(ua)) {
    return "ios";
  }
  if (/macintosh/.test(ua) && navigator.maxTouchPoints > 1) {
    return "ios";
  }
  if (/windows|linux|mac/.test(ua)) {
    return "pc";
  }
  return "unknown";
};
 
NyakoLib.safeRun = function(fn, name, platforms) {
  if (platforms == undefined) { platforms = []; }
  try {
    var platform = NyakoLib.getPlatform();
    if (platforms.length > 0 && !platforms.includes(platform)) {
      console.log("Пропущено " + name + ": недоступно для " + platform);
      return;
    }
    fn();
  } catch (e) {
    console.error("Ошибка в " + name + ":", e);
  }
};

NyakoLib.injectButton = function() {
  var btn = document.createElement("button");
  btn.setAttribute("id", "nya-config-button-script");
  btn.innerHTML = "⚙️ Настройки";
  
  var btn_style = "position: fixed; left: 25px; bottom: 25px; z-index: 2147483646; padding: 12px 18px; background: rgba(0,0,0,.65); color: #fff; border: 1px solid rgba(255,255,255,.15); border-radius: 14px; cursor: pointer; font-family: Arial, sans-serif; font-size: 14px; backdrop-filter: blur(15px); box-shadow: 0 10px 35px rgba(0,0,0,.6); transition: 0.3s;";
  btn.setAttribute("style", btn_style);
  
  btn.onmouseover = function() { btn.style.background = "rgba(0,0,0,.85)"; };
  btn.onmouseout = function() { btn.style.background = "rgba(0,0,0,.65)"; };
  
  document.body.appendChild(btn);
};


// Фунции уведомлений
NyakoLib.Notify = {};
 
NyakoLib.Notify.beep = function() {
  try {
    var ctx = new AudioContext();
    var osc = ctx.createOscillator();
    var gain = ctx.createGain();
 
    osc.type = "triangle";
    osc.connect(gain);
    gain.connect(ctx.destination);
 
    osc.frequency.setValueAtTime(1000, ctx.currentTime);
    osc.frequency.setValueAtTime(1400, ctx.currentTime + 0.15);
 
    gain.gain.setValueAtTime(0.2, ctx.currentTime);
    gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.3);
 
    osc.start(ctx.currentTime);
    osc.stop(ctx.currentTime + 0.3);
  } catch (e) {
    console.error("Ошибка в beep:", e);
  }
};
 
NyakoLib.Notify.getContainer = function() {
  var notify_container = document.getElementById("nyako-notify-container");
  if (!notify_container) {
    notify_container = document.createElement("div");
    notify_container.setAttribute("id", "nyako-notify-container");
    
    var container_style = "position: fixed; right: 25px; bottom: 25px; z-index: 2147483647; display: flex; flex-direction: column; justify-content: flex-end; gap: 15px; pointer-events: none;";
    notify_container.setAttribute("style", container_style);
    document.body.appendChild(notify_container);
  }
  return notify_container;
};
 
NyakoLib.Notify.show = function(message_text, duration_time, play_sound) {
  if (duration_time == undefined) { duration_time = 5000; }
  if (play_sound == undefined) { play_sound = true; }
 
  if (play_sound) {
    NyakoLib.Notify.beep();
  }
 
  var container = NyakoLib.Notify.getContainer();
  
  var current_notifs = container.getElementsByClassName("nyako-notify-box");
  while (current_notifs.length >= 3) {
    current_notifs[0].remove();
  }
 
  var box = document.createElement("div");
  box.setAttribute("class", "nyako-notify-box");
  
  var box_html = "<span>" + message_text + "</span>";
  box_html = box_html + "<button class=\"nyako-close\" style=\"width: 28px; height: 28px; border-radius: 50%; border: 1px solid rgba(255,255,255,.2); background: rgba(255,255,255,.08); color: #fff; cursor: pointer; font-size: 20px; display: flex; align-items: center; justify-content: center; padding: 0;\">×</button>";
  box.innerHTML = box_html;
 
  var box_style = "pointer-events: auto; min-width: 280px; max-width: 380px; padding: 16px 18px; display: flex; align-items: center; justify-content: space-between; gap: 15px; background: rgba(0,0,0,.65); backdrop-filter: blur(15px); border: 1px solid rgba(255,255,255,.15); border-radius: 14px; color: #fff; font-family: Arial, sans-serif; box-shadow: 0 10px 35px rgba(0,0,0,.6); opacity: 0; transform: translateX(30px); transition: 0.35s ease;";
  box.setAttribute("style", box_style);
 
  var close_btn = box.getElementsByClassName("nyako-close")[0];
 
  close_btn.onclick = function() {
    box.setAttribute("style", box_style + " opacity: 0; transform: translateX(30px);");
    setTimeout(function() { box.remove(); }, 350);
  };
 
  container.appendChild(box);
 
  setTimeout(function() {
    box.setAttribute("style", box_style + " opacity: 1; transform: translateX(0);");
  }, 10);
 
  if (duration_time > 0) {
    setTimeout(function() {
      if (box.parentNode) { close_btn.onclick(); }
    }, duration_time);
  }
 
  return box;
};
 
 
 
// Фунции настроек
NyakoLib.Config = {};
NyakoLib.Config.prefix = "nyako_";
NyakoLib.Config.items = {};
 
NyakoLib.Config.get = function(name, default_value) {
  return GM_getValue(NyakoLib.Config.prefix + name, default_value);
};
 
NyakoLib.Config.set = function(name, set_value) {
  GM_setValue(NyakoLib.Config.prefix + name, set_value);
};
 
NyakoLib.Config.setup = function(configs_list) {
  NyakoLib.Config.items = configs_list;
 
  GM_registerMenuCommand("⚙️ Настройки скрипта", function() {
    NyakoLib.Config.showWindow();
  });
 
  document.addEventListener("click", function(event_data) {
    var btn_element = event_data.target.closest("#nya-config-button-script");
    if (btn_element) {
      event_data.preventDefault();
      NyakoLib.Config.showWindow();
    }
  });
};
 
NyakoLib.Config.showWindow = function() {
  var old_window = document.getElementById("nyako-settings-window");
  if (old_window) {
    old_window.remove();
  }
 
  var win = document.createElement("div");
  win.setAttribute("id", "nyako-settings-window");
 
  var win_style = "position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 340px; background: rgba(0,0,0,.75); backdrop-filter: blur(15px); border: 1px solid rgba(255,255,255,.15); border-radius: 14px; color: #fff; font-family: Arial, sans-serif; box-shadow: 0 10px 40px rgba(0,0,0,.7); z-index: 2147483647; display: flex; flex-direction: column;";
  win.setAttribute("style", win_style);
 
  var header = document.createElement("div");
  header.setAttribute("style", "padding: 15px 18px; border-bottom: 1px solid rgba(255,255,255,.15); display: flex; justify-content: space-between; align-items: center; font-weight: bold; font-size: 16px;");
  
  var header_html = "<span>⚙️ Настройки</span>";
  header_html = header_html + "<button class=\"close-win\" style=\"width: 28px; height: 28px; border-radius: 50%; border: 1px solid rgba(255,255,255,.2); background: rgba(255,255,255,.08); color: #fff; cursor: pointer; font-size: 20px; display: flex; align-items: center; justify-content: center; padding: 0;\">×</button>";
  header.innerHTML = header_html;
  win.appendChild(header);
 
  var body_element = document.createElement("div");
  body_element.setAttribute("style", "padding: 15px 18px; display: flex; flex-direction: column; gap: 14px; max-height: 70vh; overflow-y: auto;");
 
  var needs_reload = false;
 
  // Локальная функция для создания одной настройки
  var createItemUI = function(key_name, opt_data) {
    let default_val = false;
    if (opt_data.defaultValue != undefined) { default_val = opt_data.defaultValue; }
    
    let opt_type = "checkbox";
    if (opt_data.type != undefined) { opt_type = opt_data.type; }
 
    let current_value = NyakoLib.Config.get(key_name, default_val);
 
    let label_element = document.createElement("label");
    label_element.setAttribute("style", "display: flex; justify-content: space-between; align-items: center; font-size: 14px; cursor: pointer;");
 
    let title_text = key_name;
    if (opt_data.title != undefined) { title_text = opt_data.title; }
 
    let label_html = "<span style=\"margin-right: 15px;\">" + title_text + "</span>";
    let input_html = "";
    
    let input_style = "padding: 4px 8px; border-radius: 6px; border: 1px solid rgba(255,255,255,.2); background: rgba(0,0,0,.5); color: #fff; outline: none; font-size: 14px; max-width: 140px;";
 
    if (opt_type == "checkbox") {
      let checked_attr = "";
      if (current_value) { checked_attr = "checked"; }
      input_html = "<input type=\"checkbox\" style=\"width: 18px; height: 18px; cursor: pointer;\" " + checked_attr + ">";
    } 
    else if (opt_type == "text" || opt_type == "number") {
      input_html = "<input type=\"" + opt_type + "\" value=\"" + current_value + "\" style=\"" + input_style + "\">";
      label_element.style.cursor = "default";
    }
    else if (opt_type == "select") {
      input_html = "<select style=\"" + input_style + "\">";
      if (opt_data.options != undefined) {
        for (let opt_name in opt_data.options) {
          let opt_val = opt_data.options[opt_name];
          let is_selected = (current_value == opt_val) ? "selected" : "";
          input_html = input_html + "<option value=\"" + opt_val + "\" " + is_selected + ">" + opt_name + "</option>";
        }
      }
      input_html = input_html + "</select>";
      label_element.style.cursor = "default";
    }
 
    label_element.innerHTML = label_html + input_html;
 
    let input_node = label_element.getElementsByTagName("input")[0];
    if (!input_node) { input_node = label_element.getElementsByTagName("select")[0]; }
    
    input_node.onchange = function() {
      let new_value = input_node.value;
      
      if (opt_type == "checkbox") {
        new_value = input_node.checked;
      } else if (opt_type == "number") {
        new_value = Number(new_value);
      }
      
      NyakoLib.Config.set(key_name, new_value);
      
      let msg_text = title_text + ": ";
      if (opt_type == "checkbox") {
        let on_text = "включено";
        let off_text = "выключено";
        if (opt_data.onText != undefined) { on_text = opt_data.onText; }
        if (opt_data.offText != undefined) { off_text = opt_data.offText; }
        
        if (new_value) { msg_text = msg_text + on_text; } else { msg_text = msg_text + off_text; }
      } else {
        msg_text = msg_text + new_value;
      }
      
      NyakoLib.Notify.show(msg_text, 5000, false);
 
      if (opt_data.reload !== false) {
        needs_reload = true;
      }
    };
 
    return label_element;
  };
 
  // Перебираем переданные настройки
  for (let top_key in NyakoLib.Config.items) {
    let top_val = NyakoLib.Config.items[top_key];
    
    // Проверяем: это настройка (старый формат) или категория (вложенный объект)
    if (top_val.title != undefined || top_val.defaultValue != undefined || top_val.type != undefined) {
      body_element.appendChild(createItemUI(top_key, top_val));
    } else {
      // Это категория
      let cat_header = document.createElement("div");
      var cat_style = "font-weight: bold; font-size: 15px; color: #e0e0e0; border-bottom: 1px solid rgba(255,255,255,.15); padding-bottom: 6px; margin-top: 5px; margin-bottom: -5px;";
      cat_header.setAttribute("style", cat_style);
      cat_header.innerText = top_key;
      body_element.appendChild(cat_header);
      
      for (let sub_key in top_val) {
        let sub_val = top_val[sub_key];
        body_element.appendChild(createItemUI(sub_key, sub_val));
      }
    }
  }
 
  win.appendChild(body_element);
 
  var win_close_btn = header.getElementsByClassName("close-win")[0];
  win_close_btn.onclick = function() {
    win.remove();
    if (needs_reload) {
      NyakoLib.Notify.show("Перезагрузка страницы для применения настроек...", 5000, false);
      setTimeout(function() { location.reload(); }, 1500);
    }
  };
 
  document.body.appendChild(win);
};
 
window.NyakoLib = NyakoLib;