您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
为 USTC 学生定制的各类实用功能:绕过验证码,自动登录,睿客网性能优化以及更多。
当前为
// ==UserScript== // @name USTC Helper // @name:zh-CN USTC 助手 // @license unlicense // @namespace http://tampermonkey.net/ // @version 0.4.1 // @description Various useful functions for USTC students: verification code bypass, auto login, rec performance improvement and more. // @description:zh-CN 为 USTC 学生定制的各类实用功能:绕过验证码,自动登录,睿客网性能优化以及更多。 // @author PRO // @match https://mail.ustc.edu.cn/ // @match https://mail.ustc.edu.cn/coremail/index.jsp* // @match https://passport.ustc.edu.cn/* // @match https://rec.ustc.edu.cn/* // @match https://recapi.ustc.edu.cn/identity/other_login?* // @match https://www.bb.ustc.edu.cn/* // @match https://jw.ustc.edu.cn/login // @icon https://passport.ustc.edu.cn/images/favicon.ico // @grant none // ==/UserScript== (function () { 'use strict'; var uhp_config = { passport: { enabled: true, // If false, all features will be disabled for passport.ustc.edu.cn bypass_code: true, // Whether to bypass verification code or not focus: true // Whether to focus on "Login" button }, mail: { enabled: true, // If false, all features will be disabled for mail.ustc.edu.cn focus: true, // Whether to focus on "Login" button domain: 'mail.ustc.edu.cn' // Automatically switch to given mail domain // Expected values: // 'mail.ustc.edu.cn' // 'ustc.edu.cn' // 'ah.edu.cn' // '' (Do nothing) }, rec: { enabled: true, // If false, all features will be disabled for rec.ustc.edu.cn & recapi.ustc.edu.cn autologin: true, // Whether automatically clicks login (USTC cas login) opencurrent: true // Whether open links in current tab (Significantly improves performance) }, bb: { enabled: true, // If false, all features will be disabled for www.bb.ustc.edu.cn autoauth: true, // Whether automatically authenticate when accessing outside school net autologin: true // Whether automatically clicks login }, jw: { enabled: true, // ... login: 'focus' // What to do to the login button: 'none', 'focus', 'click' } }; switch (window.location.host) { case 'mail.ustc.edu.cn': { if (!uhp_config.mail.enabled) { console.info("[USTC Helper] 'mail' feature disabled."); break; } if (uhp_config.mail.domain) { changeDomain(uhp_config.mail.domain); console.info(`[USTC Helper] Domain changed to ${uhp_config.mail.domain}.`); } if (uhp_config.mail.focus) { document.getElementById("login_button").focus(); console.info("[USTC Helper] Login button focused."); } break; } case 'passport.ustc.edu.cn': { if (!uhp_config.passport.enabled) { console.info("[USTC Helper] 'passport' feature disabled."); break; } let form = document.getElementsByClassName('loginForm')[0]; let options = { childList: true, attributes: false, subtree: true } function bypass() { let showCode = document.getElementsByName('showCode')[0]; showCode.value = ""; let code = document.querySelector('#valiCode'); if (code) { code.remove(); console.info("[USTC Helper] Verification code bypassed."); } else { console.info("[USTC Helper] Verification code not found."); } } function focus() { document.getElementById('login').focus(); console.info("[USTC Helper] Login button focused."); } function main() { if (uhp_config.passport.bypass_code) bypass(); if (uhp_config.passport.focus) focus(); observer.disconnect(); } let observer = new MutationObserver(main); observer.observe(form, options); break; } case 'rec.ustc.edu.cn': { if (!uhp_config.rec.enabled) { console.info("[USTC Helper] 'rec' feature disabled."); break; } if (uhp_config.rec.opencurrent) { window.webpackJsonp.push_ = window.webpackJsonp.push; window.webpackJsonp.push = (val) => { if (val[0][0] !== "chunk-5ae262a1") return window.webpackJsonp.push_(val); else { // Following script is adapted from https://rec.ustc.edu.cn/js/chunk-5ae262a1.b84e1461.js val[1]["2c03"] = function (t, e, s) { "use strict"; (function (t) { s("55dd"); var r = s("a67e"); e["a"] = { name: "GroupLister", components: { GroupCreate: function () { return Promise.all([s.e("chunk-390136ce"), s.e("chunk-662e27b9")]).then(s.bind(null, "18fa")) }, GroupAdd: function () { return s.e("chunk-5b916374").then(s.bind(null, "c1c7")) }, GroupEdit: function () { return Promise.all([s.e("chunk-390136ce"), s.e("chunk-0daeb591")]).then(s.bind(null, "1fa6")) } }, data: function () { return { status: { GroupCreateStatus: !1, GroupAddStatus: !1, GroupEditStatus: !1 }, loading: !1, nothing: !1, group: {}, sortBy: {}, headers: [{ id: 1, title: "群名称", class: "groupname", sort: "asc", showSort: !0, field: "group_name" }, { id: 2, title: "群号", class: "groupid", sort: "des", showSort: !1, field: "group_number" }, { id: 3, title: "成员", class: "groupuser", sort: "des", showSort: !1, field: "group_memeber_count" }, { id: 5, title: "分享", class: "groupshare", sort: "des", showSort: !1, field: "group_share_file_count" }, { id: 6, title: "操作", class: "groupmenu", sort: "", showSort: !1 }] } }, created: function () { this.sortBy = this.headers[0], this.getGroups() }, computed: { userInfo: function () { return this.$store.state.user.userInfo } }, watch: { $route: function () { this.getGroups() } }, filters: { identityNameFilter: function (t) { var e; switch (t) { case "owner": e = "群主"; break; case "admin": e = "管理员"; break; case "user": e = "成员"; break; default: break } return e } }, methods: { createGroup: function () { t("#newgroup").modal("show") }, addGroup: function () { t("#addgroup").modal("show") }, invite: function (t) { var e = this.$router.resolve({ name: "group", params: { groupNumber: t.group_number } }); this.$confirm({ showYesBtn: !1, showCopyBtn: !0, copyBtnText: "复制文字", title: "邀请入群", type: "confirm", content: "打开链接进入群组主页即可申请加入群组:".concat(t.group_name, ",群组主页链接:").concat(window.location.origin).concat(e.href) }).then((function () { } )).catch((function () { } )) }, goToGroupCloud: function (t, e) { if (["owner", "admin", "user"].indexOf(t.group_member_identity) < 0) return this.$message({ type: "warning", message: "您不是组群成员,无法进入群盘" }), !1; this.$store.commit("setSetting", { from: !0, drive: "groupdisk", tab: e, group: t }), this.$router.push({ name: "groupDisk", params: { groupNumber: t.group_number } }) }, isShowMenu: function (t) { return ["owner", "admin", "user"].indexOf(t.group_member_identity) > -1 }, isEditGroup: function (t) { return ["owner", "admin"].indexOf(t.group_member_identity) > -1 }, goToGroup: function (t) { var e = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : "group"; if ("wait" === t.group_is_review) return this.$message({ type: "warning", message: "群组待审核,不允许操作!" }), !1; if ("refuse" === t.group_is_review) return this.$message({ type: "warning", message: "群组审核未通过,不允许操作!" }), !1; // Instead of opening in new tab, we prefer to use vue's solution // Modifiy start this.$router.replace({ name: e, params: { groupNumber: t.group_number } }); // Modify end }, goToGroupHome: function (t) { this.$store.commit("SET_GROUP_SHOWDESC", !1), this.$router.push({ name: "group", params: { groupNumber: t } }) }, handleEditGroup: function (e) { var s = this; Object(r["g"])(e.group_number).then((function (t) { s.group = t.entity } )).catch((function (t) { s.$message({ type: "error", message: t }) } )), t("#editgroup").modal("show") }, groupRefresh: function () { this.getGroups() }, sortGroup: function (t) { if (6 === t) return !1; var e = this; this.headers.map((function (s) { return s.id === t ? (s.showSort = !0, s.sort = "des" === s.sort ? "asc" : "des", e.sortBy = s, s) : (s.showSort = !1, s.sort = "des", s) } )), this.sortGroupBy() }, getGroups: function () { var t = this; this.groups = [], this.loading = !0, this.nothing = !1, Object(r["r"])({}).then((function (e) { if (200 === e.status_code) if (t.loading = !1, t.groups = e.entity.datas, e.entity.total > 0) { var s = 0; e.entity.datas.map((function (t) { "user" != t.group_member_identity && t.group_pending_member_count > 0 && (s += t.group_pending_member_count) } )), t.$store.commit("setRequestNums", s), t.sortGroupBy(!0) } else t.nothing = !0; else t.$message({ type: "error", message: e.message }) } )).catch((function (e) { t.$message({ type: "error", message: e }) } )) }, sortGroupBy: function () { var t = this , e = arguments.length > 0 && void 0 !== arguments[0] && arguments[0]; this.groups.sort((function (s, r) { var o; return o = e ? r.group_is_review.localeCompare(s.group_is_review) : "group_name" === t.sortBy.field ? s[t.sortBy.field].localeCompare(r[t.sortBy.field]) : s[t.sortBy.field] - r[t.sortBy.field], o = "asc" === t.sortBy.sort ? o : -o, o } )) }, groupCancel: function (t) { var e = this , s = "adopt" === t.group_is_review ? "解散" : "删除"; this.$confirm({ type: "confirm", content: "".concat(s, "群后,所有关于本群组的信息都将被删除且无法恢复,确定").concat(s, "【").concat(t.group_name, "】吗?"), showCancleBtn: !0, showYesBtn: !0, custom: [] }).then((function () { Object(r["u"])({ groups_list: [t.group_number] }).then((function (t) { 200 === t.status_code ? (e.$message({ type: "success", message: t.message }), e.getGroups()) : e.$message({ type: "error", message: t.message }) } )).catch((function (t) { e.$message({ type: "error", message: t }) } )) } )).catch((function () { } )) }, groupQuit: function (t) { var e = this; this.$confirm({ type: "confirm", content: "确定退出该群组吗?", showCancleBtn: !0, showYesBtn: !0, custom: [] }).then((function () { Object(r["v"])({ group_number: t, action: "quit", members_list: [e.userInfo.user_number] }).then((function (t) { 200 === t.status_code ? (e.$message({ type: "success", message: t.message }), e.getGroups()) : e.$message({ type: "error", message: t.message }) } )).catch((function (t) { e.$message({ type: "error", message: t }) } )) } )).catch((function () { } )) } }, mounted: function () { var t = this; setTimeout((function () { for (var e in t.status) t.status[e] = !0 } ), 500) } } } ).call(this, s("1157")) }; // console.log(val); return window.webpackJsonp.push_(val); } }; } if (uhp_config.rec.autologin && document.location.pathname == '/') { let app = document.getElementById("app"); let options = { childList: true, attributes: false, subtree: true } let observer = new MutationObserver(() => { let btn = document.getElementsByClassName('navbar-login-btn')[0]; if (btn) { btn.click(); observer.disconnect(); } }); observer.observe(app, options); } else if (uhp_config.rec.opencurrent) { let app = document.getElementById("app"); let options = { childList: true, attributes: false, subtree: true } let observer = new MutationObserver(() => { let l = document.getElementsByClassName("app-list").length; if (l) { let links = app.getElementsByTagName("a"); for (let link of links) { if (link.target == '_blank') link.removeAttribute("target"); } } }); observer.observe(app, options); } break; } case 'recapi.ustc.edu.cn': { if (!uhp_config.rec.enabled) { console.info("[USTC Helper] 'rec' feature disabled."); break; } if (uhp_config.rec.autologin) { let btn = document.querySelector("#ltwo > div > button"); if (!btn) { console.error("[USTC Helper] Login button not found!"); } else { btn.click(); } } break; } case 'www.bb.ustc.edu.cn': { if (!uhp_config.bb.enabled) { console.info("[USTC Helper] 'bb' feature disabled."); break; } if (window.location.pathname == '/nginx_auth/' && uhp_config.bb.autoauth) { document.getElementsByTagName('a')[0].click(); } else if ((window.location.pathname == '/' || window.location.pathname == '/webapps/login/') && uhp_config.bb.autologin) { document.querySelector('#login > table > tbody > tr > td:nth-child(2) > span > a').click(); } break; } case 'jw.ustc.edu.cn': { if (!uhp_config.jw.enabled) { console.info("[USTC Helper] 'jw' feature disabled."); break; } if (uhp_config.jw.login) { let btn = document.getElementById('login-unified-wrapper'); if (uhp_config.jw.login == 'focus') { btn.focus(); } else if (uhp_config.jw.login == 'click') { btn.click(); } else { console.error(`[USTC Helper] Unknown option for jw.login: ${uhp_config.jw.login}`); } } break; } default: console.error("[USTC Helper] Unexpected host: " + window.location.host); break; } })();