nangua.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. /*
  2. * @File : nangua.js
  3. * @Author : jade
  4. * @Date : 2024/3/18 10:54
  5. * @Email : jadehh@1ive.com
  6. * @Software : Samples
  7. * @Desc : 南瓜影视
  8. */
  9. import {Crypto, jinja2, _} from "../lib/cat.js";
  10. import {Spider} from "./spider.js";
  11. import {VodDetail, VodShort} from "../lib/vod.js";
  12. import * as Utils from "../lib/utils.js";
  13. function stripHtmlTag(src) {
  14. return src
  15. .replace(/<\/?[^>]+(>|$)/g, '')
  16. .replace(/&.{1,5};/g, '')
  17. .replace(/\s{2,}/g, ' ');
  18. }
  19. function formatPlayUrl(src, name) {
  20. return name
  21. .trim()
  22. .replaceAll(src, '')
  23. .replace(/<|>|《|》/g, '')
  24. .replace(/\$|#/g, ' ')
  25. .trim();
  26. }
  27. class NanGuaSpider extends Spider {
  28. constructor() {
  29. super();
  30. this.siteUrl = 'http://ys.changmengyun.com';
  31. }
  32. getName() {
  33. return "🎃┃南瓜影视┃🎃"
  34. }
  35. getAppName() {
  36. return "南瓜影视"
  37. }
  38. getJSName() {
  39. return "nangua"
  40. }
  41. getType() {
  42. return 3
  43. }
  44. async init(cfg) {
  45. await super.init(cfg);
  46. this.danmuStaus = true
  47. }
  48. getHeader() {
  49. let t = new Date().getTime().toString();
  50. return {
  51. 'version_name': '1.0.6',
  52. 'version_code': '6',
  53. 'package_name': 'com.app.nanguatv',
  54. 'sign': Crypto.MD5('c431ea542cee9679#uBFszdEM0oL0JRn@' + t).toString().toLowerCase(),
  55. 'imei': 'c431ea542cee9679',
  56. 'timeMillis': t,
  57. 'User-Agent': 'okhttp/4.6.0'
  58. }
  59. }
  60. async setClasses() {
  61. let data = JSON.parse(await this.fetch(this.siteUrl + '/api.php/provide/home_nav', null, this.getHeader()));
  62. for (const key in data) {
  63. if (data[key].name !== '精选') this.classes.push({
  64. type_id: data[key].id, type_name: data[key].name,
  65. });
  66. }
  67. }
  68. async setFilterObj() {
  69. this.filterObj = {
  70. "2": [{
  71. "key": "class",
  72. "name": "类型",
  73. "value": [{"n": "全部", "v": "类型"}, {"n": "国产剧", "v": "国产剧"}, {"n": "港台剧", "v": "港台剧"}]
  74. }, {
  75. "key": "area", "name": "地区", "value": [{"n": "全部", "v": "地区"}, {"n": "内地", "v": "内地"}, {
  76. "n": "香港地区", "v": "香港地区"
  77. }, {"n": "台湾地区", "v": "台湾地区"}]
  78. }, {
  79. "key": "year",
  80. "name": "年份",
  81. "value": [{"n": "全部", "v": "年份"}, {"n": "2024", "v": "2024"}, {
  82. "n": "2023",
  83. "v": "2023"
  84. }, {"n": "2022", "v": "2022"}, {
  85. "n": "2021", "v": "2021"
  86. }, {"n": "2020", "v": "2020"}, {"n": "2019", "v": "2019"}, {"n": "2018", "v": "2018"}, {
  87. "n": "2017", "v": "2017"
  88. }, {"n": "2016", "v": "2016"}, {"n": "2015", "v": "2015"}, {"n": "10年代", "v": "10年代"}, {
  89. "n": "00年代", "v": "00年代"
  90. }, {"n": "90年代", "v": "90年代"}, {"n": "80年代", "v": "80年代"}]
  91. }, {
  92. "key": "by", "name": "排序", "value": [{"n": "热播榜", "v": "热播榜"}, {"n": "好评榜", "v": "好评榜"}, {
  93. "n": "新上线", "v": "新上线"
  94. }]
  95. }], "1": [{
  96. "key": "class", "name": "类型", "value": [{"n": "全部", "v": "类型"}, {"n": "动作片", "v": "动作片"}, {
  97. "n": "喜剧片", "v": "喜剧片"
  98. }, {"n": "爱情片", "v": "爱情片"}, {"n": "科幻片", "v": "科幻片"}, {
  99. "n": "恐怖片", "v": "恐怖片"
  100. }, {"n": "剧情片", "v": "剧情片"}, {"n": "战争片", "v": "战争片"}, {"n": "惊悚片", "v": "惊悚片"}]
  101. }, {
  102. "key": "area", "name": "地区", "value": [{"n": "全部", "v": "地区"}, {"n": "华语", "v": "华语"}, {
  103. "n": "香港地区", "v": "香港地区"
  104. }, {"n": "美国", "v": "美国"}, {"n": "欧洲", "v": "欧洲"}, {"n": "韩国", "v": "韩国"}, {
  105. "n": "日本", "v": "日本"
  106. }, {"n": "台湾地区", "v": "台湾地区"}, {"n": "泰国", "v": "泰国"}, {
  107. "n": "台湾地区", "v": "台湾地区"
  108. }, {"n": "印度", "v": "印度"}, {"n": "其它", "v": "其它"}]
  109. }, {
  110. "key": "year",
  111. "name": "年份",
  112. "value": [{"n": "全部", "v": "年份"}, {"n": "2024", "v": "2024"}, {
  113. "n": "2023",
  114. "v": "2023"
  115. }, {"n": "2022", "v": "2022"}, {
  116. "n": "2021", "v": "2021"
  117. }, {"n": "2020", "v": "2020"}, {"n": "2019", "v": "2019"}, {"n": "2018", "v": "2018"}, {
  118. "n": "2017", "v": "2017"
  119. }, {"n": "2016", "v": "2016"}, {"n": "2015", "v": "2015"}, {"n": "10年代", "v": "10年代"}, {
  120. "n": "00年代", "v": "00年代"
  121. }, {"n": "90年代", "v": "90年代"}, {"n": "80年代", "v": "80年代"}]
  122. }, {
  123. "key": "by", "name": "排序", "value": [{"n": "热播榜", "v": "热播榜"}, {"n": "好评榜", "v": "好评榜"}, {
  124. "n": "新上线", "v": "新上线"
  125. }]
  126. }], "4": [{
  127. "key": "class", "name": "类型", "value": [{"n": "全部", "v": "类型"}, {"n": "国产漫", "v": "国产漫"}, {
  128. "n": "欧美漫", "v": "欧美漫"
  129. }, {"n": "日韩漫", "v": "日韩漫"}, {"n": "港台漫", "v": "港台漫"}]
  130. }, {
  131. "key": "area",
  132. "name": "地区",
  133. "value": [{"n": "全部", "v": "地区"}, {"n": "中国大陆", "v": "中国大陆"}, {
  134. "n": "日本", "v": "日本"
  135. }, {"n": "韩国", "v": "韩国"}, {"n": "欧美", "v": "欧美"}, {"n": "其它", "v": "其它"}]
  136. }, {
  137. "key": "year",
  138. "name": "年份",
  139. "value": [{"n": "全部", "v": "年份"}, {"n": "2024", "v": "2024"}, {
  140. "n": "2023",
  141. "v": "2023"
  142. }, {"n": "2022", "v": "2022"}, {
  143. "n": "2021", "v": "2021"
  144. }, {"n": "2020", "v": "2020"}, {"n": "2019", "v": "2019"}, {"n": "2018", "v": "2018"}, {
  145. "n": "2017", "v": "2017"
  146. }, {"n": "2016", "v": "2016"}, {"n": "2015", "v": "2015"}, {"n": "10年代", "v": "10年代"}, {
  147. "n": "00年代", "v": "00年代"
  148. }, {"n": "90年代", "v": "90年代"}, {"n": "80年代", "v": "80年代"}]
  149. }, {
  150. "key": "by", "name": "排序", "value": [{"n": "热播榜", "v": "热播榜"}, {"n": "新上线", "v": "新上线"}]
  151. }, {
  152. "key": "total",
  153. "name": "状态",
  154. "value": [{"n": "全部", "v": "状态"}, {"n": "连载", "v": "连载"}, {"n": "完结", "v": "完结"}]
  155. }], "3": [{
  156. "key": "class",
  157. "name": "类型",
  158. "value": [{"n": "全部", "v": "类型"}, {"n": "大陆", "v": "大陆"}, {"n": "港台", "v": "港台"}, {
  159. "n": "日韩", "v": "日韩"
  160. }, {"n": "欧美", "v": "欧美"}]
  161. }, {
  162. "key": "area",
  163. "name": "地区",
  164. "value": [{"n": "全部", "v": "地区"}, {"n": "内地", "v": "内地"}, {"n": "港台", "v": "港台"}, {
  165. "n": "日韩", "v": "日韩"
  166. }, {"n": "欧美", "v": "欧美"}, {"n": "其它", "v": "其它"}]
  167. }, {
  168. "key": "year",
  169. "name": "年份",
  170. "value": [{"n": "全部", "v": "年份"}, {"n": "2024", "v": "2024"}, {
  171. "n": "2023",
  172. "v": "2023"
  173. }, {"n": "2022", "v": "2022"}, {
  174. "n": "2021", "v": "2021"
  175. }, {"n": "2020", "v": "2020"}, {"n": "2019", "v": "2019"}, {"n": "2018", "v": "2018"}, {
  176. "n": "2017", "v": "2017"
  177. }, {"n": "2016", "v": "2016"}, {"n": "2015", "v": "2015"}, {"n": "10年代", "v": "10年代"}, {
  178. "n": "00年代", "v": "00年代"
  179. }, {"n": "90年代", "v": "90年代"}, {"n": "80年代", "v": "80年代"}]
  180. }, {
  181. "key": "by", "name": "排序", "value": [{"n": "热播榜", "v": "热播榜"}, {"n": "新上线", "v": "新上线"}]
  182. }], "46": [{
  183. "key": "class", "name": "类型", "value": [{"n": "全部", "v": "类型"}, {"n": "日韩剧", "v": "日韩剧"}, {
  184. "n": "欧美剧", "v": "欧美剧"
  185. }, {"n": "海外剧", "v": "海外剧"}]
  186. }, {
  187. "key": "area",
  188. "name": "地区",
  189. "value": [{"n": "全部", "v": "地区"}, {"n": "韩国", "v": "韩国"}, {"n": "美剧", "v": "美剧"}, {
  190. "n": "日本", "v": "日本"
  191. }, {"n": "泰国", "v": "泰国"}, {"n": "英国", "v": "英国"}, {"n": "新加坡", "v": "新加坡"}, {
  192. "n": "其他", "v": "其他"
  193. }]
  194. }, {
  195. "key": "year",
  196. "name": "年份",
  197. "value": [{"n": "全部", "v": "年份"}, {"n": "2024", "v": "2024"}, {
  198. "n": "2023",
  199. "v": "2023"
  200. }, {"n": "2022", "v": "2022"}, {
  201. "n": "2021", "v": "2021"
  202. }, {"n": "2020", "v": "2020"}, {"n": "2019", "v": "2019"}, {"n": "2018", "v": "2018"}, {
  203. "n": "2017", "v": "2017"
  204. }, {"n": "2016", "v": "2016"}, {"n": "2015", "v": "2015"}, {"n": "10年代", "v": "10年代"}, {
  205. "n": "00年代", "v": "00年代"
  206. }, {"n": "90年代", "v": "90年代"}, {"n": "80年代", "v": "80年代"}]
  207. }, {
  208. "key": "by", "name": "排序", "value": [{"n": "热播榜", "v": "热播榜"}, {"n": "好评榜", "v": "好评榜"}, {
  209. "n": "新上线", "v": "新上线"
  210. }]
  211. }]
  212. };
  213. }
  214. async parseVodShortListFromJSONByHome(obj) {
  215. let vod_list = []
  216. for (const data of obj["video"]) {
  217. let video_vod_list = await this.parseVodShortListFromJson(data["data"])
  218. vod_list.push(...video_vod_list)
  219. }
  220. return vod_list
  221. }
  222. async parseVodShortListFromJson(obj) {
  223. let vod_list = []
  224. for (const data of obj) {
  225. let vodShort = new VodShort()
  226. vodShort.vod_id = data["id"]
  227. vodShort.vod_name = data["name"]
  228. vodShort.vod_pic = data["img"]
  229. vodShort.vod_remarks = data["remarks"]
  230. if (_.isEmpty(vodShort.vod_remarks)) {
  231. vodShort.vod_remarks = data["msg"]
  232. }
  233. vod_list.push(vodShort)
  234. }
  235. return vod_list
  236. }
  237. async parseVodShortListFromJsonBySearch(obj) {
  238. let videos = [];
  239. for (const data of obj){
  240. let vodShort = new VodShort()
  241. vodShort.vod_id = data["id"]
  242. vodShort.vod_name = data["video_name"]
  243. vodShort.vod_remarks = data["qingxidu"]
  244. vodShort.vod_pic = Utils.formatUrl(data["img"])
  245. videos.push(vodShort)
  246. }
  247. return videos
  248. }
  249. async parseVodDetailfromJson(obj) {
  250. let vodDetail = new VodDetail()
  251. vodDetail.vod_id = obj["id"]
  252. vodDetail.vod_name = obj["name"]
  253. vodDetail.vod_pic = obj["img"]
  254. vodDetail.type_name = obj["type"]
  255. vodDetail.vod_year = obj["year"]
  256. vodDetail.vod_content = stripHtmlTag(obj["info"])
  257. vodDetail.vod_remarks = '更新至: ' + obj["msg"] + ' / 评分: ' + obj["score"]
  258. let episodes = obj["player_info"];
  259. let playlist = {};
  260. episodes.forEach(function (it) {
  261. let playurls = it["video_info"];
  262. playurls.forEach(function (playurl) {
  263. let source = it.show;
  264. let t = formatPlayUrl(vodDetail.vod_name, playurl.name);
  265. if (t.length === 0) t = playurl.name.trim();
  266. if (!playlist.hasOwnProperty(source)) {
  267. playlist[source] = [];
  268. }
  269. playlist[source].push(t + '$' + playurl.url);
  270. });
  271. });
  272. vodDetail.vod_play_from = _.keys(playlist).join('$$$');
  273. let urls = _.values(playlist);
  274. let vod_play_url = [];
  275. urls.forEach(function (it) {
  276. vod_play_url.push(it.join('#'));
  277. });
  278. vodDetail.vod_play_url = vod_play_url.join('$$$');
  279. return vodDetail
  280. }
  281. async setHomeVod() {
  282. let data = JSON.parse(await this.fetch(this.siteUrl + '/api.php/provide/home_data?app=ylys&devices=android&imei=c431ea542cee9679&deviceModel=Subsystem%20for%20Android(TM)&deviceVersion=33&appVersionName=1.0.9&deviceScreen=427*250&appVersionCode=9&deviceBrand=Windows', null, this.getHeader()));
  283. this.homeVodList = await this.parseVodShortListFromJSONByHome(data)
  284. }
  285. async setCategory(tid, pg, filter, extend) {
  286. if (pg <= 0 || typeof (pg) == 'undefined') pg = 1;
  287. let reqUrl = this.siteUrl + '/api.php/provide/vod_list?app=ylys&id=' + tid + '&page=' + pg + '&imei=c431ea542cee9679&';
  288. reqUrl += jinja2('area={{ext.area}}&year={{ext.year}}&type={{ext.class}}&total={{ext.total}}&order={{ext.by}}', {ext: extend});
  289. let data = JSON.parse(await this.fetch(reqUrl, null, this.getHeader())).list;
  290. this.vodList = await this.parseVodShortListFromJson(data)
  291. let pgChk = JSON.parse(await this.fetch(this.siteUrl + '/api.php/provide/vod_list?app=ylys&id=' + tid + '&page=' + (parseInt(pg) + 1) + '&imei=c431ea542cee9679&', null, this.getHeader())).msg;
  292. this.count = (pgChk === 'ok') ? parseInt(pg) + 1 : parseInt(pg);
  293. this.limit = 20
  294. this.total = this.limit * this.count
  295. }
  296. async setDetail(id) {
  297. let data = JSON.parse(await this.fetch(this.siteUrl + '/api.php/provide/vod_detail?app=ylys&imei=c431ea542cee9679&id=' + id, null, this.getHeader())).data;
  298. this.vodDetail = await this.parseVodDetailfromJson(data)
  299. }
  300. async setSearch(wd, quick, pg) {
  301. let page = parseInt(pg)
  302. const limit = 20
  303. let data = JSON.parse(await this.fetch(this.siteUrl + '/api.php/provide/search_result_more?app=ylys&video_name=' + wd + `&pageSize=${limit}&tid=0&imei=c431ea542cee9679&page=${pg}`, null, this.getHeader())).data;
  304. this.vodList = await this.parseVodShortListFromJsonBySearch(data)
  305. let pageCount = page;
  306. if (this.vodList.length === limit) {
  307. pageCount = page + 1;
  308. }
  309. this.result.setPage(page, pageCount, limit, pageCount)
  310. }
  311. async setPlay(flag, id, flags) {
  312. try {
  313. if (id.indexOf('m3u8') !== -1) {
  314. this.playUrl = id.split('url=')[1]
  315. } else if (id.indexOf(',') !== -1) {
  316. let mjurl = id.split(',')[1]
  317. let jData = JSON.parse(await this.fetch(mjurl, null, this.getHeader()));
  318. this.playUrl = jData["data"]["url"]
  319. } else {
  320. let jData = JSON.parse(await this.fetch(id, null, this.getHeader()));
  321. this.playUrl = jData["data"]["url"]
  322. }
  323. } catch (e) {
  324. await this.jadeLog.error("播放失败")
  325. }
  326. }
  327. }
  328. let spider = new NanGuaSpider()
  329. async function init(cfg) {
  330. await spider.init(cfg)
  331. }
  332. async function home(filter) {
  333. return await spider.home(filter)
  334. }
  335. async function homeVod() {
  336. return await spider.homeVod()
  337. }
  338. async function category(tid, pg, filter, extend) {
  339. return await spider.category(tid, pg, filter, extend)
  340. }
  341. async function detail(id) {
  342. return await spider.detail(id)
  343. }
  344. async function play(flag, id, flags) {
  345. return await spider.play(flag, id, flags)
  346. }
  347. async function search(wd, quick) {
  348. return await spider.search(wd, quick)
  349. }
  350. export function __jsEvalReturn() {
  351. return {
  352. init: init, home: home, homeVod: homeVod, category: category, detail: detail, play: play, search: search,
  353. };
  354. }
  355. export {spider}