Nyako LIB

Common library for Tampermonkey/ViolentMonkey scripts

Ce script ne devrait pas être installé directement. C'est une librairie créée pour d'autres scripts. Elle doit être inclus avec la commande // @require https://update.greasyfork.org/scripts/586977/1875787/Nyako%20LIB.js

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 !)

Advertisement:

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!)

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;