您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
自动抓取允许在 VJ 上使用自己账号提交问题的 OJ 的 Cookie
- // ==UserScript==
- // @name VJudge Cookie Filler
- // @name:zh-CN VJudge Cookie Filler
- // @version 1.0.1
- // @description Auto fill cookies for those OJ which can submit problems on VJ by using their cookies.
- // @description:zh-CN 自动抓取允许在 VJ 上使用自己账号提交问题的 OJ 的 Cookie
- // @author konglils
- // @license MIT
- // @namespace https://github.com/konglils/vjudge-cookie-filler
- // @supportURL https://github.com/konglils/vjudge-cookie-filler
- // @grant GM_xmlhttpRequest
- // @grant GM_openInTab
- // @grant GM_cookie
- // @run-at document-end
- // @connect vjudge.net
- // @match https://vjudge.net/*
- // @match https://codeforces.com/*
- // @match https://qoj.ac/*
- // @match https://onlinejudge.org/*
- // @match https://www.luogu.com.cn/*
- // @match https://www.nowcoder.com/*
- // ==/UserScript==
- (function() {
- 'use strict';
- const OJ = {
- "CodeForces": {
- url: "https://codeforces.com/",
- cookieNames: ["JSESSIONID"],
- },
- "Gym": {
- url: "https://codeforces.com/",
- cookieNames: ["JSESSIONID"],
- },
- "QOJ": {
- url: "https://qoj.ac/",
- cookieNames: ["UOJSESSID"],
- },
- "UVA": {
- url: "https://onlinejudge.org/",
- cookieNames: ["8da11fa2dbfcbf0b9ab349d4b3eba6a3"],
- },
- "洛谷": {
- url: "https://www.luogu.com.cn/",
- cookieNames: ["__client_id", "_uid"],
- },
- "牛客": {
- url: "https://www.nowcoder.com/",
- cookieNames: ["t"],
- },
- };
- const VERIFY_REGEX = /^\/user\/verifiedAccount\?oj=([^&]+)$/;
- const CHECK_REGEX = /^\/user\/checkAccount\?oj=([^&]+)$/;
- const _originOpen = XMLHttpRequest.prototype.open;
- const _originSend = XMLHttpRequest.prototype.send;
- XMLHttpRequest.prototype.open = function(method, url, async, user, password) {
- this._url = url;
- return _originOpen.apply(this, arguments);
- };
- // hook
- XMLHttpRequest.prototype.send = function(body) {
- this.addEventListener("readystatechange", function() {
- if (location.hostname === "vjudge.net" && this.readyState === 4 && this.status === 200) {
- let isVerified = true;
- let oj = "";
- // verify
- const matchVerify = this._url.match(VERIFY_REGEX);
- if (matchVerify) {
- oj = decodeURI(matchVerify[1]);
- const response = JSON.parse(this.responseText);
- if (Object.keys(response).length == 0) {
- isVerified = false;
- }
- }
- // check
- const matchCheck = this._url.match(CHECK_REGEX);
- if (matchCheck) {
- oj = decodeURI(matchCheck[1]);
- const response = JSON.parse(this.responseText);
- if (Object.keys(response).length == 0) {
- isVerified = false;
- }
- }
- // not login
- if (!isVerified && oj in OJ) {
- autoFill(oj);
- }
- }
- });
- return _originSend.apply(this, arguments);
- };
- function autoFill(oj, info = "Auto filling ...") {
- updatePendInfo(info);
- GM_cookie.list({ url: OJ[oj].url }, (cookies, error) => {
- if (error) {
- updateFailInfo(oj, "Failed to read cookies");
- console.error(`Failed to read ${oj} cookies: ` + error);
- return;
- }
- // filter cookies in order
- let ojCookies = [];
- for (let name of OJ[oj].cookieNames) {
- for (let cookie of cookies) {
- if (cookie.name == name && cookie.value !== "") {
- ojCookies.push({ "name": name, "value": cookie.value });
- }
- }
- }
- if (ojCookies.length !== OJ[oj].cookieNames.length) {
- loginToOJ(oj);
- return;
- }
- GM_xmlhttpRequest({ // new verify request
- method: "POST",
- url: "/user/verifyAccount",
- headers: { "Content-Type": "application/json;charset=UTF-8" },
- data: JSON.stringify({ "oj": oj, "proof": ojCookies }),
- onload(response) {
- response = JSON.parse(response.responseText);
- if (response.success) {
- updateSuccessInfo(response.accountDisplay);
- } else {
- loginToOJ(oj);
- }
- },
- onerror(error) {
- updateFailInfo(oj, "Network error");
- console.error("Network error: " + error);
- }
- });
- });
- }
- let loggingIn = false;
- let currentOJ = "";
- function loginToOJ(oj) {
- if (loggingIn) {
- return;
- }
- updateFailInfo(oj, oj + " verify failed");
- loggingIn = true;
- currentOJ = oj;
- GM_openInTab(OJ[oj].url, {
- active: true, // new tab
- insert: true, // insert right
- });
- }
- window.addEventListener("focus", () => {
- if (loggingIn) { // If try to login to OJ, and then focus back to VJ
- autoFill(currentOJ, "Logging in ...");
- }
- })
- function updatePendInfo(info) {
- let accountStatus = document.getElementsByClassName("my-account-status")[0];
- let accountInfo = document.getElementsByClassName("my-account")[0];
- accountStatus.innerHTML = '<i class="fa fa-refresh fa-spin" title="Checking..." data-toggle="tooltip"></i>';
- accountInfo.innerHTML = info;
- }
- function updateSuccessInfo(info) {
- let accountStatus = document.getElementsByClassName("my-account-status")[0];
- let accountInfo = document.getElementsByClassName("my-account")[0];
- let removeAccount = document.getElementsByClassName("remove-my-account")[0];
- accountStatus.innerHTML = '<i class="fa fa-check text-success" title="" data-toggle="tooltip" data-original-title="Connected"></i>';
- accountInfo.innerHTML = info;
- removeAccount.style.display = "inline";
- loggingIn = false;
- }
- function updateFailInfo(oj, info) {
- let accountStatus = document.getElementsByClassName("my-account-status")[0];
- let accountInfo = document.getElementsByClassName("my-account")[0];
- accountStatus.innerHTML = '<i class="fa fa-exclamation-triangle text-danger" title="" data-toggle="tooltip" data-original-title="Disconnected. Please re-verify."></i>';
- accountInfo.innerHTML = `${info} <a href="javascript:void(0)" id="oj-login-retry">Retry</a> `;
- let fillRetry = document.getElementById("oj-login-retry");
- fillRetry.onclick = () => { autoFill(oj) };
- loggingIn = false;
- }
- })();