您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Easily get languages from Steam. Edited from "GGn Steam Language BBCode quick copy".
// ==UserScript== // @name GGn Get Languages From Steam // @version 6 // @description Easily get languages from Steam. Edited from "GGn Steam Language BBCode quick copy". // @author lucianjp, ingts // @match https://gazellegames.net/torrents.php?action=editgroup* // @match https://gazellegames.net/torrents.php?id=* // @match https://gazellegames.net/upload.php* // @match https://store.steampowered.com/app/* // @grant GM_xmlhttpRequest // @grant GM_setClipboard // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @grant unsafeWindow // @connect store.steampowered.com // @namespace https://greasyfork.org/ // ==/UserScript== const text_only = true const auto_get = true const use_language_codes = false const uppercase_language_codes = false const bold_list = false const delimiter = ', ' const globals = unsafeWindow.GetLanguagesFromSteam = {} if (window.location.hostname === 'store.steampowered.com') steamButton() if (location.href.endsWith('upload.php') && GM_getValue('steam', null)) GM_deleteValue('steam') if (auto_get && location.href.includes('torrents.php?id=')) { GM_deleteValue('steam') const steamLink = document.querySelector('a[title=Steam]') if (steamLink) GM_setValue('steam', /\d+/.exec(steamLink.href)[0]) } const langSelect = document.getElementById('language') if (location.href.includes('upload')) { ggn_upload() } function steamButton() { const $btn = document.createElement('a') const text = 'Copy BBCode' $btn.classList.add('btnv6_blue_hoverfade', 'btn_small') const $text = $btn.appendChild(document.createElement('span')) $text.innerHTML = `${text}<img src="https://ptpimg.me/sx226x.png">` $btn.addEventListener('click', function () { GM_setClipboard(globals.parseSteamLanguage(null), 'text') $text.childNodes[0].nodeValue = 'copied' setTimeout(function () { $text.childNodes[0].nodeValue = text }, 3000) }) const $container = document.querySelector('table.game_language_options').closest('.block').querySelector('.block_title') || document.querySelector('#LanguagesHeader') $container.style = 'display: flex;justify-content: space-between;align-items: center;' $container.appendChild($btn) } function ggn_upload() { let fetchInput = document.createElement('input') fetchInput.type = 'text' fetchInput.placeholder = "Steam Link or ID" langSelect.after(fetchInput) fetchInput.onblur = () => { getSteamLanguages(/\d+/.exec(fetchInput.value)).catch(() => { fetchInput.value = 'Failed to get languages' fetchInput.style.color = 'red' fetchInput.disabled = true }) } if (auto_get) { setTimeout(() => { // to support Reuploader script so it won't add languages again if (!document.getElementById('release_desc').value) { const savedID = GM_getValue('steam', null) if (savedID) { fetchInput.value = savedID fetchInput.dispatchEvent(new Event('blur')) GM_deleteValue('steam') } } }, 500) } } function getSteamLanguages(steamId) { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ url: "https://store.steampowered.com/api/appdetails?l=en&appids=" + steamId, method: 'GET', responseType: "json", onload: function (response) { if (response.status === 200 && response.response[steamId].success) { resolve(globals.parseSteamLanguage(response.response[steamId].data.supported_languages)) } else reject() } }) }) } globals.parseSteamLanguage = function (supported_languages) { const langCodes = new Map([ ["Afrikaans", "af"], ["Albanian", "sq"], ["Amharic", "am"], ["Arabic", "ar"], ["Armenian", "hy"], ["Assamese", "as"], ["Azerbaijani", "az"], ["Bangla", "bn"], ["Basque", "eu"], ["Belarusian", "be"], ["Bulgarian", "bg"], ["Bosnian", "bs"], ["Simplified Chinese", "zh-cn"], ["Traditional Chinese", "zh-tw"], ["Catalan", "ca"], ["Croatian", "hr"], ["Czech", "cs"], ["Danish", "da"], ["Dutch", "nl"], ["English", "en"], ["Estonian", "et"], ["Filipino", "tl"], ["Farsi", "fa"], ["Finnish", "fi"], ["French", "fr"], ["German", "de"], ["Greek", "el"], ["Hebrew", "he"], ["Hausa", "ha"], ["Hindi", "hi"], ["Hungarian", "hu"], ["Icelandic", "is"], ["Igbo", "ig"], ["Indonesian", "id"], ["Irish", "ga"], ["Italian", "it"], ["Japanese", "ja"], ["Kannada", "kn"], ["Korean", "ko"], ["Kazakh", "kk"], ["Khmer", "km"], ["Kurdish", "ku"], ["Kinyarwanda", "rw"], ["Kyrgyz", "ky"], ["Latvian", "lv"], ["Lithuanian", "lt"], ["Luxembourgish", "lb"], ["Macedonian", "mk"], ["Malay", "ms"], ["Malayalam", "ml"], ["Maltese", "mt"], ["Mongolian", "mn"], ["Maori", "mi"], ["Nepali", "ne"], ["Odia", "or"], ["Norwegian", "no"], ["Persian", "fa"], ["Quechua", "qu"], ["Polish", "pl"], ["Portuguese - Brazil", "pt-br"], ["Portuguese", "pt"], ["Punjabi", "pa"], ["Scots", "gd"], ["Romanian", "ro"], ["Russian", "ru"], ["Serbian", "sr"], ["Slovak", "sk"], ["Slovenian", "sl"], ["Sorbian", "sb"], ["Sotho", "st"], ["Swahili", "sw"], ["Spanish - Spain", "es"], ["Spanish - Latin America", "es-la"], ["Swedish", "sv"], ["Thai", "th"], ["Tajik", "tg"], ["Tamil", "ta"], ["Tatar", "tt"], ["Telugu", "te"], ["Tsonga", "ts"], ["Tigrinya", "ti"], ["Tswana", "tn"], ["Turkmen", "tk"], ["Turkish", "tr"], ["Ukrainian", "ua"], ["Uyghur", "ug"], ["Urdu", "ur"], ["Uzbek", "uz"], ["Venda", "ve"], ["Vietnamese", "vi"], ["Welsh", "cy"], ["Wolof", "wo"], ["Xhosa", "xh"], ["Yoruba", "yo"], ["Yiddish", "ji"], ["Zulu", "zu"], ]) const languages = {Subtitles: []} if (supported_languages) { for (const str of supported_languages.replace(/<br>.*$/, '').split(', ')) { const lang = str.replace("<strong>*<\/strong>", '') if (str.includes('*')) { if (!languages['Full Audio']) { languages['Full Audio'] = [] } languages['Full Audio'].push(lang) } languages['Subtitles'].push(lang) } } else { const table = document.querySelector('table.game_language_options') for (let r = 0; r < table.rows.length; r++) { for (let c = 0; c < table.rows[r].cells.length; c++) { if (table.rows[r].cells[c].textContent.trim() === '✔') { let header = table.rows[0].cells[c].textContent.trim() if (!languages[header]) { languages[header] = [] } languages[header].push(table.rows[r].cells[0].textContent.trim()) } } } } if (text_only) delete languages['Full Audio'] let textLanguages = languages['Subtitles'].length > 0 ? languages['Subtitles'] : languages['Interface'] let audioLanguages = languages['Full Audio'] const textMulti = textLanguages.length > 1 ? 's' : '' const audioMulti = audioLanguages && audioLanguages.length > 1 ? 's' : '' let langSelectValue if (supported_languages) { const languageList = [ 'English', 'German', 'French', 'Czech', 'Italian', 'Japanese', 'Korean', 'Polish', 'Portuguese', 'Russian', 'Spanish', ] const inLangList = !textMulti && languageList.some(lang => textLanguages[0].includes(lang)) langSelectValue = textMulti ? 'Multi-Language' : inLangList ? textLanguages[0] : 'Other' } if (use_language_codes) { textLanguages = textLanguages.map(l => { const code = langCodes.get(l) if (code) { return uppercase_language_codes ? code.toUpperCase() : code } else return l }) if (audioLanguages) { audioLanguages = audioLanguages.map(l => { const code = langCodes.get(l) if (code) { return uppercase_language_codes ? code.toUpperCase() : code } else return l }) } } const joinedText = textLanguages.join(delimiter) const joinedAudio = audioLanguages && audioLanguages.join(delimiter) function bold(str) { const lines = str.split("\n") const result = [] for (const line of lines) { const [category, list] = line.split(": ") result.push(bold_list ? `${category}: [b]${list}[/b]` : `[b]${category}[/b]: ${list}`) } return result.join("\n") } if (supported_languages) { let description if (!textMulti && (textLanguages[0].includes('Chinese') || textLanguages[0].includes('ZH'))) { langSelectValue = 'Chinese' if (audioLanguages && areSame(textLanguages, audioLanguages)) { description = bold(`Text and Audio Language${textMulti}: ${joinedText}`) } else { description = audioLanguages ? bold(`Text Language: ${joinedAudio}\nAudio Language${audioMulti}: ${joinedAudio}`) : bold(`Language: ${joinedText}`) } } else if (audioLanguages && areSame(textLanguages, audioLanguages)) { description = bold(`Text and Audio Language${textMulti}: ${joinedText}`) } else { const addText = textMulti ? `Languages: ${joinedText}` : '' // add nothing if there's only 1 language description = audioLanguages ? bold(`${addText ? 'Text ' + addText + '\n' : ''}Audio Language${audioMulti}: ${joinedAudio}`) : addText ? bold(addText) : '' } langSelect.value = langSelectValue document.getElementById('release_desc').value += description return } if (audioLanguages) { if (areSame(textLanguages, audioLanguages)) return bold(`Text and Audio Language${textMulti}: ${joinedText}`) return bold(`Text Language${textMulti}: ${joinedText}\nAudio Language${audioMulti}: ${joinedAudio}`) } return bold(`Language${textMulti}: ${joinedText}`) } function areSame(array1, array2) { return array1.length === array2.length && array1.sort().every((value, index) => value === array2.sort()[index]) }