Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/UpdateVersion.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
pull-requests: write
contents: write
runs-on: ubuntu-latest
if: github.event.pull_request.head.repo.full_name == github.repository && github.actor != 'github-actions[bot]'
if: github.event.pull_request.head.repo.full_name == github.repository && !endsWith(github.actor, '[bot]')
steps:
- name: Generate a token
id: generate_token
Expand All @@ -26,4 +26,4 @@ jobs:
- name: Update version
env:
PR_BODY: ${{ github.event.pull_request.body }}
run: node ./Update/UpdateVersion.js ${{ steps.generate_token.outputs.token }} ${{ github.event.number }} "${{ github.event.pull_request.title }}" "$PR_BODY"
run: node ./Update/UpdateVersion.js ${{ steps.generate_token.outputs.token }} ${{ github.event.number }} "${{ github.event.pull_request.title }}" "$PR_BODY" "${{ github.event.action }}"
37 changes: 37 additions & 0 deletions Update.json
Original file line number Diff line number Diff line change
Expand Up @@ -3385,6 +3385,43 @@
}
],
"Notes": "No release notes were provided for this release."
},
"3.2.1": {
"UpdateDate": 1771740586846,
"Prerelease": true,
Copy link

@cubic-dev-ai cubic-dev-ai bot Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Production releases should set "Prerelease" to false. This entry marks 3.2.2 as a prerelease, which will mislabel the production release.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Update.json, line 3391:

<comment>Production releases should set "Prerelease" to false. This entry marks 3.2.2 as a prerelease, which will mislabel the production release.</comment>

<file context>
@@ -3385,6 +3385,28 @@
+        },
+        "3.2.1": {
+            "UpdateDate": 1771740586846,
+            "Prerelease": true,
+            "UpdateContents": [
+                {
</file context>
Suggested change
"Prerelease": true,
"Prerelease": false,
Fix with Cubic

"UpdateContents": [
{
"PR": 916,
"Description": "Fix contest ranking table styling for dark mode"
}
],
"Notes": "Fix contest ranking table colors in dark mode (contestrank-oi.php and contestrank-correct.php)"
},
"3.2.2": {
"UpdateDate": 1771848993140,
"Prerelease": true,
"UpdateContents": [
{
"PR": 919,
"Description": "Gate WebSocket toast notifications by per-feature popup settings"
}
],
"Notes": "Fix WebSocket notification toasts ignoring per-feature popup settings (BBSPopup/MessagePopup)."
},
"3.3.0": {
"UpdateDate": 1772197258188,
"Prerelease": false,
"UpdateContents": [
{
"PR": 916,
"Description": "Fix contest ranking table styling for dark mode"
},
{
"PR": 919,
"Description": "Gate WebSocket toast notifications by per-feature popup settings"
}
],
"Notes": "<b>Bug 修复</b><br>\n- 修复了暗色模式下比赛排名表(contestrank-oi.php 和 contestrank-correct.php)颜色显示异常的问题(#916)<br>\n- 修复了 WebSocket 弹窗通知未遵循各功能独立弹窗开关(BBSPopup/MessagePopup)的问题(#919)"
}
}
}
7 changes: 6 additions & 1 deletion Update/UpdateVersion.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,14 @@ execSync("gh pr checkout " + PRNumber);
console.info("PR #" + PRNumber + " has been checked out.");

// Check if the last commit was made by github-actions[bot]
// Only skip for synchronize events (push-triggered) to prevent infinite loops.
// For edited events (PR title/body changes), allow metadata updates even when
// the branch tip is a bot commit.
const eventAction = String(process.argv[6] || "");
const lastCommitAuthor = execSync("git log -1 --pretty=format:'%an'").toString().trim();
console.log("Last commit author: " + lastCommitAuthor);
if (lastCommitAuthor === "github-actions[bot]") {
console.log("Event action : " + eventAction);
if (lastCommitAuthor === "github-actions[bot]" && eventAction !== "edited") {
Copy link

@cubic-dev-ai cubic-dev-ai bot Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The new skip condition contradicts the comment and still blocks non-"edited" actions like opened/reopened. If the intent is to skip only on push-triggered synchronize events, this should explicitly check for synchronize instead of !== "edited" so metadata updates aren’t skipped for other actions.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Update/UpdateVersion.js, line 18:

<comment>The new skip condition contradicts the comment and still blocks non-"edited" actions like `opened`/`reopened`. If the intent is to skip only on push-triggered `synchronize` events, this should explicitly check for `synchronize` instead of `!== "edited"` so metadata updates aren’t skipped for other actions.</comment>

<file context>
@@ -8,9 +8,14 @@ execSync("gh pr checkout " + PRNumber);
 console.log("Last commit author: " + lastCommitAuthor);
-if (lastCommitAuthor === "github-actions[bot]") {
+console.log("Event action       : " + eventAction);
+if (lastCommitAuthor === "github-actions[bot]" && eventAction !== "edited") {
     console.log("Last commit was made by github-actions[bot]. Skipping to prevent infinite loop.");
     process.exit(0);
</file context>
Suggested change
if (lastCommitAuthor === "github-actions[bot]" && eventAction !== "edited") {
if (lastCommitAuthor === "github-actions[bot]" && eventAction === "synchronize") {
Fix with Cubic

console.log("Last commit was made by github-actions[bot]. Skipping to prevent infinite loop.");
process.exit(0);
}
Expand Down
65 changes: 49 additions & 16 deletions XMOJ.user.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// ==UserScript==
// @name XMOJ
// @version 3.2.0
// @version 3.3.0
// @description XMOJ增强脚本
// @author @XMOJ-Script-dev, @langningchen and the community
// @namespace https://github/langningchen
Expand Down Expand Up @@ -650,11 +650,13 @@ function HandleNotificationMessage(event) {
console.log("WebSocket: Server confirmed connection at timestamp", notification.timestamp);
}
} else if (notification.type === 'bbs_mention') {
// Backend now provides all data needed for immediate display
CreateAndShowBBSMentionToast(notification.data);
if (UtilityEnabled("BBSPopup")) {
CreateAndShowBBSMentionToast(notification.data);
}
} else if (notification.type === 'mail_mention') {
// Backend now provides all data needed for immediate display
CreateAndShowMailMentionToast(notification.data);
if (UtilityEnabled("MessagePopup")) {
CreateAndShowMailMentionToast(notification.data);
}
} else if (notification.type === 'pong') {
if (UtilityEnabled("DebugMode")) {
console.log("WebSocket: Received pong");
Expand Down Expand Up @@ -2994,11 +2996,21 @@ async function main() {
document.querySelector("#rank").innerText = "比赛暂时还没有排名";
} else {
document.querySelector("body > div > div.mt-3 > center > h3").innerText = document.querySelector("body > div > div.mt-3 > center > h3").innerText.substring(document.querySelector("body > div > div.mt-3 > center > h3").innerText.indexOf(" -- ") + 4) + "(OI排名)";
document.querySelector("#rank > thead > tr > :nth-child(1)").innerText = "排名";
document.querySelector("#rank > thead > tr > :nth-child(2)").innerText = "用户";
document.querySelector("#rank > thead > tr > :nth-child(3)").innerText = "昵称";
document.querySelector("#rank > thead > tr > :nth-child(4)").innerText = "AC数";
document.querySelector("#rank > thead > tr > :nth-child(5)").innerText = "得分";
let HeaderCells = document.querySelectorAll("#rank > thead > tr > *");
HeaderCells[0].innerText = "排名";
HeaderCells[1].innerText = "用户";
HeaderCells[2].innerText = "昵称";
HeaderCells[3].innerText = "AC数";
HeaderCells[4].innerText = "得分";
for (let j = 0; j < HeaderCells.length; j++) {
HeaderCells[j].removeAttribute("bgcolor");
HeaderCells[j].style.setProperty("background-color", "black", "important");
HeaderCells[j].style.setProperty("color", "white", "important");
let Links = HeaderCells[j].querySelectorAll("a");
for (let k = 0; k < Links.length; k++) {
Links[k].style.setProperty("color", "white", "important");
}
}
let RefreshOIRank = async () => {
await fetch(location.href)
.then((Response) => {
Expand All @@ -3009,6 +3021,7 @@ async function main() {
TidyTable(ParsedDocument.getElementById("rank"));
let Temp = ParsedDocument.getElementById("rank").rows;
for (var i = 1; i < Temp.length; i++) {
Temp[i].style.backgroundColor = "";
let MetalCell = Temp[i].cells[0];
let Metal = document.createElement("span");
Metal.innerText = MetalCell.innerText;
Expand All @@ -3018,6 +3031,10 @@ async function main() {
GetUsernameHTML(Temp[i].cells[1], Temp[i].cells[1].innerText);
Temp[i].cells[2].innerHTML = Temp[i].cells[2].innerText;
Temp[i].cells[3].innerHTML = Temp[i].cells[3].innerText;
for (let j = 0; j < 5 && j < Temp[i].cells.length; j++) {
Temp[i].cells[j].style.backgroundColor = "";
Temp[i].cells[j].style.color = "";
}
for (let j = 5; j < Temp[i].cells.length; j++) {
let InnerText = Temp[i].cells[j].innerText;
let BackgroundColor = Temp[i].cells[j].style.backgroundColor;
Expand All @@ -3038,7 +3055,7 @@ async function main() {
} else if (FirstBlood) {
BackgroundColor = "rgb(127, 127, 255)";
} else if (Solved) {
BackgroundColor = "rgb(0, 255, 0, " + Math.max(1 / 10 * (10 - ErrorCount), 0.2) + ")";
BackgroundColor = "rgba(0, 255, 0, " + Math.max(1 / 10 * (10 - ErrorCount), 0.2) + ")";
if (ErrorCount != 0) {
InnerText += " (" + (ErrorCount == 5 ? "4+" : ErrorCount) + ")";
}
Expand Down Expand Up @@ -3080,11 +3097,21 @@ async function main() {
document.querySelector("body > div > div.mt-3 > center > h3").innerText = document.querySelector("body > div > div.mt-3 > center > h3").innerText.substring(document.querySelector("body > div > div.mt-3 > center > h3").innerText.indexOf(" -- ") + 4) + "(订正排名)";
document.querySelector("body > div > div.mt-3 > center > a").remove();
}
document.querySelector("#rank > thead > tr > :nth-child(1)").innerText = "排名";
document.querySelector("#rank > thead > tr > :nth-child(2)").innerText = "用户";
document.querySelector("#rank > thead > tr > :nth-child(3)").innerText = "昵称";
document.querySelector("#rank > thead > tr > :nth-child(4)").innerText = "AC数";
document.querySelector("#rank > thead > tr > :nth-child(5)").innerText = "得分";
let HeaderCells = document.querySelectorAll("#rank > thead > tr > *");
HeaderCells[0].innerText = "排名";
HeaderCells[1].innerText = "用户";
HeaderCells[2].innerText = "昵称";
HeaderCells[3].innerText = "AC数";
HeaderCells[4].innerText = "得分";
for (let j = 0; j < HeaderCells.length; j++) {
HeaderCells[j].removeAttribute("bgcolor");
HeaderCells[j].style.setProperty("background-color", "black", "important");
HeaderCells[j].style.setProperty("color", "white", "important");
let Links = HeaderCells[j].querySelectorAll("a");
for (let k = 0; k < Links.length; k++) {
Links[k].style.setProperty("color", "white", "important");
}
}
let RefreshCorrectRank = async () => {
await fetch(location.href)
.then((Response) => {
Expand All @@ -3095,6 +3122,7 @@ async function main() {
TidyTable(ParsedDocument.getElementById("rank"));
let Temp = ParsedDocument.getElementById("rank").rows;
for (var i = 1; i < Temp.length; i++) {
Temp[i].style.backgroundColor = "";
let MetalCell = Temp[i].cells[0];
let Metal = document.createElement("span");
Metal.innerText = MetalCell.innerText;
Expand All @@ -3104,6 +3132,10 @@ async function main() {
GetUsernameHTML(Temp[i].cells[1], Temp[i].cells[1].innerText);
Temp[i].cells[2].innerHTML = Temp[i].cells[2].innerText;
Temp[i].cells[3].innerHTML = Temp[i].cells[3].innerText;
for (let j = 0; j < 5 && j < Temp[i].cells.length; j++) {
Temp[i].cells[j].style.backgroundColor = "";
Temp[i].cells[j].style.color = "";
}
for (let j = 5; j < Temp[i].cells.length; j++) {
let InnerText = Temp[i].cells[j].innerText;
let BackgroundColor = Temp[i].cells[j].style.backgroundColor;
Expand Down Expand Up @@ -3136,6 +3168,7 @@ async function main() {
}
Temp[i].cells[j].innerHTML = InnerText;
Temp[i].cells[j].style.backgroundColor = BackgroundColor;
Temp[i].cells[j].style.color = (UtilityEnabled("DarkMode") ? "white" : "black");
}
}
document.querySelector("#rank > tbody").innerHTML = ParsedDocument.querySelector("#rank > tbody").innerHTML;
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "xmoj-script",
"version": "3.2.0",
"version": "3.3.0",
"description": "an improvement script for xmoj.tech",
"main": "AddonScript.js",
"scripts": {
Expand Down
Loading