ZJSU抢课小棉袄

发送包含指定的数据的HTTP POST,用以模拟单次点击。

// ==UserScript==
// @name         ZJSU抢课小棉袄
// @namespace    https://github.com/Zzzcy-tx/ZJSU_GetMyCoursePLZ
// @version      2.31
// @description  发送包含指定的数据的HTTP POST,用以模拟单次点击。
// @author       Zzzcy
// @match        */jwglxt/*gnmkdm=N253512*
// @icon         https://jwxt.zjgsu.edu.cn/jwglxt/logo/favicon.ico?t=1725699891340
// @grant        unsafeWindow
// @license      MPL
// ==/UserScript==

var data1, route, responseData;
let draggableBox;
const qqNumber = '552241992'
let shouldCaptureFetch = false;

const open = XMLHttpRequest.prototype.open;
const send = XMLHttpRequest.prototype.send;
const originalSend = XMLHttpRequest.prototype.send;

XMLHttpRequest.prototype.open = function (method, url) {
    //console.log(`yicibuhuo,method=${method}, data=${data}`)
    console.log(url, method);
    if (shouldCaptureFetch) {
        const parser = document.createElement('a');
        parser.href = url;
        //stuNumber = url.substring(58,69);
        //console.log(stuNumber);
    }
    return open.apply(this, arguments);
};

XMLHttpRequest.prototype.send = function (data) {
    console.log(data);
    if (shouldCaptureFetch) {
        data1 = data;
    }
    console.log(data1);
    originalSend.call(this, data);
};

const footer = document.getElementById('footerID');

const resultDiv = document.createElement('div');

resultDiv.textContent = ' 等待开启。';
resultDiv.style.textAlign = 'center';
resultDiv.style.fontFamily = 'Arial';
resultDiv.style.fontWeight = 'bold';
resultDiv.style.fontSize = '20px';
resultDiv.style.marginTop = '20px';
resultDiv.style.marginBottom = '20px';

footer.insertAdjacentElement('beforebegin', resultDiv);

const buttonContainer = document.createElement('div');
buttonContainer.style.display = 'flex';
buttonContainer.style.justifyContent = 'center';
buttonContainer.style.gap = '40px';
buttonContainer.style.marginTop = '20px';
buttonContainer.style.marginBottom = '20px';
buttonContainer.style.textAlign = 'center';
buttonContainer.style.fontFamily = 'Arial';
buttonContainer.style.fontSize = '18px';

// 创建发送 POST 请求按钮
const requestButton = document.createElement('button');
requestButton.style.padding = '5px 15px';
requestButton.textContent = '开始模拟点击';
buttonContainer.appendChild(requestButton); // 将按钮添加到容器中
// 创建停止按钮
const stopButton = document.createElement('button');
stopButton.style.padding = '5px 15px';
stopButton.textContent = '停止模拟点击';
buttonContainer.appendChild(stopButton); // 将按钮添加到容器中
// 创建录制 POST 按钮
const recordButton = document.createElement('button');
recordButton.style.padding = '5px 15px';
recordButton.textContent = '录制点击数据';
buttonContainer.appendChild(recordButton); // 将按钮添加到容器中

// 将按钮容器插入到 footer 之前
footer.insertAdjacentElement('beforebegin', buttonContainer);


let isRequesting = false;


requestButton.addEventListener('click', () => {
  if (!isRequesting) {
    isRequesting = true;
    requestLoop();
  }
});

stopButton.addEventListener('click', () => {
    isRequesting = false;
    resultDiv.textContent = '等待开启。'
});

recordButton.addEventListener('click', () => {
    if(shouldCaptureFetch){
        shouldCaptureFetch = false
        resultDiv.textContent = '未开始监听POST'
    } else {
        shouldCaptureFetch = true
        resultDiv.textContent = '正在监听POST……'
    }
});



async function sendPostRequest() {
  try {
      const data = data1;
      let xhr = new XMLHttpRequest();
      xhr.withCredentials = true;
      xhr.open('POST', `https://jwxt.zjgsu.edu.cn/jwglxt/xsxk/zzxkyzb_xkBcZyZzxkYzb.html?gnmkdm=N253512`);
      xhr.setRequestHeader('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/117.0');
      xhr.setRequestHeader('Accept', 'application/json, text/javascript, */*; q=0.01');
      xhr.setRequestHeader('Accept-Language', 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2');
      xhr.setRequestHeader('Accept-Encoding', 'gzip, deflate, br');
      xhr.setRequestHeader('Referer', `https://jwxt.zjgsu.edu.cn/jwglxt/xsxk/zzxkyzb_cxZzxkYzbIndex.html?gnmkdm=N253512&layout=default`);
      xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8');
      xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
      xhr.setRequestHeader('Origin', 'http://jwxt.zjgsu.edu.cn');
      xhr.setRequestHeader('DNT', '1');
      xhr.setRequestHeader('Connection', 'keep-alive');
      xhr.setRequestHeader('Cookie', `${route}`);
      xhr.setRequestHeader('Sec-Fetch-Dest', 'empty');
      xhr.setRequestHeader('Sec-Fetch-Mode', 'cors');
      xhr.setRequestHeader('Sec-Fetch-Site', 'same-origin');

      xhr.onload = await function() {
          responseData = xhr.response;
          console.log(xhr.response);
      };

      await xhr.send(data);
      var flag = JSON.parse(responseData).flag;
      console.log(flag);

      if(flag === '-1'){
          resultDiv.textContent = '正在等待余量放出,请耐心等待……'
      } else if( flag === '0' ){
          resultDiv.textContent = '排课时间冲突或未正确录制点击数据!请刷新界面'
      } else if( flag === '1' ){
          resultDiv.textContent = '恭喜,抢课成功! \\^_^// '
      } else {
          resultDiv.textContent = `未知错误,请联系技术人员QQ:${qqNumber}`
      }
      //resultDiv.textContent = JSON.stringify(responseData, null, 2);
      // 如果data.flag等于1,或者停止按钮按下,则停止请求
      if (flag === '1' || flag === '0' || !isRequesting) {
          isRequesting = false;
      }
  } catch (error) {
    console.error('发生错误:', error);
  }
};

async function requestLoop() {
    while (isRequesting) {
        await sendPostRequest();
        await sleep(1000);
        route = document.cookie;
    }
};

function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
};


//提示界面
(function () {
    const style = document.createElement('style');
    style.textContent =
        `
        .grabclasscontainer {
            width: 320px;
            text-align: center;
            position: fixed;
            right: 0px;
            bottom: 0px;
            height: 350px;
            border: 2px #333 solid;
            background-color: #d5e8fc;
            z-index: 999;
        }

        .grabclasscontainer label {
            flex: 1;
            text-align: right;
            margin-right: 10px;
        }


        .grabclasscontainer .dragBar {
            height: 30px;
            line-height: 30px;
            background-color: #505860;
            cursor: move;
            margin-bottom: 9px;
        }

        .grabclasscontainer .content {
            overflow-y: auto;
            height: 309px;
        }

        .grabclasscontainer .dragBar {
            height: 30px;
            line-height: 30px;
            background-color: #07c160;
            cursor: move;
            margin-bottom: 9px;
        }

        .grabclasscontainer .copyright {
            text-align: left;
        }

        .grabclasscontainer .graberror {
            color: #e91a0b;
        }

        .grabclasscontainer .grabsuccess {
            color: #0be94e;
        }
        `
    document.head.appendChild(style);
    const grabclasscontainer = document.createElement('div');
    grabclasscontainer.className = 'grabclasscontainer';
    grabclasscontainer.id = 'grabclasscontainer';
    grabclasscontainer.innerHTML = `
        <div class="dragBar" id="dragBar">
            按住拖动
        </div>
        <div class="content">
            <div class="copyright">
                【使用方式】<br>
                1.点开你想要的课,确保这课的时间段没有冲突。<br>
                2.滚动到网页最下方,点击“录制点击数据”,然后点右边的“选课”<br>
                3.中间会弹出提示“已无余量,不可选”的提示,点确定。<br>
                4.接着点击网页最下方的“开始模拟点击”,观察按钮上方提示,“正在等待余量放出,请耐心等待……”则为正常<br>
                5.不要关闭网页,不要关闭电脑,最好把网页最大化,等待抢课成功。<br><br><br>
                【联系作者】有偿帮助:QQ:${qqNumber}<br>
            </div>
        </div>
        `
    document.body.appendChild(grabclasscontainer);
    draggableBox = document.getElementById("grabclasscontainer");
    const dragBar = draggableBox.querySelector(".dragBar");
    let isDragging = false;
    let offsetX, offsetY;
    dragBar.addEventListener("mousedown", (e) => {
        isDragging = true;
        offsetX = e.clientX - draggableBox.getBoundingClientRect().left;
        offsetY = e.clientY - draggableBox.getBoundingClientRect().top;
        draggableBox.style.transition = "none";
    });
    document.addEventListener("mousemove", (e) => {
        if (!isDragging) return;
        let x = e.clientX - offsetX;
        let y = e.clientY - offsetY;
        draggableBox.style.left = x + "px";
        draggableBox.style.top = y + "px";
    });
    document.addEventListener("mouseup", () => {
        isDragging = false;
        draggableBox.style.transition = "all 0.3s ease"; // 添加平滑的过渡效果
    });
    draggableBox.querySelector('.clear').addEventListener('click', () => {
        localStorage.removeItem('targetTeacher');
        localStorage.removeItem('targetTime');
        localStorage.removeItem('firstmenu');
        localStorage.removeItem('secondmenu');
    });
})();


长期地址
遇到问题?请前往 GitHub 提 Issues。