Add pikpak support for Easy Offline
// ==UserScript== // @name Easy Offline pikpak addon // @namespace hoothin // @version 2024-08-16 // @description Add pikpak support for Easy Offline // @author hoothin // @match *://*/* // @grant GM_setValue // @grant GM_getValue // @grant GM_xmlhttpRequest // @grant GM_notification // @grant unsafeWindow // @run-at document-start // @require https://unpkg.com/[email protected]/crypto-js.js // @connect user.mypikpak.com // @connect api-drive.mypikpak.com // ==/UserScript== (function() { 'use strict'; let info = GM_getValue("pikpakUserInfo"), device_id, user_id; const CLIENT_ID = "YNxT9w7GMdWvEOKa"; const CLIENT_SECRET = "dbw2OtmVEeuUvIptb1Coyg"; const CLIENT_VERSION = "1.47.1"; const PACKAG_ENAME = "com.pikcloud.pikpak"; const SDK_VERSION = "2.0.4.204000"; const APP_NAME = "com.pikcloud.pikpak"; function captchaInit() { return new Promise(resolve => { let meta = {}; if (/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/.test(info.userName)) { meta.email = info.userName; } else if (/\d{11,18}/.test(info.userName)) { meta.phone_number = info.userName; } else { meta.username = info.userName; } let params = { "client_id": CLIENT_ID, "action": "POST:https://user.mypikpak.com/v1/auth/signin", "device_id": device_id, "meta": meta } GM_xmlhttpRequest({ method: 'POST', url: 'https://user.mypikpak.com/v1/shield/captcha/init', data: JSON.stringify(params), onload: (res) => { if(res.status === 200) { let data = JSON.parse(res.responseText); resolve(data); } else { info.loginInfo = null; GM_setValue("pikpakUserInfo", info); const msg = JSON.parse(res.responseText).error_description; alert(msg); } }, onerror: (e) => { GM_notification("Error: " + (e.statusText || e.error)); }, ontimeout: (e) => { GM_notification("Error: " + (e.statusText || e.error)); } }); }); } function buildCustomUserAgent() { let signature_base = `${device_id}${PACKAG_ENAME}1appkey`; let sha1_r###lt = CryptoJS.SHA1(signature_base).toString(CryptoJS.enc.Hex); let md5_r###lt = CryptoJS.MD5(sha1_r###lt).toString(CryptoJS.enc.Hex); let device_sign = `div101.${device_id}${md5_r###lt}`; let user_agent_parts = [ `ANDROID-${APP_NAME}/${CLIENT_VERSION}`, "protocolVersion/200", "accesstype/", `clientid/${CLIENT_ID}`, `clientversion/${CLIENT_VERSION}`, "action_type/", "networktype/WIFI", "sessionid/", `deviceid/${device_id}`, "providername/NONE", `devicesign/${device_sign}`, "refresh_token/", `sdkversion/${SDK_VERSION}`, `datetime/${Date.now()}`, `usrno/${user_id}`, `appname/${APP_NAME}`, "session_origin/", "grant_type/", "appid/", "clientip/", "devicename/Xiaomi_M2004j7ac", "osversion/13", "platformversion/10", "accessmode/", "devicemodel/M2004J7AC", ] return user_agent_parts.join(" "); } document.addEventListener("click", function(e) { if (e.target && e.target.getAttribute && e.target.getAttribute("name") === "pikpak" && e.target.parentNode.id === "icons") { GM_setValue("pikpakUserInfo", ""); alert("PikPak account has been cleared"); } }); var _unsafeWindow = (typeof unsafeWindow === 'undefined') ? window : unsafeWindow; if (!_unsafeWindow.eoAddons) _unsafeWindow.eoAddons = {}; _unsafeWindow.eoAddons.pikpak = { regex: /mypikpak\.com/, url: "http://user.mypikpak.com/", bgColor: "2265ff", noTxt: true, linkRegExp: /^magnet:\?xt|^PikPak:\/\/|\.(torrent|mp4|mp3|rar|7z|zip|rmvb|mkv|avi|iso)$/i, directUrl: function(offUrl) { if (!info) { let userName = prompt("userName"); if (!userName) return; let userPass = prompt("userPass"); if (!userPass) return; info = {userName: userName, userPass: userPass}; GM_setValue("pikpakUserInfo", info); } var postUrl = async () => { let postData; if (offUrl.indexOf('PikPak://') === 0) { const urlData = offUrl.substring(9).split('|') postData = { kind: "drive#file", name: urlData[0], size: urlData[1], hash: urlData[2], upload_type: "UPLOAD_TYPE_R###MABLE", objProvider: { provider: "UPLOAD_TYPE_UNKNOWN" } } } else { postData = { kind: "drive#file", name: "", upload_type: "UPLOAD_TYPE_URL", url: { url: offUrl }, params: {"from":"file"}, folder_type: "DOWNLOAD" } } GM_xmlhttpRequest({ method: 'POST', url: 'https://api-drive.mypikpak.com/drive/v1/files', data: JSON.stringify(postData), headers: { "Content-Type": "application/json; charset=utf-8", authorization: info.loginInfo.token_type + ' ' + info.loginInfo.access_token, "X-Captcha-Token": info.captchaData.captcha_token }, onload: (res) => { if(res.status === 200) { GM_notification("Task OK"); } else if(res.status === 401) { info.loginInfo=null; GM_setValue("pikpakUserInfo", info); const msg = JSON.parse(res.responseText).error_description; alert(msg); } else if(res.status === 400) { const msg = JSON.parse(res.responseText).error_description; alert(msg); } else if(res.status === 403) { const msg = JSON.parse(res.responseText).error_description; alert(msg); } }, onerror: (e) => { GM_notification("Error: " + (e.statusText || e.error)); }, ontimeout: (e) => { GM_notification("Error: " + (e.statusText || e.error)); } }) }; device_id = CryptoJS.MD5(`${info.userName}${info.userPass}`).toString(CryptoJS.enc.Hex); (async () => { if (!info.captchaData || info.captchaData.expires < new Date().getTime()) { let captchaData = await captchaInit(); info.captchaData = captchaData; if (!info.captchaData.expires && info.captchaData.expires_in) { info.captchaData.expires = new Date().getTime() + 1000 * info.captchaData.expires_in; } GM_setValue("pikpakUserInfo", info); } if (!info.loginInfo || info.loginInfo.expires < new Date().getTime()) { let data = { "client_id": CLIENT_ID, "client_secret": CLIENT_SECRET, "password": info.userPass, "username": info.userName, "captcha_token": info.captchaData.captcha_token, } GM_xmlhttpRequest({ method: 'POST', url: 'https://user.mypikpak.com/v1/auth/signin', data: JSON.stringify(data), headers: { 'user-agent': 'accessmode/ devicename/Netease_Mumu appname/android-com.pikcloud.pikpak cmd/login appid/ action_type/ clientid/YNxT9w7GMdWvEOKa deviceid/56e000d71f4660700ca974f2305171c5 refresh_token/ grant_type/ networktype/WIFI devicemodel/MuMu accesstype/ sessionid/ osversion/6.0.1 datetime/1636364470779 sdkversion/1.0.1.101600 protocolversion/200 clientversion/ providername/NONE clientip/ session_origin/ devicesign/div101.56e000d71f4660700ca974f2305171c5b94c3d4196a9dd74e49d7710a7af873d platformversion/10 usrno/null' }, onload: (res) => { if (res.status === 200) { info.loginInfo = JSON.parse(res.responseText); if (!info.loginInfo.expires && info.loginInfo.expires_in) { info.loginInfo.expires = new Date().getTime() + 1000 * info.loginInfo.expires_in; } GM_setValue("pikpakUserInfo", info); postUrl(); } else if (res.status === 401) { GM_setValue("pikpakUserInfo",""); const msg = JSON.parse(res.responseText).error_description; alert(msg); } else if (res.status === 400) { GM_setValue("pikpakUserInfo",""); const msg = JSON.parse(res.responseText).error_description; alert(msg); } else if (res.status === 403) { GM_setValue("pikpakUserInfo",""); const msg = JSON.parse(res.responseText).error_description; alert(msg); } }, onerror: (e) => { GM_notification("Error: " + (e.statusText || e.error)); }, ontimeout: (e) => { GM_notification("Error: " + (e.statusText || e.error)); } }) } else { postUrl(); } })(); return false; }, bgImg: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAYFBMVEUAAAArbP5MdNFMdNIrbP4sbP1QdctQdcwvbv////8dYf8sbP9smP/09/8qaf/V4f8iZf/u8/+lwP+duv+UtP+PsP9hkP92n/9nlP/K2v/F1v+7z/+Ytv9Wif9Aef91nv9e7pgKAAAACHRSTlMA+puT/PWHhQBB7XEAAACQSURBVBjTTY8JCsQwCEWdrjFm37p37n/LMdAJfSTgf4IoAPQf8fDpgek4N9NxnwQZJx0/w+UMNd/XV6nluqsBQbRp79Xqvd7ICBCuaHuElMJhdXEspMKGko/YA2LYXyKuiGt8Ca3rfwm052nbjILV1IyFBZFZck4xppwXQ8Srk2wQzXzcIBpDB8w0/vM4AfwACl4LKjajMX0AAAAASUVORK5CYII=" }; })();