// ==UserScript== // @name 淘呀号解析自营(苹果版) // @namespace http://gv1069.vip/ // @version 1.3 // @description (注:一同看官网能打开了就不需要用这个了,可能体验没一同看原生好,并且有时候会无法使用)该版本为“淘呀号”自营解析插件的苹果版,适用于苹果设备,该插件将不再依赖于一同看网站(一同看官网打不开的用户可以使用该插件),直接访问http://gv.gv1069.vip即可观看。 // @author 淘呀号团队 // @match *://*/* // @grant GM.xmlHttpRequest // @grant GM.addStyle // @grant GM_setValue // @grant GM_getValue // @connect api.gv1069.vip // @exclude http://gv1069.vip/* // @exclude https://www.yuque.com/* // @exclude https://yuque.com/* // @exclude http://www.gv1069.vip/* // @exclude https://m3u8play.com/* // @exclude https://www.m3u8play.com/* // @exclude https://greasyfork.org/* // @exclude https://www.greasyfork.org/* // @license MIT // @downloadURL https://update.greasyfork.icu/scripts/499747/%E6%B7%98%E5%91%80%E5%8F%B7%E8%A7%A3%E6%9E%90%E8%87%AA%E8%90%A5%28%E8%8B%B9%E6%9E%9C%E7%89%88%29.user.js // @updateURL https://update.greasyfork.icu/scripts/499747/%E6%B7%98%E5%91%80%E5%8F%B7%E8%A7%A3%E6%9E%90%E8%87%AA%E8%90%A5%28%E8%8B%B9%E6%9E%9C%E7%89%88%29.meta.js // ==/UserScript== (function () { 'use strict'; // 定义登录 API 地址 var yitongkanBase = "http://api.gv1069.vip"; var page = 1; var searchPage = 1; // 在页面加载时创建登录弹框 window.addEventListener('load', function () { // 创建登录框的HTML const loginBoxHTML = `

(为防止迷路,请关注微信公众号“淘呀号”)

(请通过租号网站提供的按钮复制账户密码,其他任何方式都将无法登录)

(如果忘记,请前往gv1069.vip首页综合服务窗口找回)

(请确保只安装一个解析脚本,多个解析脚本将会导致冲突)





`; // 创建退出登录按钮的HTML const logoutButtonHTML = ` `; // 将登录框插入到homeso元素下面 const homeSoElement = document.getElementById('homeso'); if (homeSoElement) { homeSoElement.insertAdjacentHTML('afterend', loginBoxHTML); const loginBox = document.getElementById('loginBox'); // 获取 header 中的 authControls 元素 const authControls = document.getElementById('authControls'); // 如果存储的token为空,则显示登录框,否则隐藏登录框 if (GM_getValue("YTToken")==null||GM_getValue("YTToken")=="") { loginBox.style.display = 'block'; } else { loginBox.style.display = 'none'; // 添加退出登录按钮到 header authControls.innerHTML = logoutButtonHTML; } // 添加登录表单提交事件监听 const loginForm = document.getElementById('loginForm'); loginForm.addEventListener('submit', function(event) { event.preventDefault(); // 阻止默认表单提交 // 获取输入的用户名和密码 const username = document.getElementById('username').value; const password = document.getElementById('password').value; if(username==""||password==""){ showToast("账户密码不能为空"); }else{ simulateBackendCommunication(username,password) } }); // 添加退出登录按钮的点击事件监听 authControls.addEventListener('click', function(event) { if (event.target && event.target.id === 'logoutButton') { // 清除本地存储中的 token GM_setValue("YTToken", ""); // 移除退出登录按钮 authControls.innerHTML = ''; // 显示登录框 loginBox.style.display = 'block'; showToast("登出成功") } }); } // 模拟后端通信 function simulateBackendCommunication(username, password) { // 定义登录 API 地址 const loginApiUrl =yitongkanBase+ "/user/login"; // 定义登录参数 const loginData = { loginName: username, password: password }; // 发送登录请求 GM.xmlHttpRequest({ method: "POST", url: loginApiUrl, data: JSON.stringify(loginData), headers: { "Content-Type": "application/json" }, onload: function (response) { // 解析返回的 JSON 数据 const responseData = JSON.parse(response.responseText); console.log(responseData) if (responseData.success) { // 将token存储在localStorage中 // localStorage.setItem('YTToken', YTToken); GM_setValue("YTToken", responseData.content.token); GM_setValue('username', username); GM_setValue('password', password); // 登录成功,隐藏登录框 loginBox.style.display = 'none'; // 在 header 中显示退出登录按钮 authControls.innerHTML = logoutButtonHTML; showToast("登录成功") } else { // 登录失败,显示错误消息 document.getElementById('loginError').style.display = 'block'; showToast("登录失败") } } }); } // 获取输入框和按钮元素 var inputElement = document.querySelector('#sos'); var buttonElement = document.querySelector('#button'); if (inputElement && buttonElement) { // 监听输入框的输入事件 inputElement.addEventListener('input', function() { console.log('输入内容:', inputElement.value); }); // 监听按钮的点击事件 buttonElement.addEventListener('click', function(event) { event.preventDefault(); // 阻止默认提交行为 console.log('按钮被点击,输入内容:', inputElement.value); searchPage=1 if(inputElement.value==""||inputElement.value==null){ showToast("搜索框不能为空"); }else{ showToast("视频检索中"); GM.xmlHttpRequest({ method: 'GET', url: yitongkanBase + "/app/search-list?limit=20&page="+searchPage+"&type=gv&keyword="+inputElement.value, onload: function (responseSearchVideo) { const responseDataSearchVideo = JSON.parse(responseSearchVideo.responseText); const videos=responseDataSearchVideo.content.data.list const count=responseDataSearchVideo.content.data.count insertItemsIntoSearchList(videos,"https://pic.yitongboy.com") insertIntoSearchPaging(searchPage,count) } }) } }); } else { console.error('未找到输入框或按钮元素'); } // 添加样式 GM.addStyle(` #gm-loading-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(255, 255, 255, 0.8); display: none; z-index: -1; display: flex; justify-content: center; align-items: center; } #gm-loading-overlay div { font-size: 20px; } #customLoginModal { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); justify-content: center; align-items: center; z-index: 1000; } #loginBox { background: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); text-align: center; } #loginBox h2 { color: #333; } .toast { visibility: hidden; min-width: 250px; margin-left: -125px; background-color: #333; color: #fff; text-align: center; border-radius: 5px; padding: 16px; position: fixed; z-index: 1; left: 50%; bottom: 30px; font-size: 17px; } .toast.show { visibility: visible; -webkit-animation: fadein 0.5s, fadeout 0.5s 2.5s; animation: fadein 0.5s, fadeout 0.5s 2.5s; } @-webkit-keyframes fadein { from {bottom: 0; opacity: 0;} to {bottom: 30px; opacity: 1;} } @keyframes fadein { from {bottom: 0; opacity: 0;} to {bottom: 30px; opacity: 1;} } @-webkit-keyframes fadeout { from {bottom: 30px; opacity: 1;} to {bottom: 0; opacity: 0;} } @keyframes fadeout { from {bottom: 30px; opacity: 1;} to {bottom: 0; opacity: 0;} } `); function showToast(message) { const toast = document.getElementById("toast"); toast.textContent = message; toast.className = "toast show"; setTimeout(function() { toast.className = toast.className.replace("show", ""); }, 3000); } function createPaging() { return `« »
` } function insertIntoPaging(index,count) { let pagingHtml=createPaging(); var pagingElement = document.querySelector('.paging'); if (pagingElement) { pagingElement.innerHTML = pagingHtml addClickEventToPaging(index,count); } else { console.error('无法找到列表元素') } } function insertIntoSearchPaging(index,count) { let pagingHtml=createPaging(); var pagingElement = document.querySelector('.paging'); if (pagingElement) { pagingElement.innerHTML = pagingHtml addClickEventToSearchPaging(index,count); } else { console.error('无法找到列表元素') } } function gotoSearchPage(index){ if(inputElement.value==""&&inputElement.value==null){ showToast("搜索框为空"); }else{ GM.xmlHttpRequest({ method: 'GET', url: yitongkanBase + "/app/search-list?limit=20&page="+index+"&type=gv&keyword="+inputElement.value, onload: function (responseSearchVideo) { scrollToTop() const responseDataSearchVideo = JSON.parse(responseSearchVideo.responseText); const videos=responseDataSearchVideo.content.data.list const count=responseDataSearchVideo.content.data.count insertItemsIntoSearchList(videos,"https://pic.yitongboy.com") insertIntoSearchPaging(index,count) } }) } } function gotoPage(page){ if(inputElement.value==""&&inputElement.value==null){ showToast("搜索框为空"); }else{ GM.xmlHttpRequest({ method: 'GET', url: yitongkanBase + "/app/get-gv-list?page="+page, onload: function (responseVideo) { scrollToTop() const responseDataVideo = JSON.parse(responseVideo.responseText); const videos=responseDataVideo.content.data.list const count=responseDataVideo.content.data.count insertItemsIntoList(videos,"https://pic.yitongboy.com") insertIntoPaging(page,count) } }) } } gotoPage(page); function isNonNegativeInteger(value) { const number = Number(value); return Number.isInteger(number) && number >= 0; } // Function to scroll to the top of the page function scrollToTop() { window.scrollTo(0, 0); } function addClickEventToPaging(index,count) { var lspan = document.querySelector('.lspan'); var rspan = document.querySelector('.rspan'); var yema = document.querySelector('.yema'); var confirmButton = document.querySelector('.confirmButton'); lspan.addEventListener('click', function() { if(index>1){ page=page-1; gotoPage(page); showToast("第"+page+"页加载中"); }else{ showToast("到头了!"); } }) rspan.addEventListener('click', function() { if(index<(count/20)){ page=page+1; gotoPage(page); showToast("第"+page+"页加载中"); }else{ showToast("真的没有了!"); } }) confirmButton.addEventListener('click', function() { var yemaValue=yema.value; if(isNonNegativeInteger(yemaValue)&&yemaValue !== ""){ if(11){ searchPage=searchPage-1; gotoSearchPage(searchPage); showToast("第"+searchPage+"页加载中"); }else{ showToast("到头了!"); } }) rspan.addEventListener('click', function() { if(index<(count/20)){ searchPage=searchPage+1; gotoSearchPage(searchPage); showToast("第"+searchPage+"页加载中"); }else{ showToast("真的没有了!"); } }) confirmButton.addEventListener('click', function() { var yemaValue=yema.value; if(isNonNegativeInteger(yemaValue)&&yemaValue !== ""){ if(1
${item.video_id} 推荐 ${new Date(item.addtime).getFullYear()}

${base64Decode(item.mv_name)}

` } function createSearchListItem(item, domain) { return `
  • ${item.id} 推荐 ${new Date(item.addtime).getFullYear()}

    ${base64Decode(item.mv_name)}

  • ` } function generateListItems(dataArray, domain) { return dataArray.map(item => createListItem(item, domain)) .join('') } function generateSearchListItems(dataArray, domain) { return dataArray.map(item => createSearchListItem(item, domain)) .join('') } function insertItemsIntoList(dataArray, domain) { var listItemsHtml = generateListItems(dataArray, domain); var listElement = document.querySelector('.s-tab-main .list.g-clear'); if (listElement) { listElement.innerHTML = listItemsHtml addClickEventToItems() addClickEventToDownloadLC() addClickEventToDownloadBQ() addClickEventToDownloadGQ() } else { console.error('无法找到列表元素') } } function insertItemsIntoSearchList(dataArray, domain) { var listItemsHtml = generateSearchListItems(dataArray, domain); var listElement = document.querySelector('.s-tab-main .list.g-clear'); if (listElement) { listElement.innerHTML = listItemsHtml addClickEventToSearchItems() addClickEventToSearchDownloadLC() addClickEventToSearchDownloadBQ() addClickEventToSearchDownloadGQ() } else { console.error('无法找到列表元素') } } // 使用 JavaScript 进行 Base64 解码 function base64Decode(encodedString) { return decodeURIComponent(escape(atob(encodedString))); } function addClickEventToSearchDownloadLC() { var items = document.querySelectorAll('.downloadLC'); items.forEach(item => { item.addEventListener('click', function() { showToast("苹果设备不支持下载,请使用安卓设备或者电脑") }) }) } function addClickEventToSearchDownloadBQ() { var items = document.querySelectorAll('.downloadBQ'); items.forEach(item => { item.addEventListener('click', function() { showToast("苹果设备不支持下载,请使用安卓设备或者电脑") }) }) } function addClickEventToSearchDownloadGQ() { var items = document.querySelectorAll('.downloadGQ'); items.forEach(item => { item.addEventListener('click', function() { showToast("苹果设备不支持下载,请使用安卓设备或者电脑") }) }) } function addClickEventToDownloadLC() { var items = document.querySelectorAll('.downloadLC'); items.forEach(item => { item.addEventListener('click', function() { showToast("苹果设备不支持下载,请使用安卓设备或者电脑") }) }) } function addClickEventToDownloadBQ() { var items = document.querySelectorAll('.downloadBQ'); items.forEach(item => { item.addEventListener('click', function() { showToast("苹果设备不支持下载,请使用安卓设备或者电脑") }) }) } function addClickEventToDownloadGQ() { var items = document.querySelectorAll('.downloadGQ'); items.forEach(item => { item.addEventListener('click', function() { showToast("苹果设备不支持下载,请使用安卓设备或者电脑") }) }) } function addClickEventToItems() { var items = document.querySelectorAll('.cover.g-playicon'); items.forEach(item => { item.addEventListener('click', function() { var videoId = item.getAttribute('data-video-id'); var videoType = item.getAttribute('data-video-type'); var vId = item.getAttribute('data-v-id'); var episodes = item.getAttribute('data-episodes'); var mvName=item.getAttribute('data-mv-name'); const tempPage = window.open('loading page'); let qualityList="" tempPage.addEventListener('load', function() { GM.xmlHttpRequest({ method: 'GET', url: yitongkanBase + "/app/get-video-url?video_id="+videoId+"&video_type="+videoType+"&v_id="+vId+"&episodes="+episodes+"&prefix=&line=&token="+GM_getValue("YTToken"), onload: function (responseUrl) { const responseDataVideo = JSON.parse(responseUrl.responseText); if (responseDataVideo.success && responseDataVideo.content != null && responseDataVideo.content != "") { const urls=responseDataVideo.content.data.video_url const keys = Object.keys(urls); const numberOfKeys = keys.length; console.log(numberOfKeys) if(numberOfKeys==1){ qualityList=`{ name: '流畅', url: '${base64Decode(urls['480'])}', type: 'hls', },` }else if(numberOfKeys==2){ qualityList=`{ name: '流畅', url: '${base64Decode(urls['480'])}', type: 'hls', }, { name: '标清', url: '${base64Decode(urls['720'])}', type: 'hls', },` }else if(numberOfKeys==3){ qualityList=`{ name: '流畅', url: '${base64Decode(urls['480'])}', type: 'hls', }, { name: '标清', url: '${base64Decode(urls['720'])}', type: 'hls', }, { name: '高清', url: '${base64Decode(urls['1080'])}', type: 'hls', },` } let playhtml=` 淘呀号

    ${base64Decode(mvName)}
    ` // 替换当前页面的内容 tempPage.document.open(); tempPage.document.write(playhtml); tempPage.document.close(); } else if (responseDataVideo.message == "2") { GM_setValue("YTToken", ""); var result = confirm("该账户已过期,请您重新购买或者取号!点击“确定”按钮自动跳转至购买界面!"); if (result) { window.location.href = "http://gv1069.vip/#/shop-account"; } } else if (responseDataVideo.message == "3") { GM_setValue("YTToken", ""); var result = confirm("请您重新登录!点击“确定”按钮自动弹出登录输入框!"); if (result) { window.location.reload(); } } else if (responseDataVideo.message == "4" || responseDataVideo.message == "5") { GM_setValue("YTToken", ""); var result = confirm("请您重新登录!点击“确定”按钮自动弹出登录输入框!"); if (result) { window.location.reload(); } } else if (responseDataVideo.message == "6") { GM_setValue("YTToken", ""); var result = confirm("您的账号在另一台设备上登录,请重新登录"); if (result) { window.location.reload(); } } else { showToast('解析失败,请点击播放按钮重试!') } } }) }); }); }); } function addClickEventToSearchItems() { var items = document.querySelectorAll('.cover.g-playicon'); items.forEach(item => { item.addEventListener('click', function() { var id = item.getAttribute('data-id'); const tempPage = window.open('loading page'); let qualityList="" tempPage.addEventListener('load', function() { GM.xmlHttpRequest({ method: 'GET', url: yitongkanBase + "/app/get-video-view?id="+id, onload: function (responseView) { const responseDataView = JSON.parse(responseView.responseText); const view=responseDataView.content.data console.log(view) var videoId = view.video_id; var videoType = view.video_type; var vId = view.v_id; var episodes = view.episodes; var mvName=view.mv_name; GM.xmlHttpRequest({ method: 'GET', url: yitongkanBase + "/app/get-video-url?video_id="+videoId+"&video_type="+videoType+"&v_id="+vId+"&episodes="+episodes+"&prefix=&line=&token="+GM_getValue("YTToken"), onload: function (responseUrl) { const responseDataVideo = JSON.parse(responseUrl.responseText); if (responseDataVideo.success && responseDataVideo.content != null && responseDataVideo.content != "") { const urls=responseDataVideo.content.data.video_url console.log(urls) const keys = Object.keys(urls); const numberOfKeys = keys.length; console.log(numberOfKeys) if(numberOfKeys==1){ qualityList=`{ name: '流畅', url: '${base64Decode(urls['480'])}', type: 'hls', },` }else if(numberOfKeys==2){ qualityList=`{ name: '流畅', url: '${base64Decode(urls['480'])}', type: 'hls', }, { name: '标清', url: '${base64Decode(urls['720'])}', type: 'hls', },` }else if(numberOfKeys==3){ qualityList=`{ name: '流畅', url: '${base64Decode(urls['480'])}', type: 'hls', }, { name: '标清', url: '${base64Decode(urls['720'])}', type: 'hls', }, { name: '高清', url: '${base64Decode(urls['1080'])}', type: 'hls', },` } let playhtml=` 淘呀号

    ${base64Decode(mvName)}
    ` // 替换当前页面的内容 tempPage.document.open(); tempPage.document.write(playhtml); tempPage.document.close(); } else if (responseDataVideo.message == "2") { GM_setValue("YTToken", ""); GM_setValue('username', ""); GM_setValue('password', ""); var result = confirm("该账户已过期,请您重新购买或者取号!点击“确定”按钮自动跳转至购买界面!"); if (result) { window.location.href = "http://gv1069.vip/#/shop-account"; } } else if (responseDataVideo.message == "3") { GM_setValue("YTToken", ""); GM_setValue('username', ""); GM_setValue('password', ""); var result = confirm("请您重新登录!点击“确定”按钮自动弹出登录输入框!"); if (result) { window.location.reload(); } } else if (responseDataVideo.message == "4" || responseDataVideo.message == "5") { GM_setValue("YTToken", ""); GM_setValue('username', ""); GM_setValue('password', ""); var result = confirm("请您重新登录!点击“确定”按钮自动弹出登录输入框!"); if (result) { window.location.reload(); } } else if (responseDataVideo.message == "6") { GM_setValue("YTToken", ""); GM_setValue('username', ""); GM_setValue('password', ""); var result = confirm("您的账号在另一台设备上登录,请重新登录"); if (result) { window.location.reload(); } } else { showToast('解析失败,请点击播放按钮重试!') } } }) } }) }); }); }); } $("body").on('click', '.close-gobutton', function () { $("#down-my-section").remove(); }) }); })();