- // ==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://greatest.deepsurf.us/
- // ==/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])
- }