Codeforces API 的简单应用:使用桌面通知系统显示特定比赛最近一次提交记录

· · 科技·工程

效果展示

背景

AtCoder Beginner Contest 里面总有那么几道签到题。有时候为了追求更快的速度,还没等上一题的评测结果出来我就得开始写下一题。于是就会让我在写下一题的时候经常担心上一题的代码有没有寄掉。

于是我产生了一个想法:利用桌面通知系统,直接把比赛中最近一次提交的结果以通知的形式显示在屏幕上,这样就省去了再次打开提交界面的麻烦。

然后我发现了一个巨大的问题。AtCoder 没有 API!!!我显然是知道破掉 Cloudflare 的方法的(网上有一堆关于这个的库),但是因为 AtCoder 没有 API,所以为了这个功能我还要手动处理账号登录这些事情,非常麻烦。然后突然想到 Codeforces 有 API,所以先拿 Codeforces API 做一个简单一点的版本。

代码

完整代码如下:

import requests, time, os, random, sys, datetime, hashlib

prev_id = 0
key = ''
private_key = ''
handle = ''
contestId = sys.argv[1]

while True:
    try:
        cdt = time.mktime(datetime.datetime.now().timetuple())
        pattern = f'contest.status?apiKey={key}&contestId={contestId}&count=1&from=1&handle={handle}&time={int(cdt)}'
        rdn = str(random.randint(0,999999)).zfill(6)
        pattern = 'https://codeforces.com/api/' + pattern + f'&apiSig={rdn}{hashlib.sha512((rdn + '/' + pattern + '#' + private_key).encode()).hexdigest()}'
        # print(pattern)
        response = requests.get(pattern)
        # print(response.json())
        if response.json()['status'] != 'OK':
            time.sleep(5)
            continue
        body = response.json()['result'][0]
        if prev_id == body['id'] or not 'verdict' in body or body['verdict'] == 'TESTING':
            time.sleep(5)
            continue
        os.system(f'notify-send --urgency={'normal' if body['verdict'] == 'OK' else 'critical'} {body['verdict']} \
\"{body['author']['contestId']}{body['problem']['index']} {body['problem']['name']}\\n\
Passed testcases: {body['passedTestCount']}\\n\
Time consumed: {body['timeConsumedMillis']}ms\"')
        prev_id = body['id']
    except:
        pass
    time.sleep(5)

你需要自行填入 Codeforces API 的公钥私钥以及你的用户名。

上述代码使用了 Linux 系统中的 notify-send 指令。网上有该命令的 Windows 移植版本,若在 Windows 上使用需要预先下载移植版本并添加至 path 中。Windows 的显示效果可能与 Linux 有所不同,而 Linux 上使用的不同桌面环境/窗口管理器的显示效果根据配置也会有所不同。该文章开头的效果在 Arch Linux Hyprland + mako 实现,配置文件由 cascade 提供。

使用方法

该脚本需要一个参数,即该比赛的编号。不是 round 号,而是访问对应网页时在地址栏显示的编号。

调用例:

$ python script.py 2124

随后保持该脚本运行即可。该脚本在正常运行情况下不会在终端输出任何内容。