OJ Judge #173
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |