Greasy Fork

Greasy Fork is available in English.

Pter Fitgirl release Uploady

Game Uploady for Pterclub

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Pter Fitgirl release Uploady
// @namespace    https://pterclub.com/forums.php?action=viewtopic&topicid=3391
// @version      1.3.3
// @description  Game Uploady for Pterclub
// @author       NeutronNoir, ZeDoCaixao, scatking, ccf2012, fyzzy1943
// @match        https://pterclub.com/uploadgame.php*
// @match        https://pterclub.com/editgame.php*
// @require      https://cdn.staticfile.org/jquery/3.5.1/jquery.min.js
// @require      https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
// @icon         https://pterclub.com/favicon.ico
// @grant        GM.xmlHttpRequest
// @grant        GM_xmlhttpRequest
// @grant        unsafeWindow
// ==/UserScript==
 
const DESCR = $('#descr');
 
function html2bb(str) {
    if (!str) return "";
    str = str.replace(/< *br *\/*>/g, "\n\n"); //*/
    str = str.replace(/< *b *>/g, "[b]");
    str = str.replace(/< *\/ *b *>/g, "[/b]");
    str = str.replace(/< *u *>/g, "[u]");
    str = str.replace(/< *\/ *u *>/g, "[/u]");
    str = str.replace(/< *i *>/g, "[i]");
    str = str.replace(/< *\/ *i *>/g, "[/i]");
    str = str.replace(/< *strong *>/g, "[b]");
    str = str.replace(/< *\/ *strong *>/g, "[/b]");
    str = str.replace(/< *em *>/g, "[i]");
    str = str.replace(/< *\/ *em *>/g, "[/i]");
    str = str.replace(/< *li *>/g, "[*]");
    str = str.replace(/< *\/ *li *>/g, "");
    str = str.replace(/< *ul *class=\\*\"bb_ul\\*\" *>/g, "");
    str = str.replace(/< *\/ *ul *>/g, "");
    str = str.replace(/< *h2 *class=\"bb_tag\" *>/g, "\n[center][u][b]");
    str = str.replace(/< *h[12] *>/g, "\n[center][u][b]");
    str = str.replace(/< *\/ *h[12] *>/g, "[/b][/u][/center]\n");
    str = str.replace(/\&quot;/g, "\"");
    str = str.replace(/\&amp;/g, "&");
    str = str.replace(/< *img *src="([^"]*)".*>/g, "\n");
    str = str.replace(/< *a [^>]*>/g, "");
    str = str.replace(/< *\/ *a *>/g, "");
    str = str.replace(/< *p *>/g, "\n\n");
    str = str.replace(/< *\/ *p *>/g, "");
    //Yeah, all these damn stars. Because people put spaces where they shouldn't.
    str = str.replace(/“/g, "\"");
    str = str.replace(/”/g, "\"");
    str = str.replace(/  +/g, " ");
    str = str.replace(/\n +/g, "\n");
    str = str.replace(/\n\n\n+/gm, "\n\n");
    str = str.replace(/\n\n\n+/gm, "\n\n");
    str = str.replace(/\[\/b\]\[\/u\]\[\/align\]\n\n/g, "[/b][/u][/align]\n");
    str = str.replace(/\n\n\[\*\]/g, "\n[*]");
    return str;
}
 
function parseSteam(response) {
    var steamPage = response.responseText;
    // var steamPage = response;
    console.log(steamPage)
 
}
 
 
function parseFitgirRepack($document){
    console.log($document)
    var info1 = $document.querySelector("div[class='entry-content'] > p:nth-child(2)" );
    var info2_headerlist = $document.querySelectorAll("div[class='entry-content'] > h3" );
 
    if (!info1) {
      console.log("Not found: div[class='entry-content']");
      return
    }
    if (!info2_headerlist) {
      console.log("Not found: div[class='entry-content'] > h3[3]");
      return
    }
    var info1_bb = html2bb(info1.textContent)
    var foundFeature = Array.from(info2_headerlist).find(gg => (gg.textContent.indexOf('Feature')>0));
    // console.log(foundFeature)
 
    var info2_header_bb = html2bb(foundFeature.innerHTML); // "Repack Feature"
    var info2_list = foundFeature.nextSibling;
    while(info2_list && info2_list.nodeType != 1) {
      info2_list = info2_list.nextSibling;
    }
    if (!info2_list) {
      console.log("Not found: ul");
      return
    }
    var info2_list_bb = html2bb(info2_list.innerHTML);
    //   console.log(info2_list_bb)
 
    var dlc_bb = '';
    var dlc_header = Array.from($document.querySelectorAll("b")).find(gg => (gg.textContent.indexOf("Included DLCs") != -1));
    if (dlc_header) {
        var dlc_list = dlc_header.parentNode.nextSibling;
        while(dlc_list && dlc_list.nodeType != 1) {
            dlc_list = dlc_list.nextSibling;
        }
        if (dlc_list) {
            dlc_bb = html2bb(dlc_list.innerHTML);
        } else {
            console.log('found dlc anchor, not found dlc list, please check.');
        }
    }
 
    // Assembly torrent info
    var output = '' + info1_bb + '\n\n\n[b]' + info2_header_bb + '[/b]\n' +  info2_list_bb + '\n'
 
    if (dlc_bb != '') {
        output = output + '\n[b]Included DLCs:[/b]\n' + dlc_bb + '\n'
    }
 
    return output;
}
 
 
function getFitgirlTitle(doc) {
    var title = '';
    var h3_list = doc.querySelectorAll("div[class='entry-content'] > h3");
    var title_html = Array.from(h3_list).find(gg => (gg.textContent.indexOf("#") != -1));
    if (!title_html) {
        console.log("Not found: title_html");
        return title;
    }
 
    var title_match = title_html.innerHTML.match(/strong\>(.*)\<\/str/i);
    if (!title_match || title_match.length != 2) {
        console.log(title_html.innerHTML);
        console.log("title not match");
        return title;
    }
 
    title = title_match[1].replace(/\<span.*?"\>/i, "");
    title = title.replace(/\<\/span\>/i, "");
    console.log(title);
 
    return title;
}
 
 
function get1337xUrl(doc) {
    // var info2_headerlist = $document.querySelectorAll("div[class='entry-content'] > h3" );
    var url_e = doc.querySelector("div[class='entry-content'] > ul:nth-child(5) > li:first-child > a:first-child");
    if (!url_e) {
        console.log("1337x url get failed: div[class='entry-content'] > ul:nth-child(5) > li:first-child > a:first-child not found.");
        return '';
    }
 
    // console.log(url);
    var url = url_e.getAttribute('href');
    return url.indexOf('1337x') != -1 ? url : ''
}
 
 
function parseSteamLanguage($document){
    let table = $document.querySelector('table.game_language_options');
 
    if(!table) return;
 
    let languages = {};
 
    for (var r = 0; r < table.rows.length; r++) {
      for (var 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());
        }
      }
    }
    let output = ''
    let keys = Object.keys(languages);
 
    for(var i = 0; i < keys.length; i++){
      let key = keys[i];
      let keygroup = [key];
 
      if(i < keys.length - 1){
        for(var iNext = i+1; iNext < keys.length; iNext){
          if(areSame(languages[keys[i]], languages[keys[iNext]])) {
            keygroup.push(keys[iNext]);
            keys.splice(iNext,1);
          } else {
            iNext++;
          }
        }
      }
 
      const multi = languages[key].length > 1;
 
      if(keys.length === 1){
        output += `[b]Language${multi ? "s": ""}[/b]: `;
      } else {
        output += `[b]${keygroup.join(' and ')} Language${multi ? "s": ""}[/b]: `;
      }
 
      if(multi){
        let lastItem = languages[key].pop();
        output += languages[key].join(', ');
        output += ` and ${lastItem}`;
      } else {
        output += languages[key];
      }
      output += '\n';
    }
    return output;
}
 
 
function areSame(array1, array2){
    return array1.length === array2.length && array1.sort().every((value, index) => value === array2.sort()[index])
}
 
// function editboxPart1(str) {
//     desc_field = "#descr";
//     var hidetext = '[hide=安装步骤]\n [*]运行 \"Verify BIN files before installation.bat\" 进行MD5验证(可选)\n [*]运行 \"setup.exe\"安装游戏\n [*]开始游玩\n [*]游戏经过高压,需要一定时间才能解压完毕,请耐心等待。[/hide]';
 
//     $(desc_field).val(hidetext + '\n\n' + str + $(desc_field).val());
// }
 
function editboxPart2(fitgirl_info) {
    var text = '[hide=安装步骤]\n [*]运行 \"Verify BIN files before installation.bat\" 进行MD5验证(可选)\n [*]运行 \"setup.exe\"安装游戏\n [*]开始游玩\n [*]游戏经过高压,需要一定时间才能解压完毕,请耐心等待。[/hide]';
 
    text = text + '\n\n[font=sans-serif]'
 
    text = text + '\n\n';
    text = text + '=+=LanguageAnchor=+=' + '\n\n';
    text = text + fitgirl_info;
 
    text = text + '[/font]';
 
    desc_field = "#descr";
    var origin_text = $(desc_field).val();
    $(desc_field).val(text + origin_text);
}
 
 
function changeStatus(msg) {
    $('#pfru_status').html(' >>' + msg);
}
 
 
function parse1337Language(doc) {
    // console.log(doc);
    if (!doc) {
        return;
    }
    var html1 = doc.querySelector("div[class='torrent-tabs']");
    if (!html1) {
        return;
    }
 
    html1 = html1.textContent;
    // console.log(html1);
 
    var lang = html1.match(/(Interface Language[\s\S]*?)Crack/im);
    if (!lang || lang.length != 2) {
        console.log(lang);
        return;
    }
 
    lang = lang[1].trim()
                .replace(/\s+/g, ' ')
                .replace(/Audio Language/g, '\nAudio Language')
                .replace(/, /g, '、')
                .replace(/Interface Language/g, '[b]界面语言[/b]')
                .replace(/Audio Language/g, '[b]音频语言[/b]')
                .replace(/Simplified Chinese/g, '简体中文')
                .replace(/Traditional Chinese/g, '繁体中文')
                .replace(/Chinese/g, '中文')
                .replace(/English/g, '英语')
                .replace(/Russian/g, '俄语')
                .replace(/German/g, '德语')
                .replace(/French/g, '法语')
                .replace(/Korean/g, '韩语')
                .replace(/Japanese/g, '日语')
                .replace(/Italian/g, '意大利语')
                .replace(/Turkish/g, '土耳其语')
                .replace(/Spanish - Latin America/g, '西班牙语-拉丁美洲')
                .replace(/Spanish - Spain/g, '西班牙语-西班牙')
                .replace(/Portuguese - Brazil/g, '葡萄牙语-巴西')
                .replace(/Portuguese/g, '葡萄牙语')
                .replace(/Thai/g, '泰语')
                .replace(/Arabic/g, '阿拉伯语')
                .replace(/Danish/g, '丹麦语')
                .replace(/Dutch/g, '荷兰语')
                .replace(/Finnish/g, '芬兰语')
                .replace(/Norwegian/g, '挪威语')
                .replace(/Polish/g, '波兰语')
                .replace(/Swedish/g, '瑞典语')
                .replace(/Catalon/g, '加泰罗尼亚语')
                .replace(/Greek/g, '希腊语')
                .replace(/Czech/g, '捷克语')
                .replace(/Estonian/g, '爱沙尼亚语')
                .replace(/Hungarian/g, '匈牙利语')
                .replace(/Spanish/g, '西班牙语')
                .replace(/Indonesian/g, '印度尼西亚语')
                ;
 
    console.log('1337x: ' + lang);
 
    return lang;
}
 
 
function replaceLangAnchor(bb_lang) {
    if (!bb_lang) {
        changeStatus('处理完成!未获取到语言!');
        return;
    }
 
    var descr = DESCR.val().replace('=+=LanguageAnchor=+=', bb_lang.trim());
    DESCR.val(descr);
    changeStatus('处理完成!');
}
 
function requestUrl(urlSteam, urlFitgirl) {
    changeStatus('开始获取FitGirl信息...');
    var bbstr;
    GM.xmlHttpRequest({
        method: "GET",
        url: urlFitgirl.val(),
        responseType: "document",
        onload: function(resp) {
            var parser = new DOMParser ();
            var ajaxDoc = parser.parseFromString(resp.responseText, "text/html");
 
            // 种子简介
            bbstr = parseFitgirRepack(ajaxDoc)
            editboxPart2(bbstr)
 
            var lang_source = $("input[name='pfru_lang_source']:checked").val();
            console.log('选择从: ' + lang_source + ' 获取游戏语言');
 
            if (lang_source == '1337x') {
                var url1337x = get1337xUrl(ajaxDoc); // 获取1337x链接
                if (url1337x && url1337x != '') {
                    console.log('访问: ' + url1337x + ' 获取语言');
                    changeStatus('正在从1337x获取语言列表...');
 
                    GM.xmlHttpRequest({
                        method: 'GET',
                        url: url1337x,
                        onload(resp) {
                            var ajaxDoc = new DOMParser ().parseFromString(resp.responseText, "text/html");
                            var bb_lang = parse1337Language(ajaxDoc);
                            replaceLangAnchor(bb_lang);
                        },
                        onerror: function(resp) {
                            console.log(resp);
                            changeStatus('语言获取失败!');
                        }
                    });
                } else {
                    changeStatus('未获取到1337x链接...');
                }
            } else {
                changeStatus('正在从steam获取语言列表...');
                GM.xmlHttpRequest({
                    method: "GET",
                    url: urlSteam.val(),
                    responseType: "document",
                    onload: function(resp){
                        var parser  = new DOMParser ();
                        var ajaxDoc = parser.parseFromString (resp.responseText, "text/html");
                        var bb_lang = parseSteamLanguage(ajaxDoc);
                        replaceLangAnchor(bb_lang);
                        // console.log (bbstr);
                    },
                    onerror: function(resp) {
                        console.log(resp);
                        changeStatus('语言获取失败!');
                    }
                });
            }
 
 
 
 
            // 获取标题
            var fitgirl_title = getFitgirlTitle(ajaxDoc); // 原始标题
            var game_title = $("h1#top").text().slice(0,-4).trim();
 
            var name1 = '游戏名称: <span style="color: red">' + game_title + '</span><br>';
            var name2 = 'FitGirl 原始名称: <span style="color: red">' + fitgirl_title + '</span>' + '<br>';
 
            var $name_e = $('#name').parent();
            $name_e.html(name1 + name2 + $name_e.html());
 
            $('#name').val((fitgirl_title.replace(game_title, '').trim() + ' -FitGirl').trim());
 
 
            // 游戏本体
            $("#categories").find("option[value='1']").attr("selected",true);
            // Portable
            $("#format").find("option[value='4']").attr("selected",true);
            // 欧美
            $("#team").find("option[value='4']").attr("selected",true);
            // 可信源
            $("#vs").attr("checked",true);
 
            // console.log (bbstr);
        }
    });
 
}
 
(function() {
    'use strict';
 
    const PFRU_HTML = '<tr><td>Steam URL</td><td><input style="width: 450px;" id="steamurl" /></td></tr>'
                    + '<tr><td>FitGirl URL</td><td><input style="width: 450px;" id="fitgirlurl" /></td></tr>';
 
    var anchor = window.location.href.includes("uploadgame") ? $("#name") : $("input[name='torrentname']");
    anchor.parent().parent().after(PFRU_HTML);
 
    const steamurl = $("#steamurl");
    const fitgirlurl = $("#fitgirlurl");
 
    var lang_source_html = '<input type="radio" name="pfru_lang_source" value="1337x" checked />1337x'
    + '<input type="radio" name="pfru_lang_source" value="steam" />steam';
 
    fitgirlurl.after(
        // '<label>替换标题:<a href="javascript:void(0);" title="勾选后获取原始标题,注意需要手动去除游戏名" style="color: red">(?)</a></label><input type="checkbox" id="pfru_get_title" />'
        lang_source_html
        + ' <input type="button" id="pfru_fill_form" value="收集信息自动填写">'
        + ' <span id="pfru_status"></span>');
 
    $('#pfru_fill_form').click(function () {
        requestUrl(steamurl, fitgirlurl);
        $("#console").val("16");
    });
 
})();