JUST Kit

用于江苏科技大学网站的补丁与工具。

当前为 2022-01-07 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name JUST Kit
  3. // @description Patches & tools for JUST Website.
  4. // @description:zh-CN 用于江苏科技大学网站的补丁与工具。
  5. // @namespace https://greasyfork.org/users/197529
  6. // @version 0.1.18
  7. // @author kkocdko
  8. // @license Unlicense
  9. // @match *://*.just.edu.cn/*
  10. // @match *://*.just.edu.cn:8080/*
  11. // @match *://*.just.edu.cn:80/*
  12. // @match *://10.250.255.34/*
  13. // @match *://10.250.255.34/authentication/*
  14. // @match *://202.195.195.198/*
  15. // @match *://202.195.206.36:8080/*
  16. // @match *://202.195.206.37:8080/*
  17. // ==/UserScript==
  18. "use strict";
  19.  
  20. const { addFloatButton, waitValue, saveStr } = {
  21. addFloatButton(text, onClick) /* 20200707-1237 */ {
  22. if (!document.addFloatButton) {
  23. const container = document.body
  24. .appendChild(document.createElement("div"))
  25. .attachShadow({ mode: "open" });
  26. container.innerHTML =
  27. "<style>:host{position:fixed;top:3px;left:3px;z-index:2147483647;height:0}#i{display:none}*{float:left;margin:4px;padding:1em;outline:0;border:0;border-radius:5px;background:#1e88e5;box-shadow:0 1px 4px rgba(0,0,0,.1);color:#fff;font-size:14px;line-height:0;transition:.3s}:active{background:#42a5f5;box-shadow:0 2px 5px rgba(0,0,0,.2)}button:active{transition:0s}:checked~button{visibility:hidden;opacity:0;transform:translateY(-3em)}label{border-radius:50%}:checked~label{opacity:.3;transform:translateY(3em)}</style><input id=i type=checkbox><label for=i></label>";
  28. document.addFloatButton = (text, onClick) => {
  29. const button = document.createElement("button");
  30. button.textContent = text;
  31. button.addEventListener("click", onClick);
  32. return container.appendChild(button);
  33. };
  34. }
  35. return document.addFloatButton(text, onClick);
  36. },
  37. waitValue(fn, interval = 200, timeout = 3000) /* 20220104-1405 */ {
  38. return new Promise((resolve, reject) => {
  39. const intervalHandle = setInterval(() => {
  40. try {
  41. const value = fn();
  42. if (!value) return;
  43. clearInterval(intervalHandle);
  44. clearTimeout(timeoutHandle);
  45. resolve(value);
  46. } catch {}
  47. }, interval);
  48. const timeoutHandle = setTimeout(() => {
  49. clearInterval(intervalHandle);
  50. reject("waitValue: timeout");
  51. }, timeout);
  52. });
  53. },
  54. saveStr(name, str) /* 20211203-1130 */ {
  55. const el = document.createElement("a");
  56. el.download = name;
  57. el.href = URL.createObjectURL(new Blob([str]));
  58. el.click();
  59. },
  60. };
  61.  
  62. // Styles
  63. // document.lastChild.appendChild(document.createElement("style")).textContent = `
  64. // .personalinfo>.list_nav_box>iframe:first-child,browserPrompt{display:none;}
  65. // `.replace(/;/g, "!important;");
  66.  
  67. // Force page to scroll on x axis
  68. waitValue(() => document.readyState !== "loading").then(() => {
  69. if (document.documentElement.offsetWidth >= 1280) return;
  70. addFloatButton("Scroll X Axis", () => {
  71. let v = document.documentElement.getAttribute("style") ?? "";
  72. v += `width:1280px!important;min-width:1280px!important;overflow-x:scroll!important`;
  73. document.documentElement.setAttribute("style", v);
  74. });
  75. });
  76.  
  77. // Auto login
  78. waitValue(() => document.querySelector(".login_btn")).then((el) => el.click());
  79.  
  80. // Fix P.E. page left frame
  81. waitValue(() => leftFrame.document.readyState === "complete").then(() => {
  82. leftFrame.document.querySelectorAll("[onclick]").forEach((el) => {
  83. const v = el.getAttribute("onclick").replace("href(", "href=(");
  84. el.setAttribute("onclick", v);
  85. });
  86. });
  87.  
  88. // Health clock in
  89. waitValue(() => input_zwtw).then(() => {
  90. addFloatButton("Clock in", () => {
  91. input_tw.value = input_zwtw.value = 36;
  92. post.click();
  93. });
  94. });
  95.  
  96. // Schedule dump
  97. waitValue(() => kbtable).then((el) => {
  98. addFloatButton("Dump schedule", () => {
  99. saveStr(
  100. `schedule_${zc.value}_${Date.now().toString(36).slice(0, -2)}.html`,
  101. `<!DOCTYPE html><meta name="viewport" content="width=device-width">` +
  102. el.outerHTML
  103. );
  104. });
  105. });
  106.  
  107. // Evaluation of teaching
  108. waitValue(() => location.pathname.endsWith("/xspj_edit.do")).then(() => {
  109. addFloatButton("Fill form", () => {
  110. for (const el of document.querySelectorAll("[type=radio]:first-child"))
  111. el.click();
  112. document.querySelector("[type=radio]:not(:first-child)").click();
  113. });
  114. });
  115.  
  116. // Fix `window.showModalDialog`
  117. (this.unsafeWindow || self).showModalDialog = async (url, args, opt = "") => {
  118. // Thanks for github.com/niutech/showModalDialog
  119. const dialog = document.body.appendChild(document.createElement("dialog"));
  120. dialog.style = `padding:0;${opt.replace(/dialog/gi, "")}`;
  121. const iframe = dialog.appendChild(document.createElement("iframe"));
  122. iframe.style = "width:100%;height:100%;border:0";
  123. iframe.src = url;
  124. dialog.showModal();
  125. await new Promise((r) => (iframe.onload = r));
  126. iframe.contentWindow.close = () => dialog.remove();
  127. iframe.contentWindow.dialogArguments = args;
  128. };
  129.  
  130. // Free WLAN?
  131. // (this.unsafeWindow || self).XMLHttpRequest = new Proxy(XMLHttpRequest, {
  132. // construct: (T, args) => {
  133. // const ret = new T(...args);
  134. // let inner = null;
  135. // Object.defineProperty(ret, "onreadystatechange", {
  136. // value(...args) {
  137. // if (ret.readyState == 4 &&ret.responseURL === "http://10.250.255.34/api/v1/login") {}
  138. // if (inner) inner(...args);
  139. // },
  140. // set: (n) => (inner = n),
  141. // });
  142. // return ret;
  143. // },
  144. // });
  145. // if (property == "responseText" && target.responseURL === "http://10.250.255.34/api/v1/login") {
  146. // const json = JSON.parse(target.responseText);
  147. // if (json?.data?.policy?.pagenumb === "mondaypage") {
  148. // json.data.policy.channels.push({ name: "XSWK", id: "1" });
  149. // target.responseText = JSON.stringify(json);
  150. // }
  151. // let b = target.responseText;
  152. // let a = `{"code":200,"message":"ok","data":{"reauth":true,"policy":{"pagenumb":"mondaypage","channels":[{"name":"中国移动","id":"2"},{"name":"中国电信","id":"3"},{"name":"中国联通","id":"4"}]}}}`;
  153. // }
  154.  
  155. /* ===== Notes ===== *
  156.  
  157. 个人主页:my.just.edu.cn
  158. VPN2反代:vpn2.just.edu.cn
  159. Bing via VPN2:client.v.just.edu.cn/https/webvpn75e21a7d71bfef5014373fde6b3dc8d6/
  160. 教务系统自动登录:jwgl.just.edu.cn:8080/sso.jsp
  161. 后勤:hqgy.just.edu.cn/sg/wechat/index.jsp
  162. 查寝分数:hqgy.just.edu.cn/sg/wechat/healthCheck.jsp
  163. 体育:tyxy.just.edu.cn
  164. 网课:teach.just.edu.cn
  165. 实验课成绩:202.195.195.198/sy/
  166. 退出登录:ids2.just.edu.cn/cas/logout
  167. 智慧树:http://portals.zhihuishu.com/just
  168. 超星:http://just.fanya.chaoxing.com/
  169.  
  170. 教务系统内网:
  171. http://202.195.206.36:8080/jsxsd
  172. http://202.195.206.37:8080/jsxsd
  173.  
  174. https://client.v.just.edu.cn/enlink/#/client/app
  175.  
  176. /* ================= */