NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name KeyJoker Auto Task // @namespace KeyJokerAutoTask // @version 0.8.5 // @description KeyJoker Auto Task,修改自https://greasyfork.org/zh-CN/scripts/383411 // @author jiyecafe // @include *://www.keyjoker.com/entries* // @include *://assets.hcaptcha.com/* // @include *://discord.com/channels/@me?keyjokertask=storageAuth // @include *://www.twitch.tv/settings/profile?keyjokertask=storageAuth // @updateURL https://github.com/jiyeme/keyjokerScript/raw/master/keyjoker.user.js // @downloadURL https://github.com/jiyeme/keyjokerScript/raw/master/keyjoker.user.js // @supportURL https://www.jysafe.cn/4332.air // @homepage https://github.com/jiyeme/keyjokerScript/ // @run-at document-start // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // @grant GM_addStyle // @grant GM_xmlhttpRequest // @grant GM_setClipboard // @grant GM_setValue // @grant GM_getValue // @grant GM_listValues // @grant GM_deleteValue // @grant GM_openInTab // @grant GM_log // @connect accounts.hcaptcha.com // @connect store.steampowered.com // @connect steamcommunity.com // @connect twitter.com // @connect facebook.com // @connect discord.com // @connect twitch.tv // @connect tumblr.com // @connect spotify.com // @connect jysafe.cn // @require https://greasyfork.org/scripts/379868-jquery-not/code/jQuery%20not%20$.js?version=700787 // @require https://cdn.staticfile.org/jquery/3.3.1/jquery.min.js // @require https://cdn.jsdelivr.net/gh/jiyeme/keyjokerScript@e1f9bc6ca24cf7e8f734bd910306737449a26830/keyjoker.ext.js // @license MIT // @copyright 2020, jiyecafe (https://openuserjs.org/users/jiyecafe) // ==/UserScript== //==OpenUserJs== //==/OpenUserJs== (function() { 'use strict'; const debug = false; const discordAuth = GM_getValue('discordAuth') || { authorization: "", status:0, updateTime: 0 } // steam信息 const steamInfo = GM_getValue('steamInfo') || { userName: '', steam64Id: '', communitySessionID: '', storeSessionID: '', comUpdateTime: 0, storeUpdateTime: 0 } const twitchAuth = GM_getValue('twitchAuth') || { "auth-token": "", status:0, updateTime: 0 } const twitterAuth = GM_getValue('twitterAuth') || { authorization: "AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA", ct0: '', updateTime: 0 } // 0-未动作|200-成功取得|401未登录|603正在取得 const getAuthStatus = { discord: false, spotify: false, steamStore: 0, steamCom: 0, tumblr: false, twitch: false, twitter: 0 } var checkSwitchId = null; const noticeFrame = { loadFrame: ()=>{ if(debug)console.log("loadFrame"); $('body').append(`<style> .fuck-task-logs li{display:list-item !important;float:none !important} #extraBtn .el-badge.item{margin-bottom:4px !important} #extraBtn .el-badge.item sup{padding-right:0 !important} .fuck-task-logs{width:auto;max-width:50%;max-height:50%;z-index:99999999999 !important} .fuck-task-logs .el-notification__group{width:100%} .fuck-task-logs .el-notification__title{text-align:center} .fuck-task-logs .el-notification__content{overflow:auto;max-height:230px} font.success{color:green} font.error{color:red;} font.warning{color:#00f;} font.wait{color:#9c27b0;} [class^=el-icon-]{font-family:element-icons !important;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;vertical-align:baseline;display:inline-block;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale} .el-icon-brush:before{content:"\\e76e"} .el-icon-document:before{content:"\\e785"} .el-icon-refresh:before{content:"\\e6d0"} .el-icon-s-promotion:before{content:"\\e7ba"} .el-icon-setting:before{content:"\\e6ca"} .el-icon-video-play:before{content:"\\e7c0"} .el-notification{display:-webkit-box;display:-ms-flexbox;display:flex;padding:14px 26px 14px 13px;border-radius:8px;-webkit-box-sizing:border-box;box-sizing:border-box;border:1px solid #ebeef5;position:fixed;background-color:#fff;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1);-webkit-transition:opacity .3s,left .3s,right .3s,top .4s,bottom .3s,-webkit-transform .3s;transition:opacity .3s,left .3s,right .3s,top .4s,bottom .3s,-webkit-transform .3s;transition:opacity .3s,transform .3s,left .3s,right .3s,top .4s,bottom .3s;transition:opacity .3s,transform .3s,left .3s,right .3s,top .4s,bottom .3s,-webkit-transform .3s;overflow:hidden} .el-notification__group{margin-left:13px;margin-right:8px} .el-notification__title{font-weight:700;font-size:16px;color:#303133;margin:0} .el-notification__content{font-size:14px;line-height:21px;margin:6px 0 0;color:#606266;text-align:justify} .el-notification__content p{margin:0} .el-badge{position:relative;vertical-align:middle;display:inline-block} .el-badge__content{background-color:#f56c6c;border-radius:10px;color:#fff;display:inline-block;font-size:12px;height:18px;line-height:18px;padding:0 6px;text-align:center;white-space:nowrap;border:1px solid #fff} .el-badge__content.is-fixed{position:absolute;top:10px;right:10px;-webkit-transform:translateY(-50%) translateX(100%);transform:translateY(-50%) translateX(100%)} .el-badge__content.is-fixed.is-dot{right:8px} .el-badge__content.is-dot{height:8px;width:8px;padding:0;right:0;border-radius:50%} .el-button{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none} .el-button{-webkit-box-sizing:border-box} .el-button{display:inline-block;line-height:1;white-space:nowrap;cursor:pointer;background:#fff;border:1px solid #dcdfe6;color:#606266;-webkit-appearance:none;text-align:center;box-sizing:border-box;outline:0;margin:0;-webkit-transition:.1s;transition:.1s;font-weight:500;padding:12px 20px;font-size:14px;border-radius:4px} .el-button:focus,.el-button:hover{color:#409eff;border-color:#c6e2ff;background-color:#ecf5ff} .el-button:active{color:#3a8ee6;border-color:#3a8ee6;outline:0} .el-button::-moz-focus-inner{border:0} .el-button.is-circle{border-radius:50%;padding:15px} #extraBtn .el-button.is-circle{padding:8px !important} @font-face{font-family:element-icons;src:url(https://cdn.bootcss.com/element-ui/2.12.0/theme-chalk/fonts/element-icons.woff) format("woff"),url(https://cdn.bootcss.com/element-ui/2.12.0/theme-chalk/fonts/element-icons.ttf) format("truetype");font-weight:400;font-display:auto;font-style:normal} </style> <div role="alert" class="el-notification fuck-task-logs right" style="bottom: 16px; z-index: 2000;"> <div class="el-notification__group"> <h2 id="extraBtn" class="el-notification__title"> <div class="el-badge item"><button id="checkUpdate" type="button" class="el-button el-button--default is-circle" title="检查更新"> <i class="el-icon-refresh"></i> </button><sup class="el-badge__content el-badge__content--undefined is-fixed is-dot" style="display: none;"></sup></div> <div class="el-badge item"><button id="fuck" type="button" class="el-button el-button--default is-circle" title="强制做任务"> <i class="el-icon-video-play"></i> </button><sup class="el-badge__content el-badge__content--undefined is-fixed is-dot" style="display: none;"></sup> </div> <div class="el-badge item"><button id="changeLog" type="button" class="el-button el-button--default is-circle" title="查看更新内容"> <i class="el-icon-document"></i> </button><sup class="el-badge__content el-badge__content--undefined is-fixed is-dot" style="display: none;"></sup></div> <div class="el-badge item"><button id="clearNotice" type="button" class="el-button el-button--default is-circle" title="清空执行日志"> <i class="el-icon-brush"></i> </button><sup class="el-badge__content el-badge__content--undefined is-fixed is-dot" style="display: none;"></sup></div> <div class="el-badge item"><button id="report" type="button" class="el-button el-button--default is-circle" title="提交建议/BUG"> <i class="el-icon-s-promotion"></i> </button><sup class="el-badge__content el-badge__content--undefined is-fixed is-dot" style="display: none;"></sup></div> </h2> <h2 class="el-notification__title">任务执行日志</h2> <div class="el-notification__content" style=""> <p></p> </li> </div> </div> </div>`) }, addNotice: function(data){ switch(data.type) { case "taskStatus": $('.el-notification__content').append('<li>' + data.task.task.name + ' <a href="' + data.task.data.url + '" target="_blank">' + (data.task.data.name||data.task.data.username) + '</a>|<font id="' + data.task.id + '" class="' + data.status +'">' + data.status +'</font></li>'); break; case "msg": $('.el-notification__content').append("<li>" + data.msg + "</li>"); break; case "authVerify": $('.el-notification__content').append('<li>' + data.name + ' |<font id="' + data.status.id + '" class="' + data.status.class +'">' + data.status.text + '</font></li>'); break; default: $('.el-notification__content').append("<li>" + data + "</li>"); break; } }, clearNotice:()=>{ $('.el-notification__content li').remove(); }, updateNotice: function(id, status){ $('font#' + id).removeClass() $('font#' + id).addClass(status) $('font#' + id).text(status) }, updateNotice1: function(data){ $('font#' + data.id).removeClass() $('font#' + data.id).addClass(data.class) $('font#' + data.id).text(data.text || data.class) } } try{ const checkTask = { reLoad: function (time,sum){ let date=new Date(); let hour=date.getHours(); let min=date.getMinutes()<10?("0"+date.getMinutes()):date.getMinutes(); if(GM_getValue("start")==1){ $(".border-bottom").text(hour+":"+min+" 执行新任务检测"); $.ajax({ url:"/entries/load", type:"get", headers:{'x-csrf-token': $('meta[name="csrf-token"]').attr('content')}, success:(data,status,xhr)=>{ if(data && (data.actions && (data.actions.length > sum) )){ if(debug)console.log(data); let date=new Date(); let hour=date.getHours(); let min=date.getMinutes()<10?("0"+date.getMinutes()):date.getMinutes(); $(".border-bottom").text(hour+":"+min+" 检测到新任务(暂停检测)"); $show({ title:"keyjoker新任务", msg:"keyjoker网站更新"+(data.actions.length-sum)+"个新任务!", icon:"https://www.keyjoker.com/favicon-32x32.png", time:0, onclick:function(){ //location.reload(true); } }); // 重载列表 noticeFrame.clearNotice(); func.reLoadTaskList(()=>{ func.do_task(data); }); GM_setValue("start", 0); checkSwitch(); }else{ setTimeout(()=>{ this.reLoad(time,sum); },time); } }, error:(err)=>{ window.location.reload(true); } }); } }, setTime: function (){ let time=prompt('请输入获取任务信息的时间间隔(单位:秒):'); if(!isNaN(time)){ GM_setValue("time",parseInt(time)); } }, start: function (r = null){ let time = GM_getValue("time"); if(!time){ time=60; } if(confirm("是否以时间间隔" + time + "秒进行任务检测?")){ GM_setValue("start",1); if(r)r(); this.next(); } }, next: function (){ // 初始化凭证获取状态 getAuthStatus.discord = false; getAuthStatus.spotify = false; getAuthStatus.steamStore = 0; getAuthStatus.steamCom = 0; getAuthStatus.tumblr = false; getAuthStatus.twitch = false; getAuthStatus.twitter = 0; let time = GM_getValue("time"); if(!time){ time=60; } let sum=$(".list-complete-item").length; if(sum>0){ this.reLoad(time*1000,sum); }else{ this.reLoad(time*1000,0); } } } const func = { // twitch & discord 凭证存储,人机验证处理 appHandle: function(){ switch(location.hostname) { case "www.twitch.tv": if(location.search == "?keyjokertask=storageAuth") { let cookie = document.cookie + ";" twitchAuth.updateTime = new Date().getTime(); if(cookie.match(/auth-token=(.+?);/) != null) { twitchAuth["auth-token"] = cookie.match(/auth-token=(.+?);/)[1] twitchAuth.status = 200; }else twitchAuth.status = 401; GM_setValue("twitchAuth", twitchAuth) console.log(twitchAuth) window.close(); } break; case "discord.com": if(location.search == "?keyjokertask=storageAuth") { discordAuth.authorization = JSON.parse(localStorage.getItem("token")); if(discordAuth.authorization == null)discordAuth.status = 401; else discordAuth.status = 200; discordAuth.updateTime = new Date().getTime(); GM_setValue("discordAuth", discordAuth); console.log(discordAuth) window.close(); } break; case "assets.hcaptcha.com": // 人机验证 func.hcaptcha2(); break; default : break; } }, authVerify:function(){ // noticeFrame.loadFrame(); noticeFrame.addNotice("检查各项凭证"); noticeFrame.addNotice({type: "authVerify", name: "<a href=\"https://discord.com/login/\" target=\"_blank\">Discord</a> Auth", status:{id: "discord", class: "wait", text:"ready"}}); noticeFrame.addNotice({type: "authVerify", name: "<a href=\"https://accounts.spotify.com/login/\" target=\"_blank\">Spotify</a> Auth ", status:{id: "spotify", class: "wait", text:"ready"}}); noticeFrame.addNotice({type: "authVerify", name: "<a href=\"https://steamcommunity.com/login/\" target=\"_blank\">Steam</a> Auth ", status:{id: "steam", class: "wait", text:"ready"}}); noticeFrame.addNotice({type: "authVerify", name: "<a href=\"https://www.tumblr.com/login\" target=\"_blank\">Tumblr</a> Auth", status:{id: "tumblr", class: "wait", text:"ready"}}); noticeFrame.addNotice({type: "authVerify", name: "<a href=\"https://www.twitch.tv/login\" target=\"_blank\">Twitch</a> Auth ", status:{id: "twitch", class: "wait", text:"ready"}}); noticeFrame.addNotice({type: "authVerify", name: "<a href=\"https://twitter.com/login/\" target=\"_blank\">Twitter</a> Auth", status:{id: "twitter", class: "wait", text:"ready"}}); this.discordAuthUpdate((status)=>{ this.statusReact(status, "discord"); }, true); this.spotifyGetAccessToken((status, ret = null)=>{ this.statusReact(status, "spotify"); }); this.steamInfoUpdate((status)=>{ this.statusReact(status, "steam"); }, "all", true); this.tumblrAuthUpdate((status, key = null)=>{ this.statusReact(status, "tumblr"); }, true); this.twitchAuthUpdate((status)=>{ this.statusReact(status, "twitch"); }, true); this.twitterAuthUpdate((status)=>{ this.statusReact(status, "twitter"); }, true); }, statusReact: (code, id)=>{ switch(code) { case 200: noticeFrame.updateNotice(id, 'success'); break; case 601: noticeFrame.updateNotice(id, 'error') break; case 401: noticeFrame.updateNotice1({id:id, class:"error", text:"Not Login"}) break; case 408: noticeFrame.updateNotice1({id:id, class:"error", text:"Time Out"}) break; case 603: noticeFrame.updateNotice1({id:id, class:"wait", text:"Getting Auth"}) break; case 604: noticeFrame.updateNotice1({id:id, class:"error", text:"Network Error"}) break; case 605: noticeFrame.updateNotice1({id:id, class:"error", text:"评论区未找到"}) break; default: noticeFrame.updateNotice1({id:id, class:"error", text:"Unknown Error"}) console.error("React Unknown Error--->" + code) break; } }, checkUpdate: function(){ noticeFrame.addNotice({type:"msg",msg:"正在检查版本信息...(当前版本:" + GM_info.script.version + ")"}) func.httpRequest({ url: 'https://task.jysafe.cn/keyjoker/script/update.php?type=ver', method: 'GET', headers:{action: "keyjoker"}, onload: (response) => { let ret = JSON.parse(response.response) if(ret.status != 200) { noticeFrame.addNotice({type:"msg", msg:"异常!<font class=\"error\">" + ret.msg + "</font>"}) return; } if(ret.ver > GM_info.script.version) { noticeFrame.addNotice({type:"msg", msg:"发现新版本!<font class=\"success\">" + ret.ver + "=>" + ret.msg + "</font>"}) }else if(ret.ver < GM_info.script.version){ noticeFrame.addNotice({type:"msg", msg:"震惊(○´・д・)ノ!<font class=\"success\">你的版本比最新版本还要新!</font>"}) }else if(ret.ver == GM_info.script.version){ noticeFrame.addNotice({type:"msg",msg:"当前已是最新版本!"}) }else{ noticeFrame.addNotice({type:"msg",msg:"<font class=\"error\">发生了未知异常!!</font>"}) } }, error:(ret)=>{ console.log(ret); noticeFrame.addNotice({type:"msg", msg:"请求异常!请至控制台查看详情!"}) }, anonymous:true }) }, // discord自动加入服务器(OK) discordJoinServerAuto: function(r, server){ this.discordAuthUpdate((ret)=>{ if(ret != 200) { r(ret); return; } this.httpRequest({ url: 'https://discord.com/api/v6/invites/' + server, method: 'POST', headers: { authorization: discordAuth.authorization, "content-type": "application/json"}, onload: (response) => { if (response.status === 200) { if(debug)console.log({ result: 'success', statusText: response.statusText, status: response.status }) r(200); } else { console.error(response); r(601); } }, error:(res)=>{ console.error(res); r(601); }, anonymous:true }) }) }, // discord自动退组服务器(OK) discordLeaveServerAuto: function(r, serverId){ this.discordAuthUpdate((ret)=>{ if(ret != 200) { r(ret); return; } $.ajax({ url: 'https://discord.com/api/v6/users/@me/guilds/' + serverId, method: 'DELETE', headers: { authorization: discordAuth.authorization, "content-type": "application/json"}, onload: (response) => { if (response.status === 604) { if(debug)console.log({ result: 'success', statusText: response.statusText, status: response.status }) r(604); } else { console.error(response); r(601); } }, error:(res)=>{ console.error(res); r(601); }, anonymous:true }) }) }, // discord凭证更新(OK) discordAuthUpdate:function(r, update = false){ if (new Date().getTime() - discordAuth.updateTime > 30 * 60 * 1000 || discordAuth.status != 200 || update) { r(603) new Promise((resolve, reject)=>{ if(false == getAuthStatus.discord || true === update) { getAuthStatus.discord = true; GM_openInTab("https://discord.com/channels/@me?keyjokertask=storageAuth", true); } let i = 0; let check = setInterval(()=>{ i++; if(GM_getValue("discordAuth") && new Date().getTime() - GM_getValue("discordAuth").updateTime <= 10 * 1000) { if(GM_getValue("discordAuth").status != 200) { clearInterval(check); reject(GM_getValue("discordAuth").status) return; } discordAuth.authorization = GM_getValue("discordAuth").authorization discordAuth.updateTime = GM_getValue("discordAuth").updateTime discordAuth.status = GM_getValue("discordAuth").status; clearInterval(check); resolve(discordAuth.status) } if(i >= 10) { clearInterval(check); reject(408) } }, 1000) }).then((ret)=>{ r(ret) }).catch((err)=>{ r(err) }) }else{ r(200) } }, // 做任务 do_task: function(data){ for(const task of data.actions) { noticeFrame.addNotice({type: "taskStatus", task:task, status:'start'}); this.runDirectUrl(task.redirect_url); let react = (code)=>{ switch(code) { case 200: noticeFrame.updateNotice(task.id, 'success') this.redeemAuto(task.redirect_url); break; case 601: noticeFrame.updateNotice(task.id, 'error') break; case 401: noticeFrame.updateNotice1({id:task.id, class:"error", text:"Not Login"}) break; case 408: noticeFrame.updateNotice1({id:task.id, class:"error", text:"Time Out"}) break; case 603: noticeFrame.updateNotice1({id:task.id, class:"wait", text:"Getting Auth"}) break; case 604: noticeFrame.updateNotice1({id:task.id, class:"error", text:"Network Error"}) break; case 605: noticeFrame.updateNotice1({id:task.id, class:"error", text:"评论区未找到"}) break; default: noticeFrame.updateNotice1({id:task.id, class:"error", text:"Unknown Error"}) console.error("React Unknown Error--->" + code) break; } } switch(task.task.name) { case "Join Steam Group": this.steamJoinGroupAuto(react, task.data.url); break; case "Rep Steam Account": this.steamRepAuto(react, task.data.id); break; case "Wishlist Steam Game": this.steamAddWishlistAuto(react, task.data.id); break; case "Follow Twitter Account": this.twitterFollowAuto(react, task.data); break; case "Join Discord Server": var server = task.data.url.split(".gg/")[1]; this.discordJoinServerAuto(react, server) break; case "Retweet Twitter Tweet": this.twitterRetweetAuto(react, task.data.url); break; case "Save Spotify Album": this.spotifySaveAuto(react, task.data); break; case "Follow Spotify Account": this.spotifyFollowAuto(react, task.data); break; case "Follow Twitch Channel": this.twitchFollowAuto(react, task.data.id); break; case "Follow Tumblr Blog": this.tumblrFollowAuto(react, task.data.name); break; default: noticeFrame.updateNotice1({id:task.id, class:"error", text:"Unknow Type:" + task.task.name}) console.error("未指定操作" + task.task.name) break; } } let i = 0; let completeCheck = setInterval(()=>{ i++; if(i >= 5)clearInterval(completeCheck); if($(".list-complete-item").length == 0) { noticeFrame.addNotice({type:"msg", msg:"任务似乎已完成,恢复监测!"}); GM_setValue("start", 1); checkSwitch(); checkTask.next(); clearInterval(completeCheck); } }, 5 * 1000) }, // [修改自https://greasyfork.org/zh-CN/scripts/370650] httpRequest: function (e) { const requestObj = {} requestObj.url = e.url requestObj.method = e.method.toUpperCase() requestObj.timeout = e.timeout || 30000 if (e.dataType) requestObj.responseType = e.dataType if (e.headers) requestObj.headers = e.headers if (e.data) requestObj.data = e.data if (e.cookie) requestObj.cookie = e.cookie if (e.anonymous) requestObj.anonymous = e.anonymous if (e.onload) requestObj.onload = e.onload if (e.fetch) requestObj.fetch = e.fetch if (e.onreadystatechange) requestObj.onreadystatechange = e.onreadystatechange requestObj.ontimeout = e.ontimeout || function (data) { if (debug) console.log(data) if (e.status) e.status.error('Error:Timeout(0)') if (e.r) e.r({ result: 'error', statusText: 'Timeout', status: 0, option: e }) } requestObj.onabort = e.onabort || function (data) { if (debug) console.log(data) if (e.status) e.status.error('Error:Aborted(0)') if (e.r) e.r({ result: 'error', statusText: 'Aborted', status: 0, option: e }) } requestObj.onerror = e.onerror || function (data) { if (debug) console.log(data) if (e.status) e.status.error('Error:Error(0)') if (e.r) e.r({ result: 'error', statusText: 'Error', status: 0, option: e }) } if (debug) console.log('发送请求:', requestObj) GM_xmlhttpRequest(requestObj); }, // 人机验证出现图片时的处理 hcaptcha2: function () { let hcaptcha2Click=setInterval(()=>{ if(document.getElementsByClassName("challenge-container").length != 0 && document.getElementsByClassName("challenge-container")[0].children.length != 0) { clearInterval(hcaptcha2Click); console.log("open hcaptcha"); let text = document.getElementsByClassName("prompt-text")[0].innerText; document.getElementsByClassName("prompt-text")[0].innerText = text + "\n正在自动获取免验证Cookie"; //$(".task-grid").remove(); //$(".challenge-example").remove(); this.httpRequest({ url: 'https://accounts.hcaptcha.com/accessibility/get_cookie', method: 'GET', headers: { 'Content-Type': 'application/json'}, onload: (response) => { GM_log(response) if(response.status == 200) { document.getElementsByClassName("prompt-text")[0].innerText = text + "\n免验证Cookie获取成功,请重新点击验证框"; }else if(response.status == 401) { document.getElementsByClassName("prompt-text")[0].innerText = text + "\n当前账号或IP的免验证Cookie获取次数已达上限,请更换hcaptcha账号或IP"; // setTimeout(()=>{window.open("https://dashboard.hcaptcha.com/welcome_accessibility")}, 3000); }else if(response.status == 500) { document.getElementsByClassName("prompt-text")[0].innerText = text + "\n未登录hCaptcha"; // setTimeout(()=>{window.open("https://dashboard.hcaptcha.com/welcome_accessibility")}, 3000); }else{ console.error(response); document.getElementsByClassName("prompt-text")[0].innerText = text + "\n发生未知错误,已将数据记录至控制台"; } }, error: () =>{ if(debug)console.error("error"); } }) } },1000); }, // OK redeemAuto: function(redirect_url){ if(0 != $('a[href="' + redirect_url + '"]').length)$('a[href="' + redirect_url + '"]').next().click(); }, reLoadTaskList: function(r){ // 重载任务列表 if(2 == document.getElementsByClassName('row').length) { $('.row')[1].remove(); $('.layout-container').append('<entries-component></entries-component>'); if(true == GM_getValue("offlineMode") && typeof offlineData === "object") { offlineData["app.js"](); r(); }else{ $.getScript("/js/app.js", (rep,status)=>{ if("success" == status)r(); else console.error(status, rep); }); } }else { r(); } }, reset: function (){ if(!confirm("你确定要执行重置操作?"))return; noticeFrame.addNotice({type:"msg",msg:"正在重置设置"}) const listValues = GM_listValues() for (const value of listValues) { if(value == "currentVer")continue; noticeFrame.addNotice({type:"msg",msg:"<font class=\"error\">正在删除:" + value + "</font>"}) GM_deleteValue(value) } noticeFrame.addNotice({type:"msg",msg:"设置重置完毕"}) }, // OK spotifySaveAuto: function(r, data, del = false){ this.spotifyGetUserInfo((status, accessToken = null, userId = null)=>{ if(status != 200) { r(status); return; } let putUrl = ""; new Promise((resolve, reject)=>{ switch(data.type) { case "album": putUrl = "https://spclient.wg.spotify.com/collection-view/v1/collection/albums/" + userId + "?base62ids=" + data.id + "&model=bookmark"; resolve(putUrl); break; case "track": this.httpRequest({ url: 'https://api.spotify.com/v1/tracks?ids=' + data.id + '&market=from_token', method: 'GET', headers:{authorization: "Bearer " + accessToken}, onload: (response) => { if(response.status == 200) { let temp = JSON.parse(response.response); putUrl = "https://spclient.wg.spotify.com/collection-view/v1/collection/albums/" + userId + "?base62ids=" + temp.tracks[0].album.id + "&model=bookmark"; resolve(putUrl); }else { console.error(response); reject(601); } }, error:(res)=>{ console.error(res); reject(601); }, anonymous:true }) break; default: console.error("spotifySaveAuto未知类型:", data); r(601); return; break; } }).then((putUrl)=>{ if(debug)console.log(putUrl) $.ajax({ type: !del?'PUT':"DELETE", url: putUrl, headers: {authorization: "Bearer " + accessToken}, success: function(data){ console.log(data); r(200); }, error: function(data){ console.error(data); r(601); }, anonymous:true }); }) }); }, // OK spotifyFollowAuto: function(r, data, del = false){ this.spotifyGetUserInfo((status, accessToken = null)=>{ if(status != 200) { r(status) return; } let putUrl = ""; switch(data.type) { case "artist": putUrl = "https://api.spotify.com/v1/me/following?type=artist&ids=" + data.id; break; case "playlist": putUrl = "https://api.spotify.com/v1/playlists/" + data.id + "/followers" break; case "user": putUrl = "https://api.spotify.com/v1/me/following?type=user&ids=" + data.id; break; default: console.error(data); r(601); return; break; } $.ajax({ type: !del?'PUT':"DELETE", url: putUrl, headers: {authorization: "Bearer " + accessToken}, success: function(data){ r(200); }, error: function(data){ console.error(data); r(604); }, anonymous:true }); }); }, // OK spotifyGetUserInfo: function(r){ r(603) this.spotifyGetAccessToken( (status, accessToken)=>{ if(status != 200) { r(status); return; } this.httpRequest({ url: 'https://api.spotify.com/v1/me', method: 'GET', headers:{authorization: "Bearer " + accessToken}, onload: (response) => { if (response.status === 200) { r(200, accessToken, JSON.parse(response.responseText).id); } else { console.error(response) r(401); } }, error:(res)=>{ console.error("error"); r(604); }, anonymous:true }) } ) }, // OK spotifyGetAccessToken: function(r){ r(603); this.httpRequest({ url: 'https://open.spotify.com/get_access_token?reason=transport&productType=web_player', method: 'GET', onload: (response) => { if (response.status === 200) { r(200, JSON.parse(response.responseText).accessToken); } else { console.log(response); r(401); } }, error:(res)=>{ if(debug)console.log(res); r(604); } }) }, // =====================Steam Start====================== // steam信息更新(In Progress)[修改自https://greasyfork.org/zh-CN/scripts/370650] steamInfoUpdate: function (r, type = 'all', update = false) { r(603); if (type === 'community' || type === 'all') { if (new Date().getTime() - steamInfo.comUpdateTime > 10 * 60 * 1000 || update) { if(603 == getAuthStatus.steamCom) { let i = 0; let steamCheck = setInterval(()=>{ i++; if(603 != getAuthStatus.steamCom) { clearInterval(steamCheck); r(getAuthStatus.steamCom); } if(i >= 10) { clearInterval(steamCheck); r(408); } }, 1000) return; } getAuthStatus.steamCom = 603; new Promise((resolve, reject) => { this.httpRequest({ url: 'https://steamcommunity.com/my', method: 'GET', onload: (response) => { if (response.status === 200) { if ($(response.responseText).find('a[href*="/login/home"]').length > 0) { getAuthStatus.steamCom = 401; reject(401); } else { const steam64Id = response.responseText.match(/g_steamID = "(.+?)";/); const communitySessionID = response.responseText.match(/g_sessionID = "(.+?)";/); const userName = response.responseText.match(/steamcommunity.com\/id\/(.+?)\/friends\//); if (steam64Id) steamInfo.steam64Id = steam64Id[1]; if (communitySessionID) steamInfo.communitySessionID = communitySessionID[1]; if (userName) steamInfo.userName = userName[1]; getAuthStatus.steamCom = 200; resolve(200); } } else { console.error(response); getAuthStatus.steamCom = 601; reject(601); } }, r: resolve }) }).then((ret) => { if(ret == 200) { steamInfo.comUpdateTime = new Date().getTime(); GM_setValue('steamInfo', steamInfo); } r(ret); }).catch(err => { console.error(err); r(err); }) } else { r(200); } } if (type === 'store' || type === 'all') { if (new Date().getTime() - steamInfo.storeUpdateTime > 10 * 60 * 1000 || update) { if(603 == getAuthStatus.steamStore) { let i = 0; let steamCheck = setInterval(()=>{ i++; if(603 != getAuthStatus.steamStore) { clearInterval(steamCheck); r(getAuthStatus.steamStore); } if(i >= 10) { clearInterval(steamCheck); r(408); } }, 1000) return; } getAuthStatus.steamStore = 603; new Promise((resolve, reject) => { this.httpRequest({ url: 'https://store.steampowered.com/stats/', method: 'GET', onload: (response) => { if (response.status === 200) { if ($(response.responseText).find('a[href*="/login/"]').length > 0) { if (debug) console.log(response) getAuthStatus.steamStore = 401; reject(401) } else { const storeSessionID = response.responseText.match(/g_sessionID = "(.+?)";/) if (storeSessionID) steamInfo.storeSessionID = storeSessionID[1] getAuthStatus.steamStore = 200; resolve(200); } } else { console.error(response); getAuthStatus.steamStore = 601; reject(601); } }, r: resolve }) }).then((ret) => { if(ret == 200) { steamInfo.storeUpdateTime = new Date().getTime(); GM_setValue('steamInfo', steamInfo); } r(ret) }).catch(err => { console.error(err); r(err); }) } else { r(200) } } }, // steam个人资料回复"+rep"(OK) steamRepAuto: function(r, id){ this.steamRepHisCheck((status, ret = null) => { if(status != 200) { r(status); return; } if(!ret){ this.httpRequest({ url: 'https://steamcommunity.com/comment/Profile/post/' + id + '/-1/', method: 'POST', data: $.param({comment:'+rep',count:6,sessionid:steamInfo.communitySessionID,feature2:-1}), headers:{'content-type': 'application/x-www-form-urlencoded'}, onload: (response) => { if(response.status == 200) { let ret = JSON.parse(response.response) if(ret.success == true)r(200); else{ console.error("发送评论失败", response); r(601); } }else{ console.error("评论返回值异常", response); r(601); } }, error: (err)=>{ console.error("请求发送异常", err); r(601); } }) }else{ r(200); } },id) }, steamRepHisCheck: function (r, id){ this.steamInfoUpdate((ret) => { if(ret != 200) { r(ret); return; } this.httpRequest({ url: "https://steamcommunity.com/profiles/" + id, method: 'GET', onload: (response) => { if(response.status == 200) { let comments = response.responseText.match(/commentthread_comments([\s\S]*)commentthread_footer/); if(debug)console.log(comments); if(comments != null)r(200, comments[1].includes(steamInfo.steam64Id) || comments[1].includes(steamInfo.userName)); else r(605); }else{ console.error("检查评论记录返回异常", response); r(601); } } //,anonymous:true }); }, "community") }, // steam加组(OK)[修改自https://greasyfork.org/zh-CN/scripts/370650] steamJoinGroupAuto: function (r, url) { this.steamInfoUpdate((ret) => { if(ret != 200) { r(ret); return; } this.httpRequest({ url: url, method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' }, data: $.param({ action: 'join', sessionID: steamInfo.communitySessionID }), onload: (response) => { if (response.status === 200 && !response.responseText.includes('grouppage_join_area')) { if(response.responseText.match(/<h3>(.+?)<\/h3>/) && response.responseText.match(/<h3>(.+?)<\/h3>/)[1] != "您已经是该组的成员了。") { console.error(response); r(601); }else r(200); } else { console.error(response); r(601); } } }) }, 'community'); }, // steam退组 steamLeaveGroupAuto: function (r, url) { let groupName = url.split('s/')[1]; this.steamGetGroupID(groupName, (groupName, groupId) => { var postUrl = ""; postUrl = (steamInfo.userName) ? 'https://steamcommunity.com/id/' + steamInfo.userName + '/home_process' : 'https://steamcommunity.com/profiles/' + steamInfo.steam64Id + '/home_process' this.httpRequest({ url: postUrl, method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' }, data: $.param({ sessionID: steamInfo.communitySessionID, action: 'leaveGroup', groupId: groupId }), onload: (response) => { if (response.status === 200 && response.finalUrl.includes('groups') && $(response.responseText.toLowerCase()).find(`a[href='https://steamcommunity.com/groups/${groupName.toLowerCase()}']`).length === 0) { r(200); } else { console.error(response); r(601); } }, r }) }) }, steamGetGroupID: function (groupName, callback) { this.steamInfoUpdate((ret) => { if(ret != 200) { r(ret); return; } new Promise(resolve => { this.httpRequest({ url: 'https://steamcommunity.com/groups/' + groupName, method: 'GET', headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' }, onload: function (response) { if (debug) console.log(response) if (response.status === 200) { const groupId = response.responseText.match(/OpenGroupChat\( '([0-9]+)'/) if (groupId === null) { console.error(response) resolve(false) } else { resolve(groupId[1]) } } else { console.error(response) resolve(false) } }, r: () => { resolve(false) } }) }).then(groupId => { if (groupId !== false && callback) callback(groupName, groupId); }).catch(err => { console.error(err); }) }) }, // steam加愿望单(In Progress)[修改自https://greasyfork.org/zh-CN/scripts/370650] steamAddWishlistAuto: function (r, gameId) { this.steamInfoUpdate((ret) => { if(ret != 200) { r(ret); return; } new Promise(resolve => { this.httpRequest({ url: 'https://store.steampowered.com/api/addtowishlist', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' }, data: $.param({ sessionid: steamInfo.storeSessionID, appid: gameId }), dataType: 'json', onload: function (response) { if (debug) console.log(response) if (response.status === 200 && response.response && response.response.success === true) { resolve({ result: 'success', statusText: response.statusText, status: response.status }) } else { resolve({ result: 'error', statusText: response.statusText, status: response.status }) } }, onabort: response => { resolve({ result: 'error', statusText: response.statusText, status: response.status }) }, onerror: response => { resolve({ result: 'error', statusText: response.statusText, status: response.status }) }, ontimeout: response => { resolve({ result: 'error', statusText: response.statusText, status: response.status }) }, r: resolve }) }).then(result => { if (result.result === 'success') { r(200) } else { this.httpRequest({ url: 'https://store.steampowered.com/app/' + gameId, method: 'GET', onload: function (response) { if (debug) console.log(response) if (response.status === 200) { if (response.responseText.includes('class="queue_actions_ctn"') && response.responseText.includes('已在库中')) { r(200) } else if ((response.responseText.includes('class="queue_actions_ctn"') && response.responseText.includes('添加至您的愿望单')) || !response.responseText.includes('class="queue_actions_ctn"')) { console.error(response); r(601); } else { r(200); } } else { console.error(response); r(601); } }, r }) } }).catch(err => { console.error(err); r(601); }) },'store') }, // steam移除愿望单(In Progress)[修改自https://greasyfork.org/zh-CN/scripts/370650] steamRemoveWishlistAuto: function (r, gameId) { this.steamInfoUpdate(() => { new Promise(resolve => { this.httpRequest({ url: 'https://store.steampowered.com/api/removefromwishlist', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' }, data: $.param({ sessionid: steamInfo.storeSessionID, appid: gameId }), dataType: 'json', onload: function (response) { if (response.status === 200 && response.response && response.response.success === true) { resolve({ result: 'success', statusText: response.statusText, status: response.status }) } else { resolve({ result: 'error', statusText: response.statusText, status: response.status }) } }, onabort: response => { resolve({ result: 'error', statusText: response.statusText, status: response.status }) }, onerror: response => { resolve({ result: 'error', statusText: response.statusText, status: response.status }) }, ontimeout: response => { resolve({ result: 'error', statusText: response.statusText, status: response.status }) }, r: resolve }) }).then(result => { if (result.result === 'success') { r(200); } else { this.httpRequest({ url: 'https://store.steampowered.com/app/' + gameId, method: 'GET', onload: function (response) { if (response.status === 200) { if (response.responseText.includes('class="queue_actions_ctn"') && (response.responseText.includes('已在库中') || response.responseText.includes('添加至您的愿望单'))) { r(200); } else { console.error(response); r(601); } } else { console.error(response); r(601); } }, r }) } }).catch(err => { console.error(err); r(601); }) }) }, // ============Tumblr Start========= // tumblr关注博客(OK) tumblrFollowAuto: function(r, name){ this.tumblrAuthUpdate((status, key = false)=>{ if(status != 200) { r(status); return; } if(false != key){ this.httpRequest({ url: 'https://www.tumblr.com/svc/follow', method: 'POST', headers: {"x-tumblr-form-key": key, "Content-Type": "application/x-www-form-urlencoded"}, data: $.param({'data[tumblelog]': name}), onload: (response) => { if(response.status == 200) { r(200); }else { console.error(response); r(601); } } }) }else{ console.error("tumblrFollowAuto->key值错误"); r(601); } }) }, // tumblr取消关注博客 tumblrUnfollowAuto: function(r, name){ this.tumblrAuthUpdate((status, key = false)=>{ if(status != 200) { r(status); return; } if(false != key){ this.httpRequest({ url: 'https://www.tumblr.com/svc/unfollow', method: 'POST', headers: {"x-tumblr-form-key": key, "Content-Type": "application/x-www-form-urlencoded"}, data: $.param({'data[tumblelog]': name}), onload: (response) => { if(response.status == 200) { r(200); }else{ console.error(response); r(601); } } }) }else{ r(601); } }) }, // tumblr获取请求头key(OK) tumblrAuthUpdate:function(r, update = false){ r(603) this.httpRequest({ url: 'https://www.tumblr.com/dashboard/iframe', method: 'GET', onload: (response) => { if(response.status == 200) { let key = response.responseText.match(/id="tumblr_form_key" content="(.+?)">/) if(key){ if(-1 != key.indexOf("!123") && -1 !=key.indexOf("|") ) { r(401); return; }else r(200, key); } else{ console.error("tumblrGetKey->get key failed.", response); r(601); } }else{ console.error(response); r(601); } } }) }, // ============Twitch Start========= // twitch关注(OK) twitchFollowAuto: function(r, channelId){ this.twitchAuthUpdate((status)=>{ if(status != 200) { r(status); return; } this.httpRequest({ url: 'https://gql.twitch.tv/gql', method: 'POST', headers: { Authorization: "OAuth " + twitchAuth["auth-token"]}, data: '[{"operationName":"FollowButton_FollowUser","variables":{"input":{"disableNotifications":false,"targetID":"' + channelId + '"}},"extensions":{"persistedQuery":{"version":1,"sha256Hash":"3efee1acda90efdff9fef6e6b4a29213be3ee490781c5b54469717b6131ffdfe"}}}]', onload: (response) => { if (response.status === 200) { r(200); } else if(response.status === 401){ twitchAuth.updateTime = 0; GM_setValue("twitchAuth", null); r(401); }else{ console.error(response); r(601); } } }) }) }, // twitch关注(OK) twitchUnfollowAuto: function(r, channelId){ this.twitchAuthUpdate((status)=>{ if(status != 200) { r(status); return; } this.httpRequest({ url: 'https://gql.twitch.tv/gql', method: 'POST', headers: { Authorization: "OAuth " + twitchAuth["auth-token"]}, data: '[{"operationName":"FollowButton_UnfollowUser","variables":{"input":{"targetID":"' + channelId + '"}},"extensions":{"persistedQuery":{"version":1,"sha256Hash":"d7fbdb4e9780dcdc0cc1618ec783309471cd05a59584fc3c56ea1c52bb632d41"}}}]', onload: (response) => { if (response.status === 200) { r(200); } else if(response.status === 401){ twitchAuth.updateTime = 0; GM_setValue("twitchAuth", null); r(401); }else{ console.error(response); r(601); } } }) }) }, // 弃用 twitchGetId: function(r, channels){ this.httpRequest({ url: 'https://api.twitch.tv/api/channels/' + channels + '/access_token?oauth_token=' + GM_getValue("twitchAuth").match(/auth-token=(.+?); /)[1] + '&need_https=true&platform=web&player_type=site&player_backend=mediaplayer', method: 'GET', onload: (response) => { if (response.status === 200) { let rep = JSON.parse(JSON.parse(response.responseText).token); r(rep.channel_id); } else { console.error(response); r('error') } }, error:(res)=>{ console.error(res); }, anonymous:true }) }, // twitch凭证更新(OK) twitchAuthUpdate:function(r, update = false){ if (new Date().getTime() - twitchAuth.updateTime > 30 * 60 * 1000 || twitchAuth.status != 200 || update) { r(603) new Promise((resolve, reject)=>{ if(false == getAuthStatus.twitch || true === update) { getAuthStatus.twitch = true; GM_openInTab("https://www.twitch.tv/settings/profile?keyjokertask=storageAuth", true); } let i = 0; let check = setInterval(()=>{ i++; if(GM_getValue("twitchAuth") && new Date().getTime() - GM_getValue("twitchAuth").updateTime <= 10 * 1000) { if(GM_getValue("twitchAuth").status != 200) { clearInterval(check); reject(401); return; } twitchAuth["auth-token"] = GM_getValue('twitchAuth')["auth-token"]; twitchAuth.updateTime = GM_getValue('twitchAuth').updateTime; twitchAuth.status = GM_getValue('twitchAuth').status; clearInterval(check); resolve(200) } if(i >= 10) { clearInterval(check); reject(408) } }, 1000) }).then((ret)=>{ r(ret); }).catch((err)=>{ r(err); }) }else{ r(200) } }, // ==========Twitter Start======== // 推特关注用户(OK) twitterFollowAuto: function(r, data){ this.twitterAuthUpdate((status)=>{ if(status != 200) { r(status); return; } this.twitterGetUserInfo((status, userId = null)=>{ if(200 != status) { r(601); return; } this.httpRequest({ url: 'https://api.twitter.com/1.1/friendships/create.json', method: 'POST', headers: { authorization: "Bearer " + twitterAuth.authorization, 'Content-Type': 'application/x-www-form-urlencoded', 'x-csrf-token':twitterAuth.ct0}, data: $.param({ include_profile_interstitial_type: 1,include_blocking: 1,include_blocked_by: 1,include_followed_by: 1,include_want_retweets: 1,include_mute_edge: 1,include_can_dm: 1,include_can_media_tag: 1,skip_status: 1,id: userId}), onload: (response) => { if (response.status === 200) { r(200); } else { console.error(response); twitterAuth.updateTime = 0; GM_setValue("twitterAuth", twitterAuth); r(601); } } }) },data.username) }) }, // 推特取消关注用户(OK) twitterUnfollowAuto: function(r, data){ this.twitterAuthUpdate((status)=>{ if(status != 200) { r(status); return; } this.twitterGetUserInfo((userId)=>{ if(debug)console.log(userId) if("error" == userId) { r(601); return; } this.httpRequest({ url: 'https://api.twitter.com/1.1/friendships/destroy.json', method: 'POST', headers: { authorization: "Bearer " + twitterAuth.authorization, 'Content-Type': 'application/x-www-form-urlencoded', 'x-csrf-token':twitterAuth.ct0}, data: $.param({ include_profile_interstitial_type: 1,include_blocking: 1,include_blocked_by: 1,include_followed_by: 1,include_want_retweets: 1,include_mute_edge: 1,include_can_dm: 1,include_can_media_tag: 1,skip_status: 1,id: userId}), onload: (response) => { if (response.status === 200) { r(200); } else { console.error(response); twitterAuth.updateTime = 0; GM_setValue("twitterAuth", twitterAuth); r(601); } } }) },data.username) }) }, // 推特转推(OK) twitterRetweetAuto: function(r, url){ let retweetId = url.split("status/")[1]; this.twitterAuthUpdate((status)=>{ if(status != 200) { r(status); return; } this.httpRequest({ url: 'https://api.twitter.com/1.1/statuses/retweet.json', method: 'POST', headers: { authorization: "Bearer " + twitterAuth.authorization, 'Content-Type': 'application/x-www-form-urlencoded', 'x-csrf-token':twitterAuth.ct0}, data: $.param({ tweet_mode: "extended",id: retweetId}), onload: (response) => { if (response.status === 200 || (response.status === 403 && response.responseText == '{"errors":[{"code":327,"message":"You have already retweeted this Tweet."}]}')) { r(200); } else { console.error(response); twitterAuth.updateTime = 0; GM_setValue("twitterAuth", twitterAuth); r(601); } } }) }) }, // 推特根据用户名获取用户id(OK) twitterGetUserInfo: function(r, userName){ if(debug)console.log("====twitterGetUserInfo===="); this.httpRequest({ url: 'https://api.twitter.com/graphql/-xfUfZsnR_zqjFd-IfrN5A/UserByScreenName?variables=%7B%22screen_name%22%3A%22' + userName + '%22%2C%22withHighlightedLabel%22%3Atrue%7D', method: 'GET', headers: { authorization: "Bearer " + twitterAuth.authorization, "content-type": "application/json"}, onload: (response) => { if (response.status === 200) { r(200, JSON.parse(response.responseText).data.user.rest_id); } else { console.error(response); r(601); } }, error:(res)=>{ console.error(res); r(601); }, anonymous:true }) }, // 推特取得用户页面响应头(OK) twitterAP:function(r){ this.httpRequest({ url: 'https://twitter.com/settings/account?k', method: 'GET', onload: (response) => { if (response.status === 200) { r(200, response.responseHeaders) } else { console.error(response); r(601); } }, error:(res)=>{ console.error(res); r(601); } }) }, // 推特凭证更新(OK) twitterAuthUpdate:function(r, update = false){ r(603); if(new Date().getTime() - twitterAuth.updateTime > 30 * 60 * 1000 || update){ if(603 == getAuthStatus.twitter) { let i = 0; let twitterCheck = setInterval(()=>{ i++; if(GM_getValue("twitterAuth") && new Date().getTime() - GM_getValue("twitterAuth").updateTime <= 5 * 1000 || getAuthStatus.twitter != 603) { clearInterval(twitterCheck); r(getAuthStatus.twitter); } if(i >= 10) { clearInterval(twitterCheck); r(408); } }, 1000); return; } getAuthStatus.twitter = 603; new Promise((resolve, reject) => { this.twitterAP((status, ret = null)=>{ if(status != 200) { reject(status); } let t = ret.match(/ct0=(.+?);/); if(t == null) { getAuthStatus.twitter = 401; reject(401); return; } let xcf = t[1]; // let ct0 = xcf; if(ct0) { twitterAuth.ct0 = ct0; getAuthStatus.twitter = 200; resolve(200) }else{ getAuthStatus.twitter = 401; reject(401) } // /*this.httpRequest({ url: 'https://api.twitter.com/1.1/jot/client_event.json', method: 'POST', headers: { authorization: "Bearer " + twitterAuth.authorization,"x-csrf-token":xcf , "content-type": "application/json"}, data: "category=perftown&log=%5B%7B%22description%22%3A%22rweb%3Aseen_ids%3Apersistence%3Aget%3Asuccess%22%2C%22product%22%3A%22rweb%22%2C%22duration_ms%22%3A568%7D%2C%7B%22description%22%3A%22rweb%3Aseen_ids%3Apersistence%3Aget%3Asuccess%22%2C%22product%22%3A%22rweb%22%2C%22duration_ms%22%3A571%7D%2C%7B%22description%22%3A%22rweb%3Ainit%3AstorePrepare%22%2C%22product%22%3A%22rweb%22%2C%22duration_ms%22%3A581%7D%2C%7B%22description%22%3A%22rweb%3Attft%3AperfSupported%22%2C%22product%22%3A%22rweb%22%2C%22duration_ms%22%3A1%7D%2C%7B%22description%22%3A%22rweb%3Attft%3Aconnect%22%2C%22product%22%3A%22rweb%22%2C%22duration_ms%22%3A22%7D%2C%7B%22description%22%3A%22rweb%3Attft%3Aprocess%22%2C%22product%22%3A%22rweb%22%2C%22duration_ms%22%3A1497%7D%2C%7B%22description%22%3A%22rweb%3Attft%3Aresponse%22%2C%22product%22%3A%22rweb%22%2C%22duration_ms%22%3A425%7D%2C%7B%22description%22%3A%22rweb%3Attft%3Ainteractivity%22%2C%22product%22%3A%22rweb%22%2C%22duration_ms%22%3A2217%7D%5D", onload: (response) => { if (response.status === 200) { let ct0 = response.responseHeaders.match(/ct0=(.+?);/)[1] if(ct0) { twitterAuth.ct0 = ct0; getAuthStatus.twitter = 200; resolve(200) }else{ getAuthStatus.twitter = 401; reject(401) } } else { console.error(response); getAuthStatus.twitter = 401; reject(401) } }, error:(res)=>{ console.error(res); reject(601) } })*/ }) }).then((status)=>{ if(status == 200) { twitterAuth.updateTime = new Date().getTime() GM_setValue("twitterAuth", twitterAuth) r(status); }else{ r(status); } }).catch((err)=>{ r(err); }) }else{ r(200); } }, // ==========Twitter End======== runDirectUrl:function(direct_url){ GM_log("====访问跳转链接====") this.httpRequest({ url: direct_url, method: 'GET', headers: {'x-csrf-token': $('meta[name="csrf-token"]').attr('content')}, onload: (response) => { }, error:(res)=>{ } }) }, test: function(){ this.twitterAuthUpdate(console.log, true); } } // ============Start=========== if(location.pathname == "/entries") { window.onload=()=>{ GM_log("main") if(document.getElementsByClassName("nav-item active").length != 0 && document.getElementsByClassName("nav-item active")[0].innerText == "Earn Credits" && document.getElementById("logout-form")) { noticeFrame.loadFrame(); // 事件绑定 eventBind(); //let isStart=setInterval(()=>{ if(GM_getValue("start")==1){ //clearInterval(isStart); checkTask.next(); } //},1000); checkUpdate(); }else{ if($('.container').length > 0) { let i = 0; let check = setInterval(()=>{ i++; if($('.container')[0].innerText == "Whoops, looks like something went wrong.")location.href = location.pathname if(i >= 10)clearInterval(check) }, 1000); } } } }else{ func.appHandle(); } function checkUpdate(){ // 隔一段时间检测新版本 if(new Date().getTime() - (GM_getValue("lastCheckUpdate") || 0) > 6 * 60 * 60 * 1000) { func.checkUpdate(); GM_setValue("lastCheckUpdate", new Date().getTime()) } } function eventBind(){ $('button#checkUpdate').click(()=>{func.checkUpdate()}) $('button#fuck').click(function(){ checkTask.start(()=>{$('.card').remove();}) }) $('button#clearNotice').click(function(){ noticeFrame.clearNotice() }) $('button#changeLog').click(function(){ noticeFrame.addNotice({type:"msg", msg:"获取日志中..."}) func.httpRequest({ url: 'https://task.jysafe.cn/keyjoker/script/update.php?type=changelog&ver=' + GM_info.script.version, method: 'GET', headers:{action: "keyjoker"}, onload: (response) => { let ret = JSON.parse(response.response) if(ret.status != 200) { noticeFrame.addNotice({type:"msg", msg:"异常!<font class=\"error\">" + ret.msg + "</font>"}) }else { noticeFrame.addNotice({type:"msg", msg:"<font class=\"success\">" + ret.msg + "</font>"}) } }, error:(ret)=>{ console.log(ret); noticeFrame.addNotice({type:"msg", msg:"<font class=\"error\">请求异常!请至控制台查看详情!</font>"}) }, anonymous:true }) }) $('button#report').click(function(){ noticeFrame.addNotice({type:"msg",msg:"目前提供以下反馈渠道:"}) noticeFrame.addNotice({type:"msg",msg:"<a href=\"https://www.jysafe.cn/4332.air\" target=\"_blank\">博客页面</a>"}) noticeFrame.addNotice({type:"msg",msg:"<a href=\"https://github.com/jiyeme/keyjokerScript/issues/new/choose\" target=\"_blank\">GitHub</a>"}) noticeFrame.addNotice({type:"msg",msg:"<a href=\"https://keylol.com/t660181-1-1\" target=\"_blank\">其乐社区</a>"}) }) // 版本升级后显示一次更新日志 if(GM_getValue("currentVer") != GM_info.script.version) { func.httpRequest({ url: 'https://task.jysafe.cn/keyjoker/script/update.php?type=changelog&ver=' + GM_info.script.version, method: 'GET', headers:{action: "keyjoker"}, onload: (response) => { let ret = JSON.parse(response.response) if(ret.status != 200) { noticeFrame.addNotice({type:"msg", msg:"异常!<font class=\"error\">" + ret.msg + "</font>"}) }else { noticeFrame.addNotice({type:"msg", msg:"<font class=\"success\">" + ret.msg + "</font>"}) } }, error:(ret)=>{ console.log(ret); noticeFrame.addNotice({type:"msg", msg:"更新日志获取异常!请至控制台查看详情!"}) }, anonymous:true }) GM_setValue("currentVer", GM_info.script.version) } } GM_registerMenuCommand("设置时间间隔", checkTask.setTime); GM_registerMenuCommand("重置设置", func.reset); GM_registerMenuCommand("凭证检测",()=>{ func.authVerify(); }); function offlineSwitch(id){ GM_unregisterMenuCommand(id); if(true == GM_getValue("offlineMode")){ let id = GM_registerMenuCommand("进入稳定模式",()=>{ GM_setValue("offlineMode", false); offlineSwitch(id); }); }else{ let id = GM_registerMenuCommand("进入极速模式",()=>{ GM_setValue("offlineMode", true); offlineSwitch(id); }); } } function checkSwitch(){ GM_unregisterMenuCommand(checkSwitchId); if(1 == GM_getValue("start")){ checkSwitchId = GM_registerMenuCommand("停止检测",()=>{ let date=new Date(); let hour=date.getHours(); let min=date.getMinutes()<10?("0"+date.getMinutes()):date.getMinutes(); GM_setValue("start",0); $(".border-bottom").text(hour + ":" + min + " 停止执行新任务检测"); checkSwitch(); }); }else{ checkSwitchId = GM_registerMenuCommand("开始检测",()=>{ checkTask.start(); checkSwitch(); }); } } checkSwitch(null); offlineSwitch(null); if(debug) { GM_registerMenuCommand("Test",()=>{ func.test(); }); } } catch (e) { setTimeout(() => { noticeFrame.addNotice({ type: 'msg', msg:"<font class\"error\">任务脚本执行期间发生预期之外的错误,详情见控制台</font>" }) }, 500) console.log('%c%s', 'color:white;background:red', e.stack) } })();