Skip to content

migrate: hustoj: fix bugs - #1013

Merged
undefined-moe merged 2 commits into
hydro-dev:masterfrom
bhscer:hustoj-migrate-fix-2
Jul 18, 2025
Merged

migrate: hustoj: fix bugs#1013
undefined-moe merged 2 commits into
hydro-dev:masterfrom
bhscer:hustoj-migrate-fix-2

Conversation

@bhscer

@bhscer bhscer commented Jul 11, 2025

Copy link
Copy Markdown
Contributor
  1. Also import contest's allow member list
  2. Private contest with empty password will let Hydro think it's public, need create a password
  3. Automatically fix invalid filename
  4. Automatically add a number char if a testcase file didn't have.
  5. Support detecting another format of upload file (current format is /upload/aa/xyz.jpg , but some file's format is /upload/aa/bb/xyz.jpg )

Summary by CodeRabbit

  • New Features

    • Users with contest access privileges are now automatically enrolled or assigned to private contests without passwords after import.
  • Improvements

    • Improved consistency in test data filename normalization and upload file path handling for better accuracy and compatibility.

@coderabbitai

coderabbitai Bot commented Jul 11, 2025

Copy link
Copy Markdown

Walkthrough

The script in packages/migrate/scripts/hustoj.ts has been updated to replace the static filename mapping with a new fixFileName function that normalizes filenames by adding zeros before extensions and replacing special characters. The regex for extracting upload file paths from problem content and contest descriptions is enhanced to capture optional subdirectories and exact filenames. During contest import, a new flag isAssignMode is set for private contests without passwords, and users with privileges are either assigned collectively or enrolled individually based on this flag. Test data synchronization and file reading now consistently use the updated filename normalization.

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

packages/migrate/scripts/hustoj.ts

Oops! Something went wrong! :(

ESLint: 9.31.0

Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@hydrooj/eslint-config' imported from /eslint.config.mjs
at Object.getPackageJSONURL (node:internal/modules/package_json_reader:255:9)
at packageResolve (node:internal/modules/esm/resolve:767:81)
at moduleResolve (node:internal/modules/esm/resolve:853:18)
at defaultResolve (node:internal/modules/esm/resolve:983:11)
at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:801:12)
at #cachedDefaultResolve (node:internal/modules/esm/loader:725:25)
at ModuleLoader.resolve (node:internal/modules/esm/loader:708:38)
at ModuleLoader.getModuleJobForImport (node:internal/modules/esm/loader:309:38)
at #link (node:internal/modules/esm/module_job:202:49)


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4c8c38e and 7aa8c82.

📒 Files selected for processing (1)
  • packages/migrate/scripts/hustoj.ts (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/migrate/scripts/hustoj.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Analyze (javascript)
  • GitHub Check: build
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f53dd45 and 4c8c38e.

📒 Files selected for processing (1)
  • packages/migrate/scripts/hustoj.ts (7 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
packages/migrate/scripts/hustoj.ts (1)
packages/utils/lib/common.ts (1)
  • noop (153-153)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (2)
packages/migrate/scripts/hustoj.ts (2)

196-206: Good improvement to file path handling!

The enhanced regex pattern and file path construction correctly handles both /upload/aa/xyz.jpg and /upload/aa/bb/xyz.jpg formats. The use of fixFileName ensures consistent filename normalization across the migration.


288-291: Excellent security enhancement for private contests!

Automatically generating secure passwords for private contests that lack them prevents unauthorized access while maintaining the contest's private nature. The 32-character hex password provides strong security.

Comment on lines +58 to +68
function fixFileName(fileName: string) {
if (fileName.endsWith('.in') || fileName.endsWith('.out')) {
const dotAt = fileName.lastIndexOf('.');
const name = fileName.slice(0, dotAt);
const suffix = fileName.slice(dotAt + 1);
if (!name.match(/[0-9]/)) {
fileName = `${name}0.${suffix}`;
}
}
return fileName.replace(/[\\/?#~!|*]/g, '_');
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance special character replacement for better cross-platform compatibility.

The current regex pattern might miss some problematic characters that could cause issues on different platforms. Consider expanding it to include Windows reserved characters and other potentially problematic ones.

 function fixFileName(fileName: string) {
+    if (!fileName) return fileName;
     if (fileName.endsWith('.in') || fileName.endsWith('.out')) {
         const dotAt = fileName.lastIndexOf('.');
         const name = fileName.slice(0, dotAt);
         const suffix = fileName.slice(dotAt + 1);
         if (!name.match(/[0-9]/)) {
             fileName = `${name}0.${suffix}`;
         }
     }
-    return fileName.replace(/[\\/?#~!|*]/g, '_');
+    // Replace Windows reserved characters and other problematic ones
+    return fileName.replace(/[<>:"/\\|?*#~!]/g, '_');
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function fixFileName(fileName: string) {
if (fileName.endsWith('.in') || fileName.endsWith('.out')) {
const dotAt = fileName.lastIndexOf('.');
const name = fileName.slice(0, dotAt);
const suffix = fileName.slice(dotAt + 1);
if (!name.match(/[0-9]/)) {
fileName = `${name}0.${suffix}`;
}
}
return fileName.replace(/[\\/?#~!|*]/g, '_');
}
function fixFileName(fileName: string) {
if (!fileName) return fileName;
if (fileName.endsWith('.in') || fileName.endsWith('.out')) {
const dotAt = fileName.lastIndexOf('.');
const name = fileName.slice(0, dotAt);
const suffix = fileName.slice(dotAt + 1);
if (!name.match(/[0-9]/)) {
fileName = `${name}0.${suffix}`;
}
}
// Replace Windows reserved characters and other problematic ones
return fileName.replace(/[<>:"/\\|?*#~!]/g, '_');
}
🤖 Prompt for AI Agents
In packages/migrate/scripts/hustoj.ts around lines 58 to 68, the regex used to
replace special characters in file names is too limited and may miss characters
that cause issues on some platforms. Update the regex pattern in the replace
method to include a broader set of reserved and problematic characters, such as
Windows reserved characters like < > : " / \ | ? * and others, to ensure better
cross-platform compatibility.

Comment on lines +301 to +304
const allowedUser:{ user_id:string }[] = await query(`SELECT * FROM privilege WHERE rightstr = 'c${tdoc.contest_id}';`);
for (let i = 0; i < allowedUser.length; i++) {
await ContestModel.attend(domainId, tid, uidMap[allowedUser[i].user_id]).catch(noop);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

⚠️ Potential issue

Add validation and improve error handling for contest enrollment.

The current implementation silently ignores errors which could hide important issues like missing users or enrollment failures. Consider validating user existence and logging errors for debugging.

         const allowedUser:{ user_id:string }[] = await query(`SELECT * FROM privilege WHERE rightstr = 'c${tdoc.contest_id}';`);
         for (let i = 0; i < allowedUser.length; i++) {
-            await ContestModel.attend(domainId, tid, uidMap[allowedUser[i].user_id]).catch(noop);
+            const uid = uidMap[allowedUser[i].user_id];
+            if (!uid) {
+                report({ message: `warning: user ${allowedUser[i].user_id} not found for contest ${tdoc.contest_id}` });
+                continue;
+            }
+            await ContestModel.attend(domainId, tid, uid).catch((err) => {
+                report({ message: `warning: failed to enroll user ${allowedUser[i].user_id} in contest ${tdoc.contest_id}: ${err.message}` });
+            });
         }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const allowedUser:{ user_id:string }[] = await query(`SELECT * FROM privilege WHERE rightstr = 'c${tdoc.contest_id}';`);
for (let i = 0; i < allowedUser.length; i++) {
await ContestModel.attend(domainId, tid, uidMap[allowedUser[i].user_id]).catch(noop);
}
const allowedUser:{ user_id:string }[] = await query(`SELECT * FROM privilege WHERE rightstr = 'c${tdoc.contest_id}';`);
for (let i = 0; i < allowedUser.length; i++) {
const uid = uidMap[allowedUser[i].user_id];
if (!uid) {
report({ message: `warning: user ${allowedUser[i].user_id} not found for contest ${tdoc.contest_id}` });
continue;
}
await ContestModel.attend(domainId, tid, uid).catch((err) => {
report({ message: `warning: failed to enroll user ${allowedUser[i].user_id} in contest ${tdoc.contest_id}: ${err.message}` });
});
}
🤖 Prompt for AI Agents
In packages/migrate/scripts/hustoj.ts around lines 301 to 304, the code
currently ignores errors during contest enrollment by using catch(noop), which
can hide issues. Modify the loop to first validate that each user exists before
attempting enrollment, and replace the silent catch with proper error handling
that logs any errors encountered during ContestModel.attend calls to aid
debugging.

Comment thread packages/migrate/scripts/hustoj.ts
@undefined-moe
undefined-moe merged commit 537c6d2 into hydro-dev:master Jul 18, 2025
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants