feat: add realtime capturing

This commit is contained in:
hh committed 2026-05-29 18:19:06 +02:00
1 parent 920a0235e2
commit 3c1a12750c
29 files changed
+967 -47

No files matched your search

@@ -0,0 +1,3 @@
from userbot.handlers.raw.dispatcher import handlers
__all__ = ["handlers"]
@@ -0,0 +1,22 @@
from pyrogram import raw
from userbot import PyroClient
HANDLES = (raw.types.UpdateContactsReset, raw.types.UpdateUser)
async def handle(
client: PyroClient, update: raw.base.Update, users: dict, _chats: dict
) -> None:
ctx = client.capture
if ctx is None:
return
if isinstance(update, raw.types.UpdateContactsReset):
await ctx.contacts.refresh()
return
if not isinstance(update, raw.types.UpdateUser):
return
user = users.get(update.user_id)
if not isinstance(user, raw.types.User) or user.min:
return
ctx.contacts.mark(user.id, is_contact=bool(user.contact))
@@ -0,0 +1,19 @@
from pyrogram import raw
from userbot import PyroClient
HANDLES = (
raw.types.UpdateDialogFilter,
raw.types.UpdateDialogFilters,
raw.types.UpdateDialogFilterOrder,
)
async def handle(
client: PyroClient, _update: raw.base.Update, _users: dict, _chats: dict
) -> None:
ctx = client.capture
if ctx is None:
return
await ctx.folders.refresh()
await ctx.reload_policies()
@@ -0,0 +1,25 @@
from collections.abc import Awaitable, Callable
from pyrogram import raw
from userbot import PyroClient
from userbot.handlers.raw import contacts, dialog_filters, reactions
RawHandler = Callable[..., Awaitable[None]]
_MODULES = (contacts, dialog_filters, reactions)
_REGISTRY: dict[type, RawHandler] = {
update_type: module.handle for module in _MODULES for update_type in module.HANDLES
}
@PyroClient.on_raw_update()
async def dispatch(
client: PyroClient, update: raw.base.Update, users: dict, chats: dict
) -> None:
handler = _REGISTRY.get(type(update))
if handler is not None:
await handler(client, update, users, chats)
handlers = dispatch.handlers
@@ -0,0 +1,49 @@
from pyrogram import raw, utils
from userbot import PyroClient
from userbot.modules.capture import repository
from userbot.modules.capture.chat_meta import meta_from_peer
HANDLES = (raw.types.UpdateMessageReactions,)
def _reaction_key(reaction: raw.base.Reaction) -> str | None:
if isinstance(reaction, raw.types.ReactionEmoji):
return reaction.emoticon
if isinstance(reaction, raw.types.ReactionCustomEmoji):
return f"custom:{reaction.document_id}"
return None
def _parse_recent(reactions: raw.base.MessageReactions) -> list[tuple[int, str]]:
recent = getattr(reactions, "recent_reactions", None) or []
parsed: list[tuple[int, str]] = []
for peer_reaction in recent:
key = _reaction_key(peer_reaction.reaction)
if key is None:
continue
try:
peer_id = utils.get_peer_id(peer_reaction.peer_id)
except (ValueError, AttributeError):
continue
parsed.append((peer_id, key))
return parsed
async def handle(
client: PyroClient,
update: raw.types.UpdateMessageReactions,
users: dict,
chats: dict,
) -> None:
ctx = client.capture
if ctx is None:
return
meta = meta_from_peer(update.peer, chats, users, ctx.contacts.ids)
toggles = ctx.resolve(meta)
if not toggles.reactions:
return
current = _parse_recent(update.reactions)
await repository.sync_reactions(
ctx.pool, ctx.account_id, meta.chat_id, update.msg_id, current
)