Greasy Fork is available in English.

淘呀号解析(苹果版)

该脚本仅支持苹果设备,安卓和电脑设备请安装主版本。

  1. // ==UserScript==
  2. // @name 淘呀号解析(苹果版)
  3. // @namespace http://gv1069.vip/
  4. // @version 2.2
  5. // @description 该脚本仅支持苹果设备,安卓和电脑设备请安装主版本。
  6. // @author 淘呀号团队
  7. // @match *://*/*
  8. // @grant GM.xmlHttpRequest
  9. // @grant GM.addStyle
  10. // @grant GM_setValue
  11. // @grant GM_getValue
  12. // @connect api.gv1069.vip
  13. // @exclude http://gv1069.vip/*
  14. // @exclude https://www.yuque.com/*
  15. // @exclude https://yuque.com/*
  16. // @exclude http://www.gv1069.vip/*
  17. // @exclude https://m3u8play.com/*
  18. // @exclude https://www.m3u8play.com/*
  19. // @exclude https://greasyfork.org/*
  20. // @exclude https://www.greasyfork.org/*
  21. // @license MIT
  22. // ==/UserScript==
  23. (function () {
  24. 'use strict';
  25. // 定义登录 API 地址
  26. var yitongkanBase = "http://api.gv1069.vip";
  27. var value = "450";
  28. var valueGao = "900";
  29. var valueChao = "1800";
  30. var valueJiu = "400";
  31. var m3u8Url = "";
  32. // 在页面加载时创建登录弹框
  33. window.addEventListener('load', function () {
  34. // 添加样式
  35. GM.addStyle(`
  36. #gm-loading-overlay {
  37. position: fixed;
  38. top: 0;
  39. left: 0;
  40. width: 100%;
  41. height: 100%;
  42. background-color: rgba(255, 255, 255, 0.8);
  43. display: none;
  44. z-index: -1;
  45. display: flex;
  46. justify-content: center;
  47. align-items: center;
  48. }
  49. #gm-loading-overlay div {
  50. font-size: 20px;
  51. }
  52. #customLoginModal {
  53. display: none;
  54. position: fixed;
  55. top: 0;
  56. left: 0;
  57. width: 100%;
  58. height: 100%;
  59. background: rgba(0, 0, 0, 0.5);
  60. justify-content: center;
  61. align-items: center;
  62. z-index: 1000;
  63. }
  64. #loginBox {
  65. background: #fff;
  66. padding: 20px;
  67. border-radius: 8px;
  68. box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
  69. text-align: center;
  70. }
  71. #loginBox h2 {
  72. color: #333;
  73. }
  74. `);
  75. // 创建加载中的遮罩层
  76. const loadingOverlay = document.createElement('div');
  77. loadingOverlay.id = 'gm-loading-overlay';
  78. loadingOverlay.innerHTML = '<div>正在解析一同看资源,请稍后...</div>';
  79. document.body.appendChild(loadingOverlay);
  80. const logoutButton = document.createElement('button');
  81. logoutButton.innerText = '日租号专用退出登录按钮(切换账户时请点我)';
  82. logoutButton.style.margin = '30px 50px'; // 调整按钮与div的间距
  83. logoutButton.style.height = '70px';
  84. logoutButton.style.width = '300px';
  85. logoutButton.style.cursor = 'pointer';
  86. logoutButton.addEventListener('click', logout);
  87. // 寻找具有id为homeso的div
  88. const homesoDiv = document.getElementById('homeso');
  89. // 将按钮插入到div下方
  90. if (homesoDiv) {
  91. homesoDiv.appendChild(logoutButton);
  92. } else {
  93. console.warn('找不到具有id为homeso的div。');
  94. }
  95. // 处理退出登录的逻辑,根据实际情况修改
  96. function logout() {
  97. GM_setValue("YTToken", "");
  98. GM_setValue('username', "");
  99. GM_setValue('password', "");
  100. // 刷新页面或跳转到登录页
  101. location.reload();
  102. }
  103. // 显示加载中
  104. function showLoading() {
  105. loadingOverlay.style.display = 'flex';
  106. loadingOverlay.style.zIndex = 9999;
  107. }
  108. // 隐藏加载中
  109. function hideLoading() {
  110. loadingOverlay.style.display = 'none';
  111. loadingOverlay.style.zIndex = -1;
  112. }
  113. // Create a modal container
  114. const modalContainer = document.createElement('div');
  115. modalContainer.id = 'customLoginModal';
  116. modalContainer.style.display = 'none';
  117. document.body.appendChild(modalContainer);
  118. // Create the login box
  119. const loginBox = document.createElement('div');
  120. loginBox.id = 'loginBox';
  121. loginBox.innerHTML = `
  122. <h2>日租号专用登录通道</h2>
  123. <h3 style="margin-top:5px;color:red;">(请勿在一同看的登录框登录!!!不要手输账户名密码!!!)</h3>
  124. <h4 style="margin-top:5px;color:red;">(请通过租号网址提供的蓝色复制按钮复制账户名密码并且确保只装了一个解析脚本,否则会一直提示登录)</h4>
  125. <h4 style="margin-top:5px;color:red;">(如果忘记,请前往gv1069.vip的综合服务窗口找回)</h4>
  126. <form style="margin-top:20px;">
  127. <label for="username">用户名:</label>
  128. <input type="text" id="username" name="username" required><br>
  129. <label for="password" style="margin-top:10px;">密码:</label>
  130. <input type="password" id="password" name="password" required><br>
  131. <button id="submitBtn" style="margin-top:10px;">登录</button>
  132. </form>
  133. `;
  134. // Create close button
  135. const closeButton = document.createElement('span');
  136. closeButton.id = 'closeButton';
  137. closeButton.innerHTML = '&times;';
  138. closeButton.style.position = 'relative';
  139. closeButton.style.top = '10px';
  140. closeButton.style.right = '10px';
  141. closeButton.style.cursor = 'pointer';
  142. closeButton.style.fontSize = '50px';
  143. closeButton.style.color = '#000';
  144. // Append close button to login box
  145. loginBox.appendChild(closeButton);
  146. modalContainer.appendChild(loginBox);
  147. // Add click event to close button
  148. closeButton.addEventListener('click', function () {
  149. modalContainer.style.display = 'none';
  150. });
  151. // Show the login box
  152. function openLoginBox() {
  153. modalContainer.style.display = 'flex';
  154. }
  155. // Close the login box
  156. function closeLoginBox() {
  157. modalContainer.style.display = 'none';
  158. }
  159. var token = GM_getValue("YTToken");
  160. var username = GM_getValue("username");
  161. var password = GM_getValue("password");
  162. // 查找具有指定 class 的所有 UL 标签
  163. var ulElements = document.querySelectorAll('ul.list.g-clear');
  164. if (ulElements) {
  165. // 创建加载中的遮罩层
  166. const loadingOverlay = document.createElement('div');
  167. loadingOverlay.id = 'gm-loading-overlay';
  168. loadingOverlay.innerHTML = '<div>正在解析一同看资源,请稍后...</div>';
  169. document.body.appendChild(loadingOverlay);
  170. if (token == null || token == "") {
  171. showLoginPrompt();
  172. }
  173. }
  174. // 遍历每个 UL 元素
  175. ulElements.forEach(function (ulElement) {
  176. // 遍历 UL 元素中的每个 LI 元素
  177. ulElement.querySelectorAll('li').forEach(function (liElement, index) {
  178. // 查找 LI 元素中的 A 标签
  179. var aElement = liElement.querySelector('a');
  180. // 在 LI 元素上增加高度
  181. liElement.style.height = 600 + 'px';
  182. // 创建播放按钮
  183. var playButton1 = document.createElement('button');
  184. playButton1.innerText = '点我播放(请勿点击上方图片文字)';
  185. playButton1.style.height = '70px'; // 50px 是你想要设置的高度
  186. // 创建播放按钮
  187. var playButton5 = document.createElement('button');
  188. playButton5.innerText = '标清视频下载';
  189. playButton5.style.height = '35px'; // 50px 是你想要设置的高度
  190. playButton5.style.marginTop = '10px';
  191. // 创建播放按钮
  192. var playButton6 = document.createElement('button');
  193. playButton6.innerText = '标清视频下载(仅针对早期视频)';
  194. playButton6.style.height = '35px'; // 50px 是你想要设置的高度
  195. playButton6.style.marginTop = '10px';
  196. // 创建播放按钮
  197. var playButton7 = document.createElement('button');
  198. playButton7.innerText = '高清视频下载';
  199. playButton7.style.height = '35px'; // 50px 是你想要设置的高度
  200. playButton7.style.marginTop = '10px';
  201. // 创建播放按钮
  202. var playButton8 = document.createElement('button');
  203. playButton8.innerText = '超清视频下载';
  204. playButton8.style.height = '35px'; // 50px 是你想要设置的高度
  205. playButton8.style.marginTop = '10px';
  206. // 添加点击事件监听器(默认标清播放)
  207. playButton1.addEventListener('click', function (event) {
  208. showLoading(); // 显示加载中
  209. if (token == null || token == "") {
  210. var result = confirm("您未登录,请在日租号专用登录通道进行登录!请勿在一同看官方界面登录!点击“确定”按钮前往专用登录通道!");
  211. if (result) {
  212. window.location.reload();
  213. }
  214. hideLoading(); // 隐藏加载中
  215. } else {
  216. hideLoading(); // 隐藏加载中
  217. const tempPage = window.open('loading page');
  218. tempPage.addEventListener('load', function() {
  219. // 重定向到目标页面
  220. GM.xmlHttpRequest({
  221. method: 'GET',
  222. url: yitongkanBase+"/yitong/get-video-page?video_link=" + aElement.href +"&token=" + token,
  223. onload: function(response) {
  224. const data=JSON.parse(response.responseText)
  225. if (data.success && data.content != null && data.content != "") {
  226. let strings = data.content.match(/(url: ')[^\\s]+/g)
  227. let m3u8Url = strings[0].split("'")[1]
  228. GM.xmlHttpRequest({
  229. method: 'GET',
  230. url: yitongkanBase+"/yitong/update-fresh-code?expire_time=" + m3u8Url.split("/")[1] + "&fresh_flag=" + m3u8Url.split("/")[2],
  231. onload: function(response) {
  232. }
  233. });
  234. let updatedString = data.content
  235. .replace('document.body.appendChild(dom);', '')
  236. // 替换当前页面的内容
  237. tempPage.document.open();
  238. tempPage.document.write(updatedString);
  239. tempPage.document.close();
  240. }else if (data.message == "2") {
  241. GM_setValue("YTToken", "");
  242. GM_setValue('username', "");
  243. GM_setValue('password', "");
  244. var result = confirm("该账户已过期,请您重新购买或者取号!点击“确定”按钮自动跳转至购买界面!");
  245. if (result) {
  246. window.location.href = "http://gv1069.vip/#/shop-account";
  247. }
  248.  
  249. } else if (data.message == "3") {
  250. GM_setValue("YTToken", "");
  251. GM_setValue('username', "");
  252. GM_setValue('password', "");
  253. var result = confirm("请您重新登录!");
  254. if (result) {
  255. window.location.reload();
  256. }
  257. } else if (data.message == "4" || data.message == "5") {
  258. GM_setValue("YTToken", "");
  259. GM_setValue('username', "");
  260. GM_setValue('password', "");
  261. var result = confirm("请您重新登录!");
  262. if (result) {
  263. window.location.reload();
  264. }
  265.  
  266. } else if (data.message == "6") {
  267. GM_setValue("YTToken", "");
  268. GM_setValue('username', "");
  269. GM_setValue('password', "");
  270. var result = confirm("您的账号在另一台设备上登录,请重新登录");
  271. if (result) {
  272. window.location.reload();
  273. }
  274. } else {
  275. alert('解析失败,请点击播放按钮重试!');
  276. }
  277. }
  278. });
  279. });
  280. }
  281. });
  282. // 添加点击事件监听器(默认标清视频下载)
  283. playButton5.addEventListener('click', function (event) {
  284. alert("由于系统限制,苹果设备不支持下载,请前往安卓端和电脑端进行下载!");
  285. });
  286. // 添加点击事件监听器(早期标清视频下载)
  287. playButton6.addEventListener('click', function (event) {
  288. alert("由于系统限制,苹果设备不支持下载,请前往安卓端和电脑端进行下载!");
  289. });
  290. // 添加点击事件监听器(高清视频下载)
  291. playButton7.addEventListener('click', function (event) {
  292. alert("由于系统限制,苹果设备不支持下载,请前往安卓端和电脑端进行下载!");
  293. });
  294. // 添加点击事件监听器(超清视频下载)
  295. playButton8.addEventListener('click', function (event) {
  296. alert("由于系统限制,苹果设备不支持下载,请前往安卓端和电脑端进行下载!");
  297. });
  298. // 设置播放按钮宽度
  299. playButton1.style.width = liElement.clientWidth + 'px';
  300. // 设置播放按钮宽度
  301. playButton5.style.width = liElement.clientWidth + 'px';
  302. // 设置播放按钮宽度
  303. playButton6.style.width = liElement.clientWidth + 'px';
  304. // 设置播放按钮宽度
  305. playButton7.style.width = liElement.clientWidth + 'px';
  306. // 设置播放按钮宽度
  307. playButton8.style.width = liElement.clientWidth + 'px';
  308. // 添加播放按钮到 LI 元素
  309. liElement.appendChild(playButton1);
  310. // 添加播放按钮到 LI 元素
  311. liElement.appendChild(playButton5);
  312. // 添加播放按钮到 LI 元素
  313. liElement.appendChild(playButton6);
  314. // 添加播放按钮到 LI 元素
  315. liElement.appendChild(playButton7);
  316. // 添加播放按钮到 LI 元素
  317. liElement.appendChild(playButton8);
  318. });
  319. });
  320. // 弹框显示函数
  321. function showLoginPrompt() {
  322. // 使用prompt函数创建弹框
  323. // Trigger the login box
  324. openLoginBox();
  325. // 获取用户名和密码输入框的值
  326. const usernameInput = document.getElementById('username');
  327. const passwordInput = document.getElementById('password');
  328. const submitButton = document.getElementById('submitBtn');
  329. // 添加点击事件监听器
  330. submitButton.addEventListener('click', function () {
  331. const username = usernameInput.value;
  332. const password = passwordInput.value;
  333. if (username != "" && password != "") {
  334. // 模拟后端通信,实际情况应该使用fetch或其他方式与后端通信
  335. simulateBackendCommunication(username, password);
  336. } else {
  337. alert('登录失败,用户名和密码不可为空!');
  338. }
  339. });
  340. }
  341. // 模拟后端通信
  342. function simulateBackendCommunication(username, password) {
  343. // 定义登录 API 地址
  344. const loginApiUrl = "http://api.gv1069.vip/user/login";
  345. // 定义登录参数
  346. const loginData = {
  347. loginName: username,
  348. password: password
  349. };
  350. // 发送登录请求
  351. GM.xmlHttpRequest({
  352. method: "POST",
  353. url: loginApiUrl,
  354. data: JSON.stringify(loginData),
  355. headers: {
  356. "Content-Type": "application/json"
  357. },
  358. onload: function (response) {
  359. // 解析返回的 JSON 数据
  360. const responseData = JSON.parse(response.responseText);
  361. console.log(responseData)
  362. if (responseData.success) {
  363. closeLoginBox();
  364. GM_setValue('YTToken', responseData.content.token);
  365. GM_setValue('username', username);
  366. GM_setValue('password', password);
  367. alert('登录成功,请尽情享受您的观影时间!');
  368. } else {
  369. if (responseData.message == "账户已过期,请重新购买") {
  370. closeLoginBox();
  371. GM_setValue("YTToken", "");
  372. GM_setValue('username', "");
  373. GM_setValue('password', "");
  374. var result = confirm("该账户已过期,请您重新购买或者取号!点击“确定”按钮自动跳转至购买界面!");
  375. if (result) {
  376. window.location.href = "http://gv1069.vip/#/shop-account";
  377. } else {
  378. window.location.href = "http://gv1069.vip/#/shop-account";
  379. }
  380. } else {
  381. alert('登录失败,请检查用户名和密码。');
  382. }
  383. }
  384. },
  385. onerror: function (error) {
  386. console.error("Error:", error);
  387. }
  388. });
  389. }
  390. });
  391. })();