copymanga_open.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. import { Crypto, _, load } from './lib/cat.js';
  2. let key = 'copymanga';
  3. let url = 'https://www.mangacopy.com';
  4. let siteKey = '';
  5. let siteType = 0;
  6. const PC_UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36';
  7. async function request(reqUrl) {
  8. let resp = await req(reqUrl, {
  9. headers: {
  10. 'User-Agent': PC_UA,
  11. },
  12. });
  13. return resp.content;
  14. }
  15. // cfg = {skey: siteKey, ext: extend}
  16. async function init(cfg) {
  17. siteKey = cfg.skey;
  18. siteType = cfg.stype;
  19. }
  20. async function home(filter) {
  21. var html = await request(url + '/comics');
  22. const $ = load(html);
  23. let filterObj = {};
  24. let region = {
  25. key: 'region',
  26. name: '地區',
  27. init: '',
  28. };
  29. let regionValues = [];
  30. regionValues.push({ n: '全部', v: '' });
  31. regionValues.push({ n: '日漫', v: '0' });
  32. regionValues.push({ n: '韓漫', v: '1' });
  33. regionValues.push({ n: '美漫', v: '2' });
  34. region['value'] = regionValues;
  35. let ordering = {
  36. key: 'ordering',
  37. name: '排序',
  38. init: '-datetime_updated',
  39. };
  40. let orderingValues = [];
  41. orderingValues.push({ n: '更新時間↓', v: '-datetime_updated' });
  42. orderingValues.push({ n: '更新時間↑', v: 'datetime_updated' });
  43. orderingValues.push({ n: '熱門↓', v: '-popular' });
  44. orderingValues.push({ n: '熱門↑', v: 'popular' });
  45. ordering['value'] = orderingValues;
  46. let status = {
  47. key: 'sort',
  48. name: '狀態',
  49. init: '',
  50. };
  51. let statusValues = [];
  52. statusValues.push({ n: '全部', v: '' });
  53. statusValues.push({ n: '連載中', v: '0' });
  54. statusValues.push({ n: '已完結', v: '1' });
  55. statusValues.push({ n: '短篇', v: '2' });
  56. status['value'] = statusValues;
  57. filterObj['c1'] = [];
  58. let themeValues = [{ n: '全部', v: '' }];
  59. for (const a of $('div.classify-right>a[href*="theme="]')) {
  60. themeValues.push({
  61. n: $(a).text().trim(),
  62. v: a.attribs.href.match(/.*?theme=(.*)&/)[1],
  63. });
  64. }
  65. _.each(_.chunk(themeValues, 11), (vals) => {
  66. let theme = {
  67. key: 'theme',
  68. name: '',
  69. init: '',
  70. value: vals,
  71. };
  72. filterObj['c1'].push(theme);
  73. });
  74. filterObj['c1'].push(region);
  75. filterObj['c1'].push(status);
  76. filterObj['c1'].push(ordering);
  77. return {
  78. class: [{ type_name: 'all', type_id: 'c1' }],
  79. filters: filterObj,
  80. };
  81. }
  82. async function category(tid, pg, filter, extend) {
  83. if (pg == 0) pg = 1;
  84. let link = url + `/comics?theme=${extend.theme || ''}&region=${extend.region || ''}&status=${extend.status || ''}&ordering=${extend.ordering || '-datetime_updated'}`;
  85. if (pg > 1) {
  86. link += '&offset=' + (pg - 1) * 50 + '&limit=50';
  87. }
  88. var html = await request(link);
  89. const $ = load(html);
  90. const list = eval($('div[class="row exemptComic-box"]')[0].attribs.list);
  91. let books = [];
  92. for (const book of list) {
  93. books.push({
  94. book_id: book.path_word,
  95. book_name: book.name,
  96. book_pic: book.cover,
  97. book_remarks: book.author ? book.author[0].name : '',
  98. });
  99. }
  100. return {
  101. page: pg,
  102. pagecount: list.length == 50 ? pg + 1 : pg,
  103. list: books,
  104. };
  105. }
  106. async function detail(id) {
  107. var html = await request(url + `/comic/${id}`);
  108. const $ = load(html);
  109. let book = {
  110. book_name: $('h6').text().trim(),
  111. book_director: _.map($('span.comicParticulars-right-txt>a[href*="/author/"]'), (a) => $(a).text().trim()).join('/'),
  112. book_content: $('p.intro').text().trim(),
  113. };
  114. const data = JSON.parse(await request(url + `/comicdetail/${id}/chapters`)).results;
  115. var key = Crypto.enc.Utf8.parse('xxxmanga.woo.key');
  116. var iv = Crypto.enc.Utf8.parse(data.substr(0, 16));
  117. var src = Crypto.enc.Hex.parse(data.substr(16));
  118. var dst = Crypto.AES.decrypt({ ciphertext: src }, key, { iv: iv, padding: Crypto.pad.Pkcs7 });
  119. dst = Crypto.enc.Utf8.stringify(dst);
  120. const groups = JSON.parse(dst).groups;
  121. let urls = _.map(groups.default.chapters, (c) => {
  122. return c.name + '$' + id + '|' + c.id;
  123. }).join('#');
  124. book.volumes = '默認';
  125. book.urls = urls;
  126. return {
  127. list: [book],
  128. };
  129. }
  130. async function play(flag, id, flags) {
  131. try {
  132. var info = id.split('|');
  133. var html = await request(url + `/comic/${info[0]}/chapter/${info[1]}`);
  134. const $ = load(html);
  135. const data = $('div.imageData')[0].attribs.contentkey;
  136. var key = Crypto.enc.Utf8.parse('xxxmanga.woo.key');
  137. var iv = Crypto.enc.Utf8.parse(data.substr(0, 16));
  138. var src = Crypto.enc.Hex.parse(data.substr(16));
  139. var dst = Crypto.AES.decrypt({ ciphertext: src }, key, { iv: iv, padding: Crypto.pad.Pkcs7 });
  140. dst = Crypto.enc.Utf8.stringify(dst);
  141. const list = JSON.parse(dst);
  142. var content = [];
  143. for (let index = 0; index < list.length; index++) {
  144. const element = list[index];
  145. content[index] = element.url;
  146. }
  147. return {
  148. content: content,
  149. };
  150. } catch (e) {
  151. return {
  152. content: '',
  153. };
  154. }
  155. }
  156. async function search(wd, quick, pg) {
  157. if (pg == 0) pg = 1;
  158. const link = `${url}/api/kb/web/searcha/comics?offset=${pg > 1 ? ((pg - 1) * 12).toString() : ''}&platform=2&limit=12&q=${wd}&q_type=`;
  159. var list = JSON.parse(await request(link)).results.list;
  160. const books = [];
  161. for (const book of list) {
  162. books.push({
  163. book_id: book.path_word,
  164. book_name: book.name,
  165. book_pic: book.cover,
  166. book_remarks: book.author ? book.author[0].name : '',
  167. });
  168. }
  169. return {
  170. page: pg,
  171. pagecount: list.length == 12 ? pg + 1 : pg,
  172. list: books,
  173. };
  174. }
  175. export function __jsEvalReturn() {
  176. return {
  177. init: init,
  178. home: home,
  179. category: category,
  180. detail: detail,
  181. play: play,
  182. search: search,
  183. };
  184. }