ForcePilot/backend/package/yuxi/channel/extensions/telegram/chat.py

183 lines
6.9 KiB
Python
Raw Normal View History

from __future__ import annotations
import logging
from typing import Any
logger = logging.getLogger(__name__)
class TelegramChat:
def __init__(self, outbound):
self._outbound = outbound
async def _call(self, token: str, method: str, payload: dict) -> dict | list | int | None:
return await self._outbound._api_call(token, method, payload)
async def get_chat(self, account_id: str, chat_id: str) -> dict | None:
token = await self._resolve_token(account_id)
if not token:
return None
result = await self._call(token, "getChat", {"chat_id": chat_id})
return result if isinstance(result, dict) else None
async def get_chat_member(
self, account_id: str, chat_id: str, user_id: int,
) -> dict | None:
token = await self._resolve_token(account_id)
if not token:
return None
result = await self._call(
token, "getChatMember", {"chat_id": chat_id, "user_id": user_id},
)
return result if isinstance(result, dict) else None
async def get_chat_member_count(self, account_id: str, chat_id: str) -> int | None:
token = await self._resolve_token(account_id)
if not token:
return None
result = await self._call(token, "getChatMemberCount", {"chat_id": chat_id})
return result if isinstance(result, int) else None
async def get_chat_administrators(self, account_id: str, chat_id: str) -> list[dict] | None:
token = await self._resolve_token(account_id)
if not token:
return None
result = await self._call(token, "getChatAdministrators", {"chat_id": chat_id})
return result if isinstance(result, list) else None
async def get_user_profile_photos(
self, account_id: str, user_id: int, *, limit: int = 100,
) -> dict | None:
token = await self._resolve_token(account_id)
if not token:
return None
result = await self._call(
token, "getUserProfilePhotos",
{"user_id": user_id, "limit": limit},
)
return result if isinstance(result, dict) else None
async def pin_message(
self, account_id: str, chat_id: str, message_id: int, *,
disable_notification: bool = False,
) -> bool:
token = await self._resolve_token(account_id)
if not token:
return False
result = await self._call(
token, "pinChatMessage",
{"chat_id": chat_id, "message_id": message_id, "disable_notification": disable_notification},
)
return result is not None and not isinstance(result, dict)
async def unpin_message(
self, account_id: str, chat_id: str, message_id: int | None = None,
) -> bool:
token = await self._resolve_token(account_id)
if not token:
return False
payload: dict[str, Any] = {"chat_id": chat_id}
if message_id:
payload["message_id"] = message_id
result = await self._call(token, "unpinChatMessage", payload)
return result is not None and not isinstance(result, dict)
async def create_forum_topic(
self, account_id: str, chat_id: str, name: str, *,
icon_color: int | None = None, icon_custom_emoji_id: str | None = None,
) -> dict | None:
token = await self._resolve_token(account_id)
if not token:
return None
payload: dict[str, Any] = {"chat_id": chat_id, "name": name}
if icon_color is not None:
payload["icon_color"] = icon_color
if icon_custom_emoji_id:
payload["icon_custom_emoji_id"] = icon_custom_emoji_id
result = await self._call(token, "createForumTopic", payload)
return result if isinstance(result, dict) else None
async def close_forum_topic(
self, account_id: str, chat_id: str, message_thread_id: int,
) -> bool:
token = await self._resolve_token(account_id)
if not token:
return False
result = await self._call(
token, "closeForumTopic",
{"chat_id": chat_id, "message_thread_id": message_thread_id},
)
return result is not None and not isinstance(result, dict)
async def reopen_forum_topic(
self, account_id: str, chat_id: str, message_thread_id: int,
) -> bool:
token = await self._resolve_token(account_id)
if not token:
return False
result = await self._call(
token, "reopenForumTopic",
{"chat_id": chat_id, "message_thread_id": message_thread_id},
)
return result is not None and not isinstance(result, dict)
async def delete_forum_topic(
self, account_id: str, chat_id: str, message_thread_id: int,
) -> bool:
token = await self._resolve_token(account_id)
if not token:
return False
result = await self._call(
token, "deleteForumTopic",
{"chat_id": chat_id, "message_thread_id": message_thread_id},
)
return result is not None and not isinstance(result, dict)
async def edit_forum_topic(
self, account_id: str, chat_id: str, message_thread_id: int, *,
name: str | None = None, icon_custom_emoji_id: str | None = None,
) -> bool:
token = await self._resolve_token(account_id)
if not token:
return False
payload: dict[str, Any] = {"chat_id": chat_id, "message_thread_id": message_thread_id}
if name:
payload["name"] = name
if icon_custom_emoji_id:
payload["icon_custom_emoji_id"] = icon_custom_emoji_id
result = await self._call(token, "editForumTopic", payload)
return result is not None and not isinstance(result, dict)
async def edit_general_forum_topic(
self, account_id: str, chat_id: str, name: str,
) -> bool:
token = await self._resolve_token(account_id)
if not token:
return False
result = await self._call(
token, "editGeneralForumTopic",
{"chat_id": chat_id, "name": name},
)
return result is not None and not isinstance(result, dict)
async def set_chat_member_tag(
self, account_id: str, chat_id: str, user_id: int, tag: str,
) -> bool:
token = await self._resolve_token(account_id)
if not token:
return False
result = await self._call(
token, "setChatMemberTag",
{"chat_id": chat_id, "user_id": user_id, "tag": tag},
)
return result is not None and not isinstance(result, dict)
async def _resolve_token(self, account_id: str | None) -> str:
from yuxi.channel.extensions.telegram.config import TelegramConfigAdapter
adapter = TelegramConfigAdapter()
aid = account_id or "default"
account = await adapter.resolve_account(aid)
return account.get("token", "")