您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
GreaysFork 快速输入脚本同步信息,并批量增加多个国家的语言代码,而不用一个个地点击选择框再去对应的网址。
当前为
// ==UserScript== // @name GreaysFork Enhanced WebHook Sync Settings // @description Quickly input script sync information and batch add language codes for multiple countries without the need to click // @name:zh-CN GreaysFork 增强WebHook同步设置 // @description:zh-CN GreaysFork 快速输入脚本同步信息,并批量增加多个国家的语言代码,而不用一个个地点击选择框再去对应的网址。 // @name:zh-TW GreaysFork 增強WebHook同步設定 // @description:zh-TW GreaysFork 快速輸入腳本同步資訊,並批量增加多個國家的語言代碼,而不用逐個點擊選擇框再去對應的網址。 // @name:zh-HK GreaysFork 增強WebHook同步設置 // @description:zh-HK GreaysFork 快速輸入腳本同步信息,並批量增加多個國家語言代碼,而不用逐個點擊選擇框再去對應的網址。 // @name:ja GreaysFork WebHook同期設定の強化 // @description:ja GreaysFork スクリプト同期情報を素早く入力し、複数の国の言語コードを一括で追加します。選択ボックスを一つ一つクリックする必要はありません。 // @name:ko GreaysFork WebHook 동기화 설정 강화 // @description:ko GreaysFork 스크립트 동기화 정보를 빠르게 입력하고, 여러 국가의 언어 코드를 한 번에 추가합니다. 선택 상자를 하나하나 클릭할 필요가 없습니다. // @name:ru Улучшенные настройки синхронизации WebHook для GreaysFork // @description:ru Быстрое ввод данных синхронизации скриптов GreaysFork и массовое добавление языковых кодов нескольких стран без необходимости поочередного выбора из выпадающего списка и перехода по соответствующим ссылкам. // @name:en GreaysFork Enhanced WebHook Sync Settings // @description:en Quickly input script sync information and batch add language codes for multiple countries without the need to click through each selection box and visit corresponding URLs. // @name:fr GreaysFork Amélioration des paramètres de synchronisation WebHook // @description:fr Saisie rapide des informations de synchronisation des scripts GreaysFork et ajout en masse des codes de langue pour plusieurs pays sans avoir à sélectionner chaque option individuellement et visiter les URL correspondantes. // @name:de GreaysFork Verbesserte WebHook-Synchronisierungseinstellungen // @description:de Schnelles Eingeben von Skriptsynchronisierungsinformationen und gleichzeitiges Hinzufügen von Sprachcodes für mehrere Länder, ohne jedes Auswahlfeld einzeln anzuklicken und die entsprechenden URLs zu besuchen. // @name:vi Cài đặt đồng bộ WebHook GreaysFork được nâng cao // @description:vi Nhập nhanh thông tin đồng bộ hóa kịch bản GreaysFork và thêm hàng loạt mã ngôn ngữ cho nhiều quốc gia mà không cần phải nhấp từng ô chọn và truy cập các URL tương ứng. // @namespace http://tampermonkey.net/ // @version 1.0 // @compatible chrome // @compatible firefox // @compatible edge // @compatible opera // @compatible safari // @icon https://github.com/ChinaGodMan/UserScripts/raw/main/docs/icon/Scripts%20Icons/RedFork.svg // @author 人民的勤务员 <[email protected]> // @match *://gf.qytechs.cn/* // @license MIT // @supportURL https://github.com/ChinaGodMan/UserScripts/issues // @homepageURL https://github.com/ChinaGodMan/UserScripts // @namespace https://github.com/ChinaGodMan/UserScripts // ==/UserScript== (function () { 'use strict' let isCreated1 = null let isCreated = null const global = { syncingfrom: null,//脚本同步地址 adminUrl: null,//同步地址 defaultAttribute: null,//默认匹配@name //用于设置时显示用 inputModal: null,//设置床窗口 inputModalTextArea: null,//链接 inputModalScript: null,//输入同步脚本地址框 inputModalDefault: null, //默认匹配@name的输入框 attribute_other: null,///本地化附加信息,用于设置时显示. scriptname: null } document.head.appendChild(document.createElement('style')).textContent = ` #main-header ~ .width-constraint > .text-content:only-child > ul li { font-size: 0.88rem; } /* Basic Styling for Submit Inputs and Buttons */ .Sync-Modal button { font-family: 'Arial', sans-serif; font-size: 10pt; color: #FFFFFF; background-color: #007BFF; border: none; border-radius: 5px; padding: 8px 16px; cursor: pointer; transition: background-color 0.3s ease; text-align: center; outline: none; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); } /* Hover effect */ input[type="submit"]:hover, button:hover { background-color: #0056b3; } /* Active (pressed) effect */ input[type="submit"]:active, button:active { background-color: #004494; } /* Focus effect for accessibility */ input[type="submit"]:focus, button:focus { box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.5); } .Sync-Modal textarea { border: 0; padding: 0; font-family: inherit; font-weight: 900; color: #a83710; font-size: inherit; appearance: none; border: none; outline: none; resize: none; } .Sync-Modal input { border: 0; padding: 0; font-family: inherit; font-weight: 900; color: #80ecd3; font-size: inherit; appearance: none; border: none; outline: none; resize: none; } .custom-label { font-weight: bold; color: #bfe6a0; } ` function creatSetModal() { if (isCreated) return } document.body.insertAdjacentHTML('beforeend', ` <div class="Sync-Modal"> <button id="openSyncButton" style="position:fixed;top:10px;right:10px;z-index:1000;display:none;">Open Modal</button> <button id="openSyncOnadminPage" style="position:fixed;top:300px;right:200px;z-index:1000;display:none;">Set sync</button> <div id="inputWindow" style="display:none;position:fixed;left:0;top:0;width:100%;height:100%;background-color:rgba(0,0,0,0.5);justify-content:center;align-items:center;z-index:1001;"> <div style="background-color:white;padding:20px;border-radius:5px;width:1000px;max-width:90%;height:95%;max-height:100%;"> <center><label id="ScriptName">Source Syncing</label> </center> <h2 style="color: blue;"><label id="SyncLabel" label for="SyncScript">Source Syncing</label></h2> <input type="text" id="SyncScriptForm" style="width:100%;margin-bottom:10px;"> <h3> <label for="default" class="custom-label">Default additional info (language matches @name)</label> </h3> <input type="text" id="inputdefaultAttribute" style="width:100%;margin-bottom:10px;"> <h3>For locale (matches @name:XX):</h3> <textarea id="urlTextArea" rows="6" style="height:600px;width:100%;"></textarea> <br> <div style="display: flex; justify-content: flex-end;"> <button id="submitModalButton" style="margin-left: 10px;">Update and sync now</button> <button id="closeSyncButton" style="margin-left: 10px; background-color: red;">Close</button> </div> </div> </div> </div> `) global.inputModal = document.getElementById('inputWindow') global.inputModalScript = document.getElementById('SyncScriptForm') global.inputModalDefault = document.getElementById('inputdefaultAttribute') global.inputModalTextArea = document.getElementById('urlTextArea') const openModalButton = document.getElementById('openSyncButton') const closeModalButton = document.getElementById('closeSyncButton') const submitModalButton = document.getElementById('submitModalButton') const openSyncOnadminPage = document.getElementById('openSyncOnadminPage') openModalButton.addEventListener('click', addAdminButtons) closeModalButton.addEventListener('click', () => global.inputModal.style.display = 'none') submitModalButton.addEventListener('click', handleSubmit) function handleSubmit() { syncUpdate(SyncScriptForm.value, global.inputModalDefault.value, global.adminUrl) } openSyncOnadminPage.addEventListener('click', () => { openSuperAdmin(window.location.href.replace(/\/[^\/]*$/, ''), "", false) }) //取消鲨臂按钮 addNavLink("Set sync", '#', false, false, "ScriptSyncLink") var customClassName = 'ScriptSyncLink' var link = document.querySelector(`.${customClassName} > a`) if (link) { link.addEventListener('click', function (event) { event.preventDefault() addAdminButtons() }) } if (window.location.pathname.includes("/admin")) { // openSyncOnadminPage.style.display = "block" const targetElement = document.querySelector("#script-content > section:nth-child(2) > h3") const newLink = document.createElement('a') newLink.href = '#' newLink.textContent = 'Set sync' newLink.addEventListener('click', function (event) { event.preventDefault() openSuperAdmin(window.location.href.replace(/\/[^\/]*$/, ''), "", false) }) targetElement.insertAdjacentElement('afterend', newLink) } async function syncUpdate(scriptSyncIdentifier, additionalInfoSyncIdentifier, postUrl) { const urls = global.inputModalTextArea.value.trim().split('\n') const translateTable = [ { "code": "aa", "value": "1" }, { "code": "ab", "value": "2" }, { "code": "ae", "value": "3" }, { "code": "af", "value": "4" }, { "code": "ak", "value": "5" }, { "code": "am", "value": "6" }, { "code": "as", "value": "8" }, { "code": "ast", "value": "9" }, { "code": "av", "value": "10" }, { "code": "ay", "value": "11" }, { "code": "az", "value": "12" }, { "code": "ba", "value": "13" }, { "code": "be", "value": "14" }, { "code": "bh", "value": "16" }, { "code": "bi", "value": "17" }, { "code": "bm", "value": "18" }, { "code": "bn", "value": "19" }, { "code": "bo", "value": "20" }, { "code": "br", "value": "21" }, { "code": "bs", "value": "22" }, { "code": "ca", "value": "23" }, { "code": "ce", "value": "24" }, { "code": "ceb", "value": "25" }, { "code": "ch", "value": "26" }, { "code": "chr", "value": "27" }, { "code": "co", "value": "28" }, { "code": "cr", "value": "29" }, { "code": "cs", "value": "30" }, { "code": "cu", "value": "31" }, { "code": "cv", "value": "32" }, { "code": "cy", "value": "33" }, { "code": "da", "value": "34" }, { "code": "de", "value": "35" }, { "code": "dv", "value": "36" }, { "code": "dz", "value": "37" }, { "code": "ee", "value": "38" }, { "code": "el", "value": "39" }, { "code": "en", "value": "40" }, { "code": "eo", "value": "41" }, { "code": "es", "value": "42" }, { "code": "et", "value": "43" }, { "code": "eu", "value": "44" }, { "code": "fa", "value": "45" }, { "code": "ff", "value": "46" }, { "code": "fi", "value": "47" }, { "code": "fil", "value": "48" }, { "code": "fj", "value": "49" }, { "code": "fo", "value": "50" }, { "code": "fr", "value": "51" }, { "code": "fy", "value": "52" }, { "code": "ga", "value": "53" }, { "code": "gd", "value": "54" }, { "code": "gl", "value": "55" }, { "code": "gn", "value": "56" }, { "code": "gsw-berne", "value": "57" }, { "code": "gu", "value": "58" }, { "code": "gv", "value": "59" }, { "code": "ha", "value": "60" }, { "code": "he", "value": "61" }, { "code": "hi", "value": "62" }, { "code": "hmn", "value": "63" }, { "code": "ho", "value": "64" }, { "code": "hr", "value": "65" }, { "code": "ht", "value": "66" }, { "code": "hu", "value": "67" }, { "code": "hy", "value": "68" }, { "code": "hz", "value": "69" }, { "code": "ia", "value": "70" }, { "code": "id", "value": "71" }, { "code": "ie", "value": "72" }, { "code": "ig", "value": "73" }, { "code": "ik", "value": "74" }, { "code": "is", "value": "75" }, { "code": "it", "value": "76" }, { "code": "iu", "value": "77" }, { "code": "ja", "value": "78" }, { "code": "jv", "value": "79" }, { "code": "ka", "value": "80" }, { "code": "kg", "value": "81" }, { "code": "ki", "value": "82" }, { "code": "kj", "value": "83" }, { "code": "kk", "value": "84" }, { "code": "kl", "value": "85" }, { "code": "km", "value": "86" }, { "code": "kn", "value": "87" }, { "code": "ko", "value": "88" }, { "code": "kr", "value": "89" }, { "code": "ks", "value": "90" }, { "code": "ku", "value": "91" }, { "code": "kv", "value": "92" }, { "code": "kw", "value": "93" }, { "code": "ky", "value": "94" }, { "code": "la", "value": "95" }, { "code": "lb", "value": "96" }, { "code": "lg", "value": "97" }, { "code": "lif", "value": "98" }, { "code": "ln", "value": "99" }, { "code": "lo", "value": "100" }, { "code": "lt", "value": "101" }, { "code": "lu", "value": "102" }, { "code": "lv", "value": "103" }, { "code": "mg", "value": "104" }, { "code": "mh", "value": "105" }, { "code": "mi", "value": "106" }, { "code": "mk", "value": "107" }, { "code": "ml", "value": "108" }, { "code": "mn", "value": "109" }, { "code": "mo", "value": "110" }, { "code": "mr", "value": "111" }, { "code": "ms", "value": "112" }, { "code": "mt", "value": "113" }, { "code": "my", "value": "114" }, { "code": "na", "value": "115" }, { "code": "nb", "value": "119" }, { "code": "nd", "value": "120" }, { "code": "ne", "value": "121" }, { "code": "ng", "value": "122" }, { "code": "nl", "value": "118" }, { "code": "nn", "value": "124" }, { "code": "no", "value": "125" }, { "code": "nr", "value": "126" }, { "code": "nv", "value": "127" }, { "code": "ny", "value": "128" }, { "code": "oc", "value": "129" }, { "code": "pa", "value": "131" }, { "code": "pi", "value": "132" }, { "code": "ps", "value": "133" }, { "code": "pt", "value": "134" }, { "code": "qu", "value": "135" }, { "code": "rm", "value": "136" }, { "code": "rn", "value": "137" }, { "code": "ro", "value": "138" }, { "code": "ru", "value": "139" }, { "code": "rw", "value": "140" }, { "code": "sa", "value": "141" }, { "code": "sc", "value": "142" }, { "code": "sd", "value": "143" }, { "code": "sg", "value": "144" }, { "code": "sh", "value": "145" }, { "code": "si", "value": "146" }, { "code": "sk", "value": "149" }, { "code": "sl", "value": "150" }, { "code": "sm", "value": "151" }, { "code": "sn", "value": "152" }, { "code": "so", "value": "153" }, { "code": "sq", "value": "154" }, { "code": "sr", "value": "155" }, { "code": "ss", "value": "156" }, { "code": "st", "value": "157" }, { "code": "su", "value": "158" }, { "code": "sv", "value": "159" }, { "code": "sw", "value": "160" }, { "code": "ta", "value": "161" }, { "code": "te", "value": "162" }, { "code": "tg", "value": "163" }, { "code": "th", "value": "165" }, { "code": "ti", "value": "166" }, { "code": "tk", "value": "167" }, { "code": "tl", "value": "168" }, { "code": "tn", "value": "169" }, { "code": "to", "value": "170" }, { "code": "tr", "value": "171" }, { "code": "ts", "value": "172" }, { "code": "tt", "value": "173" }, { "code": "tw", "value": "174" }, { "code": "ty", "value": "175" }, { "code": "ug", "value": "176" }, { "code": "uk", "value": "177" }, { "code": "ur", "value": "178" }, { "code": "uz", "value": "179" }, { "code": "ve", "value": "180" }, { "code": "vi", "value": "181" }, { "code": "vo", "value": "182" }, { "code": "wa", "value": "183" }, { "code": "wo", "value": "184" }, { "code": "xh", "value": "185" }, { "code": "yi", "value": "186" }, { "code": "zh-CN", "value": "187" }, { "code": "zh-TW", "value": "188" }, { "code": "zu", "value": "189" } ] const csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content") const formDataObj = { _method: 'patch', authenticity_token: csrfToken, 'script[sync_identifier]': scriptSyncIdentifier, 'script[sync_type]': 'webhook', } if (additionalInfoSyncIdentifier) { formDataObj['additional_info_sync[0][attribute_default]'] = 'true' formDataObj['additional_info_sync[0][sync_identifier]'] = additionalInfoSyncIdentifier formDataObj['additional_info_sync[0][value_markup]'] = 'markdown' } urls.forEach((url, index) => { const localeKey = extractLocaleKey(url) const locale = translateTable.find(entry => entry.code === localeKey) const cleanUrl = url.replace(/##.*/, '') formDataObj[`additional_info_sync[${index + 1}][attribute_default]`] = 'false' formDataObj[`additional_info_sync[${index + 1}][locale]`] = locale ? locale.value : '' formDataObj[`additional_info_sync[${index + 1}][sync_identifier]`] = cleanUrl formDataObj[`additional_info_sync[${index + 1}][value_markup]`] = 'markdown' }) formDataObj['update-and-sync'] = '更新设置并立即同步' const formData = new URLSearchParams(formDataObj) console.log(formData.toString()) const postResp = await fetch(postUrl + '/sync_update', { method: 'POST', headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: formData }) global.inputModal.style.display = 'none' alert((postResp.ok || postResp.status === 302) ? global.scriptname + ' Sync Successful!' : 'Synchronization failed, please check the input.') } function extractLocaleKey(url) { let localeKey = url.includes('##') ? url.match(/##.*\((.*?)\)$/) || url.match(/##(.*?)$/) : url.match(/README_(.*?)\.md/) return localeKey ? localeKey[1] : null } //----设置主窗口 function addAdminButtons() { fetch('https://gf.qytechs.cn/zh-CN/users/webhook-info') .then(response => response.ok ? response.text() : Promise.reject('Network response was not ok')) .then(data => createModalWindow(parseLinks(data))) .catch(error => console.error('Fetch operation failed:', error)) } function parseLinks(data) { const parser = new DOMParser() const doc = parser.parseFromString(data, 'text/html') const firstUl = doc.querySelector('ul') if (!firstUl) return [] return Array.from(firstUl.querySelectorAll('li')).map(li => { const links = li.querySelectorAll('a') return { firstHref: links[0]?.href || '', firstTitle: links[0]?.textContent || '', secondHref: links[1]?.href || '', secondTitle: links[1]?.textContent || '' } }) } function openSuperAdmin(url, syncjs, isFetch = false) { global.adminUrl = url if (isFetch) { updateWebHookInfo(url + "/admin") } else { updateWebHookInfo() } global.inputModalScript.value = global.syncingfrom global.inputModalDefault.value = global.defaultAttribute global.inputModalTextArea.value = global.attribute_other global.inputModal.style.display = 'flex' document.querySelector("h2 label[for='SyncScript']").textContent = global.scriptname + "←Source Syncing" document.getElementById("ScriptName").textContent = global.scriptname } function createModalWindow(linksData) { const modalHtml = ` <center> <div class="Sync-Modal"> <div id="adminModal" style="display: none; position: fixed; z-index: 1000; left: 0; top: 50px; width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; background-color: transparent;"> <div style="background-color: #fefefe; padding: 20px; border: 1px solid #888; width: 80%; max-width: 600px;"> <span id="closeLinkModal" style="color: red; float: right; font-size: 28px; font-weight: bold; cursor: pointer;">×</span> <h2>Here are the scripts you have already set up to sync</h2> <ul id="linksList" style="list-style-type: none; padding: 0; max-height: 60vh; overflow-y: auto;"> </ul> </div> </div> </div> </center> ` document.body.insertAdjacentHTML('beforeend', modalHtml) const modal = document.getElementById('adminModal') const closeModal = document.getElementById('closeLinkModal') const linksList = document.getElementById('linksList') // <button style="margin-left: 10px; background-color: red; color: white; border: none; padding: 10px; cursor: pointer;" onclick="window.open('${link.firstHref}/delete', '_blank')">删除</button> linksData.forEach(link => { const listItem = document.createElement('li') listItem.style.marginBottom = '10px' listItem.innerHTML = ` <div style="display: flex; justify-content: space-between; align-items: center;"> <a href="${link.firstHref}" target="_blank" style="text-decoration: none; color: blue;">${link.firstTitle}</a> <div> <a href="${link.secondHref}" target="_blank" style="text-decoration: none; color: blue;">Source Syncing</a> <button style="margin-left: 10px;" onclick="window.open('${link.firstHref}')">View</button> <button class="super-admin-btn" style="margin-left: 10px;" onclick="openSuperAdmin('${link.firstHref}/admin')">Set Sync</button> </div> </div> ` linksList.appendChild(listItem) listItem.querySelector('.super-admin-btn').addEventListener('click', () => { openSuperAdmin(link.firstHref, link.secondHref, true) }) }) modal.style.display = 'block' closeModal.addEventListener('click', () => { modal.style.display = 'none' modal.remove() }) window.addEventListener('click', (event) => { return//不关闭 if (event.target === modal) { modal.style.display = 'none' modal.remove() } }) } function updateStateFromDOM(dom) { const syncInputElement = dom.getElementById('script_sync_identifier') if (syncInputElement) { global.syncingfrom = syncInputElement.value } else { console.warn("Input element with id 'script_sync_identifier' not found") } const defaultInputElement = dom.querySelector('input#script-version-additional-info-0.previewable') if (defaultInputElement) { global.defaultAttribute = defaultInputElement.value } else { console.warn("Default input element not found") } const inputElements = dom.querySelectorAll('input[id^="script-version-additional-info-"].previewable') global.scriptname = dom.querySelector("#script-info > header > h2").textContent global.attribute_other = '' inputElements.forEach((inputElement, index) => { if (inputElement.id !== "script-version-additional-info-0") { if (global.attribute_other) { global.attribute_other += '\n' } const previousSibling = inputElement.previousElementSibling const selectElement = previousSibling?.previousElementSibling const selectedText = selectElement?.options[selectElement.selectedIndex]?.text global.attribute_other += `${inputElement.value}##${selectedText}` } }) } function updateWebHookInfo(url = null) { if (url) { try { const xhr = new XMLHttpRequest() xhr.open("GET", url, false) // `false` 使请求同步 xhr.send(null) if (xhr.status >= 200 && xhr.status < 300) { const htmlText = xhr.responseText const parser = new DOMParser() const doc = parser.parseFromString(htmlText, 'text/html') updateStateFromDOM(doc) console.log("Data fetched from URL and parsed:", global) } else { throw new Error(`Network response was not ok: ${xhr.statusText}`) } } catch (error) { console.error("Error fetching data from URL:", error) } } else { updateStateFromDOM(document) console.log("Data fetched from current page:", global) } } function addNavLink(link_text, linkurl, newtab, lastone, lclassname) { var li = document.createElement('li') if (lclassname) { li.className = lclassname } else { li.className = 'scripts-index-link' } var a = document.createElement('a') a.href = linkurl a.innerText = link_text li.appendChild(a) var nav = document.querySelector('div#site-nav > nav') if (nav) { if (lastone) { nav.append(li) } else { nav.prepend(li) } } } })()
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址