hitv.user.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. // ==UserScript==
  2. // @name hitv
  3. // @namespace gmspider
  4. // @version 2024.11.12
  5. // @description Hi视频 GMSpider
  6. // @author Luomo
  7. // @match https://www.upfuhn.com/*
  8. // @require https://cdn.jsdelivr.net/gh/CatVodSpider-GM/Spiders-Lib@main/lib/browser-extension-url-match-1.2.0.min.js
  9. // @require https://cdn.jsdelivr.net/gh/CatVodSpider-GM/SFW-Spiders@main/Spiders-Lib/ajaxHooker-1.4.3.js
  10. // @grant GM_setValue
  11. // @grant GM_getValue
  12. // @grant unsafeWindow
  13. // @run-at document-start
  14. // ==/UserScript==
  15. console.log(JSON.stringify(GM_info));
  16. (function () {
  17. const GMSpiderArgs = {};
  18. if (typeof GmSpiderInject !== 'undefined') {
  19. let args = JSON.parse(GmSpiderInject.GetSpiderArgs());
  20. GMSpiderArgs.fName = args.shift();
  21. GMSpiderArgs.fArgs = args;
  22. } else {
  23. GMSpiderArgs.fName = "searchContent";
  24. GMSpiderArgs.fArgs = [true];
  25. // GMSpiderArgs.fName = "categoryContent";
  26. // GMSpiderArgs.fArgs = ["82", 2, true, {tag: "动作", y: "2024", o: "1", a: "大陆"}];
  27. }
  28. Object.freeze(GMSpiderArgs);
  29. let hookConfigs = {
  30. "homeContent": [{
  31. matcher: matchPattern("https://*/v1/report_channel_data").assertValid(),
  32. onResponseHook: function (response) {
  33. Array.from(document.querySelectorAll(".left-wrap .tab-box:nth-child(2) .swiper-slide span"))
  34. .find(el => el.textContent === "全部").dispatchEvent(new Event("click"));
  35. }
  36. }, {
  37. dataKey: "ys_video_sites", matcher: matchPattern("https://*/v1/ys_video_sites?*").assertValid()
  38. }], "categoryContent": [{
  39. matcher: matchPattern("https://*/v1/report_channel_data").assertValid(),
  40. onResponseHook: function (response) {
  41. const extend = GMSpiderArgs.fArgs[3];
  42. let tag = extend?.tag ?? "全部"
  43. Array.from(document.querySelectorAll(".left-wrap .tab-box:nth-child(2) .swiper-slide span"))
  44. .find(el => el.textContent === tag).dispatchEvent(new Event("click"));
  45. }
  46. }, {
  47. dataKey: "ys_video_sites",
  48. matcher: matchPattern("https://*/v1/ys_video_sites?*").assertValid(),
  49. onRequestHook: function (response) {
  50. const page = GMSpiderArgs.fArgs[1];
  51. const filter = GMSpiderArgs.fArgs[2];
  52. const extend = GMSpiderArgs.fArgs[3];
  53. const url = new URL(response.url);
  54. const params = new URLSearchParams(url.search);
  55. params.set("pn", page)
  56. if (filter) {
  57. params.set("a", extend?.a ?? "");
  58. params.set("y", extend?.y ?? "");
  59. params.set("o", extend?.o ?? 0);
  60. }
  61. url.search = params.toString();
  62. response.url = url.toString();
  63. }
  64. }],
  65. "detailContent": [{
  66. dataKey: "meta", matcher: matchPattern("https://*/v1/report_channel_data").assertValid()
  67. }],
  68. "searchContent": [{
  69. dataKey: "meta", matcher: matchPattern("https://*/v1/report_channel_data").assertValid()
  70. }],
  71. };
  72. const GmSpider = (function () {
  73. const categoryFilterCachePrefix = "category_";
  74. const filterTag = {
  75. key: "tag", name: "分类", value: []
  76. };
  77. const filterArea = {
  78. key: "o", name: "地区", value: []
  79. };
  80. const filterYear = {
  81. key: "y", name: "年份", value: []
  82. };
  83. const filterSort = {
  84. key: "o",
  85. name: "排序",
  86. value: [{n: "综合", v: "0"}, {n: "最新", v: "2"}, {n: "最热", v: "1"}, {n: "评分", v: "5"},]
  87. };
  88. return {
  89. homeContent: function (filter) {
  90. let result = {
  91. class: [{type_id: "85", type_name: "短剧"}, {type_id: "81", type_name: "电影"}, {
  92. type_id: "82",
  93. type_name: "电视剧"
  94. }, {type_id: "83", type_name: "综艺"}, {type_id: "84", type_name: "动漫"},], filters: {}, list: []
  95. };
  96. document.querySelectorAll(".left-wrap .tab-box:nth-child(3) .swiper-slide span").forEach((filter) => {
  97. filterArea.value.push({
  98. n: filter.textContent, v: filter.textContent,
  99. })
  100. });
  101. document.querySelectorAll(".left-wrap .tab-box:nth-child(4) .swiper-slide span").forEach((filter) => {
  102. filterYear.value.push({
  103. n: filter.textContent, v: filter.textContent,
  104. })
  105. });
  106. result.class.forEach((category) => {
  107. const categoryFilter = [];
  108. const cacheFilter = localStorage.getItem(categoryFilterCachePrefix + category.type_id);
  109. if (typeof cacheFilter !== "undefined" && cacheFilter !== null) {
  110. categoryFilter.push(JSON.parse(cacheFilter));
  111. }
  112. categoryFilter.push(filterArea, filterYear, filterSort);
  113. result.filters[category.type_id] = categoryFilter;
  114. })
  115. hookResult.ys_video_sites.data.data.forEach((media) => {
  116. result.list.push({
  117. vod_id: media.video_site_id,
  118. vod_name: media.video_name,
  119. vod_pic: media.video_vertical_url,
  120. vod_remarks: "评分:" + media.score,
  121. vod_year: media.years
  122. })
  123. });
  124. return result;
  125. }, categoryContent: function (tid, pg, filter, extend) {
  126. let result = {
  127. list: [], pagecount: Math.ceil(hookResult.ys_video_sites.data.total / 21)
  128. };
  129. document.querySelectorAll(".left-wrap .tab-box:nth-child(2) .swiper-slide span").forEach((filter) => {
  130. filterTag.value.push({
  131. n: filter.textContent, v: filter.textContent,
  132. })
  133. });
  134. localStorage.setItem(categoryFilterCachePrefix + tid, JSON.stringify(filterTag));
  135. hookResult.ys_video_sites.data.data.forEach((media) => {
  136. result.list.push({
  137. vod_id: media.video_site_id,
  138. vod_name: media.video_name,
  139. vod_pic: media.video_vertical_url,
  140. vod_remarks: "评分:" + media.score,
  141. vod_year: media.years
  142. })
  143. })
  144. return result;
  145. }, detailContent: function (ids) {
  146. let playUrl = [];
  147. let vod = {};
  148. const formatData = JSON.parse(document.getElementById("__NUXT_DATA__").innerHTML);
  149. formatData.forEach((data) => {
  150. if (typeof (vod?.vod_id) == "undefined" && typeof (data?.video_desc) === "number") {
  151. vod = {
  152. vod_id: formatData[data.video_site_id],
  153. vod_name: formatData[data.video_name],
  154. vod_content: formatData[data.video_desc],
  155. vod_year: formatData[data.years],
  156. vod_area: formatData[data.area],
  157. vod_actor: formatData[data.main_actor],
  158. type_name: formatData[data.tag],
  159. vod_play_data: [{
  160. from: "Hi视频",
  161. media: playUrl
  162. }]
  163. };
  164. }
  165. if (typeof (data?.series_num) === "number") {
  166. playUrl.push({
  167. name: formatData[data.series_num],
  168. type: "finalUrl",
  169. ext: {
  170. header: {
  171. "User-Agent": window.navigator.userAgent,
  172. "Referer": window.location.href
  173. },
  174. url: formatData[data.video_url]
  175. }
  176. })
  177. }
  178. })
  179. return vod;
  180. }, searchContent: function (key, quick, pg) {
  181. const result = {
  182. list: [],
  183. page: pg,
  184. pagecount: 1
  185. };
  186. const formatData = JSON.parse(document.getElementById("__NUXT_DATA__").innerHTML);
  187. console.log(formatData);
  188. formatData.forEach((data) => {
  189. if (typeof (data?.first_video_series) === "number") {
  190. let firstVideo = formatData[data.first_video_series];
  191. result.list.push({
  192. vod_id: formatData[firstVideo.video_site_id],
  193. vod_name: formatData[firstVideo.video_name],
  194. vod_pic: formatData[firstVideo.video_vertical_url],
  195. vod_remarks: formatData[firstVideo.tag],
  196. vod_year: formatData[firstVideo.years]
  197. })
  198. formatData[data.video_sites].forEach((videoIndex) => {
  199. let video = formatData[videoIndex];
  200. result.list.push({
  201. vod_id: formatData[video.video_site_id],
  202. vod_name: formatData[video.video_name],
  203. vod_pic: formatData[video.video_vertical_url],
  204. vod_remarks: formatData[video.tag],
  205. vod_year: formatData[video.years]
  206. })
  207. })
  208. }
  209. })
  210. return result;
  211. }
  212. };
  213. })();
  214. let spiderExecuted = false;
  215. let dataReadyCount = 0;
  216. let hookResult = {};
  217. ajaxHooker.hook(request => {
  218. hookConfigs[GMSpiderArgs.fName].forEach((hookConfig) => {
  219. if (typeof hookConfig.onRequestHook === "function" && hookConfig.matcher.match(request.url)) {
  220. hookConfig.onRequestHook(request);
  221. }
  222. });
  223. if (!spiderExecuted) {
  224. let dataTodoCount = 0;
  225. hookConfigs[GMSpiderArgs.fName].forEach((hookConfig) => {
  226. if (typeof hookConfig.dataKey !== "undefined") {
  227. if (hookConfig?.require !== false) {
  228. dataTodoCount++;
  229. }
  230. }
  231. if (hookConfig.matcher.match(request.url)) {
  232. request.response = res => {
  233. if (typeof hookConfig.onResponseHook === "function") {
  234. hookConfig.onResponseHook(res);
  235. }
  236. if (typeof hookConfig.dataKey !== "undefined") {
  237. if (hookConfig?.require !== false) {
  238. dataReadyCount++;
  239. }
  240. let data = JSON.parse(res.text);
  241. if (typeof data === 'object' && data) {
  242. hookResult[hookConfig.dataKey] = data;
  243. } else {
  244. hookResult[hookConfig.dataKey] = res.text;
  245. }
  246. if (dataTodoCount === dataReadyCount) {
  247. spiderExecuted = true;
  248. const result = GmSpider[GMSpiderArgs.fName](...GMSpiderArgs.fArgs);
  249. console.log(result);
  250. if (typeof GmSpiderInject !== 'undefined' && spiderExecuted) {
  251. GmSpiderInject.SetSpiderResult(JSON.stringify(result));
  252. }
  253. }
  254. }
  255. };
  256. }
  257. });
  258. }
  259. });
  260. })();