-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathworker.py
More file actions
126 lines (108 loc) · 4.78 KB
/
Copy pathworker.py
File metadata and controls
126 lines (108 loc) · 4.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# Copyright (C) 2026 Dariush Lashani
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
"""AI Worker: پردازشِ صفِ قضاوتهای AI تو یه پروسهی جدا. جابها رو از
Redis میخونه، قضاوت رو اجرا میکنه، و نتیجه رو مستقیم از طریق Bot API
برای کاربر میفرسته.
"""
import asyncio
import base64
import logging
import os
from telegram import Bot
import redis_client as rc
import metrics
from ban_enforcement import enforce_ban
from judge import judge_report
from profile_judge import judge_profile_report
from verdict_notify import notify_chat_verdict, notify_profile_verdict
BOT_TOKEN = os.environ["BOT_TOKEN"]
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(name)s %(levelname)s %(message)s",
)
logger = logging.getLogger("bluechat.worker")
async def _process_job(bot: Bot, job: dict) -> None:
job_type = job.get("type")
if job_type == "chat_report":
try:
result = await judge_report(
report_id=job["report_id"],
session_id=job["session_id"],
reporter_id=job["reporter_id"],
reported_id=job["reported_id"],
reason=job["reason"],
details=job.get("details"),
)
except Exception:
logger.exception("خطا در judge_report report_id=%s", job.get("report_id"))
result = {"verdict": "pending"}
metrics.ai_jobs_done.labels(type="chat_report").inc()
await notify_chat_verdict(bot, job["reporter_id"], job["reported_id"], result)
# اگه این قضاوت باعثِ بنشدنِ کسی شده (گزارششده، گزارشدهنده، یا
# هردو)، همون لحظه از چتِ ۱به۱/اتاقِ چتِ فعلیش هم خارج بشه.
if result.get("reported_auto_banned"):
await enforce_ban(bot, result["reported_id"])
if result.get("reporter_auto_banned"):
await enforce_ban(bot, result["reporter_id"])
if result.get("reporter_also_guilty_auto_banned"):
await enforce_ban(bot, result["reporter_id"])
elif job_type == "profile_report":
image_b64 = job.get("image_b64")
image_bytes = base64.b64decode(image_b64) if image_b64 else None
try:
result = await judge_profile_report(
job["profile_report_id"],
job["reporter_id"],
job["reported_id"],
job["snapshot"],
image_bytes,
)
except Exception:
logger.exception("خطا در judge_profile_report id=%s", job.get("profile_report_id"))
result = {"verdict": "pending"}
metrics.ai_jobs_done.labels(type="profile_report").inc()
await notify_profile_verdict(bot, job["reporter_id"], job["reported_id"], result)
# گزارشِ پروفایل با guilty بلافاصله بن میکنه (نه بعدِ ۵ اخطار)،
# dismissed هم میتونه با ۵مین اخطارِ گزارشدهنده بناش کنه.
if result.get("verdict") == "guilty":
await enforce_ban(bot, result["reported_id"])
elif result.get("auto_banned"):
await enforce_ban(bot, result["reporter_id"])
else:
logger.warning("نوع job ناشناخته: %s", job_type)
async def _update_queue_gauge() -> None:
while True:
try:
size = await rc.r.llen(rc.KEY_AI_JOBS)
metrics.ai_queue_size.set(size)
except Exception:
pass
await asyncio.sleep(15)
async def main() -> None:
metrics.start_metrics_server()
bot = Bot(token=BOT_TOKEN)
logger.info("AI worker started, listening for jobs")
asyncio.create_task(_update_queue_gauge())
while True:
try:
job = await rc.pop_ai_job(timeout=5)
if job is None:
continue
asyncio.create_task(_process_job(bot, job))
except Exception:
logger.exception("خطای غیرمنتظره در حلقهی worker")
await asyncio.sleep(1)
if __name__ == "__main__":
asyncio.run(main())