fix(userbot): encode absent pyrogram raw payloads as empty json

This commit is contained in:
hh
2026-09-06 21:26:13 +02:00
parent 6a6e63ff75
commit 676680319b
15 changed files with 63 additions and 25 deletions
+2 -1
View File
@@ -5,6 +5,7 @@ from userbot.modules.capture import repository
from userbot.modules.capture.chat_meta import meta_from_chat
from userbot.modules.capture.message import sender_id
from userbot.modules.media import capture_media, media_unique_id, self_destruct_ttl
from userbot.modules.raw_json import raw_json
from utils.events import notify_bg_event
@@ -33,7 +34,7 @@ async def on_edited_message(client: PyroClient, message: Message) -> None:
message.date,
sender_id(message),
message.text or message.caption,
str(message),
raw_json(message),
message.edit_date,
media_unique_id(message),
has_media=message.media is not None,
+2 -1
View File
@@ -4,6 +4,7 @@ from pyrogram.types import User
from userbot import PyroClient
from userbot.modules.presence import repository
from userbot.modules.raw_json import raw_json
from utils.events import notify_bg_event
@@ -20,7 +21,7 @@ async def on_user_status(client: PyroClient, user: User) -> None:
user.status.name.lower(),
user.last_online_date,
user.next_offline_date,
str(user.raw),
raw_json(user.raw),
)
await ctx.watches.on_status(user.id, is_online=user.status.name.lower() == "online")
await notify_bg_event(ctx.pool, "presence", ctx.account_id, chat_id=user.id)
+7 -4
View File
@@ -7,6 +7,7 @@ from userbot.modules.avatars import capture_avatar
from userbot.modules.profiles import active_username, snapshot_from_user
from userbot.modules.profiles.parse import ProfileFields
from userbot.modules.profiles.repository import get_peer, write_profile
from userbot.modules.raw_json import raw_json
HANDLES = (raw.types.UpdateUserName, raw.types.UpdateUser, raw.types.UpdateUserPhone)
@@ -24,7 +25,9 @@ async def _handle_user(
current = await get_peer(ctx.pool, ctx.account_id, update.user_id)
if current == fields:
return
await write_profile(ctx.pool, ctx.account_id, update.user_id, fields, str(raw_user))
await write_profile(
ctx.pool, ctx.account_id, update.user_id, fields, raw_json(raw_user)
)
changed_photo = current is None or current.photo_unique_id != photo_unique_id
if photo_file_id and photo_unique_id and changed_photo:
await capture_avatar(
@@ -34,7 +37,7 @@ async def _handle_user(
"peer",
photo_file_id,
photo_unique_id,
str(raw_user),
raw_json(raw_user),
)
@@ -65,9 +68,9 @@ async def handle(
"last_name": update.last_name or None,
"username": active_username(update.usernames),
},
str(update),
raw_json(update),
)
elif isinstance(update, raw.types.UpdateUserPhone):
await _merge_partial(
client, update.user_id, {"phone": update.phone or None}, str(update)
client, update.user_id, {"phone": update.phone or None}, raw_json(update)
)
@@ -4,6 +4,7 @@ from pyrogram import raw, utils
from userbot import PyroClient
from userbot.modules.capture.chat_meta import meta_from_chat_id
from userbot.modules.raw_json import raw_json
from userbot.modules.read_receipts import repository as receipts
from userbot.modules.stt import repository
from userbot.modules.stt.gate import safe_transcribe
@@ -41,7 +42,7 @@ async def handle(
cand_chat_id,
datetime.now(UTC),
message_id,
str(update),
raw_json(update),
)
continue
if not untranscribed:
@@ -3,6 +3,7 @@ from datetime import UTC, datetime
from pyrogram import raw, utils
from userbot import PyroClient
from userbot.modules.raw_json import raw_json
from userbot.modules.read_receipts import repository
from utils.events import notify_bg_event
@@ -23,7 +24,7 @@ async def handle(
chat_id,
datetime.now(UTC),
update.max_id,
str(update),
raw_json(update),
)
await notify_bg_event(
ctx.pool, "receipt", ctx.account_id, chat_id=chat_id, message_id=update.max_id
@@ -5,6 +5,7 @@ from typing import TYPE_CHECKING
from userbot.modules.capture.chat_meta import chat_kind
from userbot.modules.profiles.parse import ProfileFields, snapshot_from_high_level
from userbot.modules.profiles.repository import get_peer, write_profile
from userbot.modules.raw_json import raw_json
from utils.policy.models import ChatKind
if TYPE_CHECKING:
@@ -59,7 +60,7 @@ async def _capture_peer(message: Message, ctx: CaptureContext) -> None:
fields, photo_file_id, photo_unique_id = snapshot_from_high_level(user)
if not await ctx.peer_identity.changed(ctx.pool, ctx.account_id, user.id, fields):
return
await write_profile(ctx.pool, ctx.account_id, user.id, fields, str(user))
await write_profile(ctx.pool, ctx.account_id, user.id, fields, raw_json(user))
if photo_file_id and photo_unique_id:
from userbot.modules.avatars import note_avatar # noqa: PLC0415
@@ -95,7 +96,7 @@ async def _capture_chat(message: Message, ctx: CaptureContext) -> None:
photo_unique_id,
None,
message.date,
str(message),
raw_json(message),
)
if photo_file_id and photo_unique_id:
from userbot.modules.avatars import note_avatar # noqa: PLC0415
@@ -6,6 +6,7 @@ from userbot.modules.capture.context import CaptureContext
from userbot.modules.links import extract_links
from userbot.modules.links import repository as links_repository
from userbot.modules.media import capture_media, self_destruct_ttl
from userbot.modules.raw_json import raw_json
from utils.policy.models import CaptureToggles
@@ -47,7 +48,7 @@ async def capture_message(
message.date,
sender_id(message),
message.text or message.caption,
str(message),
raw_json(message),
has_media=message.media is not None,
is_self_destruct=self_destruct_ttl(message) is not None,
)
@@ -68,5 +69,5 @@ async def capture_message(
links = extract_links(message)
if links:
await links_repository.insert_links(
ctx.pool, ctx.account_id, chat_id, message.id, links, str(message)
ctx.pool, ctx.account_id, chat_id, message.id, links, raw_json(message)
)
+13 -6
View File
@@ -5,6 +5,7 @@ from userbot.modules.avatars import capture_avatar
from userbot.modules.capture.context import CaptureContext
from userbot.modules.capture.message import sender_id
from userbot.modules.groups import repository
from userbot.modules.raw_json import raw_json
async def capture_service(
@@ -28,7 +29,7 @@ async def capture_service(
None,
actor,
ts,
str(message),
raw_json(message),
)
elif service is enums.MessageServiceType.NEW_CHAT_PHOTO:
photo = message.new_chat_photo
@@ -43,11 +44,17 @@ async def capture_service(
unique_id,
actor,
ts,
str(message),
raw_json(message),
)
if photo is not None and unique_id is not None:
await capture_avatar(
client, ctx, chat_id, "chat", photo.file_id, unique_id, str(message)
client,
ctx,
chat_id,
"chat",
photo.file_id,
unique_id,
raw_json(message),
)
elif service is enums.MessageServiceType.DELETE_CHAT_PHOTO:
await repository.insert_chat_history(
@@ -60,7 +67,7 @@ async def capture_service(
None,
actor,
ts,
str(message),
raw_json(message),
)
elif service is enums.MessageServiceType.NEW_CHAT_MEMBERS:
for member in message.new_chat_members or []:
@@ -73,7 +80,7 @@ async def capture_service(
"join",
actor,
ts,
str(message),
raw_json(message),
)
elif service is enums.MessageServiceType.LEFT_CHAT_MEMBER:
member = message.left_chat_member
@@ -87,5 +94,5 @@ async def capture_service(
"leave",
actor,
ts,
str(message),
raw_json(message),
)
@@ -8,6 +8,7 @@ from userbot.modules.capture.context import CaptureContext
from userbot.modules.jobs.context import JobContext
from userbot.modules.jobs.registry import register
from userbot.modules.stories.service import save_story
from utils.logging import logger
SAVE_EVERY = 10
@@ -38,6 +39,9 @@ async def _drain(
raise
except RPCError:
continue
except Exception:
logger.exception(f"Failed to save story {story.id} from {name}")
continue
saved += 1
if saved % SAVE_EVERY == 0:
await ctx.report_progress({"saved": saved, "source": name})
@@ -11,6 +11,7 @@ from userbot.modules.jobs.context import JobContext
from userbot.modules.jobs.registry import register
from userbot.modules.profiles.parse import snapshot_from_high_level
from userbot.modules.profiles.repository import write_profile
from userbot.modules.raw_json import raw_json
MEMBER_CAP = 200
@@ -26,7 +27,7 @@ LIMIT 100
async def _save_user(ctx: CaptureContext, user: User) -> None:
fields, photo_file_id, photo_unique_id = snapshot_from_high_level(user)
await write_profile(ctx.pool, ctx.account_id, user.id, fields, str(user))
await write_profile(ctx.pool, ctx.account_id, user.id, fields, raw_json(user))
if photo_file_id and photo_unique_id:
await note_avatar(
ctx.pool, ctx.account_id, user.id, "peer", photo_unique_id, photo_file_id
@@ -48,7 +49,7 @@ async def _enrich_chat_meta(client: Client, ctx: CaptureContext, chat_id: int) -
photo_unique_id,
None,
datetime.now(UTC),
str(chat),
raw_json(chat),
)
if photo_file_id and photo_unique_id:
await note_avatar(
@@ -5,6 +5,7 @@ from userbot.modules.jobs.context import JobContext
from userbot.modules.jobs.registry import register
from userbot.modules.profiles.parse import snapshot_from_high_level
from userbot.modules.profiles.repository import write_profile
from userbot.modules.raw_json import raw_json
@register("sync_contacts")
@@ -21,7 +22,7 @@ async def sync_contacts(ctx: JobContext) -> None:
if not isinstance(user, User):
continue
fields, photo_file_id, photo_unique_id = snapshot_from_high_level(user)
await write_profile(ctx.pool, ctx.account_id, user.id, fields, str(user))
await write_profile(ctx.pool, ctx.account_id, user.id, fields, raw_json(user))
if photo_file_id and photo_unique_id:
await note_avatar(
ctx.pool,
@@ -9,6 +9,8 @@ from userbot.modules.jobs.registry import register
from userbot.modules.profiles.parse import snapshot_from_high_level
from userbot.modules.profiles.repository import write_profile
from userbot.modules.profiles.snapshots import save_group, save_private
from userbot.modules.raw_json import raw_json
from utils.logging import logger
SAVE_EVERY = 100
USERS_BATCH = 200
@@ -31,7 +33,9 @@ async def _enrich_users(client: Client, ctx: CaptureContext, ids: list[int]) ->
if not isinstance(user, User):
continue
fields, photo_file_id, photo_unique_id = snapshot_from_high_level(user)
await write_profile(ctx.pool, ctx.account_id, user.id, fields, str(user))
await write_profile(
ctx.pool, ctx.account_id, user.id, fields, raw_json(user)
)
if photo_file_id and photo_unique_id:
await note_avatar(
ctx.pool,
@@ -66,6 +70,8 @@ async def sync_dialogs(ctx: JobContext) -> None:
await save_group(capture, chat)
except (BadRequest, Forbidden):
pass
except Exception:
logger.exception(f"Failed to snapshot dialog {chat_id}")
await ctx.pool.execute(_UPSERT_DIALOG, ctx.account_id, chat_id)
processed += 1
if processed % SAVE_EVERY == 0:
@@ -7,12 +7,13 @@ from userbot.modules.capture.context import CaptureContext
from userbot.modules.groups.repository import insert_chat_history
from userbot.modules.profiles.parse import snapshot_from_chat
from userbot.modules.profiles.repository import write_profile
from userbot.modules.raw_json import raw_json
async def save_private(ctx: CaptureContext, chat: Chat) -> bool:
chat_id = chat.id or 0
fields, photo_file_id, photo_unique_id = snapshot_from_chat(chat)
await write_profile(ctx.pool, ctx.account_id, chat_id, fields, str(chat))
await write_profile(ctx.pool, ctx.account_id, chat_id, fields, raw_json(chat))
if photo_file_id and photo_unique_id:
await note_avatar(
ctx.pool, ctx.account_id, chat_id, "peer", photo_unique_id, photo_file_id
@@ -35,7 +36,7 @@ async def save_group(ctx: CaptureContext, chat: Chat) -> None:
photo_unique_id,
None,
datetime.now(UTC),
str(chat),
raw_json(chat),
)
if photo_file_id and photo_unique_id:
await note_avatar(
+8
View File
@@ -0,0 +1,8 @@
from pyrogram.raw.core import TLObject
from pyrogram.types import Object
EMPTY_JSON = "{}"
def raw_json(obj: Object | TLObject | None) -> str:
return EMPTY_JSON if obj is None else str(obj)
@@ -3,6 +3,7 @@ from pyrogram.types import Story
from userbot.modules.capture.context import CaptureContext
from userbot.modules.download import download_bytes
from userbot.modules.raw_json import raw_json
from userbot.modules.stories import repository
@@ -40,7 +41,7 @@ async def save_story(client: Client, capture: CaptureContext, story: Story) -> N
storage_key,
file_size,
story.views,
str(story.raw),
raw_json(story.raw),
pinned=bool(story.pinned),
deleted=bool(story.deleted),
downloaded=downloaded,