hanxiucao.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625
  1. /*
  2. * @File : hanxiucao.js
  3. * @Author : jade
  4. * @Date : 2024/04/13 19:38
  5. * @Email : jadehh@1ive.com
  6. * @Software : Samples
  7. * @Desc :
  8. */
  9. import {_, Crypto} from '../lib/cat.js';
  10. import {VodDetail, VodShort} from "../lib/vod.js"
  11. import {Spider} from "./spider.js";
  12. import * as Utils from "../lib/utils.js";
  13. function He(e, {key: t, iv: s} = {}) {
  14. let VITE_APP_AES_KEY = "B77A9FF7F323B5404902102257503C2F"
  15. let VITE_APP_AES_IV = "B77A9FF7F323B5404902102257503C2F"
  16. var o = Crypto.enc.Utf8.parse(e)
  17. , A = Crypto.AES.encrypt(o, Crypto.enc.Utf8.parse(t || VITE_APP_AES_KEY), {
  18. iv: Crypto.enc.Utf8.parse(s || VITE_APP_AES_IV),
  19. mode: Crypto.mode.CBC,
  20. padding: Crypto.pad.Pkcs7
  21. });
  22. return Crypto.enc.Base64.stringify(A.ciphertext)
  23. }
  24. function Kt() {
  25. const e = new Date;
  26. return He(parseInt(e.getTime() / 1e3) + e.getTimezoneOffset() * 60 + -1)
  27. }
  28. function bt(e) {
  29. const wA = "46cc793c53dc451b"
  30. let t = Crypto.enc.Utf8.parse(wA)
  31. , s = Crypto.AES.decrypt(e, t, {
  32. mode: Crypto.mode.ECB,
  33. padding: Crypto.pad.Pkcs7
  34. });
  35. return Crypto.enc.Utf8.stringify(s).toString()
  36. }
  37. class HanXiuCaoSpider extends Spider {
  38. constructor() {
  39. super();
  40. this.siteUrl = "https://api.qianyuewenhua.xyz"
  41. }
  42. async spiderInit(inReq = null) {
  43. if (inReq !== null) {
  44. this.jsBase = await js2Proxy(inReq, "imgBt", this.getHeader());
  45. } else {
  46. this.jsBase = await js2Proxy(true, this.siteType, this.siteKey, 'imgBt/', this.getHeader());
  47. }
  48. }
  49. async init(cfg) {
  50. await super.init(cfg);
  51. this.danmuStaus = true
  52. await this.spiderInit(null)
  53. }
  54. getAppName() {
  55. return "含羞草"
  56. }
  57. getName() {
  58. return "🔞┃含羞草┃🔞"
  59. }
  60. getJSName() {
  61. return "hanxiucao"
  62. }
  63. getType() {
  64. return 3
  65. }
  66. getParams(params) {
  67. return {"endata": He(JSON.stringify(params)), "ents": Kt()}
  68. }
  69. async setClasses() {
  70. let params = this.getParams({"channel": "pc"})
  71. let response = await this.post(this.siteUrl + "/panel/list", params, this.getHeader(), "")
  72. let resJson = JSON.parse(response)
  73. for (const data of resJson["data"]["list"]) {
  74. let type_id = data["panelId"]
  75. let type_name = data["panelName"]
  76. if (type_name !== "首页") {
  77. this.classes.push(this.getTypeDic(type_name, type_id))
  78. }
  79. }
  80. }
  81. async getFilter(Layouts) {
  82. let extend_list = []
  83. for (const data of Layouts) {
  84. let layoutObj = JSON.parse(data["layoutContent"])
  85. for (const layout of layoutObj["sortKeys"]) {
  86. let extend_dic = {}
  87. if (layout["label"] !== "综合排序") {
  88. extend_dic = {"key": "sorts", "name": layout["label"].toString(), value: []}
  89. extend_dic["value"].push({"n": "升序", "v": layout["value"].toString() + "-" + "升序"})
  90. extend_dic["value"].push({"n": "降序", "v": layout["value"].toString() + "-" + "降序"})
  91. } else {
  92. extend_dic = {"key": "sorts", "name": "排序", value: []}
  93. extend_dic["value"].push({"n": layout["label"].toString(), "v": layout["value"].toString()})
  94. }
  95. extend_list.push(extend_dic)
  96. }
  97. }
  98. return extend_list
  99. }
  100. async getNvYouFilter(Layouts) {
  101. let extend_list = []
  102. let params = {
  103. "uids": [],
  104. "page": 1,
  105. "length": 20
  106. }
  107. for (let i = 0; i < Layouts.length; i++) {
  108. let data = Layouts[i]
  109. let layoutObj = JSON.parse(data["layoutContent"])
  110. params["uids"] = layoutObj["list"]
  111. let resJson = JSON.parse(await this.post(this.siteUrl + "/user/getUpList", this.getParams(params), this.getHeader(), ""))
  112. let extend_dic = {"key": `tags`, "name": data["layoutName"], value: []}
  113. for (const layout of resJson["data"]["list"]) {
  114. extend_dic["value"].push({"n": layout["user_nicename"], "v": JSON.stringify(layout)})
  115. }
  116. extend_list.push(extend_dic)
  117. }
  118. let sort_list = [
  119. {
  120. "key": "sorts",
  121. "name": "发布时间",
  122. "value": [
  123. {
  124. "n": "升序",
  125. "v": "1-升序"
  126. },
  127. {
  128. "n": "降序",
  129. "v": "1-降序"
  130. }
  131. ]
  132. },
  133. {
  134. "key": "sorts",
  135. "name": "点赞数量",
  136. "value": [
  137. {
  138. "n": "升序",
  139. "v": "5-升序"
  140. },
  141. {
  142. "n": "降序",
  143. "v": "5-降序"
  144. }
  145. ]
  146. },
  147. {
  148. "key": "sorts",
  149. "name": "收藏数量",
  150. "value": [
  151. {
  152. "n": "升序",
  153. "v": "6-升序"
  154. },
  155. {
  156. "n": "降序",
  157. "v": "6-降序"
  158. }
  159. ]
  160. }
  161. ]
  162. return [...extend_list, ...sort_list]
  163. }
  164. async getZhuanTiFilter(Layouts) {
  165. let extend_list = []
  166. let params = {
  167. "page": 1,
  168. "length": 36,
  169. "subjectIds": []
  170. }
  171. for (let i = 0; i < Layouts.length; i++) {
  172. let data = Layouts[i]
  173. let layoutObj = JSON.parse(data["layoutContent"])
  174. params["subjectIds"] = layoutObj["list"]
  175. let resJson = JSON.parse(await this.post(this.siteUrl + "/subject/list", this.getParams(params), this.getHeader(), ""))
  176. let extend_dic = {"key": `tags`, "name": data["layoutName"], value: []}
  177. for (const layout of resJson["data"]["list"]) {
  178. extend_dic["value"].push({"n": layout["name"], "v": JSON.stringify(layout)})
  179. }
  180. extend_list.push(extend_dic)
  181. }
  182. let sort_dic = {
  183. "key": "sorts",
  184. "name": "排序",
  185. "value": [
  186. {
  187. "n": "推荐",
  188. "v": "8"
  189. },
  190. {
  191. "n": "最新",
  192. "v": "1"
  193. },
  194. {
  195. "n": "最热",
  196. "v": "2"
  197. }
  198. ]
  199. }
  200. extend_list.push(sort_dic)
  201. return extend_list
  202. }
  203. async getChuanMeiFilter(Layouts) {
  204. let extend_list = []
  205. let extend_dic = {"key": `tags`, "name": "传媒", value: []}
  206. for (let i = 0; i < Layouts.length; i++) {
  207. let data = Layouts[i]
  208. extend_dic["value"].push({"n": data["layoutName"], "v": data["layoutContent"]})
  209. }
  210. extend_list.push(extend_dic)
  211. for (const layout of JSON.parse(Layouts[0]["layoutContent"])["moreOrderType"]) {
  212. extend_dic = {"key": "sorts", "name": layout["label"].toString(), value: []}
  213. extend_dic["value"].push({"n": "升序", "v": layout["value"].toString() + "-" + "升序"})
  214. extend_dic["value"].push({"n": "降序", "v": layout["value"].toString() + "-" + "降序"})
  215. extend_list.push(extend_dic)
  216. }
  217. extend_list.push(extend_dic)
  218. return extend_list
  219. }
  220. async getHeJiFilter(Layouts) {
  221. let extend_list = []
  222. let params = {
  223. "page": 1,
  224. "length": 24,
  225. "gatherType": 1,
  226. "gatherIds": []
  227. }
  228. let extend_dic = {"key": `tags`, "name": "合集", value: []}
  229. let resJson = JSON.parse(await this.post(this.siteUrl + "/gather/getList", this.getParams(params), this.getHeader(), ""))
  230. for (const data of resJson["data"]["list"]) {
  231. extend_dic["value"].push({"n": data["name"], "v": data["gatherId"].toString()})
  232. }
  233. extend_list.push(extend_dic)
  234. return extend_list
  235. }
  236. async setFilterObj() {
  237. for (let i = 0; i < this.classes.length; i++) {
  238. let type_dic = this.classes[i]
  239. let type_id = type_dic["type_id"]
  240. let type_name = type_dic["type_name"]
  241. let filterList = []
  242. if (type_id !== "最近更新") {
  243. type_id = parseInt(type_id)
  244. let params = this.getParams({"panelId": type_id})
  245. let response = await this.post(this.siteUrl + "/panel/get", params, this.getHeader(), "")
  246. let resJson = JSON.parse(response)
  247. let layoutList = resJson["data"]["info"]["Layouts"]
  248. let layOutObj = JSON.parse(resJson["data"]["info"]["Layouts"][0]["layoutContent"])
  249. if (type_id > 174 && type_id < 181) {
  250. let layOutObj = JSON.parse(resJson["data"]["info"]["Layouts"][0]["layoutContent"])
  251. type_id = type_id + "$" + JSON.stringify(layOutObj)
  252. filterList = await this.getFilter(layoutList)
  253. } else {
  254. switch (type_id) {
  255. case 172:
  256. filterList = await this.getHeJiFilter(layoutList)
  257. type_id = type_id + "$" + filterList[0]["value"][0]["v"]
  258. break
  259. case 173:
  260. filterList = await this.getChuanMeiFilter(layoutList)
  261. type_id = type_id + "$" + JSON.stringify(layOutObj)
  262. break
  263. case 182:
  264. filterList = await this.getNvYouFilter(layoutList)
  265. type_id = type_id + "$" + filterList[0]["value"][0]["v"]
  266. break
  267. case 209:
  268. filterList = await this.getZhuanTiFilter(layoutList)
  269. type_id = type_id + "$" + filterList[0]["value"][0]["v"]
  270. break
  271. default:
  272. break
  273. }
  274. }
  275. this.classes[i] = this.getTypeDic(type_name, type_id)
  276. this.filterObj[type_id] = filterList
  277. }
  278. }
  279. }
  280. async parseVodShortListFromJson(obj) {
  281. let vod_list = []
  282. for (const data of obj) {
  283. let vodShort = new VodShort()
  284. vodShort.vod_id = data["id"]
  285. vodShort.vod_name = data["name"]
  286. vodShort.vod_pic = this.jsBase + Utils.base64Encode(data["coverImgUrl"])
  287. if (data["hot"] === undefined) {
  288. vodShort.vod_remarks = "观看:" + (data["seeCount"] / 10000).toFixed(1).toString() + "W"
  289. } else {
  290. vodShort.vod_remarks = "热度:" + (data["hot"] / 1000).toFixed(1).toString() + "K"
  291. }
  292. vod_list.push(vodShort)
  293. }
  294. return vod_list
  295. }
  296. async parseVodShortListFromGatherJson(obj) {
  297. let vod_list = []
  298. for (const data of obj) {
  299. let vodShort = new VodShort()
  300. vodShort.vod_id = data["gatherId"]
  301. vodShort.vod_name = data["name"]
  302. vodShort.vod_pic = this.jsBase + Utils.base64Encode(data["coverImgUrl"])
  303. vod_list.push(vodShort)
  304. }
  305. return vod_list
  306. }
  307. async parseVodDetailFromDoc(detailObj) {
  308. let vodDetail = new VodDetail()
  309. vodDetail.vod_name = detailObj["name"]
  310. vodDetail.vod_year = detailObj["addTime"]
  311. vodDetail.vod_pic = this.jsBase + Utils.base64Encode(detailObj["coverImgUrl"])
  312. vodDetail.type_name = detailObj["typeName"]
  313. vodDetail.vod_content = detailObj["tags"]
  314. let vodItems = []
  315. let params = {
  316. "videoId": detailObj["id"]
  317. }
  318. let resJson = JSON.parse(await this.post(this.siteUrl + "/videos/getPreUrl", this.getParams(params), this.getHeader(), ""))
  319. let playList = resJson["data"]["url"].split("?")
  320. let playUrl = playList[0] + "?sign" + playList[1].split("&sign").slice(-1)[0]
  321. vodItems.push(vodDetail.vod_name + "$" + playUrl)
  322. let playObj = {"线路1": vodItems.join("#")}
  323. vodDetail.vod_play_url = _.values(playObj).join('$$$');
  324. vodDetail.vod_play_from = _.keys(playObj).join('$$$');
  325. return vodDetail
  326. }
  327. async getHomeVod(params) {
  328. let params_str = this.getParams(params)
  329. let response = await this.post(this.siteUrl + "/videos/getList", params_str, this.getHeader(), "")
  330. return await this.parseVodShortListFromJson(JSON.parse(response)["data"]["list"])
  331. }
  332. async setHomeVod() {
  333. let vod_list1 = await this.getHomeVod({
  334. "page": 1,
  335. "length": 16,
  336. "offset": 0,
  337. "typeIds": [],
  338. "orderType": 1,
  339. "payType": [3, 4]
  340. })
  341. let vod_list2 = await this.getHomeVod({
  342. "page": 1,
  343. "length": 16,
  344. "offset": 0,
  345. "typeIds": [],
  346. "orderType": 3,
  347. "payType": [
  348. 1
  349. ]
  350. })
  351. let vod_list3 = await this.getHomeVod({
  352. "page": 1,
  353. "length": 32,
  354. "offset": 0,
  355. "typeIds": [],
  356. "orderType": 1,
  357. "payType": [
  358. 3
  359. ]
  360. })
  361. this.homeVodList = [...vod_list1, ...vod_list2, ...vod_list3];
  362. }
  363. getSortParams(params, extend) {
  364. let orderTypeStr = extend["sorts"] ?? ""
  365. if (!_.isEmpty(orderTypeStr)) {
  366. let orderType = orderTypeStr.split("-")[0]
  367. params["orderType"] = parseInt(orderType)
  368. let orderModeStr = orderTypeStr.split("-")[1]
  369. let orderMode = 0
  370. if (orderModeStr === "升序") {
  371. orderMode = "1"
  372. } else {
  373. orderMode = "0"
  374. }
  375. params["orderMode"] = parseInt(orderMode)
  376. }
  377. return params
  378. }
  379. getTopParams(type_id, layOutObj, pg, extend) {
  380. let defaultOderType
  381. if (type_id === 180) {
  382. defaultOderType = "1"
  383. } else {
  384. defaultOderType = "7"
  385. }
  386. let orderMode = "1"
  387. let orderType
  388. let orderTypeStr = extend["sorts"] ?? defaultOderType
  389. let isOrderModel = false
  390. if (orderTypeStr.indexOf("-") > -1) {
  391. orderType = orderTypeStr.split("-")[0]
  392. let orderModeStr = orderTypeStr.split("-")[1]
  393. if (orderModeStr === "升序") {
  394. orderMode = "1"
  395. } else {
  396. orderMode = "0"
  397. }
  398. isOrderModel = true
  399. } else {
  400. orderType = defaultOderType
  401. }
  402. let params = {
  403. "orderType": parseInt(orderType), //或者7
  404. "tags": [],
  405. "length": 11,
  406. "page": parseInt(pg),
  407. "typeIds": layOutObj["classs"],
  408. "payType": layOutObj["payType"],
  409. }
  410. if (isOrderModel) {
  411. params["orderMode"] = parseInt(orderMode)
  412. }
  413. return params
  414. }
  415. getChuanMeiParams(layOutObj, pg, extend) {
  416. let obj
  417. if (!_.isEmpty(extend["tags"])) {
  418. obj = JSON.parse(extend["tags"])
  419. } else {
  420. obj = layOutObj
  421. }
  422. let params = {
  423. "page": parseInt(pg),
  424. "length": 32,
  425. "offset": 32 * parseInt(pg - 1),
  426. "tag": obj["videoLables"].join(","),
  427. "typeIds": obj["classs"],
  428. "orderType": obj["orderType"],
  429. "payType": obj["payType"]
  430. }
  431. params = this.getSortParams(params, extend)
  432. return params
  433. }
  434. getNvYouParams(layoutObj, pg, extend) {
  435. let obj
  436. if (!_.isEmpty(extend["tags"])) {
  437. obj = JSON.parse(extend["tags"])
  438. } else {
  439. obj = layoutObj
  440. }
  441. let params = {"videoSort": 1, "touid": obj["id"], "page": parseInt(pg), "length": 12, "orderType": 1}
  442. params = this.getSortParams(params, extend)
  443. return params
  444. }
  445. getZhuantiParams(layoutObj, pg, extend) {
  446. let obj
  447. if (!_.isEmpty(extend["tags"])) {
  448. obj = JSON.parse(extend["tags"])
  449. } else {
  450. obj = layoutObj
  451. }
  452. let orderType = extend["sorts"] ?? "8"
  453. return {
  454. "page": parseInt(pg),
  455. "length": 12,
  456. "offset": 12 * (parseInt(pg) - 1),
  457. "orderType": parseInt(orderType),
  458. "subjectId": obj["id"]
  459. }
  460. }
  461. async setCategory(tid, pg, filter, extend) {
  462. let tid_list = tid.split("$")
  463. let type_id = parseInt(tid_list[0])
  464. let layOutObj = JSON.parse(tid_list[1])
  465. let params = {}
  466. let url = "/videos/getList"
  467. if (type_id > 174 && type_id < 181) {
  468. params = this.getTopParams(type_id, layOutObj, pg, extend)
  469. } else {
  470. switch (type_id) {
  471. case 173:
  472. params = this.getChuanMeiParams(layOutObj, pg, extend)
  473. break
  474. case 182:
  475. params = this.getNvYouParams(layOutObj, pg, extend)
  476. url = "/user/getSpaceVideo"
  477. break
  478. case 209:
  479. params = this.getZhuantiParams(layOutObj, pg, extend)
  480. break
  481. case 172:
  482. let gatherId = extend["tags"] ?? layOutObj
  483. params = {
  484. "gatherId": parseInt(gatherId)
  485. }
  486. url = "/gather/getDetail"
  487. break
  488. default:
  489. break
  490. }
  491. }
  492. let resJson = JSON.parse(await this.post(this.siteUrl + url, this.getParams(params), this.getHeader(), ""))
  493. if (type_id === 172) {
  494. this.vodList = await this.parseVodShortListFromJson(resJson["data"]["info"]["videos"])
  495. } else {
  496. this.vodList = await this.parseVodShortListFromJson(resJson["data"]["list"])
  497. }
  498. }
  499. async setDetail(id) {
  500. let params = {
  501. "videoId": parseInt(id),
  502. "videoSort": 1
  503. }
  504. let resJson = JSON.parse(await this.post(this.siteUrl + "/videos/getInfo", this.getParams(params), this.getHeader(), ""))
  505. this.vodDetail = await this.parseVodDetailFromDoc(resJson["data"]["info"])
  506. }
  507. async proxy(segments, headers) {
  508. let what = segments[0];
  509. let url = Utils.base64Decode(segments[1]);
  510. if (what === 'imgBt') {
  511. let response = await req(url, {buffer: 0});
  512. return JSON.stringify({
  513. code: 200,
  514. buffer: 2,
  515. content: bt(response.content).replaceAll("data:image/jpeg;base64,", "").replaceAll("data:image/jpg;base64,", "").replaceAll("data:image/png;base64", ""),
  516. headers: headers,
  517. });
  518. }
  519. }
  520. async setSearch(wd, quick, pg) {
  521. let params = {
  522. "page": parseInt(pg),
  523. "length": 12,
  524. "type": 1,
  525. "key": wd
  526. }
  527. let resJson = JSON.parse(await this.post(this.siteUrl + "/base/globalSearch", this.getParams(params), this.getHeader(), ""))
  528. this.vodList = await this.parseVodShortListFromJson(resJson["data"]["infos"])
  529. this.result.setPage(parseInt(pg), resJson["data"]["count"] / 12, 12, resJson["data"]["count"])
  530. }
  531. }
  532. let spider = new HanXiuCaoSpider()
  533. async function init(cfg) {
  534. await spider.init(cfg)
  535. }
  536. async function home(filter) {
  537. return await spider.home(filter)
  538. }
  539. async function homeVod() {
  540. return await spider.homeVod()
  541. }
  542. async function category(tid, pg, filter, extend) {
  543. return await spider.category(tid, pg, filter, extend)
  544. }
  545. async function detail(id) {
  546. return await spider.detail(id)
  547. }
  548. async function play(flag, id, flags) {
  549. return await spider.play(flag, id, flags)
  550. }
  551. async function search(wd, quick) {
  552. return await spider.search(wd, quick)
  553. }
  554. async function proxy(segments, headers) {
  555. return await spider.proxy(segments, headers)
  556. }
  557. export function __jsEvalReturn() {
  558. return {
  559. init: init,
  560. home: home,
  561. homeVod: homeVod,
  562. category: category,
  563. detail: detail,
  564. play: play,
  565. search: search,
  566. proxy: proxy
  567. };
  568. }
  569. export {spider, bt}