diff --git a/.verify-helper/docs/static/document.ja.md b/.verify-helper/docs/static/document.ja.md
index c2b0892a..b2c5c054 100644
--- a/.verify-helper/docs/static/document.ja.md
+++ b/.verify-helper/docs/static/document.ja.md
@@ -113,7 +113,7 @@ verification_file_suffix = ".test.sed"
| [Library Checker](https://judge.yosupo.jp/) | |
| [Aizu Online Judge](https://onlinejudge.u-aizu.ac.jp/home) | |
| [HackerRank](https://www.hackerrank.com/) | |
-| [AtCoder](https://atcoder.jp) | 環境変数 `DROPBOX_TOKEN` の設定が必要です。token の値は `$ oj d --system https://atcoder.jp/contests/agc001/tasks/agc001_a` として表示されるヒントに従って取得してください。 |
+| [AtCoder](https://atcoder.jp) | 環境変数 `DROPBOX_TOKEN` の設定が必要です。token の値は `$ oj d --system https://atcoder.jp/contests/agc001/tasks/agc001_a` として表示されるヒントに従って取得してください。
(2024.03.16追記)
現在ヘルプ通りにはトークンを取得できなくなっています。まずからAppを作成し、Permissions で `files.metadata.read` と `sharing.read` にチェックをつけます。ここで、generate access token で一時的なトークンを作成し、環境変数`DROPBOX_TOKEN`に設定することができますが、これは短期間で失効してしまうので、再設定が面倒な方はを参考に、Refresh Tokenを取得して環境変数`DROPBOX_REFRESH_TOKEN`を、App作成時に出てきたApp KeyとApp Secretをそれぞれ環境変数`DROPBOX_APP_KEY`,`DROPBOX_APP_SECRET`として登録してください。これらを用いて毎回アクセストークンを自動で生成して適用するようになります。 |
| [yukicoder](https://yukicoder.me) | 環境変数 `YUKICODER_TOKEN` の設定が必要です。[ヘルプ - yukicoder](https://yukicoder.me/help) の「ログインしてないと使えない機能をAPIとして使いたい」の節や [暗号化されたシークレットの作成と利用 - GitHub ヘルプ](https://help.github.com/ja/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets#creating-encrypted-secrets) 参考にして設定してください。 |
これらの他サービスはテストケースを利用できる形で公開してくれていないため利用できません。
diff --git a/.verify-helper/docs/static/document.md b/.verify-helper/docs/static/document.md
index ee10850a..a966af7b 100644
--- a/.verify-helper/docs/static/document.md
+++ b/.verify-helper/docs/static/document.md
@@ -112,7 +112,7 @@ verification_file_suffix = ".test.sed"
| [Library Checker](https://judge.yosupo.jp/) | |
| [Aizu Online Judge](https://onlinejudge.u-aizu.ac.jp/home) | |
| [HackerRank](https://www.hackerrank.com/) | |
-| [AtCoder](https://atcoder.jp) | You must set the `DROPBOX_TOKEN` environment variable. You can obtain the token by following the HINT message shown by `$ oj d --system https://atcoder.jp/contests/agc001/tasks/agc001_a`. |
+| [AtCoder](https://atcoder.jp) | You must set the `DROPBOX_TOKEN` environment variable. You can obtain the token by following the HINT message shown by `$ oj d --system https://atcoder.jp/contests/agc001/tasks/agc001_a`.
(Added on 2024.03.16)
Currently, obtaining tokens according to the help is not possible. First, create an App from , and check files.metadata.read and sharing.read under Permissions. Here, you can generate a temporary token by clicking on "generate access token" and set it to the environment variable `DROPBOX_TOKEN`. However, since this token expires after a short period, for those who find reconfiguration troublesome, please refer to to obtain a Refresh Token and set it to the environment variable `DROPBOX_REFRESH_TOKEN`, and register the App Key and App Secret obtained during App creation as environment variables `DROPBOX_APP_KEY` and `DROPBOX_APP_SECRET`, respectively. By using these, an access token will be automatically generated and applied each time.|
| [yukicoder](https://yukicoder.me) | You must set the `YUKICODER_TOKEN` environment variable. See 「ログインしてないと使えない機能をAPIとして使いたい」 in [ヘルプ - yukicoder](https://yukicoder.me/help) and [Creating and using encrypted secrets - GitHub Help](https://help.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets). |
Other judging platforms do not currently publish the test cases in usable forms, and so are not currently supported.
diff --git a/onlinejudge_verify/verify.py b/onlinejudge_verify/verify.py
index 83a0b096..a7353757 100644
--- a/onlinejudge_verify/verify.py
+++ b/onlinejudge_verify/verify.py
@@ -1,14 +1,18 @@
# Python Version: 3.x
import hashlib
+import json
import math
import os
import pathlib
+import re
import subprocess
import time
import traceback
from logging import getLogger
from typing import *
+import requests
+
import onlinejudge
import onlinejudge_verify.languages.list
import onlinejudge_verify.marker
@@ -34,7 +38,10 @@ def succeeded(self) -> bool:
def exec_command(command: List[str]):
# NOTE: secrets like YUKICODER_TOKEN are masked
- logger.info('$ %s', ' '.join(command))
+ # dropbox-tokenを新規に取得する場合は、そのトークンが表示されるのでそれもマスクする
+ dropbox_token_pattern = re.compile(r'(--dropbox-token)\s+([^\s]+)')
+ message = dropbox_token_pattern.sub(r'\1 ***', ' '.join(command))
+ logger.info('$ %s', message)
cwd = pathlib.Path.cwd()
try:
@@ -47,6 +54,19 @@ def exec_command(command: List[str]):
os.chdir(str(cwd))
+def get_fresh_dropbox_token() -> str:
+ data = {
+ 'grant_type': 'refresh_token',
+ 'refresh_token': os.environ['DROPBOX_REFRESH_TOKEN'],
+ }
+ response = requests.post('https://api.dropbox.com/oauth2/token', data=data, auth=(os.environ['DROPBOX_APP_KEY'], os.environ['DROPBOX_APP_SECRET']), timeout=30)
+ try:
+ data = response.json()
+ return data.get('access_token', '')
+ except json.JSONDecodeError:
+ return ''
+
+
def verify_file(path: pathlib.Path, *, compilers: List[str], tle: float, jobs: int) -> Optional[bool]:
logger.info('verify: %s', path)
@@ -81,6 +101,9 @@ def verify_file(path: pathlib.Path, *, compilers: List[str], tle: float, jobs: i
if os.environ.get('DROPBOX_TOKEN'):
command += ['--dropbox-token', os.environ['DROPBOX_TOKEN']]
+ # 短期間で失効するDROPBOX_TOKENを新規に取得するオプションを用意する
+ elif os.environ.get('DROPBOX_REFRESH_TOKEN') and os.environ.get('DROPBOX_APP_KEY') and os.environ.get('DROPBOX_APP_SECRET'):
+ command += ['--dropbox-token', get_fresh_dropbox_token()]
if os.environ.get('YUKICODER_TOKEN'):
command += ['--yukicoder-token', os.environ['YUKICODER_TOKEN']]
try: