pikpak助手

pikpak网盘助手,绕过ip限制,支持aria2下载!

目前為 2022-09-12 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name pikpak助手
  3. // @name:zh-CN pikpak助手
  4. // @namespace http://tampermonkey.net/
  5. // @version 0.3
  6. // @description pikpak网盘助手,绕过ip限制,支持aria2下载!
  7. // @description:zh-CN pikpak网盘助手,绕过ip限制,支持aria2下载!
  8. // @author xiaoziguys
  9. // @match https://mypikpak.com/*
  10. // @icon https://www.google.com/s2/favicons?sz=64&domain=mypikpak.com
  11. // @grant unsafeWindow
  12. // @grant GM_xmlhttpRequest
  13. // @run-at document-start
  14. // @license MIT
  15. // ==/UserScript==
  16. function getPlatform () {
  17. let u = navigator.userAgent;
  18. let isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1; //判断是否是 android终端
  19. let isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //判断是否是 iOS终端
  20. if(isAndroid){
  21. return 'Android';
  22. }else if(isIOS){
  23. return 'IOS';
  24. }else{
  25. return 'PC';
  26. }
  27. }
  28. function Toast(dom, value) {
  29. dom.innerText = value
  30. dom.style.visibility = 'visible'
  31. setTimeout(() => {dom.style.visibility = 'hidden'}, 1000)
  32. }
  33. function addStyle(id, tag, css) {
  34. tag = tag || 'style';
  35. let doc = document, styleDom = doc.getElementById(id);
  36. if (styleDom) return;
  37. let style = doc.createElement(tag);
  38. style.rel = 'stylesheet';
  39. style.id = id;
  40. tag === 'style' ? style.innerHTML = css : style.href = css;
  41. doc.getElementsByTagName('head')[0].appendChild(style);
  42. }
  43. function post(url, data, headers, type) {
  44. console.log(url, data, headers, type)
  45. data = JSON.stringify(data);
  46. return new Promise((resolve, reject) => {
  47. GM_xmlhttpRequest({
  48. method: "POST", url, headers, data,
  49. responseType: type || 'json',
  50. onload: (res) => {
  51. type === 'blob' ? resolve(res) : resolve(res.response || res.responseText);
  52. },
  53. onerror: (err) => {
  54. reject(err);
  55. },
  56. });
  57. });
  58. }
  59. async function postData(url = '', data = {}, customHeaders = {}, method = 'GET') {
  60. // Default options are marked with *
  61. let options = {
  62. method: method, // *GET, POST, PUT, DELETE, etc.
  63. mode: 'cors', // no-cors, *cors, same-origin
  64. cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
  65. credentials: 'same-origin', // include, *same-origin, omit
  66. headers: {
  67. 'Content-Type': 'application/json',
  68. // 'Content-Type': 'application/x-www-form-urlencoded',
  69. ...customHeaders
  70. },
  71. redirect: 'follow', // manual, *follow, error
  72. referrerPolicy: 'no-referrer'
  73. }
  74. if (method === 'GET') {
  75. const response = await fetch(url, {
  76. method: 'GET', // *GET, POST, PUT, DELETE, etc.
  77. mode: 'cors', // no-cors, *cors, same-origin
  78. cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
  79. credentials: 'same-origin', // include, *same-origin, omit
  80. headers: {
  81. 'Content-Type': 'application/json',
  82. // 'Content-Type': 'application/x-www-form-urlencoded',
  83. ...customHeaders
  84. },
  85. redirect: 'follow', // manual, *follow, error
  86. referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
  87. });
  88. return response.json(); // parses JSON response into native JavaScript objects
  89. } else {
  90. return new Promise((resolve, reject) => {
  91. let xhr = new XMLHttpRequest();
  92. xhr.onreadystatechange = function () {
  93. if (xhr.readyState === 4) {
  94. if (xhr.status === 200) {
  95. resolve(JSON.parse(xhr.response))
  96. } else {
  97. reject({})
  98. }
  99. }
  100. }
  101. xhr.open(method, url) // 带参数
  102. xhr.setRequestHeader('content-type', 'application/json')// 设置服务端要求的参数类型,后面会专门出一期,针对各种常用content-type讲解
  103. xhr.send(JSON.stringify(data));// 带上复杂参数
  104. })
  105. }
  106. }
  107.  
  108. (function() {
  109. 'use strict';
  110. // divert region limit
  111. document.cookie = "pp_access_to_visit=true"
  112. let flag = setInterval(() => {
  113. let container = document.getElementsByClassName('context-menu')
  114. if (container[0]) {
  115. clearInterval(flag)
  116. // ready
  117. let ariaHost = window.localStorage.getItem('ariaHost') || ''
  118. let ariaPath = window.localStorage.getItem('ariaPath') || ''
  119. // add download btn
  120. let aria2Btn = document.createElement('button')
  121. aria2Btn.innerText = '推送到aria2'
  122. aria2Btn.className = 'el-button el-button--primary'
  123. aria2Btn.style.marginTop = '10px'
  124. container[0].append(aria2Btn)
  125. // aria2配置dom
  126. let btnBox = document.getElementsByClassName('add-resources')[0]
  127. let configBtn = document.createElement('button')
  128. configBtn.innerText = '配置aira2'
  129. configBtn.className = 'el-button el-button--primary'
  130. configBtn.style.marginTop = '10px'
  131. btnBox.append(configBtn)
  132. // form
  133. let form = document.createElement('div')
  134. form.id = 'aria2form'
  135. addStyle('','',`
  136. #aria2form {
  137. top: 20vh;
  138. position: fixed;
  139. background: #fff;
  140. left: calc(50vw - 50px);
  141. /* height: 30px; */
  142. padding: 20px;
  143. box-shadow: 0 2px 8px rgb(0 0 0 / 10%);;
  144. border-radius: 4px;
  145. visibility: hidden;
  146. }
  147. .xz-input {
  148. border: #d9d9d9 1px solid;
  149. margin-bottom: 10px;
  150. padding: 5px;
  151. margin-top: 5px;
  152. }
  153. #aria2Toast {
  154. top: 5vh;
  155. position: fixed;
  156. background: #fff;
  157. left: 50%;
  158. transform: translate(-50%, 0);
  159. /* height: 30px; */
  160. padding: 20px;
  161. box-shadow: 0 2px 8px rgb(0 0 0 / 10%);;
  162. border-radius: 4px;
  163. visibility: hidden;
  164. }
  165. `)
  166. document.body.append(form)
  167. form.innerHTML = `
  168. 服务器:<br/>
  169. <div class="el-input xz-input"><input class="el-input__inner" id="aria2Host"></input></div>
  170. 路径:<br/>
  171. <div class="el-input xz-input"><input class="el-input__inner" id="aria2path"></input></div>
  172. <button class="el-button el-button--primary" id="ariaSaveBtn">保存</button>
  173. `
  174. //toast
  175. let toast = document.createElement('div')
  176. toast.id = 'aria2Toast'
  177. document.body.append(toast)
  178. // 配置aria2
  179. let ariaSaveBtn = document.getElementById('ariaSaveBtn')
  180. let ariaInput = document.getElementById('aria2Host')
  181. let ariaPathInput = document.getElementById('aria2path')
  182. ariaInput.value = ariaHost
  183. ariaPathInput.value = ariaPath
  184. configBtn.addEventListener('click', () => {
  185. form.style.visibility = 'visible'
  186. })
  187. ariaSaveBtn.addEventListener('click', () => {
  188. form.style.visibility = 'visible'
  189. window.localStorage.setItem('ariaHost',ariaInput.value)
  190. window.localStorage.setItem('ariaPath',ariaPathInput.value)
  191. ariaHost = ariaInput.value || ''
  192. ariaPath = ariaPathInput.value || ''
  193. Toast(toast, '配置成功')
  194. form.style.visibility = 'hidden'
  195. })
  196. // token
  197. let token = ''
  198. let captcha = ''
  199. for (let i = 0; i < 10; i++) {
  200. let key = window.localStorage.key(i)
  201. if (key && key.startsWith('credentials')) {
  202. let tokenData = JSON.parse(window.localStorage.getItem(key))
  203. token = tokenData.token_type + ' ' + tokenData.access_token
  204. continue
  205. }
  206. if (key && key.startsWith('captcha')) {
  207. let tokenData = JSON.parse(window.localStorage.getItem(key))
  208. captcha = tokenData.token
  209. }
  210. }
  211. let header = {
  212. Authorization: token,
  213. 'x-device-id': window.localStorage.getItem('deviceid'),
  214. 'x-captcha-token': captcha
  215. }
  216. // push to aria2
  217. aria2Btn.addEventListener('click', async () => {
  218. if (!ariaHost) {
  219. Toast(toast, '请先配置aria2')
  220. return
  221. }
  222. let item = document.getElementsByClassName('selected')[0]
  223. let id = item.getAttribute('id')
  224. try {
  225. let res = await postData('https://api-drive.mypikpak.com/drive/v1/files/' + id + '?',{},header)
  226. let ariaData = {
  227. id: new Date().getTime(),
  228. jsonrpc:'2.0',
  229. method:'aria2.addUri',
  230. params:[
  231. 'token:xiaoziguys',
  232. [res.web_content_link],
  233. { out: res.name }
  234. ]
  235. }
  236. ariaPath && (ariaData.params[2].dir = ariaPath)
  237. let ariares = {}
  238. if (['Android','IOS'].includes(getPlatform())) {
  239. ariares = await postData(ariaHost, ariaData,{}, 'POST')
  240. } else {
  241. ariares = await post(ariaHost, ariaData, {}, '')
  242. }
  243. console.log('ariares', ariares)
  244. if(ariares.result) {
  245. Toast(toast, 'aria2下载成功')
  246. } else {
  247. Toast(toast, 'aria2下载失败,请查看配置')
  248. }
  249. } catch(e) {
  250. console.log('ariares', e)
  251. }
  252. })
  253. }
  254. }, 1000)
  255. // Your code here...
  256. })();