Nyako LIB

Common library for Tampermonkey/ViolentMonkey scripts

Questo script non dovrebbe essere installato direttamente. È una libreria per altri script da includere con la chiave // @require https://update.greasyfork.org/scripts/586977/1875787/Nyako%20LIB.js

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

You will need to install an extension such as Tampermonkey to install this script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Advertisement:

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

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;