Skip to content

OJ Judge

OJ Judge #173

Workflow file for this run

name: OJ Judge
on:
issues:
types: [opened]
jobs:
judge:
runs-on: ubuntu-latest
if: contains(github.event.issue.title, '评测')
steps:
- uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: Install dependencies
run: |
pip install cryptography psutil
- name: Decrypt and Judge
id: judge
env:
PRIVATE_KEY: ${{ secrets.RSA_PRIVATE_KEY }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ISSUE_CREATOR: ${{ github.event.issue.user.login }}
run: |
# 解析题目名称
PROBLEM_NAME=$(echo "${{ github.event.issue.title }}" | sed 's/评测//')
# 保存私钥
echo "$PRIVATE_KEY" > private.pem
# 解密提交的代码
echo "${{ github.event.issue.body }}" | base64 -d > encrypted_code
python3 -c "
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
import base64
import os
with open('private.pem', 'rb') as f:
private_key = serialization.load_pem_private_key(f.read(), password=None)
with open('encrypted_code', 'rb') as f:
encrypted_data = f.read()
# 提取RSA加密的AES密钥(前256字节),IV(接下来的16字节)和加密数据
encrypted_key = encrypted_data[:256]
iv = encrypted_data[256:272]
encrypted_content = encrypted_data[272:]
# 解密AES密钥
aes_key = private_key.decrypt(
encrypted_key,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# 使用AES解密数据
cipher = Cipher(algorithms.AES(aes_key), modes.CBC(iv), backend=default_backend())
decryptor = cipher.decryptor()
decrypted_padded = decryptor.update(encrypted_content) + decryptor.finalize()
# 移除PKCS7 padding
pad_length = decrypted_padded[-1]
decrypted = decrypted_padded[:-pad_length]
content = decrypted.decode('utf-8')
username, lang, code = content.split('\n', 2)
issue_creator = os.environ['ISSUE_CREATOR']
if username.strip() != issue_creator:
with open('judge_result.txt', 'w') as f:
f.write('CHEATING')
else:
with open('solution.cpp', 'wb') as f:
f.write(code.encode('utf-8'))
with open('lang.txt', 'w') as f:
f.write(lang.strip())
with open('judge_result.txt', 'w') as f:
f.write('OK')
"
# 检查判定结果
JUDGE_RESULT=$(cat judge_result.txt)
if [ "$JUDGE_RESULT" = "CHEATING" ]; then
# 创建作弊标签
gh label create "CHEATING" --color "ff0000" || true
# 添加作弊标签和回复
gh issue edit ${{ github.event.issue.number }} --add-label "CHEATING"
gh issue comment ${{ github.event.issue.number }} --body "检测到代码抄袭行为!"
gh issue close ${{ github.event.issue.number }}
else
# 处理 list.txt,移除 \r 确保兼容性
sed -i 's/\r//' ./problems/list.txt
# 计算题目 ID
ID=$(grep -n "^$PROBLEM_NAME$" ./problems/list.txt | cut -d: -f1)
if [ -z "$ID" ]; then
echo "题目不存在: $PROBLEM_NAME" >&2
exit 1
fi
LANG=$(cat lang.txt)
# 运行评测
RESULT=$(python3 judge.py private.pem "problems/$ID" solution.cpp "$LANG")
# 回复结果
gh issue comment ${{ github.event.issue.number }} --body "$RESULT"
# 获取状态
STATUS=$(cat judge_status.txt)
# 确保标签存在
create_label_if_not_exists() {
local label=$1
local color=$2
gh label list | grep -q "^$label\s" || gh label create "$label" --color "$color"
}
# 为不同的标签设置不同的颜色
create_label_if_not_exists "AC" "0e8a16"
create_label_if_not_exists "MLE" "1e90ff"
create_label_if_not_exists "WA" "d93f0b"
create_label_if_not_exists "TLE" "ff69b4"
create_label_if_not_exists "CE" "808080"
# 添加标签
gh issue edit ${{ github.event.issue.number }} --add-label "$STATUS"
gh issue close ${{ github.event.issue.number }}
fi