tiantian.js 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. /*
  2. * @File : tiantian.js
  3. * @Author : jade
  4. * @Date : 2024/04/15 10:48
  5. * @Email : jadehh@1ive.com
  6. * @Software : Samples
  7. * @Desc : 天天影视
  8. */
  9. import {Spider} from "./spider.js";
  10. import {_} from "../lib/cat.js";
  11. import * as Utils from "../lib/utils.js";
  12. import {VodDetail, VodShort} from "../lib/vod.js";
  13. class TianTianSpider extends Spider {
  14. constructor() {
  15. super();
  16. this.siteUrl = "http://op.ysdqjs.cn"
  17. this.cookie = ""
  18. this.extendObj = {"extend": "类型", "area": "地区", "year": "年代"}
  19. this.parseMap = {};
  20. }
  21. async request(reqUrl, method, data) {
  22. const headers = {
  23. 'User-Agent': Utils.CHROME,
  24. };
  25. if (!_.isEmpty(this.cookie)) {
  26. headers['Cookie'] = this.cookie;
  27. }
  28. const postType = method === 'post' ? 'form-data' : '';
  29. let res = await req(reqUrl, {
  30. method: method || 'get', headers: headers, data: data, postType: postType,
  31. });
  32. if (res.code === 403) {
  33. const path = res.data.match(/window\.location\.href ="(.*?)"/)[1];
  34. this.cookie = _.isArray(res.headers['set-cookie']) ? res.headers['set-cookie'].join(';') : res.headers['set-cookie'];
  35. headers['Cookie'] = this.cookie;
  36. res = await req(this.siteUrl + path, {
  37. method: method || 'get', headers: headers, data: data, postType: postType,
  38. });
  39. }
  40. return res.content;
  41. }
  42. async postData(url, data) {
  43. const timestamp = Math.floor(new Date().getTime() / 1000);
  44. const key = 'kj5649ertj84ks89r4jh8s45hf84hjfds04k';
  45. const sign = md5X(key + timestamp).toString();
  46. let defaultData = {
  47. sign: sign, timestamp: timestamp,
  48. };
  49. const reqData = data ? _.merge(defaultData, data) : defaultData;
  50. return await this.request(url, 'post', reqData);
  51. }
  52. getName() {
  53. return "⛄┃天天影视┃⛄"
  54. }
  55. getAppName() {
  56. return "天天影视"
  57. }
  58. getJSName() {
  59. return "tiantian"
  60. }
  61. getType() {
  62. return 3
  63. }
  64. async init(cfg) {
  65. await super.init(cfg);
  66. this.danmuStaus = true
  67. }
  68. generateParam(tid, pg, extend, limit) {
  69. const param = {
  70. type_id: tid, page: pg, limit: limit,
  71. };
  72. if (extend["extend"] !== undefined && extend["extend"] !== "全部") {
  73. param.class = extend["extend"];
  74. }
  75. if (extend["area"] !== undefined && extend["area"] !== "全部") {
  76. param.area = extend.area;
  77. }
  78. if (extend["lang"] !== undefined && extend["lang"] !== "全部") {
  79. param.lang = extend.lang;
  80. }
  81. if (extend["year"] !== undefined && extend["year"] !== "全部") {
  82. param.year = extend.year;
  83. }
  84. return param;
  85. }
  86. async getFilter(data) {
  87. let extend_list = []
  88. Object.keys(data).forEach(key => {
  89. if (Array.isArray(data[key])) {
  90. if (!_.isEmpty(this.extendObj[key])) {
  91. let extend_dic = {"key": key, "name": this.extendObj[key], "value": []}
  92. let add_year_status = false
  93. for (const extend_data of data[key]) {
  94. if (key === "year") {
  95. if (!data[key].includes("2024") && extend_data !== "全部" && !add_year_status) {
  96. extend_dic["value"].push({"n": "2024", "v": "2024"})
  97. add_year_status = true
  98. }
  99. }
  100. if (!_.isEmpty(extend_data)) {
  101. extend_dic["value"].push({"n": extend_data, "v": extend_data})
  102. }
  103. }
  104. if (extend_dic["value"].length > 1) {
  105. extend_list.push(extend_dic)
  106. }
  107. }
  108. }
  109. })
  110. return extend_list
  111. }
  112. async setClasses() {
  113. let resJson = JSON.parse(await this.postData(this.siteUrl + '/v2/type/top_type'))
  114. for (const data of resJson["data"]["list"]) {
  115. let type_name = data["type_name"]
  116. let type_id = data["type_id"].toString()
  117. this.classes.push(this.getTypeDic(type_name, type_id))
  118. this.filterObj[type_id] = await this.getFilter(data)
  119. }
  120. }
  121. async parseVodShortListFromJson(vodList) {
  122. let vod_list = []
  123. for (const vodData of vodList) {
  124. let vodShort = new VodShort()
  125. vodShort.load_data(vodData)
  126. if (_.isEmpty(vodShort.vod_pic) && vodData["vod_pic_thumb"] !== undefined) {
  127. vodShort.vod_pic = vodData["vod_pic_thumb"]
  128. }
  129. if (vodShort.vod_name !== "首页轮播") {
  130. vod_list.push(vodShort)
  131. }
  132. }
  133. return vod_list
  134. }
  135. async parseVodDetailfromJson(detailObj) {
  136. let vodDetail = new VodDetail()
  137. vodDetail.load_data(detailObj)
  138. vodDetail.vod_content = Utils.formatContent(vodDetail.vod_content)
  139. const playInfo = detailObj["vod_play_list"];
  140. const playVod = {};
  141. _.each(playInfo, (obj) => {
  142. const sourceName = obj.name;
  143. let playList = '';
  144. const videoInfo = obj.urls;
  145. const parse = obj["parse_urls"];
  146. if (!_.isEmpty(parse)) this.parseMap[sourceName] = parse;
  147. const vodItems = _.map(videoInfo, (epObj) => {
  148. const epName = epObj.name;
  149. const playUrl = epObj.url;
  150. return epName + '$' + playUrl;
  151. });
  152. if (_.isEmpty(vodItems)) return;
  153. playList = vodItems.join('#');
  154. playVod[sourceName] = playList;
  155. });
  156. vodDetail.vod_play_from = _.keys(playVod).join('$$$');
  157. vodDetail.vod_play_url = _.values(playVod).join('$$$');
  158. return vodDetail
  159. }
  160. async setHomeVod() {
  161. let resJson = JSON.parse(await this.postData(this.siteUrl + '/v2/type/tj_vod'))
  162. let vod_list = []
  163. for (const data of resJson["data"]["type_vod"]) {
  164. if (data["type_name"] !== "广告") {
  165. vod_list = await this.parseVodShortListFromJson(data["vod"])
  166. this.homeVodList = [...this.homeVodList, ...vod_list]
  167. }
  168. }
  169. vod_list = await this.parseVodShortListFromJson(resJson["data"]["loop"])
  170. this.homeVodList = [...this.homeVodList, ...vod_list]
  171. vod_list = await this.parseVodShortListFromJson(resJson["data"]["cai"])
  172. this.homeVodList = [...this.homeVodList, ...vod_list]
  173. }
  174. async setCategory(tid, pg, filter, extend) {
  175. const limit = 12;
  176. const param = this.generateParam(tid, pg, extend, limit);
  177. const resJson = JSON.parse(await this.postData(this.siteUrl + '/v2/home/type_search', param));
  178. this.vodList = await this.parseVodShortListFromJson(resJson["data"]["list"])
  179. }
  180. async setDetail(id) {
  181. const param = {
  182. vod_id: id,
  183. }
  184. const resJson = JSON.parse(await this.postData(this.siteUrl + '/v2/home/vod_details', param));
  185. this.vodDetail = await this.parseVodDetailfromJson(resJson["data"])
  186. }
  187. async setPlay(flag, id, flags) {
  188. const parsers = this.parseMap[flag];
  189. if (flag.indexOf("芒果") > -1 || flag.indexOf("腾讯") > -1 || flag.indexOf("爱奇艺") > -1) {
  190. if (!this.catOpenStatus) {
  191. this.danmuUrl = await this.danmuSpider.downloadDanmu("https://dmku.thefilehosting.com/?ac=dm&url=" + id)
  192. }
  193. }
  194. if (!_.isEmpty(parsers)) {
  195. for (const parser of parsers) {
  196. if (_.isEmpty(parser)) continue;
  197. try {
  198. const resp = await this.request(parser + id);
  199. const json = JSON.parse(resp);
  200. if (!_.isEmpty(json.url)) {
  201. this.playUrl = json.url;
  202. break;
  203. }
  204. } catch (e) {
  205. }
  206. }
  207. }
  208. }
  209. async setSearch(wd, quick, pg) {
  210. const limit = 12;
  211. const param = {
  212. keyword: wd, page: pg, limit: limit,
  213. };
  214. const resJson = JSON.parse(await this.postData(this.siteUrl + '/v2/home/search', param));
  215. this.vodList = await this.parseVodShortListFromJson(resJson["data"]["list"])
  216. const page = parseInt(pg);
  217. let pageCount = page;
  218. if (this.vodList.length === limit) {
  219. pageCount = page + 1;
  220. }
  221. this.result.setPage(page, pageCount, limit, pageCount)
  222. }
  223. }
  224. let spider = new TianTianSpider()
  225. async function init(cfg) {
  226. await spider.init(cfg)
  227. }
  228. async function home(filter) {
  229. return await spider.home(filter)
  230. }
  231. async function homeVod() {
  232. return await spider.homeVod()
  233. }
  234. async function category(tid, pg, filter, extend) {
  235. return await spider.category(tid, pg, filter, extend)
  236. }
  237. async function detail(id) {
  238. return await spider.detail(id)
  239. }
  240. async function play(flag, id, flags) {
  241. return await spider.play(flag, id, flags)
  242. }
  243. async function search(wd, quick) {
  244. return await spider.search(wd, quick)
  245. }
  246. export function __jsEvalReturn() {
  247. return {
  248. init: init, home: home, homeVod: homeVod, category: category, detail: detail, play: play, search: search,
  249. };
  250. }
  251. export {spider, TianTianSpider}