Common library for Tampermonkey/ViolentMonkey scripts
Hindi dapat direktang i-install ang script na ito. Ito ay isang library para sa iba pang mga script na isasama sa meta directive. // @require https://update.greasyfork.org/scripts/586977/1875787/Nyako%20LIB.js
// ==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;