Pter Fitgirl release Uploady

Game Uploady for Pterclub

  1. // ==UserScript==
  2. // @name Pter Fitgirl release Uploady
  3. // @namespace https://pterclub.com/forums.php?action=viewtopic&topicid=3391
  4. // @version 1.3.3
  5. // @description Game Uploady for Pterclub
  6. // @author NeutronNoir, ZeDoCaixao, scatking, ccf2012, fyzzy1943
  7. // @match https://pterclub.com/uploadgame.php*
  8. // @match https://pterclub.com/editgame.php*
  9. // @require https://cdn.staticfile.org/jquery/3.5.1/jquery.min.js
  10. // @require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
  11. // @icon https://pterclub.com/favicon.ico
  12. // @grant GM.xmlHttpRequest
  13. // @grant GM_xmlhttpRequest
  14. // @grant unsafeWindow
  15. // ==/UserScript==
  16. const DESCR = $('#descr');
  17. function html2bb(str) {
  18. if (!str) return "";
  19. str = str.replace(/< *br *\/*>/g, "\n\n"); //*/
  20. str = str.replace(/< *b *>/g, "[b]");
  21. str = str.replace(/< *\/ *b *>/g, "[/b]");
  22. str = str.replace(/< *u *>/g, "[u]");
  23. str = str.replace(/< *\/ *u *>/g, "[/u]");
  24. str = str.replace(/< *i *>/g, "[i]");
  25. str = str.replace(/< *\/ *i *>/g, "[/i]");
  26. str = str.replace(/< *strong *>/g, "[b]");
  27. str = str.replace(/< *\/ *strong *>/g, "[/b]");
  28. str = str.replace(/< *em *>/g, "[i]");
  29. str = str.replace(/< *\/ *em *>/g, "[/i]");
  30. str = str.replace(/< *li *>/g, "[*]");
  31. str = str.replace(/< *\/ *li *>/g, "");
  32. str = str.replace(/< *ul *class=\\*\"bb_ul\\*\" *>/g, "");
  33. str = str.replace(/< *\/ *ul *>/g, "");
  34. str = str.replace(/< *h2 *class=\"bb_tag\" *>/g, "\n[center][u][b]");
  35. str = str.replace(/< *h[12] *>/g, "\n[center][u][b]");
  36. str = str.replace(/< *\/ *h[12] *>/g, "[/b][/u][/center]\n");
  37. str = str.replace(/\&quot;/g, "\"");
  38. str = str.replace(/\&amp;/g, "&");
  39. str = str.replace(/< *img *src="([^"]*)".*>/g, "\n");
  40. str = str.replace(/< *a [^>]*>/g, "");
  41. str = str.replace(/< *\/ *a *>/g, "");
  42. str = str.replace(/< *p *>/g, "\n\n");
  43. str = str.replace(/< *\/ *p *>/g, "");
  44. //Yeah, all these damn stars. Because people put spaces where they shouldn't.
  45. str = str.replace(/“/g, "\"");
  46. str = str.replace(/”/g, "\"");
  47. str = str.replace(/ +/g, " ");
  48. str = str.replace(/\n +/g, "\n");
  49. str = str.replace(/\n\n\n+/gm, "\n\n");
  50. str = str.replace(/\n\n\n+/gm, "\n\n");
  51. str = str.replace(/\[\/b\]\[\/u\]\[\/align\]\n\n/g, "[/b][/u][/align]\n");
  52. str = str.replace(/\n\n\[\*\]/g, "\n[*]");
  53. return str;
  54. }
  55. function parseSteam(response) {
  56. var steamPage = response.responseText;
  57. // var steamPage = response;
  58. console.log(steamPage)
  59. }
  60. function parseFitgirRepack($document){
  61. console.log($document)
  62. var info1 = $document.querySelector("div[class='entry-content'] > p:nth-child(2)" );
  63. var info2_headerlist = $document.querySelectorAll("div[class='entry-content'] > h3" );
  64. if (!info1) {
  65. console.log("Not found: div[class='entry-content']");
  66. return
  67. }
  68. if (!info2_headerlist) {
  69. console.log("Not found: div[class='entry-content'] > h3[3]");
  70. return
  71. }
  72. var info1_bb = html2bb(info1.textContent)
  73. var foundFeature = Array.from(info2_headerlist).find(gg => (gg.textContent.indexOf('Feature')>0));
  74. // console.log(foundFeature)
  75. var info2_header_bb = html2bb(foundFeature.innerHTML); // "Repack Feature"
  76. var info2_list = foundFeature.nextSibling;
  77. while(info2_list && info2_list.nodeType != 1) {
  78. info2_list = info2_list.nextSibling;
  79. }
  80. if (!info2_list) {
  81. console.log("Not found: ul");
  82. return
  83. }
  84. var info2_list_bb = html2bb(info2_list.innerHTML);
  85. // console.log(info2_list_bb)
  86. var dlc_bb = '';
  87. var dlc_header = Array.from($document.querySelectorAll("b")).find(gg => (gg.textContent.indexOf("Included DLCs") != -1));
  88. if (dlc_header) {
  89. var dlc_list = dlc_header.parentNode.nextSibling;
  90. while(dlc_list && dlc_list.nodeType != 1) {
  91. dlc_list = dlc_list.nextSibling;
  92. }
  93. if (dlc_list) {
  94. dlc_bb = html2bb(dlc_list.innerHTML);
  95. } else {
  96. console.log('found dlc anchor, not found dlc list, please check.');
  97. }
  98. }
  99. // Assembly torrent info
  100. var output = '' + info1_bb + '\n\n\n[b]' + info2_header_bb + '[/b]\n' + info2_list_bb + '\n'
  101. if (dlc_bb != '') {
  102. output = output + '\n[b]Included DLCs:[/b]\n' + dlc_bb + '\n'
  103. }
  104. return output;
  105. }
  106. function getFitgirlTitle(doc) {
  107. var title = '';
  108. var h3_list = doc.querySelectorAll("div[class='entry-content'] > h3");
  109. var title_html = Array.from(h3_list).find(gg => (gg.textContent.indexOf("#") != -1));
  110. if (!title_html) {
  111. console.log("Not found: title_html");
  112. return title;
  113. }
  114. var title_match = title_html.innerHTML.match(/strong\>(.*)\<\/str/i);
  115. if (!title_match || title_match.length != 2) {
  116. console.log(title_html.innerHTML);
  117. console.log("title not match");
  118. return title;
  119. }
  120. title = title_match[1].replace(/\<span.*?"\>/i, "");
  121. title = title.replace(/\<\/span\>/i, "");
  122. console.log(title);
  123. return title;
  124. }
  125. function get1337xUrl(doc) {
  126. // var info2_headerlist = $document.querySelectorAll("div[class='entry-content'] > h3" );
  127. var url_e = doc.querySelector("div[class='entry-content'] > ul:nth-child(5) > li:first-child > a:first-child");
  128. if (!url_e) {
  129. console.log("1337x url get failed: div[class='entry-content'] > ul:nth-child(5) > li:first-child > a:first-child not found.");
  130. return '';
  131. }
  132. // console.log(url);
  133. var url = url_e.getAttribute('href');
  134. return url.indexOf('1337x') != -1 ? url : ''
  135. }
  136. function parseSteamLanguage($document){
  137. let table = $document.querySelector('table.game_language_options');
  138. if(!table) return;
  139. let languages = {};
  140. for (var r = 0; r < table.rows.length; r++) {
  141. for (var c = 0; c < table.rows[r].cells.length; c++) {
  142. if(table.rows[r].cells[c].textContent.trim() === '✔'){
  143. let header = table.rows[0].cells[c].textContent.trim();
  144. if(!languages[header]) {
  145. languages[header] = [];
  146. }
  147. languages[header].push(table.rows[r].cells[0].textContent.trim());
  148. }
  149. }
  150. }
  151. let output = ''
  152. let keys = Object.keys(languages);
  153. for(var i = 0; i < keys.length; i++){
  154. let key = keys[i];
  155. let keygroup = [key];
  156. if(i < keys.length - 1){
  157. for(var iNext = i+1; iNext < keys.length; iNext){
  158. if(areSame(languages[keys[i]], languages[keys[iNext]])) {
  159. keygroup.push(keys[iNext]);
  160. keys.splice(iNext,1);
  161. } else {
  162. iNext++;
  163. }
  164. }
  165. }
  166. const multi = languages[key].length > 1;
  167. if(keys.length === 1){
  168. output += `[b]Language${multi ? "s": ""}[/b]: `;
  169. } else {
  170. output += `[b]${keygroup.join(' and ')} Language${multi ? "s": ""}[/b]: `;
  171. }
  172. if(multi){
  173. let lastItem = languages[key].pop();
  174. output += languages[key].join(', ');
  175. output += ` and ${lastItem}`;
  176. } else {
  177. output += languages[key];
  178. }
  179. output += '\n';
  180. }
  181. return output;
  182. }
  183. function areSame(array1, array2){
  184. return array1.length === array2.length && array1.sort().every((value, index) => value === array2.sort()[index])
  185. }
  186. // function editboxPart1(str) {
  187. // desc_field = "#descr";
  188. // var hidetext = '[hide=安装步骤]\n [*]运行 \"Verify BIN files before installation.bat\" 进行MD5验证(可选)\n [*]运行 \"setup.exe\"安装游戏\n [*]开始游玩\n [*]游戏经过高压,需要一定时间才能解压完毕,请耐心等待。[/hide]';
  189. // $(desc_field).val(hidetext + '\n\n' + str + $(desc_field).val());
  190. // }
  191. function editboxPart2(fitgirl_info) {
  192. var text = '[hide=安装步骤]\n [*]运行 \"Verify BIN files before installation.bat\" 进行MD5验证(可选)\n [*]运行 \"setup.exe\"安装游戏\n [*]开始游玩\n [*]游戏经过高压,需要一定时间才能解压完毕,请耐心等待。[/hide]';
  193. text = text + '\n\n[font=sans-serif]'
  194. text = text + '\n\n';
  195. text = text + '=+=LanguageAnchor=+=' + '\n\n';
  196. text = text + fitgirl_info;
  197. text = text + '[/font]';
  198. desc_field = "#descr";
  199. var origin_text = $(desc_field).val();
  200. $(desc_field).val(text + origin_text);
  201. }
  202. function changeStatus(msg) {
  203. $('#pfru_status').html(' >>' + msg);
  204. }
  205. function parse1337Language(doc) {
  206. // console.log(doc);
  207. if (!doc) {
  208. return;
  209. }
  210. var html1 = doc.querySelector("div[class='torrent-tabs']");
  211. if (!html1) {
  212. return;
  213. }
  214. html1 = html1.textContent;
  215. // console.log(html1);
  216. var lang = html1.match(/(Interface Language[\s\S]*?)Crack/im);
  217. if (!lang || lang.length != 2) {
  218. console.log(lang);
  219. return;
  220. }
  221. lang = lang[1].trim()
  222. .replace(/\s+/g, ' ')
  223. .replace(/Audio Language/g, '\nAudio Language')
  224. .replace(/, /g, '、')
  225. .replace(/Interface Language/g, '[b]界面语言[/b]')
  226. .replace(/Audio Language/g, '[b]音频语言[/b]')
  227. .replace(/Simplified Chinese/g, '简体中文')
  228. .replace(/Traditional Chinese/g, '繁体中文')
  229. .replace(/Chinese/g, '中文')
  230. .replace(/English/g, '英语')
  231. .replace(/Russian/g, '俄语')
  232. .replace(/German/g, '德语')
  233. .replace(/French/g, '法语')
  234. .replace(/Korean/g, '韩语')
  235. .replace(/Japanese/g, '日语')
  236. .replace(/Italian/g, '意大利语')
  237. .replace(/Turkish/g, '土耳其语')
  238. .replace(/Spanish - Latin America/g, '西班牙语-拉丁美洲')
  239. .replace(/Spanish - Spain/g, '西班牙语-西班牙')
  240. .replace(/Portuguese - Brazil/g, '葡萄牙语-巴西')
  241. .replace(/Portuguese/g, '葡萄牙语')
  242. .replace(/Thai/g, '泰语')
  243. .replace(/Arabic/g, '阿拉伯语')
  244. .replace(/Danish/g, '丹麦语')
  245. .replace(/Dutch/g, '荷兰语')
  246. .replace(/Finnish/g, '芬兰语')
  247. .replace(/Norwegian/g, '挪威语')
  248. .replace(/Polish/g, '波兰语')
  249. .replace(/Swedish/g, '瑞典语')
  250. .replace(/Catalon/g, '加泰罗尼亚语')
  251. .replace(/Greek/g, '希腊语')
  252. .replace(/Czech/g, '捷克语')
  253. .replace(/Estonian/g, '爱沙尼亚语')
  254. .replace(/Hungarian/g, '匈牙利语')
  255. .replace(/Spanish/g, '西班牙语')
  256. .replace(/Indonesian/g, '印度尼西亚语')
  257. ;
  258. console.log('1337x: ' + lang);
  259. return lang;
  260. }
  261. function replaceLangAnchor(bb_lang) {
  262. if (!bb_lang) {
  263. changeStatus('处理完成!未获取到语言!');
  264. return;
  265. }
  266. var descr = DESCR.val().replace('=+=LanguageAnchor=+=', bb_lang.trim());
  267. DESCR.val(descr);
  268. changeStatus('处理完成!');
  269. }
  270. function requestUrl(urlSteam, urlFitgirl) {
  271. changeStatus('开始获取FitGirl信息...');
  272. var bbstr;
  273. GM.xmlHttpRequest({
  274. method: "GET",
  275. url: urlFitgirl.val(),
  276. responseType: "document",
  277. onload: function(resp) {
  278. var parser = new DOMParser ();
  279. var ajaxDoc = parser.parseFromString(resp.responseText, "text/html");
  280. // 种子简介
  281. bbstr = parseFitgirRepack(ajaxDoc)
  282. editboxPart2(bbstr)
  283. var lang_source = $("input[name='pfru_lang_source']:checked").val();
  284. console.log('选择从: ' + lang_source + ' 获取游戏语言');
  285. if (lang_source == '1337x') {
  286. var url1337x = get1337xUrl(ajaxDoc); // 获取1337x链接
  287. if (url1337x && url1337x != '') {
  288. console.log('访问: ' + url1337x + ' 获取语言');
  289. changeStatus('正在从1337x获取语言列表...');
  290. GM.xmlHttpRequest({
  291. method: 'GET',
  292. url: url1337x,
  293. onload(resp) {
  294. var ajaxDoc = new DOMParser ().parseFromString(resp.responseText, "text/html");
  295. var bb_lang = parse1337Language(ajaxDoc);
  296. replaceLangAnchor(bb_lang);
  297. },
  298. onerror: function(resp) {
  299. console.log(resp);
  300. changeStatus('语言获取失败!');
  301. }
  302. });
  303. } else {
  304. changeStatus('未获取到1337x链接...');
  305. }
  306. } else {
  307. changeStatus('正在从steam获取语言列表...');
  308. GM.xmlHttpRequest({
  309. method: "GET",
  310. url: urlSteam.val(),
  311. responseType: "document",
  312. onload: function(resp){
  313. var parser = new DOMParser ();
  314. var ajaxDoc = parser.parseFromString (resp.responseText, "text/html");
  315. var bb_lang = parseSteamLanguage(ajaxDoc);
  316. replaceLangAnchor(bb_lang);
  317. // console.log (bbstr);
  318. },
  319. onerror: function(resp) {
  320. console.log(resp);
  321. changeStatus('语言获取失败!');
  322. }
  323. });
  324. }
  325. // 获取标题
  326. var fitgirl_title = getFitgirlTitle(ajaxDoc); // 原始标题
  327. var game_title = $("h1#top").text().slice(0,-4).trim();
  328. var name1 = '游戏名称: <span style="color: red">' + game_title + '</span><br>';
  329. var name2 = 'FitGirl 原始名称: <span style="color: red">' + fitgirl_title + '</span>' + '<br>';
  330. var $name_e = $('#name').parent();
  331. $name_e.html(name1 + name2 + $name_e.html());
  332. $('#name').val((fitgirl_title.replace(game_title, '').trim() + ' -FitGirl').trim());
  333. // 游戏本体
  334. $("#categories").find("option[value='1']").attr("selected",true);
  335. // Portable
  336. $("#format").find("option[value='4']").attr("selected",true);
  337. // 欧美
  338. $("#team").find("option[value='4']").attr("selected",true);
  339. // 可信源
  340. $("#vs").attr("checked",true);
  341. // console.log (bbstr);
  342. }
  343. });
  344. }
  345. (function() {
  346. 'use strict';
  347. const PFRU_HTML = '<tr><td>Steam URL</td><td><input style="width: 450px;" id="steamurl" /></td></tr>'
  348. + '<tr><td>FitGirl URL</td><td><input style="width: 450px;" id="fitgirlurl" /></td></tr>';
  349. var anchor = window.location.href.includes("uploadgame") ? $("#name") : $("input[name='torrentname']");
  350. anchor.parent().parent().after(PFRU_HTML);
  351. const steamurl = $("#steamurl");
  352. const fitgirlurl = $("#fitgirlurl");
  353. var lang_source_html = '<input type="radio" name="pfru_lang_source" value="1337x" checked />1337x'
  354. + '<input type="radio" name="pfru_lang_source" value="steam" />steam';
  355. fitgirlurl.after(
  356. // '<label>替换标题:<a href="javascript:void(0);" title="勾选后获取原始标题,注意需要手动去除游戏名" style="color: red">(?)</a></label><input type="checkbox" id="pfru_get_title" />'
  357. lang_source_html
  358. + ' <input type="button" id="pfru_fill_form" value="收集信息自动填写">'
  359. + ' <span id="pfru_status"></span>');
  360. $('#pfru_fill_form').click(function () {
  361. requestUrl(steamurl, fitgirlurl);
  362. $("#console").val("16");
  363. });
  364. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址