一键转种至 fsm

目前支持:馒头/emp/pb/ptt/exo/kamept/kufirc/bitporn/ilolicon/rousi/nicept/kelu/happyfappy (适配更新后的馒头 启用脚本后需要设置馒头的TOKEN)

  1. // ==UserScript==
  2. // @name 一键转种至 fsm
  3. // @namespace https://github.com/tomyangsh/userscrips
  4. // @match https://www.happyfappy.org/torrents.php?id=*
  5. // @match https://our.kelu.one/details.php?id=*
  6. // @match https://www.nicept.net/details.php?id=*
  7. // @match https://rousi.zip/details.php?id=*
  8. // @match https://share.ilolicon.com/details.php?id=*
  9. // @match https://bitporn.eu/details.php?id=*
  10. // @match https://kufirc.com/torrents.php?id=*
  11. // @match https://kamept.com/details.php?id=*
  12. // @match https://exoticaz.to/torrent/*
  13. // @match https://www.pttime.org/details.php?id=*
  14. // @match https://pornbay.org/torrents.php?id=*
  15. // @match https://www.empornium.is/torrents.php?id=*
  16. // @match https://www.empornium.sx/torrents.php?id=*
  17. // @match https://kp.m-team.cc/detail/*
  18. // @match https://zp.m-team.io/detail/*
  19. // @match https://xp.m-team.cc/detail/*
  20. // @match https://fsm.name/Torrents/new?autofill
  21. // @grant GM_getValue
  22. // @grant GM_setValue
  23. // @grant GM.xmlHttpRequest
  24. // @grant GM_registerMenuCommand
  25. // @version 2.11.9
  26. // @author 大統領 (fix by seed)
  27. // @description 目前支持:馒头/emp/pb/ptt/exo/kamept/kufirc/bitporn/ilolicon/rousi/nicept/kelu/happyfappy (适配更新后的馒头 启用脚本后需要设置馒头的TOKEN)
  28. // @icon https://img.fsm.name/21/69/2169f715a4805d2643db30a4b8fd95d0.jpg
  29. // @license MIT
  30. // ==/UserScript==
  31.  
  32. // 添加设置MT TOKEN的菜单
  33. GM_registerMenuCommand("设置MT TOKEN", () => {
  34. const token = prompt("请输入MT TOKEN:");
  35. if (token) {
  36. GM_setValue("MT_TOKEN", token);
  37. alert("MT TOKEN设置成功!");
  38. }
  39. });
  40.  
  41. const HOST = document.location.host.match(/([^.]+)\.\w+$/)[1];
  42.  
  43. function process_luminance() {
  44. const link_box = document.querySelector('div.linkbox');
  45.  
  46. const fsm_link = create_link(function () {
  47. let title = document.querySelector('h2').innerText;
  48. let info_node = document.querySelector('#descbox');
  49. let img_list = []
  50.  
  51. let image_cover = document.querySelector('#coverimage img').src.replace('resize/250/', '');
  52. img_list.push(image_cover);
  53. info_node.querySelectorAll('img').forEach(node => {
  54. let image = node.src.replace(/\.(th|md)(\.\w+)$/, '$2');
  55. img_list.push(image);
  56. });
  57.  
  58. const tag = document.querySelector('td.cats_col div').title;
  59. const torrent_url = document.querySelector('a.blueButton').href;
  60. const upload_info = {
  61. "title": title,
  62. "img_list": img_list,
  63. "tag": tag,
  64. "torrent_url": torrent_url
  65. }
  66. GM_setValue("upload_info", upload_info);
  67. })
  68.  
  69. link_box.append(fsm_link);
  70. }
  71.  
  72. function process_nexus() {
  73. let subtitle;
  74. let action_bar;
  75. let tags = [];
  76.  
  77. document.querySelectorAll('td.rowhead').forEach(td => {
  78. switch (td.innerText) {
  79. case '资源标签':
  80. case '標簽':
  81. case '标签': {
  82. td.nextElementSibling.querySelectorAll('span').forEach(span => {
  83. tags.push(span.innerText);
  84. })
  85.  
  86. break;
  87. }
  88. case '副標題':
  89. case '副标题': {
  90. subtitle = td.nextElementSibling.innerText;
  91.  
  92. break;
  93. }
  94. case '基本資訊':
  95. case '基本信息': {
  96. const attribute = td.nextElementSibling.innerText;
  97. if (attribute.match('无码')) {
  98. tags.push('无码');
  99. } else if (attribute.match('有码')) {
  100. tags.push('有码');
  101. }
  102.  
  103. break;
  104. }
  105. case 'Basic Info': {
  106. const type = td.nextElementSibling.innerText.match(/Type:\s(\w+)/)[1];
  107. tags.push(type);
  108.  
  109. break;
  110. }
  111. case 'Action':
  112. case '行為':
  113. case '行为': {
  114. action_bar = td.nextElementSibling;
  115.  
  116. break;
  117. }
  118. }
  119. })
  120.  
  121. const fsm_link = create_link(function () {
  122. const title = document.querySelector('h1').firstChild.textContent;
  123. const info_node = document.querySelector('#kdescr');
  124. const img_list = [];
  125.  
  126. info_node.querySelectorAll('img').forEach(img => {
  127. let image = img.src.replace('.thumb.jpg', '');
  128. img_list.push(image);
  129. })
  130.  
  131. const tag = tags.join();
  132. const torrent_url = document.querySelector('a.index').href;
  133. const upload_info = {
  134. "title": title,
  135. "subtitle": subtitle,
  136. "img_list": img_list,
  137. "tag": tag,
  138. "torrent_url": torrent_url
  139. }
  140. GM_setValue("upload_info", upload_info);
  141. })
  142.  
  143. action_bar.append(' | ');
  144. action_bar.append(fsm_link);
  145. }
  146.  
  147. function load_torrent(url) {
  148. GM.xmlHttpRequest({
  149. url: url,
  150. method: "GET",
  151. responseType: 'blob',
  152. onload: res => {
  153. const torrent_file = new window.File([res.response], 'file.torrent', { type: "application/x-bittorrent" });
  154. const container = new DataTransfer();
  155. container.items.add(torrent_file);
  156.  
  157. let input_file = document.querySelector('input.el-upload__input');
  158. input_file.files = container.files;
  159. input_file.dispatchEvent(new Event('change'));
  160. },
  161. onerror: res => {
  162. console.log(res);
  163. alert("加载种子失败,可能是你点得太快了!");
  164. }
  165. })
  166. }
  167.  
  168. function upload_img(source_url) {
  169. let referer = source_url.match(/https?:\/\/.+?\//)[0];
  170.  
  171. GM.xmlHttpRequest({
  172. url: source_url,
  173. method: "GET",
  174. responseType: 'blob',
  175. headers: {
  176. 'Referer': referer
  177. },
  178. onload: res => {
  179. const image_file = new window.File([res.response], 'file.jpg');
  180. const container = new DataTransfer();
  181. container.items.add(image_file);
  182.  
  183. let input_file = document.querySelectorAll('input.el-upload__input')[1];
  184. input_file.files = container.files;
  185. input_file.dispatchEvent(new Event('change'));
  186. }
  187. })
  188. }
  189.  
  190. function add_observer(action) {
  191. const observer = new MutationObserver(action);
  192. const target = document.querySelector('title');
  193. const config = { childList: true };
  194. observer.observe(target, config);
  195. }
  196.  
  197. function create_link(collect_data) {
  198. const fsm_link = document.createElement('a');
  199. fsm_link.innerText = '[转至 FSM]';
  200. fsm_link.style = "cursor: pointer;";
  201. fsm_link.onclick = function() {
  202. collect_data();
  203. const url_autofill = 'https://fsm.name/Torrents/new?autofill';
  204. window.open(url_autofill, '_blank').focus();
  205. }
  206.  
  207. GM_setValue("source_url", document.location.href);
  208.  
  209. return fsm_link;
  210. }
  211.  
  212. switch (HOST) {
  213. case 'happyfappy':
  214. case 'kufirc':
  215. case 'pornbay':
  216. case 'empornium':
  217. process_luminance();
  218. break;
  219. case 'kelu':
  220. case 'nicept':
  221. case 'rousi':
  222. case 'ilolicon':
  223. case 'bitporn':
  224. case 'kamept':
  225. case 'pttime':
  226. process_nexus();
  227. break;
  228. case 'exoticaz': {
  229. const action_bar = document.querySelector('div.p-2 div.float-right');
  230.  
  231. function collect_data () {
  232. const title = document.querySelector('h1').innerText;
  233. const img_list = [];
  234. const tags = [];
  235.  
  236. document.querySelectorAll('#TorrentDescription img').forEach(img => {
  237. img_list.push(img.src);
  238. })
  239.  
  240. document.querySelectorAll('#screenshots img').forEach(img => {
  241. img_list.push(img.src);
  242. })
  243.  
  244. document.querySelectorAll('div.tags a').forEach(a => {
  245. tags.push(a.innerText);
  246. })
  247.  
  248. const tag = tags.join();
  249. const torrent_url = document.querySelector('a.btn-xs').href;
  250. const upload_info = {
  251. "title": title,
  252. "img_list": img_list,
  253. "tag": tag,
  254. "torrent_url": torrent_url
  255. }
  256. GM_setValue("upload_info", upload_info);
  257. }
  258.  
  259. const fsm_link = create_link(collect_data);
  260. action_bar.prepend(fsm_link);
  261.  
  262. break;
  263. }
  264. case 'm-team': {
  265. function append_link() {
  266. const fsm_link = create_link(function () {
  267. const title = document.querySelector('h2 span').innerText;
  268. let subtitle = '';
  269. let img_list = [];
  270. let tags = [];
  271.  
  272. document.querySelectorAll('th.ant-descriptions-item-label').forEach(th => {
  273. switch (th.innerText) {
  274. case '副標題': {
  275. subtitle = th.nextSibling.innerText;
  276.  
  277. break;
  278. }
  279. case 'Tag': {
  280. th.nextSibling.querySelectorAll('span div div').forEach(tag_node => {
  281. tags.push(tag_node.innerText);
  282. })
  283.  
  284. break;
  285. }
  286. case '基本資訊': {
  287. const attribute = th.nextSibling.innerText;
  288. if (attribute.match('無碼')) {
  289. tags.push('无码');
  290. } else if (attribute.match('有碼')) {
  291. tags.push('有码');
  292. } else if (attribute.match('寫真')) {
  293. tags.push('写真');
  294. } else if (attribute.match('遊戲')) {
  295. tags.push('黄油');
  296. } else if (attribute.match('漫畫')) {
  297. tags.push('漫画');
  298. } else if (attribute.match('動畫')) {
  299. tags.push('动画');
  300. }
  301.  
  302. break;
  303. }
  304. }
  305. });
  306.  
  307. let tag = tags.join();
  308.  
  309. document.querySelectorAll('.braft-output-content img').forEach(img => {
  310. img_list.push(img.src);
  311. });
  312.  
  313. let torrent_id = document.location.href.match(/\d+/)[0];
  314. const token = GM_getValue("MT_TOKEN");
  315. if (!token) {
  316. alert("请先设置MT TOKEN!点击脚本图标选择'设置MT TOKEN'");
  317. return;
  318. }
  319. const form_data = new FormData();
  320. form_data.append("id", torrent_id)
  321.  
  322. GM.xmlHttpRequest({
  323. url: 'https://api2.m-team.cc/api/torrent/genDlToken',
  324. method: 'POST',
  325. responseType: 'json',
  326. data: form_data,
  327. headers: {
  328. "x-api-key": token
  329. },
  330. synchronous: false,
  331. onload: res => {
  332. console.log(res);
  333. const torrent_url = res.response.data;
  334.  
  335. const upload_info = {
  336. "title": title,
  337. "subtitle": subtitle,
  338. "img_list": img_list,
  339. "tag": tag,
  340. "torrent_url": torrent_url
  341. }
  342. GM_setValue("upload_info", upload_info);
  343. }
  344. })
  345. })
  346.  
  347. let action_bar;
  348.  
  349. document.querySelectorAll('span').forEach(node => {
  350. if (node.innerText == '行為') {
  351. action_bar = node.parentNode.nextSibling.childNodes[0].childNodes[0];
  352. }
  353. })
  354.  
  355. action_bar.append(fsm_link);
  356. }
  357.  
  358. add_observer(append_link);
  359.  
  360. break;
  361. }
  362. case 'fsm': {
  363. function fill_info(mutations) {
  364. if (!document.querySelector('title').innerText.match('FSM')) {return;}
  365.  
  366. const editor = document.querySelector('div.ql-editor');
  367. const upload_info = GM_getValue("upload_info");
  368. const note_node = document.createElement('div');
  369. note_node.innerText = "请等待下方图片全部上传完成后再点击发布!记得删去不必要的图片,及拖动改变顺序,第一张图片会用作封面";
  370. editor.parentNode.parentNode.parentNode.prepend(note_node);
  371.  
  372. let input_title = document.querySelectorAll('label')[1].control;
  373. input_title.value = upload_info.title;
  374. input_title.dispatchEvent(new Event('input'));
  375.  
  376. let input_tag = document.querySelectorAll('label')[2].control;
  377. input_tag.value = upload_info.tag;
  378. input_tag.dispatchEvent(new Event('input'));
  379.  
  380. let input_source = document.querySelectorAll('label')[3].control;
  381. input_source.value = GM_getValue("source_url");
  382. input_source.dispatchEvent(new Event('input'));
  383.  
  384. if (upload_info.subtitle) {
  385. let subtitle_node = document.createElement('p');
  386. subtitle_node.innerText = upload_info.subtitle;
  387. editor.append(subtitle_node);
  388. }
  389.  
  390. for (let img_url of upload_info.img_list) {
  391. upload_img(img_url);
  392. }
  393.  
  394. if (upload_info.torrent_url) {
  395. load_torrent(upload_info.torrent_url);
  396. }
  397.  
  398. }
  399.  
  400. add_observer(fill_info);
  401.  
  402. break;
  403. }
  404. }