KeyJoker Auto Task

KeyJoker Auto Task,修改自https://greasyfork.org/zh-CN/scripts/383411

当前为 2021-07-21 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name KeyJoker Auto Task
  3. // @namespace KeyJokerAutoTask
  4. // @version 0.9.1
  5. // @description KeyJoker Auto Task,修改自https://greasyfork.org/zh-CN/scripts/383411
  6. // @author 祭夜
  7. // @icon https://www.jysafe.cn/assets/images/avatar.jpg
  8. // @include *://www.keyjoker.com/entries*
  9. // @include *://assets.hcaptcha.com/*
  10. // @include *://discord.com/channels/@me?keyjokertask=storageAuth
  11. // @include *://www.twitch.tv/settings/profile?keyjokertask=storageAuth
  12. // @include *://twitter.com/settings/account?keyjokertask=storageAuth
  13. // @supportURL https://www.jysafe.cn/4332.air
  14. // @homepage https://github.com/jiyeme/keyjokerScript/
  15. // @run-at document-start
  16. // @grant GM_registerMenuCommand
  17. // @grant GM_unregisterMenuCommand
  18. // @grant GM_addStyle
  19. // @grant GM_xmlhttpRequest
  20. // @grant GM_setClipboard
  21. // @grant GM_setValue
  22. // @grant GM_getValue
  23. // @grant GM_listValues
  24. // @grant GM_deleteValue
  25. // @grant GM_openInTab
  26. // @grant GM_log
  27. // @connect hcaptcha.com
  28. // @connect store.steampowered.com
  29. // @connect steamcommunity.com
  30. // @connect twitter.com
  31. // @connect facebook.com
  32. // @connect discord.com
  33. // @connect twitch.tv
  34. // @connect tumblr.com
  35. // @connect spotify.com
  36. // @connect jysafe.cn
  37. // @require https://greasyfork.org/scripts/379868-jquery-not/code/jQuery%20not%20$.js?version=700787
  38. // @require https://cdn.staticfile.org/jquery/3.3.1/jquery.min.js
  39. // @require https://cdn.jsdelivr.net/gh/jiyeme/keyjokerScript@e1f9bc6ca24cf7e8f734bd910306737449a26830/keyjoker.ext.js
  40. // ==/UserScript==
  41.  
  42. (function() {
  43. 'use strict';
  44. const debug = false;
  45. const discordAuth = GM_getValue('discordAuth') || {
  46. authorization: "",
  47. status:0,
  48. updateTime: 0
  49. }
  50. // steam信息
  51. const steamInfo = GM_getValue('steamInfo') || {
  52. userName: '',
  53. steam64Id: '',
  54. communitySessionID: '',
  55. storeSessionID: '',
  56. comUpdateTime: 0,
  57. storeUpdateTime: 0
  58. }
  59. const twitchAuth = GM_getValue('twitchAuth') || {
  60. "auth-token": "",
  61. status:0,
  62. updateTime: 0
  63. }
  64. const twitterAuth = GM_getValue('twitterAuth') || {
  65. authorization: "AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA",
  66. ct0: '',
  67. status: 0,
  68. updateTime: 0
  69. }
  70.  
  71. var completeCheck = null;
  72.  
  73. // 0-未动作|200-成功取得|401未登录|603正在取得
  74. const getAuthStatus = {
  75. discord: false,
  76. spotify: false,
  77. steamStore: 0,
  78. steamCom: 0,
  79. tumblr: false,
  80. twitch: false,
  81. twitter: 0
  82. }
  83. var checkSwitchId = null;
  84. const noticeFrame = {
  85. loadFrame: ()=>{
  86. if(debug)console.log("loadFrame");
  87. $('body').append(`<style>
  88. .fuck-task-logs li{display:list-item !important;float:none !important}
  89. #extraBtn .el-badge.item{margin-bottom:4px !important}
  90. #extraBtn .el-badge.item sup{padding-right:0 !important}
  91. .fuck-task-logs{width:auto;max-width:50%;max-height:50%;z-index:99999999999 !important}
  92. .fuck-task-logs .el-notification__group{width:100%}
  93. .fuck-task-logs .el-notification__title{text-align:center}
  94. .fuck-task-logs .el-notification__content{overflow:auto;max-height:230px}
  95. font.success{color:green}
  96. font.error{color:red;}
  97. font.warning{color:#00f;}
  98. font.wait{color:#9c27b0;}
  99. [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}
  100. .el-icon-brush:before{content:"\\e76e"}
  101. .el-icon-document:before{content:"\\e785"}
  102. .el-icon-refresh:before{content:"\\e6d0"}
  103. .el-icon-s-promotion:before{content:"\\e7ba"}
  104. .el-icon-setting:before{content:"\\e6ca"}
  105. .el-icon-video-play:before{content:"\\e7c0"}
  106. .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}
  107. .el-notification__group{margin-left:13px;margin-right:8px}
  108. .el-notification__title{font-weight:700;font-size:16px;color:#303133;margin:0}
  109. .el-notification__content{font-size:14px;line-height:21px;margin:6px 0 0;color:#606266;text-align:justify}
  110. .el-notification__content p{margin:0}
  111. .el-badge{position:relative;vertical-align:middle;display:inline-block}
  112. .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}
  113. .el-badge__content.is-fixed{position:absolute;top:10px;right:10px;-webkit-transform:translateY(-50%) translateX(100%);transform:translateY(-50%) translateX(100%)}
  114. .el-badge__content.is-fixed.is-dot{right:8px}
  115. .el-badge__content.is-dot{height:8px;width:8px;padding:0;right:0;border-radius:50%}
  116. .el-button{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}
  117. .el-button{-webkit-box-sizing:border-box}
  118. .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}
  119. .el-button:focus,.el-button:hover{color:#409eff;border-color:#c6e2ff;background-color:#ecf5ff}
  120. .el-button:active{color:#3a8ee6;border-color:#3a8ee6;outline:0}
  121. .el-button::-moz-focus-inner{border:0}
  122. .el-button.is-circle{border-radius:50%;padding:15px}
  123. #extraBtn .el-button.is-circle{padding:8px !important}
  124. @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}
  125. </style>
  126. <div role="alert" class="el-notification fuck-task-logs right" style="bottom: 16px; z-index: 2000;">
  127. <div class="el-notification__group">
  128. <h2 id="extraBtn" class="el-notification__title">
  129. <div class="el-badge item"><button id="checkUpdate" type="button" class="el-button el-button--default is-circle"
  130. title="检查更新">
  131. <i class="el-icon-refresh"></i>
  132. </button><sup class="el-badge__content el-badge__content--undefined is-fixed is-dot"
  133. style="display: none;"></sup></div>
  134. <div class="el-badge item"><button id="fuck" type="button" class="el-button el-button--default is-circle" title="强制做任务">
  135. <i class="el-icon-video-play"></i>
  136. </button><sup class="el-badge__content el-badge__content--undefined is-fixed is-dot" style="display: none;"></sup>
  137. </div>
  138. <div class="el-badge item"><button id="changeLog" type="button" class="el-button el-button--default is-circle"
  139. title="查看更新内容">
  140. <i class="el-icon-document"></i>
  141. </button><sup class="el-badge__content el-badge__content--undefined is-fixed is-dot" style="display: none;"></sup></div>
  142. <div class="el-badge item"><button id="clearNotice" type="button" class="el-button el-button--default is-circle"
  143. title="清空执行日志">
  144. <i class="el-icon-brush"></i>
  145. </button><sup class="el-badge__content el-badge__content--undefined is-fixed is-dot"
  146. style="display: none;"></sup></div>
  147. <div class="el-badge item"><button id="report" type="button" class="el-button el-button--default is-circle"
  148. title="提交建议/BUG">
  149. <i class="el-icon-s-promotion"></i>
  150. </button><sup class="el-badge__content el-badge__content--undefined is-fixed is-dot"
  151. style="display: none;"></sup></div>
  152. </h2>
  153. <h2 class="el-notification__title">任务执行日志</h2>
  154. <div class="el-notification__content" style="">
  155. <p></p>
  156. </li>
  157. </div>
  158. </div>
  159. </div>`)
  160. },
  161. addNotice: function(data){
  162. switch(data.type)
  163. {
  164. case "taskStatus":
  165. $('.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>');
  166. break;
  167. case "msg":
  168. $('.el-notification__content').append("<li>" + data.msg + "</li>");
  169. break;
  170. case "authVerify":
  171. $('.el-notification__content').append('<li>' + data.name + ' |<font id="' + data.status.id + '" class="' + data.status.class +'">' + data.status.text + '</font></li>');
  172. break;
  173. default:
  174. $('.el-notification__content').append("<li>" + data + "</li>");
  175. break;
  176. }
  177. },
  178. clearNotice:()=>{
  179. $('.el-notification__content li').remove();
  180. },
  181. updateNotice: function(id, status){
  182. $('font#' + id).removeClass()
  183. $('font#' + id).addClass(status)
  184. $('font#' + id).text(status)
  185. },
  186. updateNotice1: function(data){
  187. $('font#' + data.id).removeClass()
  188. $('font#' + data.id).addClass(data.class)
  189. $('font#' + data.id).text(data.text || data.class)
  190. }
  191. }
  192. try{
  193. const checkTask = {
  194. reLoad: function (time,sum){
  195. let date=new Date();
  196. let hour=date.getHours();
  197. let min=date.getMinutes()<10?("0"+date.getMinutes()):date.getMinutes();
  198. if(GM_getValue("start")==1){
  199. $(".border-bottom").text(hour+":"+min+" 执行新任务检测");
  200. $.ajax({
  201. url:"/entries/load",
  202. type:"get",
  203. headers:{'x-csrf-token': $('meta[name="csrf-token"]').attr('content')},
  204. success:(data,status,xhr)=>{
  205. if(data && (data.actions && (data.actions.length > sum) )){
  206. if(debug)console.log(data);
  207. let date=new Date();
  208. let hour=date.getHours();
  209. let min=date.getMinutes()<10?("0"+date.getMinutes()):date.getMinutes();
  210. $(".border-bottom").text(hour+":"+min+" 检测到新任务(暂停检测)");
  211. $show({
  212. title:"keyjoker新任务",
  213. msg:"keyjoker网站更新"+(data.actions.length-sum)+"个新任务!",
  214. icon:"https://www.keyjoker.com/favicon-32x32.png",
  215. time:0,
  216. onclick:function(){
  217. //location.reload(true);
  218. }
  219. });
  220. // 重载列表
  221. noticeFrame.clearNotice();
  222. func.reLoadTaskList(()=>{
  223. func.do_task(data);
  224. });
  225. GM_setValue("start", 0);
  226. checkSwitch();
  227. }else{
  228. setTimeout(()=>{
  229. this.reLoad(time,sum);
  230. },time);
  231. }
  232. },
  233. error:(err)=>{
  234. window.location.reload(true);
  235. }
  236. });
  237. }
  238. },
  239. setTime: function (){
  240. let time=prompt('请输入获取任务信息的时间间隔(单位:秒):');
  241. if(!isNaN(time)){
  242. GM_setValue("time",parseInt(time));
  243. }
  244. },
  245. start: function (r = null){
  246. let time = GM_getValue("time");
  247. if(!time){
  248. time=60;
  249. }
  250. if(confirm("是否以时间间隔" + time + "秒进行任务检测?")){
  251. GM_setValue("start",1);
  252. if(r)r();
  253. this.next();
  254. }
  255. },
  256. next: function (){
  257. // 初始化凭证获取状态
  258. getAuthStatus.discord = false;
  259. getAuthStatus.spotify = false;
  260. getAuthStatus.steamStore = 0;
  261. getAuthStatus.steamCom = 0;
  262. getAuthStatus.tumblr = false;
  263. getAuthStatus.twitch = false;
  264. getAuthStatus.twitter = 0;
  265. let time = GM_getValue("time");
  266. if(!time){
  267. time=60;
  268. }
  269. let sum=$(".list-complete-item").length;
  270. if(sum>0){
  271. this.reLoad(time*1000,sum);
  272. }else{
  273. this.reLoad(time*1000,0);
  274. }
  275. }
  276. }
  277. const DISCORD = (()=>{
  278. const AuthUpdate = (r, update)=>{
  279. if (new Date().getTime() - discordAuth.updateTime > 30 * 60 * 1000 || discordAuth.status != 200 || update) {
  280. r(603)
  281. new Promise((resolve, reject)=>{
  282. if(false == getAuthStatus.discord || true === update)
  283. {
  284. getAuthStatus.discord = true;
  285. GM_openInTab("https://discord.com/channels/@me?keyjokertask=storageAuth", true);
  286. }
  287. let i = 0;
  288. let check = setInterval(()=>{
  289. i++;
  290. if(GM_getValue("discordAuth") && new Date().getTime() - GM_getValue("discordAuth").updateTime <= 10 * 1000)
  291. {
  292. if(GM_getValue("discordAuth").status != 200)
  293. {
  294. clearInterval(check);
  295. reject(GM_getValue("discordAuth").status)
  296. return;
  297. }
  298. discordAuth.authorization = GM_getValue("discordAuth").authorization
  299. discordAuth.updateTime = GM_getValue("discordAuth").updateTime
  300. discordAuth.status = GM_getValue("discordAuth").status;
  301. clearInterval(check);
  302. resolve(discordAuth.status)
  303. }
  304. if(i >= 10)
  305. {
  306. clearInterval(check);
  307. reject(408)
  308. }
  309. }, 1000)
  310. }).then((ret)=>{
  311. r(ret)
  312. }).catch((err)=>{
  313. r(err)
  314. })
  315. }else{
  316. r(200)
  317. }
  318. }
  319. const JoinServer = (r, server)=>{
  320. AuthUpdate((ret)=>{
  321. if(ret != 200)
  322. {
  323. r(ret);
  324. return;
  325. }
  326. func.httpRequest({
  327. url: 'https://discord.com/api/v6/invites/' + server,
  328. method: 'POST',
  329. headers: { authorization: discordAuth.authorization, "content-type": "application/json"},
  330. onload: (response) => {
  331. if (response.status === 200) {
  332. if(debug)console.log({ result: 'success', statusText: response.statusText, status: response.status })
  333. r(200);
  334. } else {
  335. console.error(response);
  336. r(601);
  337. }
  338. },
  339. error:(res)=>{
  340. console.error(res);
  341. r(601);
  342. },
  343. anonymous:true
  344. })
  345. })
  346. }
  347. const LeaveServer = (r, serverId)=>{
  348. AuthUpdate((ret)=>{
  349. if(ret != 200)
  350. {
  351. r(ret);
  352. return;
  353. }
  354. $.ajax({
  355. url: 'https://discord.com/api/v6/users/@me/guilds/' + serverId,
  356. method: 'DELETE',
  357. headers: { authorization: discordAuth.authorization, "content-type": "application/json"},
  358. onload: (response) => {
  359. if (response.status === 604) {
  360. if(debug)console.log({ result: 'success', statusText: response.statusText, status: response.status })
  361. r(604);
  362. } else {
  363. console.error(response);
  364. r(601);
  365. }
  366. },
  367. error:(res)=>{
  368. console.error(res);
  369. r(601);
  370. },
  371. anonymous:true
  372. })
  373. })
  374. }
  375. return {
  376. AuthUpdate: AuthUpdate,
  377. JoinServer: JoinServer,
  378. LeaveServer: LeaveServer
  379. }
  380. })();
  381. const SPOTIFY = (()=>{
  382. const GetUserInfo = (r)=>{
  383. r(603)
  384. GetAccessToken(
  385. (status, accessToken)=>{
  386. if(status != 200)
  387. {
  388. r(status);
  389. return;
  390. }
  391. func.httpRequest({
  392. url: 'https://api.spotify.com/v1/me',
  393. method: 'GET',
  394. headers:{authorization: "Bearer " + accessToken},
  395. onload: (response) => {
  396. if (response.status === 200) {
  397. r(200, accessToken, JSON.parse(response.responseText).id);
  398. } else {
  399. console.error(response)
  400. r(401);
  401. }
  402. },
  403. error:(res)=>{
  404. console.error("error");
  405. r(604);
  406. },
  407. anonymous:true
  408. })
  409. }
  410. )
  411. }
  412. const GetAccessToken = function(r){
  413. r(603);
  414. func.httpRequest({
  415. url: 'https://open.spotify.com/get_access_token?reason=transport&productType=web_player',
  416. method: 'GET',
  417. onload: (response) => {
  418. if (response.status === 200) {
  419. r(200, JSON.parse(response.responseText).accessToken);
  420. } else {
  421. console.log(response);
  422. r(401);
  423. }
  424. },
  425. error:(res)=>{
  426. if(debug)console.log(res);
  427. r(604);
  428. }
  429. })
  430. }
  431. const SaveAuto = (r, data, del = false)=>{
  432. GetUserInfo((status, accessToken = null, userId = null)=>{
  433. if(status != 200)
  434. {
  435. r(status);
  436. return;
  437. }
  438. let putUrl = "";
  439. new Promise((resolve, reject)=>{
  440. switch(data.type)
  441. {
  442. case "album":
  443. putUrl = "https://spclient.wg.spotify.com/collection-view/v1/collection/albums/" + userId + "?base62ids=" + data.id + "&model=bookmark";
  444. resolve(putUrl);
  445. break;
  446. case "track":
  447. func.httpRequest({
  448. url: 'https://api.spotify.com/v1/tracks?ids=' + data.id + '&market=from_token',
  449. method: 'GET',
  450. headers:{authorization: "Bearer " + accessToken},
  451. onload: (response) => {
  452. if(response.status == 200)
  453. {
  454. let temp = JSON.parse(response.response);
  455. putUrl = "https://spclient.wg.spotify.com/collection-view/v1/collection/albums/" + userId + "?base62ids=" + temp.tracks[0].album.id + "&model=bookmark";
  456. resolve(putUrl);
  457. }else
  458. {
  459. console.error(response);
  460. reject(601);
  461. }
  462. },
  463. error:(res)=>{
  464. console.error(res);
  465. reject(601);
  466. },
  467. anonymous:true
  468. })
  469. break;
  470. default:
  471. console.error("spotifySaveAuto未知类型:", data);
  472. r(601);
  473. return;
  474. break;
  475. }
  476. }).then((putUrl)=>{
  477. if(debug)console.log(putUrl)
  478. $.ajax({
  479. type: !del?'PUT':"DELETE",
  480. url: putUrl,
  481. headers: {authorization: "Bearer " + accessToken},
  482. success: function(data){
  483. console.log(data);
  484. r(200);
  485. },
  486. error: function(data){
  487. console.error(data);
  488. r(601);
  489. },
  490. anonymous:true
  491. });
  492. })
  493. });
  494. }
  495. const Follow = (r, data, del = false)=>{
  496. GetUserInfo((status, accessToken = null)=>{
  497. if(status != 200)
  498. {
  499. r(status)
  500. return;
  501. }
  502. let putUrl = "";
  503. switch(data.type)
  504. {
  505. case "artist":
  506. putUrl = "https://api.spotify.com/v1/me/following?type=artist&ids=" + data.id;
  507. break;
  508. case "playlist":
  509. putUrl = "https://api.spotify.com/v1/playlists/" + data.id + "/followers"
  510. break;
  511. case "user":
  512. putUrl = "https://api.spotify.com/v1/me/following?type=user&ids=" + data.id;
  513. break;
  514. default:
  515. console.error(data);
  516. r(601);
  517. return;
  518. break;
  519. }
  520. $.ajax({
  521. type: !del?'PUT':"DELETE",
  522. url: putUrl,
  523. headers: {authorization: "Bearer " + accessToken},
  524. success: function(data){
  525. r(200);
  526. },
  527. error: function(data){
  528. console.error(data);
  529. r(604);
  530. },
  531. anonymous:true
  532. });
  533. });
  534. }
  535. return {
  536. GetAccessToken: GetAccessToken,
  537. SaveAuto: SaveAuto,
  538. Follow: Follow
  539. }
  540. })();
  541. const STEAM = (()=>{
  542. const InfoUpdate = (r, type = 'all', update = false)=> {
  543. r(603);
  544. if (type === 'community' || type === 'all') {
  545. if (new Date().getTime() - steamInfo.comUpdateTime > 10 * 60 * 1000 || update) {
  546. if(603 == getAuthStatus.steamCom)
  547. {
  548. let i = 0;
  549. let steamCheck = setInterval(()=>{
  550. i++;
  551. if(603 != getAuthStatus.steamCom)
  552. {
  553. clearInterval(steamCheck);
  554. r(getAuthStatus.steamCom);
  555. }
  556. if(i >= 10)
  557. {
  558. clearInterval(steamCheck);
  559. r(408);
  560. }
  561. }, 1000)
  562. return;
  563. }
  564. getAuthStatus.steamCom = 603;
  565. new Promise((resolve, reject) => {
  566. func.httpRequest({
  567. url: 'https://steamcommunity.com/my',
  568. method: 'GET',
  569. onload: (response) => {
  570. if (response.status === 200) {
  571. if ($(response.responseText).find('a[href*="/login/home"]').length > 0) {
  572. getAuthStatus.steamCom = 401;
  573. reject(401);
  574. } else {
  575. const steam64Id = response.responseText.match(/g_steamID = "(.+?)";/);
  576. const communitySessionID = response.responseText.match(/g_sessionID = "(.+?)";/);
  577. const userName = response.responseText.match(/steamcommunity.com\/id\/(.+?)\/friends\//);
  578. if (steam64Id) steamInfo.steam64Id = steam64Id[1];
  579. if (communitySessionID) steamInfo.communitySessionID = communitySessionID[1];
  580. if (userName) steamInfo.userName = userName[1];
  581. getAuthStatus.steamCom = 200;
  582. resolve(200);
  583. }
  584. } else {
  585. console.error(response);
  586. getAuthStatus.steamCom = 601;
  587. reject(601);
  588. }
  589. },
  590. r: resolve
  591. })
  592. }).then((ret) => {
  593. if(ret == 200)
  594. {
  595. steamInfo.comUpdateTime = new Date().getTime();
  596. GM_setValue('steamInfo', steamInfo);
  597. }
  598. r(ret);
  599. }).catch(err => {
  600. console.error(err);
  601. r(err);
  602. })
  603. } else {
  604. r(200);
  605. }
  606. }
  607. if (type === 'store' || type === 'all') {
  608. if (new Date().getTime() - steamInfo.storeUpdateTime > 10 * 60 * 1000 || update) {
  609. if(603 == getAuthStatus.steamStore)
  610. {
  611. let i = 0;
  612. let steamCheck = setInterval(()=>{
  613. i++;
  614. if(603 != getAuthStatus.steamStore)
  615. {
  616. clearInterval(steamCheck);
  617. r(getAuthStatus.steamStore);
  618. }
  619. if(i >= 10)
  620. {
  621. clearInterval(steamCheck);
  622. r(408);
  623. }
  624. }, 1000)
  625. return;
  626. }
  627. getAuthStatus.steamStore = 603;
  628. new Promise((resolve, reject) => {
  629. func.httpRequest({
  630. url: 'https://store.steampowered.com/stats/',
  631. method: 'GET',
  632. onload: (response) => {
  633. if (response.status === 200) {
  634. if ($(response.responseText).find('a[href*="/login/"]').length > 0) {
  635. if (debug) console.log(response)
  636. getAuthStatus.steamStore = 401;
  637. reject(401)
  638. } else {
  639. const storeSessionID = response.responseText.match(/g_sessionID = "(.+?)";/)
  640. if (storeSessionID) steamInfo.storeSessionID = storeSessionID[1]
  641. getAuthStatus.steamStore = 200;
  642. resolve(200);
  643. }
  644. } else {
  645. console.error(response);
  646. getAuthStatus.steamStore = 601;
  647. reject(601);
  648. }
  649. },
  650. r: resolve
  651. })
  652. }).then((ret) => {
  653. if(ret == 200)
  654. {
  655. steamInfo.storeUpdateTime = new Date().getTime();
  656. GM_setValue('steamInfo', steamInfo);
  657. }
  658. r(ret)
  659. }).catch(err => {
  660. console.error(err);
  661. r(err);
  662. })
  663. } else {
  664. r(200)
  665. }
  666. }
  667. }
  668. const Rep = (r, id)=>{
  669. RepHisCheck((status, ret = null) => {
  670. if(status != 200)
  671. {
  672. r(status);
  673. return;
  674. }
  675. if(!ret){
  676. func.httpRequest({
  677. url: 'https://steamcommunity.com/comment/Profile/post/' + id + '/-1/',
  678. method: 'POST',
  679. data: $.param({comment:'+rep',count:6,sessionid:steamInfo.communitySessionID,feature2:-1}),
  680. headers:{'content-type': 'application/x-www-form-urlencoded'},
  681. onload: (response) => {
  682. if(response.status == 200)
  683. {
  684. let ret = JSON.parse(response.response)
  685. if(ret.success == true)r(200);
  686. else{
  687. console.error("发送评论失败", response);
  688. r(601);
  689. }
  690. }else{
  691. console.error("评论返回值异常", response);
  692. r(601);
  693. }
  694. },
  695. error: (err)=>{
  696. console.error("请求发送异常", err);
  697. r(601);
  698. }
  699. })
  700. }else{
  701. r(200);
  702. }
  703. },id)
  704. }
  705. const RepHisCheck = function (r, id){
  706. InfoUpdate((ret) => {
  707. if(ret != 200)
  708. {
  709. r(ret);
  710. return;
  711. }
  712. func.httpRequest({
  713. url: "https://steamcommunity.com/profiles/" + id,
  714. method: 'GET',
  715. onload: (response) => {
  716. if(response.status == 200)
  717. {
  718. let comments = response.responseText.match(/commentthread_comments([\s\S]*)commentthread_footer/);
  719. if(debug)console.log(comments);
  720. if(comments != null)
  721. {
  722. if(comments[1].includes(steamInfo.steam64Id) || steamInfo.userName?comments[1].includes(steamInfo.userName):false)
  723. {
  724. r(200, true);
  725. }
  726. else if(!response.responseText.includes("commentthread_textarea"))
  727. {
  728. r(605)
  729. }else{
  730. r(200, false);
  731. }
  732. }
  733. else r(605);
  734. }else{
  735. console.error("检查评论记录返回异常", response);
  736. r(601);
  737. }
  738. }
  739. //,anonymous:true
  740. });
  741. }, "community")
  742. }
  743. const JoinGroupAuto = function (r, url) {
  744. InfoUpdate((ret) => {
  745. if(ret != 200)
  746. {
  747. r(ret);
  748. return;
  749. }
  750. func.httpRequest({
  751. url: url,
  752. method: 'POST',
  753. headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
  754. data: $.param({ action: 'join', sessionID: steamInfo.communitySessionID }),
  755. onload: (response) => {
  756. if (response.status === 200 && !response.responseText.includes('grouppage_join_area')) {
  757. if(response.responseText.match(/<h3>(.+?)<\/h3>/) && response.responseText.match(/<h3>(.+?)<\/h3>/)[1] != "您已经是该组的成员了。")
  758. {
  759. console.error(response);
  760. r(601);
  761. }else r(200);
  762. } else {
  763. console.error(response);
  764. r(601);
  765. }
  766. }
  767. })
  768. }, 'community');
  769. }
  770. const LeaveGroup = function (r, url) {
  771. let groupName = url.split('s/')[1];
  772. GetGroupID(groupName, (groupName, groupId) => {
  773. var postUrl = "";
  774. postUrl = (steamInfo.userName) ? 'https://steamcommunity.com/id/' + steamInfo.userName + '/home_process' : 'https://steamcommunity.com/profiles/' + steamInfo.steam64Id + '/home_process'
  775. func.httpRequest({
  776. url: postUrl,
  777. method: 'POST',
  778. headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
  779. data: $.param({ sessionID: steamInfo.communitySessionID, action: 'leaveGroup', groupId: groupId }),
  780. onload: (response) => {
  781. if (response.status === 200 && response.finalUrl.includes('groups') && $(response.responseText.toLowerCase()).find(`a[href='https://steamcommunity.com/groups/${groupName.toLowerCase()}']`).length === 0) {
  782. r(200);
  783. } else {
  784. console.error(response);
  785. r(601);
  786. }
  787. },
  788. r
  789. })
  790. })
  791. }
  792. const GetGroupID = function (groupName, callback) {
  793. InfoUpdate((ret) => {
  794. if(ret != 200)
  795. {
  796. r(ret);
  797. return;
  798. }
  799. new Promise(resolve => {
  800. func.httpRequest({
  801. url: 'https://steamcommunity.com/groups/' + groupName,
  802. method: 'GET',
  803. headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
  804. onload: function (response) {
  805. if (debug) console.log(response)
  806. if (response.status === 200) {
  807. const groupId = response.responseText.match(/OpenGroupChat\( '([0-9]+)'/)
  808. if (groupId === null) {
  809. console.error(response)
  810. resolve(false)
  811. } else {
  812. resolve(groupId[1])
  813. }
  814. } else {
  815. console.error(response)
  816. resolve(false)
  817. }
  818. },
  819. r: () => {
  820. resolve(false)
  821. }
  822. })
  823. }).then(groupId => {
  824. if (groupId !== false && callback) callback(groupName, groupId);
  825. }).catch(err => {
  826. console.error(err);
  827. })
  828. })
  829. }
  830. const AddWishlistAuto = function (r, gameId) {
  831. InfoUpdate((ret) => {
  832. if(ret != 200)
  833. {
  834. r(ret);
  835. return;
  836. }
  837. new Promise(resolve => {
  838. func.httpRequest({
  839. url: 'https://store.steampowered.com/api/addtowishlist',
  840. method: 'POST',
  841. headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
  842. data: $.param({ sessionid: steamInfo.storeSessionID, appid: gameId }),
  843. dataType: 'json',
  844. onload: function (response) {
  845. if (debug) console.log(response)
  846. if (response.status === 200 && response.response && response.response.success === true) {
  847. resolve({ result: 'success', statusText: response.statusText, status: response.status })
  848. } else {
  849. resolve({ result: 'error', statusText: response.statusText, status: response.status })
  850. }
  851. },
  852. onabort: response => { resolve({ result: 'error', statusText: response.statusText, status: response.status }) },
  853. onerror: response => { resolve({ result: 'error', statusText: response.statusText, status: response.status }) },
  854. ontimeout: response => { resolve({ result: 'error', statusText: response.statusText, status: response.status }) },
  855. r: resolve
  856. })
  857. }).then(result => {
  858. if (result.result === 'success') {
  859. r(200)
  860. } else {
  861. func.httpRequest({
  862. url: 'https://store.steampowered.com/app/' + gameId,
  863. method: 'GET',
  864. onload: function (response) {
  865. if (debug) console.log(response)
  866. if (response.status === 200) {
  867. if (response.responseText.includes('class="queue_actions_ctn"') && response.responseText.includes('已在库中')) {
  868. r(200)
  869. } else if ((response.responseText.includes('class="queue_actions_ctn"') && !response.responseText.includes('add_to_wishlist_area" style="display: none;"')) || !response.responseText.includes('class="queue_actions_ctn"')) {
  870. console.error(response);
  871. r(601);
  872. } else {
  873. r(200);
  874. }
  875. } else {
  876. console.error(response);
  877. r(601);
  878. }
  879. },
  880. r
  881. })
  882. }
  883. }).catch(err => {
  884. console.error(err);
  885. r(601);
  886. })
  887. },'store')
  888. }
  889. const RemoveWishlistAuto = function (r, gameId) {
  890. this.steamInfoUpdate(() => {
  891. new Promise(resolve => {
  892. func.httpRequest({
  893. url: 'https://store.steampowered.com/api/removefromwishlist',
  894. method: 'POST',
  895. headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
  896. data: $.param({ sessionid: steamInfo.storeSessionID, appid: gameId }),
  897. dataType: 'json',
  898. onload: function (response) {
  899. if (response.status === 200 && response.response && response.response.success === true) {
  900. resolve({ result: 'success', statusText: response.statusText, status: response.status })
  901. } else {
  902. resolve({ result: 'error', statusText: response.statusText, status: response.status })
  903. }
  904. },
  905. onabort: response => { resolve({ result: 'error', statusText: response.statusText, status: response.status }) },
  906. onerror: response => { resolve({ result: 'error', statusText: response.statusText, status: response.status }) },
  907. ontimeout: response => { resolve({ result: 'error', statusText: response.statusText, status: response.status }) },
  908. r: resolve
  909. })
  910. }).then(result => {
  911. if (result.result === 'success') {
  912. r(200);
  913. } else {
  914. func.httpRequest({
  915. url: 'https://store.steampowered.com/app/' + gameId,
  916. method: 'GET',
  917. onload: function (response) {
  918. if (response.status === 200) {
  919. if (response.responseText.includes('class="queue_actions_ctn"') && (response.responseText.includes('已在库中') || response.responseText.includes('添加至您的愿望单'))) {
  920. r(200);
  921. } else {
  922. console.error(response);
  923. r(601);
  924. }
  925. } else {
  926. console.error(response);
  927. r(601);
  928. }
  929. },
  930. r
  931. })
  932. }
  933. }).catch(err => {
  934. console.error(err);
  935. r(601);
  936. })
  937. })
  938. }
  939. return {
  940. InfoUpdate: InfoUpdate,
  941. Rep: Rep,
  942. JoinGroup: JoinGroupAuto,
  943. LeaveGroup: LeaveGroup,
  944. AddWishlist: AddWishlistAuto
  945. }
  946. })();
  947. const TUMBLR = (()=>{
  948. const FollowAuto = function(r, name){
  949. AuthUpdate((status, key = false)=>{
  950. if(status != 200)
  951. {
  952. r(status);
  953. return;
  954. }
  955. if(false != key){
  956. func.httpRequest({
  957. url: 'https://www.tumblr.com/svc/follow',
  958. method: 'POST',
  959. headers: {"x-tumblr-form-key": key, "Content-Type": "application/x-www-form-urlencoded"},
  960. data: $.param({'data[tumblelog]': name}),
  961. onload: (response) => {
  962. if(response.status == 200)
  963. {
  964. r(200);
  965. }else
  966. {
  967. console.error(response);
  968. r(601);
  969. }
  970. }
  971. })
  972. }else{
  973. console.error("tumblrFollowAuto->key值错误");
  974. r(601);
  975. }
  976. })
  977. }
  978. const UnfollowAuto = function(r, name){
  979. AuthUpdate((status, key = false)=>{
  980. if(status != 200)
  981. {
  982. r(status);
  983. return;
  984. }
  985. if(false != key){
  986. func.httpRequest({
  987. url: 'https://www.tumblr.com/svc/unfollow',
  988. method: 'POST',
  989. headers: {"x-tumblr-form-key": key, "Content-Type": "application/x-www-form-urlencoded"},
  990. data: $.param({'data[tumblelog]': name}),
  991. onload: (response) => {
  992. if(response.status == 200)
  993. {
  994. r(200);
  995. }else{
  996. console.error(response);
  997. r(601);
  998. }
  999. }
  1000. })
  1001. }else{
  1002. r(601);
  1003. }
  1004. })
  1005. }
  1006. const AuthUpdate = function(r, update = false){
  1007. r(603)
  1008. func.httpRequest({
  1009. url: 'https://www.tumblr.com/dashboard/iframe',
  1010. method: 'GET',
  1011. onload: (response) => {
  1012. if(response.status == 200)
  1013. {
  1014. let key = response.responseText.match(/id="tumblr_form_key" content="(.+?)">/)
  1015. if(key){
  1016. if(-1 != key.indexOf("!123") && -1 !=key.indexOf("|") )
  1017. {
  1018. r(401);
  1019. return;
  1020. }else r(200, key);
  1021. }
  1022. else{
  1023. console.error("tumblrGetKey->get key failed.", response);
  1024. r(601);
  1025. }
  1026. }else{
  1027. console.error(response);
  1028. r(601);
  1029. }
  1030. }
  1031. })
  1032. }
  1033. return {
  1034. AuthUpdate: AuthUpdate,
  1035. Follow: FollowAuto,
  1036. UnfollowAuto: UnfollowAuto
  1037. }
  1038. })();
  1039. const TWITCH = (()=>{
  1040. const FollowAuto = function(r, channelId){
  1041. AuthUpdate((status)=>{
  1042. if(status != 200)
  1043. {
  1044. r(status);
  1045. return;
  1046. }
  1047. func.httpRequest({
  1048. url: 'https://gql.twitch.tv/gql',
  1049. method: 'POST',
  1050. headers: { Authorization: "OAuth " + twitchAuth["auth-token"]},
  1051. data: '[{"operationName":"FollowButton_FollowUser","variables":{"input":{"disableNotifications":false,"targetID":"' + channelId + '"}},"extensions":{"persistedQuery":{"version":1,"sha256Hash":"3efee1acda90efdff9fef6e6b4a29213be3ee490781c5b54469717b6131ffdfe"}}}]',
  1052. onload: (response) => {
  1053. if (response.status === 200) {
  1054. r(200);
  1055. } else if(response.status === 401){
  1056. twitchAuth.updateTime = 0;
  1057. GM_setValue("twitchAuth", null);
  1058. r(401);
  1059. }else{
  1060. console.error(response);
  1061. r(601);
  1062. }
  1063. }
  1064. })
  1065. })
  1066. }
  1067. const UnfollowAuto = function(r, channelId){
  1068. AuthUpdate((status)=>{
  1069. if(status != 200)
  1070. {
  1071. r(status);
  1072. return;
  1073. }
  1074. func.httpRequest({
  1075. url: 'https://gql.twitch.tv/gql',
  1076. method: 'POST',
  1077. headers: { Authorization: "OAuth " + twitchAuth["auth-token"]},
  1078. data: '[{"operationName":"FollowButton_UnfollowUser","variables":{"input":{"targetID":"' + channelId + '"}},"extensions":{"persistedQuery":{"version":1,"sha256Hash":"d7fbdb4e9780dcdc0cc1618ec783309471cd05a59584fc3c56ea1c52bb632d41"}}}]',
  1079. onload: (response) => {
  1080. if (response.status === 200) {
  1081. r(200);
  1082. } else if(response.status === 401){
  1083. twitchAuth.updateTime = 0;
  1084. GM_setValue("twitchAuth", null);
  1085. r(401);
  1086. }else{
  1087. console.error(response);
  1088. r(601);
  1089. }
  1090. }
  1091. })
  1092. })
  1093. }
  1094. // 弃用
  1095. const twitchGetId = function(r, channels){
  1096. func.httpRequest({
  1097. 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',
  1098. method: 'GET',
  1099. onload: (response) => {
  1100. if (response.status === 200) {
  1101. let rep = JSON.parse(JSON.parse(response.responseText).token);
  1102. r(rep.channel_id);
  1103. } else {
  1104. console.error(response);
  1105. r('error')
  1106. }
  1107. },
  1108. error:(res)=>{
  1109. console.error(res);
  1110. },
  1111. anonymous:true
  1112. })
  1113. }
  1114. const AuthUpdate = function(r, update = false){
  1115. if (new Date().getTime() - twitchAuth.updateTime > 30 * 60 * 1000 || twitchAuth.status != 200 || update) {
  1116. r(603)
  1117. new Promise((resolve, reject)=>{
  1118. if(false == getAuthStatus.twitch || true === update)
  1119. {
  1120. getAuthStatus.twitch = true;
  1121. GM_openInTab("https://www.twitch.tv/settings/profile?keyjokertask=storageAuth", true);
  1122. }
  1123. let i = 0;
  1124. let check = setInterval(()=>{
  1125. i++;
  1126. if(GM_getValue("twitchAuth") && new Date().getTime() - GM_getValue("twitchAuth").updateTime <= 10 * 1000)
  1127. {
  1128. if(GM_getValue("twitchAuth").status != 200)
  1129. {
  1130. clearInterval(check);
  1131. reject(401);
  1132. return;
  1133. }
  1134. twitchAuth["auth-token"] = GM_getValue('twitchAuth')["auth-token"];
  1135. twitchAuth.updateTime = GM_getValue('twitchAuth').updateTime;
  1136. twitchAuth.status = GM_getValue('twitchAuth').status;
  1137. clearInterval(check);
  1138. resolve(200)
  1139. }
  1140. if(i >= 10)
  1141. {
  1142. clearInterval(check);
  1143. reject(408)
  1144. }
  1145. }, 1000)
  1146. }).then((ret)=>{
  1147. r(ret);
  1148. }).catch((err)=>{
  1149. r(err);
  1150. })
  1151. }else{
  1152. r(200)
  1153. }
  1154. }
  1155. return {
  1156. AuthUpdate: AuthUpdate,
  1157. FollowAuto: FollowAuto,
  1158. UnfollowAuto: UnfollowAuto
  1159. }
  1160. })();
  1161. const TWITTER = (()=>{
  1162. const FollowAuto = function(r, data){
  1163. AuthUpdate((status)=>{
  1164. if(status != 200)
  1165. {
  1166. r(status);
  1167. return;
  1168. }
  1169. GetUserInfo((status, userId = null)=>{
  1170. if(200 != status)
  1171. {
  1172. r(601);
  1173. return;
  1174. }
  1175. func.httpRequest({
  1176. url: 'https://api.twitter.com/1.1/friendships/create.json',
  1177. method: 'POST',
  1178. headers: { authorization: "Bearer " + twitterAuth.authorization, 'Content-Type': 'application/x-www-form-urlencoded', 'x-csrf-token':twitterAuth.ct0},
  1179. 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}),
  1180. onload: (response) => {
  1181. if (response.status === 200) {
  1182. r(200);
  1183. } else {
  1184. console.error(response);
  1185. twitterAuth.updateTime = 0;
  1186. GM_setValue("twitterAuth", twitterAuth);
  1187. r(601);
  1188. }
  1189. }
  1190. })
  1191. },data.username)
  1192. })
  1193. }
  1194. const UnfollowAuto = function(r, data){
  1195. AuthUpdate((status)=>{
  1196. if(status != 200)
  1197. {
  1198. r(status);
  1199. return;
  1200. }
  1201. GetUserInfo((userId)=>{
  1202. if(debug)console.log(userId)
  1203. if("error" == userId)
  1204. {
  1205. r(601);
  1206. return;
  1207. }
  1208. func.httpRequest({
  1209. url: 'https://api.twitter.com/1.1/friendships/destroy.json',
  1210. method: 'POST',
  1211. headers: { authorization: "Bearer " + twitterAuth.authorization, 'Content-Type': 'application/x-www-form-urlencoded', 'x-csrf-token':twitterAuth.ct0},
  1212. 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}),
  1213. onload: (response) => {
  1214. if (response.status === 200) {
  1215. r(200);
  1216. } else {
  1217. console.error(response);
  1218. twitterAuth.updateTime = 0;
  1219. GM_setValue("twitterAuth", twitterAuth);
  1220. r(601);
  1221. }
  1222. }
  1223. })
  1224. },data.username)
  1225. })
  1226. }
  1227. const RetweetAuto = function(r, url){
  1228. let retweetId = url.split("status/")[1];
  1229. AuthUpdate((status)=>{
  1230. if(status != 200)
  1231. {
  1232. r(status);
  1233. return;
  1234. }
  1235. func.httpRequest({
  1236. url: 'https://api.twitter.com/1.1/statuses/retweet.json',
  1237. method: 'POST',
  1238. headers: { authorization: "Bearer " + twitterAuth.authorization, 'Content-Type': 'application/x-www-form-urlencoded', 'x-csrf-token':twitterAuth.ct0},
  1239. data: $.param({ tweet_mode: "extended",id: retweetId}),
  1240. onload: (response) => {
  1241. if (response.status === 200 || (response.status === 403 && response.responseText == '{"errors":[{"code":327,"message":"You have already retweeted this Tweet."}]}')) {
  1242. r(200);
  1243. } else {
  1244. console.error(response);
  1245. twitterAuth.updateTime = 0;
  1246. GM_setValue("twitterAuth", twitterAuth);
  1247. r(601);
  1248. }
  1249. }
  1250. })
  1251. })
  1252. }
  1253. const GetUserInfo = function(r, userName){
  1254. if(debug)console.log("====twitterGetUserInfo====");
  1255. func.httpRequest({
  1256. url: 'https://api.twitter.com/graphql/-xfUfZsnR_zqjFd-IfrN5A/UserByScreenName?variables=%7B%22screen_name%22%3A%22' + userName + '%22%2C%22withHighlightedLabel%22%3Atrue%7D',
  1257. method: 'GET',
  1258. headers: { authorization: "Bearer " + twitterAuth.authorization, "content-type": "application/json"},
  1259. onload: (response) => {
  1260. if (response.status === 200) {
  1261. r(200, JSON.parse(response.responseText).data.user.rest_id);
  1262. } else {
  1263. console.error(response);
  1264. r(601);
  1265. }
  1266. },
  1267. error:(res)=>{
  1268. console.error(res);
  1269. r(601);
  1270. },
  1271. anonymous:true
  1272. })
  1273. }
  1274. const AuthUpdate = function(r, update = false){
  1275. if(new Date().getTime() - twitterAuth.updateTime > 30 * 60 * 1000 || update){
  1276. r(603);
  1277. new Promise((resolve, reject)=>{
  1278. if(false == getAuthStatus.twitter || true === update)
  1279. {
  1280. getAuthStatus.twitter = true;
  1281. GM_openInTab("https://twitter.com/settings/account?keyjokertask=storageAuth", true);
  1282. }
  1283. let i = 0;
  1284. let check = setInterval(()=>{
  1285. i++;
  1286. if(GM_getValue("twitterAuth") && new Date().getTime() - GM_getValue("twitterAuth").updateTime <= 10 * 1000)
  1287. {
  1288. if(GM_getValue("twitterAuth").status != 200)
  1289. {
  1290. clearInterval(check);
  1291. reject(GM_getValue("twitterAuth").status)
  1292. return;
  1293. }
  1294. twitterAuth.ct0 = GM_getValue("twitterAuth").ct0;
  1295. twitterAuth.updateTime = GM_getValue("twitterAuth").updateTime
  1296. twitterAuth.status = GM_getValue("twitterAuth").status;
  1297. clearInterval(check);
  1298. resolve(twitterAuth.status)
  1299. }
  1300. if(i >= 10)
  1301. {
  1302. clearInterval(check);
  1303. reject(408)
  1304. }
  1305. }, 1000)
  1306. }).then((ret)=>{
  1307. r(ret)
  1308. }).catch((err)=>{
  1309. r(err)
  1310. })
  1311. }else{
  1312. r(200);
  1313. }
  1314. }
  1315. // 推特取得用户页面响应头(OK)
  1316. /*twitterAP:function(r){
  1317. func.httpRequest({
  1318. url: 'https://twitter.com/settings/account?k',
  1319. method: 'GET',
  1320. onload: (response) => {
  1321. if (response.status === 200) {
  1322. if(debug)console.log(response)
  1323. r(200, response.responseHeaders)
  1324. } else {
  1325. console.error(response);
  1326. r(601);
  1327. }
  1328. },
  1329. error:(res)=>{
  1330. console.error(res);
  1331. r(601);
  1332. }
  1333. })
  1334. },*/
  1335.  
  1336. return {
  1337. FollowAuto: FollowAuto,
  1338. RetweetAuto: RetweetAuto,
  1339. AuthUpdate: AuthUpdate
  1340. }
  1341. })();
  1342. const func = {
  1343. // twitch & discord 凭证存储,人机验证处理
  1344. appHandle: function(){
  1345. switch(location.hostname)
  1346. {
  1347. case "www.twitch.tv":
  1348. if(location.search == "?keyjokertask=storageAuth")
  1349. {
  1350. let cookie = document.cookie + ";"
  1351. twitchAuth.updateTime = new Date().getTime();
  1352. if(cookie.match(/auth-token=(.+?);/) != null)
  1353. {
  1354. twitchAuth["auth-token"] = cookie.match(/auth-token=(.+?);/)[1]
  1355. twitchAuth.status = 200;
  1356. }else twitchAuth.status = 401;
  1357. GM_setValue("twitchAuth", twitchAuth)
  1358. console.log(twitchAuth)
  1359. window.close();
  1360. }
  1361. window.close();
  1362. break;
  1363. case "discord.com":
  1364. if(location.search == "?keyjokertask=storageAuth")
  1365. {
  1366. discordAuth.authorization = JSON.parse(localStorage.getItem("token"));
  1367. if(discordAuth.authorization == null)discordAuth.status = 401;
  1368. else discordAuth.status = 200;
  1369. discordAuth.updateTime = new Date().getTime();
  1370. GM_setValue("discordAuth", discordAuth);
  1371. console.log(discordAuth)
  1372. window.close();
  1373. }
  1374. break;
  1375. case "twitter.com":
  1376. if(location.search == "?keyjokertask=storageAuth")
  1377. {
  1378. let m = document.cookie.match(/ct0=(.+?);/);
  1379. if(m != null && m[1])
  1380. {
  1381. twitterAuth.status = 200;
  1382. twitterAuth.ct0 = m[1];
  1383. twitterAuth.updateTime = new Date().getTime()
  1384. }else{
  1385. twitterAuth.status = 401;
  1386. }
  1387. GM_setValue("twitterAuth", twitterAuth)
  1388. window.close();
  1389. }
  1390. break;
  1391. case "assets.hcaptcha.com":
  1392. // 人机验证
  1393. func.hcaptcha2();
  1394. break;
  1395. default :
  1396. break;
  1397. }
  1398. },
  1399. authVerify:function(){
  1400. // noticeFrame.loadFrame();
  1401. noticeFrame.addNotice("检查各项凭证");
  1402. noticeFrame.addNotice({type: "authVerify", name: "<a href=\"https://discord.com/login/\" target=\"_blank\">Discord</a> Auth", status:{id: "discord", class: "wait", text:"ready"}});
  1403. noticeFrame.addNotice({type: "authVerify", name: "<a href=\"https://accounts.spotify.com/login/\" target=\"_blank\">Spotify</a> Auth&nbsp;", status:{id: "spotify", class: "wait", text:"ready"}});
  1404. noticeFrame.addNotice({type: "authVerify", name: "<a href=\"https://steamcommunity.com/login/\" target=\"_blank\">Steam</a> Auth&nbsp;&nbsp;", status:{id: "steam", class: "wait", text:"ready"}});
  1405. noticeFrame.addNotice({type: "authVerify", name: "<a href=\"https://www.tumblr.com/login\" target=\"_blank\">Tumblr</a> Auth", status:{id: "tumblr", class: "wait", text:"ready"}});
  1406. noticeFrame.addNotice({type: "authVerify", name: "<a href=\"https://www.twitch.tv/login\" target=\"_blank\">Twitch</a> Auth&nbsp;", status:{id: "twitch", class: "wait", text:"ready"}});
  1407. noticeFrame.addNotice({type: "authVerify", name: "<a href=\"https://twitter.com/login/\" target=\"_blank\">Twitter</a> Auth", status:{id: "twitter", class: "wait", text:"ready"}});
  1408. DISCORD.AuthUpdate((status)=>{
  1409. this.statusReact(status, "discord");
  1410. }, true);
  1411. SPOTIFY.GetAccessToken((status, ret = null)=>{
  1412. this.statusReact(status, "spotify");
  1413. });
  1414. STEAM.InfoUpdate((status)=>{
  1415. this.statusReact(status, "steam");
  1416. }, "all", true);
  1417. TUMBLR.AuthUpdate((status, key = null)=>{
  1418. this.statusReact(status, "tumblr");
  1419. }, true);
  1420. TWITCH.AuthUpdate((status)=>{
  1421. this.statusReact(status, "twitch");
  1422. }, true);
  1423. TWITTER.AuthUpdate((status)=>{
  1424. this.statusReact(status, "twitter");
  1425. }, true);
  1426. },
  1427. statusReact: (code, id)=>{
  1428. switch(code)
  1429. {
  1430. case 200:
  1431. noticeFrame.updateNotice(id, 'success');
  1432. break;
  1433. case 601:
  1434. noticeFrame.updateNotice(id, 'error')
  1435. break;
  1436. case 401:
  1437. noticeFrame.updateNotice1({id:id, class:"error", text:"Not Login"})
  1438. break;
  1439. case 408:
  1440. noticeFrame.updateNotice1({id:id, class:"error", text:"Time Out"})
  1441. break;
  1442. case 603:
  1443. noticeFrame.updateNotice1({id:id, class:"wait", text:"Getting Auth"})
  1444. break;
  1445. case 604:
  1446. noticeFrame.updateNotice1({id:id, class:"error", text:"Network Error"})
  1447. break;
  1448. case 605:
  1449. noticeFrame.updateNotice1({id:id, class:"error", text:"评论区未找到"})
  1450. break;
  1451. default:
  1452. noticeFrame.updateNotice1({id:id, class:"error", text:"Unknown Error"})
  1453. console.error("React Unknown Error--->", code)
  1454. break;
  1455. }
  1456. },
  1457. checkUpdate: function(){
  1458. noticeFrame.addNotice({type:"msg",msg:"正在检查版本信息...(当前版本:" + GM_info.script.version + ")"})
  1459. func.httpRequest({
  1460. url: 'https://task.jysafe.cn/keyjoker/script/update.php?type=ver',
  1461. method: 'GET',
  1462. headers:{action: "keyjoker"},
  1463. onload: (response) => {
  1464. let ret = JSON.parse(response.response)
  1465. if(ret.status != 200)
  1466. {
  1467. noticeFrame.addNotice({type:"msg", msg:"异常!<font class=\"error\">" + ret.msg + "</font>"})
  1468. return;
  1469. }
  1470. if(this.checkVersion(ret.ver))
  1471. {
  1472. noticeFrame.addNotice({type:"msg", msg:"发现新版本!<font class=\"success\">" + ret.ver + "=>" + ret.msg + "</font>"})
  1473. }else{
  1474. noticeFrame.addNotice({type:"msg",msg:"当前已是最新版本!"})
  1475. }
  1476. },
  1477. error:(ret)=>{
  1478. console.log(ret);
  1479. noticeFrame.addNotice({type:"msg", msg:"请求异常!请至控制台查看详情!"})
  1480. },
  1481. anonymous:true
  1482. })
  1483. },
  1484. checkVersion: function(ver){
  1485. let new_ver = ver.split('.');
  1486. let old_ver = GM_info.script.version.split('.');
  1487. for(var i=0; i<new_ver.length && i<old_ver.length; i++){
  1488. let _new = parseInt(new_ver[i]);
  1489. let _old = parseInt(old_ver[i]);
  1490. if(_new >_old){
  1491. // 需更新
  1492. return 1;
  1493. }else if(_new == _old){
  1494. continue;
  1495. }else{
  1496. break;
  1497. }
  1498. }
  1499. return 0;
  1500. },
  1501. // 做任务
  1502. do_task: function(data){
  1503. for(const task of data.actions)
  1504. {
  1505. noticeFrame.addNotice({type: "taskStatus", task:task, status:'start'});
  1506. this.runDirectUrl(task.redirect_url);
  1507. let react = (code)=>{
  1508. switch(code)
  1509. {
  1510. case 200:
  1511. noticeFrame.updateNotice(task.id, 'success')
  1512. this.redeemAuto(task.redirect_url);
  1513. break;
  1514. case 601:
  1515. noticeFrame.updateNotice(task.id, 'error')
  1516. break;
  1517. case 401:
  1518. noticeFrame.updateNotice1({id:task.id, class:"error", text:"Not Login"})
  1519. break;
  1520. case 408:
  1521. noticeFrame.updateNotice1({id:task.id, class:"error", text:"Time Out"})
  1522. break;
  1523. case 603:
  1524. noticeFrame.updateNotice1({id:task.id, class:"wait", text:"Getting Auth"})
  1525. break;
  1526. case 604:
  1527. noticeFrame.updateNotice1({id:task.id, class:"error", text:"Network Error"})
  1528. break;
  1529. case 605:
  1530. noticeFrame.updateNotice1({id:task.id, class:"error", text:"评论区未找到"})
  1531. break;
  1532. default:
  1533. noticeFrame.updateNotice1({id:task.id, class:"error", text:"Unknown Error"})
  1534. console.error("React Unknown Error--->" + code)
  1535. break;
  1536. }
  1537. }
  1538. switch(task.task.name)
  1539. {
  1540. case "Join Steam Group":
  1541. STEAM.JoinGroup(react, task.data.url);
  1542. break;
  1543. case "Rep Steam Account":
  1544. STEAM.Rep(react, task.data.id);
  1545. break;
  1546. case "Wishlist Steam Game":
  1547. STEAM.AddWishlist(react, task.data.id);
  1548. break;
  1549. case "Follow Twitter Account":
  1550. TWITTER.FollowAuto(react, task.data);
  1551. break;
  1552. case "Join Discord Server":
  1553. var server = task.data.url.split(".gg/")[1];
  1554. DISCORD.JoinServer(react, server)
  1555. break;
  1556. case "Retweet Twitter Tweet":
  1557. TWITTER.RetweetAuto(react, task.data.url);
  1558. break;
  1559. case "Save Spotify Album":
  1560. SPOTIFY.SaveAuto(react, task.data);
  1561. break;
  1562. case "Follow Spotify Account":
  1563. SPOTIFY.Follow(react, task.data);
  1564. break;
  1565. case "Follow Twitch Channel":
  1566. TWITCH.FollowAuto(react, task.data.id);
  1567. break;
  1568. case "Follow Tumblr Blog":
  1569. TUMBLR.Follow(react, task.data.name);
  1570. break;
  1571. default:
  1572. noticeFrame.updateNotice1({id:task.id, class:"error", text:"Unknow Type:" + task.task.name})
  1573. console.error("未指定操作" + task.task.name)
  1574. break;
  1575. }
  1576. }
  1577.  
  1578. let i = 0;
  1579.  
  1580. // 清除上次残留线程
  1581. if(null != completeCheck)clearInterval(completeCheck);
  1582. let discordCheck = true;
  1583. completeCheck = setInterval(()=>{
  1584. i++;
  1585. //if(i >= 5)clearInterval(completeCheck);
  1586. // click reedem
  1587. $('button[class="btn btn-primary"]').click();
  1588. if(1 == $('#fraud-warning-modal[style!="display: none;"]').length){
  1589. // 有弹窗,模拟点击OK
  1590. $('button.btn.btn-secondary[type!="button"]')[0].click();
  1591. }
  1592. if( document.getElementById("toast-container")){
  1593. // 操作不存在
  1594. if(document.getElementById("toast-container").textContent == "This action does not exist.")
  1595. $('.card').remove();
  1596. // check discord error [Could not refresh Discord information, please try again.]
  1597. if(discordCheck == true && document.getElementById("toast-container").textContent == "Could not refresh Discord information, please try again.")
  1598. {
  1599. discordCheck = false;
  1600. GM_openInTab("https://www.keyjoker.com/account/identities", true)
  1601. }
  1602. }
  1603. if($(".list-complete-item").length == 0)
  1604. {
  1605. clearInterval(completeCheck);
  1606. noticeFrame.addNotice({type:"msg", msg:"任务似乎已完成,恢复监测!"});
  1607. GM_setValue("start", 1);
  1608. checkSwitch();
  1609. checkTask.next();
  1610. }
  1611. }, 5 * 1000)
  1612. },
  1613. // [修改自https://greasyfork.org/zh-CN/scripts/370650]
  1614. httpRequest: function (e) {
  1615. const requestObj = {}
  1616. requestObj.url = e.url
  1617. requestObj.method = e.method.toUpperCase()
  1618. requestObj.timeout = e.timeout || 30000
  1619. if (e.dataType) requestObj.responseType = e.dataType
  1620. if (e.headers) requestObj.headers = e.headers
  1621. if (e.data) requestObj.data = e.data
  1622. if (e.cookie) requestObj.cookie = e.cookie
  1623. if (e.anonymous) requestObj.anonymous = e.anonymous
  1624. if (e.onload) requestObj.onload = e.onload
  1625. if (e.fetch) requestObj.fetch = e.fetch
  1626. if (e.onreadystatechange) requestObj.onreadystatechange = e.onreadystatechange
  1627. requestObj.ontimeout = e.ontimeout || function (data) {
  1628. if (debug) console.log(data)
  1629. if (e.status) e.status.error('Error:Timeout(0)')
  1630. if (e.r) e.r({ result: 'error', statusText: 'Timeout', status: 0, option: e })
  1631. }
  1632. requestObj.onabort = e.onabort || function (data) {
  1633. if (debug) console.log(data)
  1634. if (e.status) e.status.error('Error:Aborted(0)')
  1635. if (e.r) e.r({ result: 'error', statusText: 'Aborted', status: 0, option: e })
  1636. }
  1637. requestObj.onerror = e.onerror || function (data) {
  1638. if (debug) console.log(data)
  1639. if (e.status) e.status.error('Error:Error(0)')
  1640. if (e.r) e.r({ result: 'error', statusText: 'Error', status: 0, option: e })
  1641. }
  1642. if (debug) console.log('发送请求:', requestObj)
  1643. GM_xmlhttpRequest(requestObj);
  1644. },
  1645. // 人机验证出现图片时的处理
  1646. hC_get_c:function(r){
  1647. new Promise((resolve, reject)=>{
  1648. this.httpRequest({
  1649. url: 'https://hcaptcha.com/checksiteconfig?host=dashboard.hcaptcha.com&sitekey=e4b28873-6852-49c0-9784-7231f004b96b&sc=1&swa=1',
  1650. method: 'GET',
  1651. headers: { 'Content-Type': 'application/json; charset=utf-8'},
  1652. onload: (response) => {
  1653. let ret = JSON.parse(response.response);
  1654. if(ret.pass){
  1655. GM_log(ret);
  1656. resolve(ret.c);
  1657. }else{
  1658. reject();
  1659. }
  1660. },
  1661. error: () =>{
  1662. if(debug)console.error("error");
  1663. }
  1664. })
  1665. }).then((c)=>{
  1666. r(c);
  1667. }).catch((err)=>{
  1668. console.error(err);
  1669. //let text = document.getElementsByClassName("prompt-text")[0].innerText;
  1670. //document.getElementsByClassName("prompt-text")[0].innerText = text + "\n免验证Cookie获取异常,请手动进行验证";
  1671. });
  1672.  
  1673. },
  1674. hC_getcaptcha: function(r){
  1675. this.hC_get_c((c)=>{
  1676. new Promise((resolve, reject)=>{
  1677. this.httpRequest({
  1678. url: 'https://hcaptcha.com/getcaptcha',
  1679. method: 'POST',
  1680. headers: { 'Content-Type': 'application/x-www-form-urlencoded'},
  1681. data: $.param({
  1682. sitekey:'e4b28873-6852-49c0-9784-7231f004b96b',
  1683. host:'dashboard.hcaptcha.com',
  1684. n:'暂未实现获取方案',
  1685. c:JSON.stringify(c)
  1686. }),
  1687. onload: (response) => {
  1688. let rep = JSON.parse(response.response);
  1689. if(rep.pass)resolve(rep.generated_pass_UUID);
  1690. else {
  1691. console.error("getcaptcha ERROR")
  1692. reject(rep);
  1693. }
  1694. },
  1695. error: () =>{
  1696. if(debug)console.error("error");
  1697. }
  1698. })
  1699. }).then((c)=>{
  1700. r(c);
  1701. }).catch((err)=>{
  1702. console.error(err);
  1703. r(false)
  1704. //let text = document.getElementsByClassName("prompt-text")[0].innerText;
  1705. //document.getElementsByClassName("prompt-text")[0].innerText = text + "\ngetcaptcha failed!";
  1706. });
  1707. });
  1708. },
  1709. hcaptcha2: function () {
  1710. return false;
  1711. let hcaptcha2Click=setInterval(()=>{
  1712. if(document.getElementsByClassName("challenge-container").length != 0 && document.getElementsByClassName("challenge-container")[0].children.length != 0)
  1713. {
  1714. clearInterval(hcaptcha2Click);
  1715. console.log("open hcaptcha");
  1716. let text = document.getElementsByClassName("prompt-text")[0].innerText;
  1717. document.getElementsByClassName("prompt-text")[0].innerText = text + "\n正在自动获取免验证Cookie";
  1718. //$(".task-grid").remove();
  1719. //$(".challenge-example").remove();
  1720.  
  1721. new Promise((resolve, reject)=>{
  1722. // csrf token
  1723. this.httpRequest({
  1724. url: 'https://accounts.hcaptcha.com/user',
  1725. method: 'GET',
  1726. headers: { 'Content-Type': 'application/json'},
  1727. onload: (response) => {
  1728. GM_log(response);
  1729. let rep = JSON.parse(response.response);
  1730. if(response.status == 200)
  1731. {
  1732. resolve(rep.csrf_token);
  1733. }else{
  1734. reject(response);
  1735. }
  1736. },
  1737. error: (err) =>{
  1738. if(debug)console.error(err);
  1739. }
  1740. })
  1741. }).then((csrf)=>{
  1742. this.hC_getcaptcha((token)=>{
  1743. if(token == false)
  1744. {
  1745. document.getElementsByClassName("prompt-text")[0].innerText = text + "\ntoken 获取失败";
  1746. return ;
  1747. }
  1748. this.httpRequest({
  1749. url: 'https://accounts.hcaptcha.com/accessibility/get_cookie',
  1750. method: 'POST',
  1751. headers: { 'Content-Type': 'application/json','x-csrf-token':csrf},
  1752. data:JSON.stringify({token:token}),
  1753. onload: (response) => {
  1754. if(response.status == 200)
  1755. {
  1756. document.getElementsByClassName("prompt-text")[0].innerText = text + "\n免验证Cookie获取成功,请重新点击验证框";
  1757. }else if(response.status == 401)
  1758. {
  1759. document.getElementsByClassName("prompt-text")[0].innerText = text + "\n当前账号或IP的免验证Cookie获取次数已达上限,请更换hcaptcha账号或IP";
  1760. // setTimeout(()=>{window.open("https://dashboard.hcaptcha.com/welcome_accessibility")}, 3000);
  1761. }else if(response.status == 500)
  1762. {
  1763. document.getElementsByClassName("prompt-text")[0].innerText = text + "\n未登录hCaptcha";
  1764. // setTimeout(()=>{window.open("https://dashboard.hcaptcha.com/welcome_accessibility")}, 3000);
  1765. }else{
  1766. console.error(response);
  1767. document.getElementsByClassName("prompt-text")[0].innerText = text + "\n发生未知错误,已将数据记录至控制台";
  1768. }
  1769. },
  1770. error: (err) =>{
  1771. console.error(err);
  1772. }
  1773. })
  1774. });
  1775. }).catch((err)=>{
  1776. if(err.status == 401)
  1777. {
  1778. document.getElementsByClassName("prompt-text")[0].innerText = text + "\n未登录hCaptcha";
  1779. // setTimeout(()=>{window.open("https://dashboard.hcaptcha.com/welcome_accessibility")}, 3000);
  1780. }else{
  1781. document.getElementsByClassName("prompt-text")[0].innerText = text + "\n未知错误";
  1782. }
  1783. console.error(err);
  1784. });
  1785. }
  1786. },1000);
  1787. },
  1788. // OK
  1789. redeemAuto: function(redirect_url){
  1790. if(0 != $('a[href="' + redirect_url + '"]').length)$('a[href="' + redirect_url + '"]').next().click();
  1791. },
  1792. reLoadTaskList: function(r){
  1793. // 重载任务列表
  1794. if(2 == document.getElementsByClassName('row').length)
  1795. {
  1796. $('.row')[1].remove();
  1797. $('.layout-container').append('<entries-component></entries-component>');
  1798. if(true == GM_getValue("offlineMode") && typeof offlineData === "object")
  1799. {
  1800. offlineData["app.js"]();
  1801. r();
  1802. }else{
  1803. $.getScript("/js/app.js", (rep,status)=>{
  1804. if("success" == status)r();
  1805. else console.error(status, rep);
  1806. });
  1807. }
  1808. }else
  1809. {
  1810. r();
  1811. }
  1812. },
  1813. reset: function (){
  1814. if(!confirm("你确定要执行重置操作?"))return;
  1815. noticeFrame.addNotice({type:"msg",msg:"正在重置设置"})
  1816. const listValues = GM_listValues()
  1817. for (const value of listValues) {
  1818. if(value == "currentVer")continue;
  1819. noticeFrame.addNotice({type:"msg",msg:"<font class=\"error\">正在删除:" + value + "</font>"})
  1820. GM_deleteValue(value)
  1821. }
  1822. noticeFrame.addNotice({type:"msg",msg:"设置重置完毕"})
  1823. },
  1824.  
  1825. runDirectUrl:function(direct_url){
  1826. GM_log("====访问跳转链接====")
  1827. this.httpRequest({
  1828. url: direct_url,
  1829. method: 'GET',
  1830. headers: {'x-csrf-token': $('meta[name="csrf-token"]').attr('content')},
  1831. onload: (response) => {
  1832. },
  1833. error:(res)=>{
  1834. }
  1835. })
  1836. },
  1837. test: function(){
  1838. // GM_openInTab("https://discord.com/channels/@me?keyjokertask=storageAuth", true);
  1839. }
  1840. }
  1841. // ============Start===========
  1842. if(location.pathname == "/entries")
  1843. {
  1844. window.onload=()=>{
  1845. GM_log("main")
  1846. if(document.getElementsByClassName("nav-item active").length != 0 && document.getElementsByClassName("nav-item active")[0].innerText == "Earn Credits" && document.getElementById("logout-form"))
  1847. {
  1848. noticeFrame.loadFrame();
  1849. // 事件绑定
  1850. eventBind();
  1851. //let isStart=setInterval(()=>{
  1852. if(GM_getValue("start")==1){
  1853. //clearInterval(isStart);
  1854. checkTask.next();
  1855. }
  1856. //},1000);
  1857. checkUpdate();
  1858. }else{
  1859. if($('.container').length > 0)
  1860. {
  1861. let i = 0;
  1862. let check = setInterval(()=>{
  1863. i++;
  1864. if($('.container')[0].innerText == "Whoops, looks like something went wrong.")location.href = location.pathname
  1865. if(i >= 10)clearInterval(check)
  1866. }, 1000);
  1867. }
  1868. }
  1869. }
  1870. }else{
  1871. func.appHandle();
  1872. }
  1873. function checkUpdate(){
  1874. // 隔一段时间检测新版本
  1875. if(new Date().getTime() - (GM_getValue("lastCheckUpdate") || 0) > 6 * 60 * 60 * 1000)
  1876. {
  1877. func.checkUpdate();
  1878. GM_setValue("lastCheckUpdate", new Date().getTime())
  1879. }
  1880. }
  1881. function eventBind(){
  1882. $('button#checkUpdate').click(()=>{func.checkUpdate()})
  1883. $('button#fuck').click(function(){
  1884. checkTask.start(()=>{$('.card').remove();})
  1885. })
  1886. $('button#clearNotice').click(function(){
  1887. noticeFrame.clearNotice()
  1888. })
  1889. $('button#changeLog').click(function(){
  1890. noticeFrame.addNotice({type:"msg", msg:"获取日志中..."})
  1891. func.httpRequest({
  1892. url: 'https://task.jysafe.cn/keyjoker/script/update.php?type=changelog&ver=' + GM_info.script.version,
  1893. method: 'GET',
  1894. headers:{action: "keyjoker"},
  1895. onload: (response) => {
  1896. let ret = JSON.parse(response.response)
  1897. if(ret.status != 200)
  1898. {
  1899. noticeFrame.addNotice({type:"msg", msg:"异常!<font class=\"error\">" + ret.msg + "</font>"})
  1900. }else
  1901. {
  1902. noticeFrame.addNotice({type:"msg", msg:"<font class=\"success\">" + ret.msg + "</font>"})
  1903. }
  1904. },
  1905. error:(ret)=>{
  1906. console.log(ret);
  1907. noticeFrame.addNotice({type:"msg", msg:"<font class=\"error\">请求异常!请至控制台查看详情!</font>"})
  1908. },
  1909. anonymous:true
  1910. })
  1911. })
  1912. $('button#report').click(function(){
  1913. noticeFrame.addNotice({type:"msg",msg:"目前提供以下反馈渠道:"})
  1914. noticeFrame.addNotice({type:"msg",msg:"<a href=\"https://www.jysafe.cn/4332.air\" target=\"_blank\">博客页面</a>"})
  1915. noticeFrame.addNotice({type:"msg",msg:"<a href=\"https://github.com/jiyeme/keyjokerScript/issues/new/choose\" target=\"_blank\">GitHub</a>"})
  1916. noticeFrame.addNotice({type:"msg",msg:"<a href=\"https://keylol.com/t660181-1-1\" target=\"_blank\">其乐社区</a>"})
  1917. })
  1918. // 版本升级后显示一次更新日志
  1919. if(GM_getValue("currentVer") != GM_info.script.version)
  1920. {
  1921. func.httpRequest({
  1922. url: 'https://task.jysafe.cn/keyjoker/script/update.php?type=changelog&ver=' + GM_info.script.version,
  1923. method: 'GET',
  1924. headers:{action: "keyjoker"},
  1925. onload: (response) => {
  1926. let ret = JSON.parse(response.response)
  1927. if(ret.status != 200)
  1928. {
  1929. noticeFrame.addNotice({type:"msg", msg:"异常!<font class=\"error\">" + ret.msg + "</font>"})
  1930. }else
  1931. {
  1932. noticeFrame.addNotice({type:"msg", msg:"<font class=\"success\">" + ret.msg + "</font>"})
  1933. }
  1934. },
  1935. error:(ret)=>{
  1936. console.log(ret);
  1937. noticeFrame.addNotice({type:"msg", msg:"更新日志获取异常!请至控制台查看详情!"})
  1938. },
  1939. anonymous:true
  1940. })
  1941. GM_setValue("currentVer", GM_info.script.version)
  1942. }
  1943. }
  1944. GM_registerMenuCommand("设置时间间隔", checkTask.setTime);
  1945. GM_registerMenuCommand("重置设置", func.reset);
  1946. GM_registerMenuCommand("凭证检测",()=>{
  1947. func.authVerify();
  1948. });
  1949. function offlineSwitch(id){
  1950. GM_unregisterMenuCommand(id);
  1951. if(true == GM_getValue("offlineMode")){
  1952. let id = GM_registerMenuCommand("进入稳定模式",()=>{
  1953. GM_setValue("offlineMode", false);
  1954. offlineSwitch(id);
  1955. });
  1956. }else{
  1957. let id = GM_registerMenuCommand("进入极速模式",()=>{
  1958. GM_setValue("offlineMode", true);
  1959. offlineSwitch(id);
  1960. });
  1961. }
  1962. }
  1963. function checkSwitch(){
  1964. GM_unregisterMenuCommand(checkSwitchId);
  1965. if(1 == GM_getValue("start")){
  1966. checkSwitchId = GM_registerMenuCommand("停止检测",()=>{
  1967. let date=new Date();
  1968. let hour=date.getHours();
  1969. let min=date.getMinutes()<10?("0"+date.getMinutes()):date.getMinutes();
  1970. GM_setValue("start",0);
  1971. $(".border-bottom").text(hour + ":" + min + " 停止执行新任务检测");
  1972. checkSwitch();
  1973. });
  1974. }else{
  1975. checkSwitchId = GM_registerMenuCommand("开始检测",()=>{
  1976. checkTask.start();
  1977. checkSwitch();
  1978. });
  1979. }
  1980. }
  1981. checkSwitch(null);
  1982. offlineSwitch(null);
  1983. if(debug)
  1984. {
  1985. GM_registerMenuCommand("Test",()=>{
  1986. func.test();
  1987. });
  1988. }
  1989. } catch (e) {
  1990. setTimeout(() => {
  1991. noticeFrame.addNotice({ type: 'msg', msg:"<font class\"error\">任务脚本执行期间发生预期之外的错误,详情见控制台</font>" })
  1992. }, 500)
  1993. console.log('%c%s', 'color:white;background:red', e.stack)
  1994. }
  1995. })();