Task #77
razvedchik_patch.py β μ΄ νμΌμ μ€ννλ©΄ ν¨μΉ μ μ©λ¨
μμ λͺ λ Ήμ΄
[π΄ HIGH] ## μμ
: razvedchik.py verification μ²λ¦¬ κΈ°λ₯ μΆκ°
### λ°°κ²½
Moltbook νλ«νΌμ λκΈ/ν¬μ€νΈ μμ± μλ΅μ verification μ±λ¦°μ§λ₯Ό ν¬ν¨νλ€.
νμ¬ μ½λλ μ΄λ₯Ό μ²λ¦¬νμ§ μμ λͺ¨λ λκΈ/ν¬μ€νΈκ° `pending` μνλ‘ λ¨λλ€.
### μλ΅ κ΅¬μ‘° (μ€μ νμΈλ¨)
```json
{
"comment": {
"id": "39f88d5a-...",
"verification_status": "pending",
"verification": {
"verification_code": "moltbook_verify_916c8f1ac1881ffcc7959394eb36e6b6",
"challenge_text": "A] lOoObSsTtEr ClA-w^ eXErTs- TwEnTy] sIx Ne^ wToNs, aNd [AnOtHeR ClAw] aDdS- FoUrTeEn, WhAt/] iS- ToTaL FoRcE?",
"expires_at": "2026-03-25 20:10:31.072445+00",
"instructions": "Solve the math problem and respond with ONLY the number (with 2 decimal places, e.g., '525.00'). Send your answer to POST /api/v1/verify with the verification_code."
}
}
}
```
### challenge_text ν¨ν΄ λΆμ
- μλμ μΌλ‘ obfuscate: λμλ¬Έμ νΌν©, νΉμλ¬Έμ(], ^, -, ~, /, |, *) λ
Έμ΄μ¦
- μ«μλ μμ΄ λ¨μ΄λ‘ νκΈ°: twenty six, fourteen, thirty, fifteen λ±
- μ°μ°: λ§μ
(and ... adds) λλ κ³±μ
(multiplies by)
- μλ΅ νμ: μμμ 2μ리 λ¬Έμμ΄ (e.g., "40.00")
### μ²λ¦¬ API
`POST /api/v1/verify`
Body: `{"verification_code": "moltbook_verify_xxx", "answer": "40.00"}`
### ꡬν μꡬμ¬ν
**νμΌ: `/home/grass/leninbot/razvedchik.py`**
#### 1. `solve_challenge_text(challenge_text: str) -> str` μ μ λ©μλ μΆκ° (MoltbookClient ν΄λμ€)
- challenge_textλ₯Ό μλ¬Έμλ‘ λ³ν ν νΉμλ¬Έμ/λ
Έμ΄μ¦ μ κ±°
- μμ΄ μ«μ λ¨μ΄λ₯Ό μ μλ‘ λ³ν (one~ninety nine λ²μλ©΄ μΆ©λΆ):
```
one=1, two=2, three=3, four=4, five=5, six=6, seven=7, eight=8, nine=9, ten=10,
eleven=11, twelve=12, thirteen=13, fourteen=14, fifteen=15, sixteen=16, seventeen=17,
eighteen=18, nineteen=19, twenty=20, thirty=30, forty=40, fifty=50, sixty=60,
seventy=70, eighty=80, ninety=90
("twenty six" β 26, "thirty three" β 33 λ± λ³΅ν© μ«μ μ²λ¦¬)
```
- μ°μ° κ°μ§:
- "adds", "and ... adds", "plus" β λ§μ
- "multiplies by", "multiply by", "times" β κ³±μ
- "minus", "subtract" β λΊμ
- κ²°κ³Όλ₯Ό `f"{result:.2f}"` νμμΌλ‘ λ°ν
- μ€ν¨ μ None λ°ν (β LLM fallback)
#### 2. `_verify_content(verification: dict) -> bool` λ©μλ μΆκ° (MoltbookClient ν΄λμ€)
```python
def _verify_content(self, verification: dict) -> bool:
"""verification μ±λ¦°μ§ ν΄κ²° λ° POST /api/v1/verify νΈμΆ"""
code = verification.get("verification_code")
challenge = verification.get("challenge_text", "")
expires_at = verification.get("expires_at", "")
if not code or not challenge:
return False
# λ§λ£ μ²΄ν¬ (μ¬μ 5μ΄)
# expires_at νμ± β νμ¬ μκ°κ³Ό λΉκ΅
answer = self.solve_challenge_text(challenge)
if answer is None:
logger.warning("[razvedchik] μ±λ¦°μ§ ν΄κ²° μ€ν¨ β challenge: %s", challenge[:80])
return False
logger.info("[razvedchik] verification μλ β code=%s answer=%s", code[-8:], answer)
try:
resp = self._client.post("/verify", json={"verification_code": code, "answer": answer})
resp.raise_for_status()
result = resp.json()
success = result.get("success") or result.get("verified") or result.get("status") == "verified"
if success:
logger.info("[razvedchik] β
Verification μ±κ³΅")
else:
logger.warning("[razvedchik] β Verification μ€ν¨: %s", result)
return bool(success)
except Exception as e:
logger.error("[razvedchik] Verification API μ€λ₯: %s", e)
return False
```
#### 3. `post_comment()` μμ
λκΈ κ²μ ν μλ΅μμ verification νλ κ°μ§ β `_verify_content()` μλ νΈμΆ:
```python
resp = self.client.post(f"/posts/{post_id}/comments", body)
# verification μ²λ¦¬
comment_obj = resp.get("comment", {}) if isinstance(resp, dict) else {}
verification = comment_obj.get("verification")
if verification:
verified = self.client._verify_content(verification)
resp["_verified"] = verified
return resp
```
#### 4. `post_observation()` μμ
ν¬μ€νΈ κ²μ ν λμΌνκ² verification μ²λ¦¬:
```python
resp = self.client.post("/posts", body)
# verification μ²λ¦¬
post_obj = resp.get("post", {}) if isinstance(resp, dict) else {}
verification = post_obj.get("verification")
if verification:
verified = self.client._verify_content(verification)
resp["_verified"] = verified
return resp
```
#### 5. `_build_report()` μμ
comment_resultsμ `verified` νλ μΆκ°:
```python
"verified": r.get("response", {}).get("_verified"),
```
#### 6. `patrol()` STEP 3 μμ
λκΈ κ²°κ³Ό μ μ₯ μ `"verified"` νλ ν¬ν¨:
```python
comment_results.append({
...
"verified": resp.get("_verified"),
})
```
### ꡬν μμ
1. νμΌ μ½κΈ°: `read_file("razvedchik.py", line_start=158, line_end=190)` β solve_verification μμΉ
2. `solve_challenge_text` ꡬν λ° λ¨μ ν
μ€νΈ
3. `_verify_content` ꡬν
4. `post_comment`, `post_observation` μμ
5. `_build_report`, `patrol` μμ
6. λ¬Έλ² κ²μ¦: `python -m py_compile razvedchik.py`
7. λ°±μ
μμ± ν μ μ₯
### μ£Όμμ¬ν
- `_verify_content`μμ `self._client`λ httpx.Client μΈμ€ν΄μ€ β `.post(path, json=...)` λ°©μ μ¬μ© (λ¨, MoltbookClient._requestλ₯Ό ν΅ν΄ νΈμΆνμ§ λ§ κ² β μ¬κ· λ°©μ§)
- expires_at νμ±: `dateutil.parser.parse` λλ `datetime.fromisoformat` μ¬μ©
- μμ μ λ°λμ λ°±μ
: `razvedchik.py.bak.YYYYMMDD_HHMMSS`
- μμ ν `python -m py_compile razvedchik.py` ν΅κ³Ό νμΈ
- git commit/pushκΉμ§ μλ£
### κΈ°λ κ²°κ³Ό
λ€μ μμ°°λΆν° λͺ¨λ λκΈ/ν¬μ€νΈκ° `pending` β `verified` μνλ‘ μ νλ¨.
μμ°° λ³΄κ³ μμ verification κ²°κ³Ό κΈ°λ‘.