Compare commits
No commits in common. "2ee39ee069b438e505153d85384e00276bdf1299" and "e96a6a8ca20b299051b7d3c48a75c6583d6bd465" have entirely different histories.
2ee39ee069
...
e96a6a8ca2
1 changed files with 213 additions and 290 deletions
503
main.py
503
main.py
|
|
@ -735,10 +735,9 @@ async def get_messages(chat_id: Union[int, str], page: int = 1, page_size: int =
|
|||
reply_info = f" | reply to {msg.reply_to.reply_to_msg_id}"
|
||||
|
||||
engagement_info = get_engagement_info(msg)
|
||||
safe_text = (msg.message or "").replace("\n", "\\n")
|
||||
|
||||
lines.append(
|
||||
f"ID: {msg.id} | {sender_name} | Date: {msg.date}{reply_info}{engagement_info} | Message: {safe_text}"
|
||||
f"ID: {msg.id} | {sender_name} | Date: {msg.date}{reply_info}{engagement_info} | Message: {msg.message}"
|
||||
)
|
||||
return "\n".join(lines)
|
||||
except Exception as e:
|
||||
|
|
@ -747,8 +746,8 @@ async def get_messages(chat_id: Union[int, str], page: int = 1, page_size: int =
|
|||
)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(title="Send Message", openWorldHint=True, destructiveHint=True)
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(title="Send Message", openWorldHint=True, destructiveHint=True)
|
||||
)
|
||||
@validate_id("chat_id")
|
||||
async def send_message(
|
||||
|
|
@ -771,13 +770,13 @@ async def send_message(
|
|||
return log_and_format_error("send_message", e, chat_id=chat_id)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Subscribe Public Channel",
|
||||
# openWorldHint=True,
|
||||
# destructiveHint=True,
|
||||
# idempotentHint=True,
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Subscribe Public Channel",
|
||||
openWorldHint=True,
|
||||
destructiveHint=True,
|
||||
idempotentHint=True,
|
||||
)
|
||||
)
|
||||
@validate_id("channel")
|
||||
async def subscribe_public_channel(channel: Union[int, str]) -> str:
|
||||
|
|
@ -816,22 +815,6 @@ async def list_inline_buttons(
|
|||
return "message_id must be an integer."
|
||||
|
||||
entity = await resolve_entity(chat_id)
|
||||
|
||||
def _has_inline(msg):
|
||||
if getattr(msg, "buttons", None):
|
||||
return True
|
||||
rm = getattr(msg, "reply_markup", None)
|
||||
return bool(rm and hasattr(rm, "rows"))
|
||||
|
||||
def _flat_buttons(msg):
|
||||
btns = getattr(msg, "buttons", None)
|
||||
if btns:
|
||||
return [btn for row in btns for btn in row]
|
||||
rm = getattr(msg, "reply_markup", None)
|
||||
if rm and hasattr(rm, "rows"):
|
||||
return [btn for row in rm.rows for btn in row.buttons]
|
||||
return []
|
||||
|
||||
target_message = None
|
||||
|
||||
if message_id is not None:
|
||||
|
|
@ -840,12 +823,18 @@ async def list_inline_buttons(
|
|||
target_message = target_message[0] if target_message else None
|
||||
else:
|
||||
recent_messages = await client.get_messages(entity, limit=limit)
|
||||
target_message = next((msg for msg in recent_messages if _has_inline(msg)), None)
|
||||
target_message = next(
|
||||
(msg for msg in recent_messages if getattr(msg, "buttons", None)), None
|
||||
)
|
||||
|
||||
if not target_message:
|
||||
return "No message with inline buttons found."
|
||||
|
||||
buttons = _flat_buttons(target_message)
|
||||
buttons_attr = getattr(target_message, "buttons", None)
|
||||
if not buttons_attr:
|
||||
return f"Message {target_message.id} does not contain inline buttons."
|
||||
|
||||
buttons = [btn for row in buttons_attr for btn in row]
|
||||
if not buttons:
|
||||
return f"Message {target_message.id} does not contain inline buttons."
|
||||
|
||||
|
|
@ -853,8 +842,9 @@ async def list_inline_buttons(
|
|||
f"Buttons for message {target_message.id} (date {target_message.date}):",
|
||||
]
|
||||
for idx, btn in enumerate(buttons):
|
||||
raw_button = getattr(btn, "button", None)
|
||||
text = getattr(btn, "text", "") or "<no text>"
|
||||
url = getattr(btn, "url", None)
|
||||
url = getattr(raw_button, "url", None) if raw_button else None
|
||||
has_callback = bool(getattr(btn, "data", None))
|
||||
parts = [f"[{idx}] text='{text}'"]
|
||||
parts.append("callback=yes" if has_callback else "callback=no")
|
||||
|
|
@ -873,10 +863,10 @@ async def list_inline_buttons(
|
|||
)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Press Inline Button", openWorldHint=True, destructiveHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Press Inline Button", openWorldHint=True, destructiveHint=True
|
||||
)
|
||||
)
|
||||
@validate_id("chat_id")
|
||||
async def press_inline_button(
|
||||
|
|
@ -913,49 +903,25 @@ async def press_inline_button(
|
|||
|
||||
entity = await resolve_entity(chat_id)
|
||||
|
||||
def _has_inline_buttons(msg):
|
||||
"""Check if a message has inline buttons via buttons property or reply_markup."""
|
||||
if getattr(msg, "buttons", None):
|
||||
return True
|
||||
rm = getattr(msg, "reply_markup", None)
|
||||
return bool(rm and hasattr(rm, "rows"))
|
||||
|
||||
def _extract_buttons(msg):
|
||||
"""Extract flat list of buttons from buttons property or reply_markup fallback."""
|
||||
btns = getattr(msg, "buttons", None)
|
||||
if btns:
|
||||
return [btn for row in btns for btn in row]
|
||||
rm = getattr(msg, "reply_markup", None)
|
||||
if rm and hasattr(rm, "rows"):
|
||||
return [btn for row in rm.rows for btn in row.buttons]
|
||||
return []
|
||||
|
||||
target_message = None
|
||||
if message_id is not None:
|
||||
# Fetch by ID first, then fall back to recent-message search if
|
||||
# reply_markup is missing (Telethon sometimes omits it for ID fetches).
|
||||
target_message = await client.get_messages(entity, ids=message_id)
|
||||
if isinstance(target_message, list):
|
||||
target_message = target_message[0] if target_message else None
|
||||
if target_message and not _has_inline_buttons(target_message):
|
||||
# Fallback: search recent messages for the same ID with markup
|
||||
recent = await client.get_messages(entity, limit=30)
|
||||
fallback = next(
|
||||
(m for m in recent if m.id == target_message.id and _has_inline_buttons(m)),
|
||||
None,
|
||||
)
|
||||
if fallback:
|
||||
target_message = fallback
|
||||
else:
|
||||
recent_messages = await client.get_messages(entity, limit=20)
|
||||
target_message = next(
|
||||
(msg for msg in recent_messages if _has_inline_buttons(msg)), None
|
||||
(msg for msg in recent_messages if getattr(msg, "buttons", None)), None
|
||||
)
|
||||
|
||||
if not target_message:
|
||||
return "No message with inline buttons found. Specify message_id to target a specific message."
|
||||
|
||||
buttons = _extract_buttons(target_message)
|
||||
buttons_attr = getattr(target_message, "buttons", None)
|
||||
if not buttons_attr:
|
||||
return f"Message {target_message.id} does not contain inline buttons."
|
||||
|
||||
buttons = [btn for row in buttons_attr for btn in row]
|
||||
if not buttons:
|
||||
return f"Message {target_message.id} does not contain inline buttons."
|
||||
|
||||
|
|
@ -983,16 +949,16 @@ async def press_inline_button(
|
|||
)
|
||||
return f"Button not found. Available buttons: {available}"
|
||||
|
||||
btn_data = getattr(target_button, "data", None)
|
||||
if not btn_data:
|
||||
url = getattr(target_button, "url", None)
|
||||
if not getattr(target_button, "data", None):
|
||||
raw_button = getattr(target_button, "button", None)
|
||||
url = getattr(raw_button, "url", None) if raw_button else None
|
||||
if url:
|
||||
return f"Selected button opens a URL instead of sending a callback: {url}"
|
||||
return "Selected button does not provide callback data to press."
|
||||
|
||||
callback_result = await client(
|
||||
functions.messages.GetBotCallbackAnswerRequest(
|
||||
peer=entity, msg_id=target_message.id, data=btn_data
|
||||
peer=entity, msg_id=target_message.id, data=target_button.data
|
||||
)
|
||||
)
|
||||
|
||||
|
|
@ -1699,10 +1665,10 @@ async def get_message_context(
|
|||
)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Add Contact", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Add Contact", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
async def add_contact(
|
||||
phone: Optional[str] = None,
|
||||
|
|
@ -1832,10 +1798,10 @@ async def add_contact(
|
|||
return log_and_format_error("add_contact", e, phone=phone, username=username)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Delete Contact", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Delete Contact", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
@validate_id("user_id")
|
||||
async def delete_contact(user_id: Union[int, str]) -> str:
|
||||
|
|
@ -1852,10 +1818,10 @@ async def delete_contact(user_id: Union[int, str]) -> str:
|
|||
return log_and_format_error("delete_contact", e, user_id=user_id)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Block User", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Block User", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
@validate_id("user_id")
|
||||
async def block_user(user_id: Union[int, str]) -> str:
|
||||
|
|
@ -1872,10 +1838,10 @@ async def block_user(user_id: Union[int, str]) -> str:
|
|||
return log_and_format_error("block_user", e, user_id=user_id)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Unblock User", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Unblock User", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
@validate_id("user_id")
|
||||
async def unblock_user(user_id: Union[int, str]) -> str:
|
||||
|
|
@ -1904,8 +1870,8 @@ async def get_me() -> str:
|
|||
return log_and_format_error("get_me", e)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(title="Create Group", openWorldHint=True, destructiveHint=True)
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(title="Create Group", openWorldHint=True, destructiveHint=True)
|
||||
)
|
||||
@validate_id("user_ids")
|
||||
async def create_group(title: str, user_ids: List[Union[int, str]]) -> str:
|
||||
|
|
@ -1965,10 +1931,10 @@ async def create_group(title: str, user_ids: List[Union[int, str]]) -> str:
|
|||
return log_and_format_error("create_group", e, title=title, user_ids=user_ids)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Invite To Group", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Invite To Group", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
@validate_id("group_id", "user_ids")
|
||||
async def invite_to_group(group_id: Union[int, str], user_ids: List[Union[int, str]]) -> str:
|
||||
|
|
@ -2019,10 +1985,10 @@ async def invite_to_group(group_id: Union[int, str], user_ids: List[Union[int, s
|
|||
return log_and_format_error("invite_to_group", e, group_id=group_id, user_ids=user_ids)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Leave Chat", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Leave Chat", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
@validate_id("chat_id")
|
||||
async def leave_chat(chat_id: Union[int, str]) -> str:
|
||||
|
|
@ -2125,8 +2091,8 @@ async def get_participants(chat_id: Union[int, str]) -> str:
|
|||
return log_and_format_error("get_participants", e, chat_id=chat_id)
|
||||
|
||||
|
||||
#@mcp.tool(annotations=ToolAnnotations(title="Send File", openWorldHint=True, destructiveHint=True))
|
||||
#@validate_id("chat_id")
|
||||
@mcp.tool(annotations=ToolAnnotations(title="Send File", openWorldHint=True, destructiveHint=True))
|
||||
@validate_id("chat_id")
|
||||
async def send_file(
|
||||
chat_id: Union[int, str],
|
||||
file_path: str,
|
||||
|
|
@ -2157,8 +2123,8 @@ async def send_file(
|
|||
)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(title="Download Media", openWorldHint=True, destructiveHint=True)
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(title="Download Media", openWorldHint=True, destructiveHint=True)
|
||||
)
|
||||
@validate_id("chat_id")
|
||||
async def download_media(
|
||||
|
|
@ -2218,10 +2184,10 @@ async def download_media(
|
|||
)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Update Profile", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Update Profile", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
async def update_profile(first_name: str = None, last_name: str = None, about: str = None) -> str:
|
||||
"""
|
||||
|
|
@ -2240,10 +2206,10 @@ async def update_profile(first_name: str = None, last_name: str = None, about: s
|
|||
)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Set Profile Photo", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Set Profile Photo", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
async def set_profile_photo(file_path: str, ctx: Optional[Context] = None) -> str:
|
||||
"""
|
||||
|
|
@ -2267,10 +2233,10 @@ async def set_profile_photo(file_path: str, ctx: Optional[Context] = None) -> st
|
|||
return log_and_format_error("set_profile_photo", e, file_path=file_path)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Delete Profile Photo", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Delete Profile Photo", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
async def delete_profile_photo() -> str:
|
||||
"""
|
||||
|
|
@ -2316,10 +2282,10 @@ async def get_privacy_settings() -> str:
|
|||
return log_and_format_error("get_privacy_settings", e)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Set Privacy Settings", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Set Privacy Settings", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
@validate_id("allow_users", "disallow_users")
|
||||
async def set_privacy_settings(
|
||||
|
|
@ -2417,8 +2383,8 @@ async def set_privacy_settings(
|
|||
return log_and_format_error("set_privacy_settings", e, key=key)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(title="Import Contacts", openWorldHint=True, destructiveHint=True)
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(title="Import Contacts", openWorldHint=True, destructiveHint=True)
|
||||
)
|
||||
async def import_contacts(contacts: list) -> str:
|
||||
"""
|
||||
|
|
@ -2469,8 +2435,8 @@ async def get_blocked_users() -> str:
|
|||
return log_and_format_error("get_blocked_users", e)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(title="Create Channel", openWorldHint=True, destructiveHint=True)
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(title="Create Channel", openWorldHint=True, destructiveHint=True)
|
||||
)
|
||||
async def create_channel(title: str, about: str = "", megagroup: bool = False) -> str:
|
||||
"""
|
||||
|
|
@ -2487,10 +2453,10 @@ async def create_channel(title: str, about: str = "", megagroup: bool = False) -
|
|||
)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Edit Chat Title", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Edit Chat Title", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
@validate_id("chat_id")
|
||||
async def edit_chat_title(chat_id: Union[int, str], title: str) -> str:
|
||||
|
|
@ -2511,10 +2477,10 @@ async def edit_chat_title(chat_id: Union[int, str], title: str) -> str:
|
|||
return log_and_format_error("edit_chat_title", e, chat_id=chat_id, title=title)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Edit Chat Photo", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Edit Chat Photo", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
@validate_id("chat_id")
|
||||
async def edit_chat_photo(
|
||||
|
|
@ -2556,10 +2522,10 @@ async def edit_chat_photo(
|
|||
return log_and_format_error("edit_chat_photo", e, chat_id=chat_id, file_path=file_path)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Delete Chat Photo", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Delete Chat Photo", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
@validate_id("chat_id")
|
||||
async def delete_chat_photo(chat_id: Union[int, str]) -> str:
|
||||
|
|
@ -2589,10 +2555,10 @@ async def delete_chat_photo(chat_id: Union[int, str]) -> str:
|
|||
return log_and_format_error("delete_chat_photo", e, chat_id=chat_id)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Promote Admin", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Promote Admin", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
@validate_id("group_id", "user_id")
|
||||
async def promote_admin(
|
||||
|
|
@ -2660,10 +2626,10 @@ async def promote_admin(
|
|||
return log_and_format_error("promote_admin", e, group_id=group_id, user_id=user_id)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Demote Admin", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Demote Admin", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
@validate_id("group_id", "user_id")
|
||||
async def demote_admin(group_id: Union[int, str], user_id: Union[int, str]) -> str:
|
||||
|
|
@ -2713,10 +2679,10 @@ async def demote_admin(group_id: Union[int, str], user_id: Union[int, str]) -> s
|
|||
return log_and_format_error("demote_admin", e, group_id=group_id, user_id=user_id)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Ban User", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Ban User", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
@validate_id("chat_id", "user_id")
|
||||
async def ban_user(chat_id: Union[int, str], user_id: Union[int, str]) -> str:
|
||||
|
|
@ -2764,10 +2730,10 @@ async def ban_user(chat_id: Union[int, str], user_id: Union[int, str]) -> str:
|
|||
return log_and_format_error("ban_user", e, chat_id=chat_id, user_id=user_id)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Unban User", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Unban User", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
@validate_id("chat_id", "user_id")
|
||||
async def unban_user(chat_id: Union[int, str], user_id: Union[int, str]) -> str:
|
||||
|
|
@ -2903,10 +2869,10 @@ async def get_invite_link(chat_id: Union[int, str]) -> str:
|
|||
return log_and_format_error("get_invite_link", e, chat_id=chat_id)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Join Chat By Link", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Join Chat By Link", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
async def join_chat_by_link(link: str) -> str:
|
||||
"""
|
||||
|
|
@ -2988,10 +2954,10 @@ async def export_chat_invite(chat_id: Union[int, str]) -> str:
|
|||
return log_and_format_error("export_chat_invite", e, chat_id=chat_id)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Import Chat Invite", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Import Chat Invite", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
async def import_chat_invite(hash: str) -> str:
|
||||
"""
|
||||
|
|
@ -3049,8 +3015,8 @@ async def import_chat_invite(hash: str) -> str:
|
|||
return log_and_format_error("import_chat_invite", e, hash=hash)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(title="Send Voice", openWorldHint=True, destructiveHint=True)
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(title="Send Voice", openWorldHint=True, destructiveHint=True)
|
||||
)
|
||||
@validate_id("chat_id")
|
||||
async def send_voice(
|
||||
|
|
@ -3092,8 +3058,8 @@ async def send_voice(
|
|||
return log_and_format_error("send_voice", e, chat_id=chat_id, file_path=file_path)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(title="Upload File", openWorldHint=True, destructiveHint=True)
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(title="Upload File", openWorldHint=True, destructiveHint=True)
|
||||
)
|
||||
async def upload_file(file_path: str, ctx: Optional[Context] = None) -> str:
|
||||
"""
|
||||
|
|
@ -3123,8 +3089,8 @@ async def upload_file(file_path: str, ctx: Optional[Context] = None) -> str:
|
|||
return log_and_format_error("upload_file", e, file_path=file_path)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(title="Forward Message", openWorldHint=True, destructiveHint=True)
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(title="Forward Message", openWorldHint=True, destructiveHint=True)
|
||||
)
|
||||
@validate_id("from_chat_id", "to_chat_id")
|
||||
async def forward_message(
|
||||
|
|
@ -3148,10 +3114,10 @@ async def forward_message(
|
|||
)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Edit Message", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Edit Message", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
@validate_id("chat_id")
|
||||
async def edit_message(chat_id: Union[int, str], message_id: int, new_text: str) -> str:
|
||||
|
|
@ -3168,10 +3134,10 @@ async def edit_message(chat_id: Union[int, str], message_id: int, new_text: str)
|
|||
)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Delete Message", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Delete Message", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
@validate_id("chat_id")
|
||||
async def delete_message(chat_id: Union[int, str], message_id: int) -> str:
|
||||
|
|
@ -3186,10 +3152,10 @@ async def delete_message(chat_id: Union[int, str], message_id: int) -> str:
|
|||
return log_and_format_error("delete_message", e, chat_id=chat_id, message_id=message_id)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Pin Message", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Pin Message", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
@validate_id("chat_id")
|
||||
async def pin_message(chat_id: Union[int, str], message_id: int) -> str:
|
||||
|
|
@ -3204,10 +3170,10 @@ async def pin_message(chat_id: Union[int, str], message_id: int) -> str:
|
|||
return log_and_format_error("pin_message", e, chat_id=chat_id, message_id=message_id)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Unpin Message", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Unpin Message", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
@validate_id("chat_id")
|
||||
async def unpin_message(chat_id: Union[int, str], message_id: int) -> str:
|
||||
|
|
@ -3222,10 +3188,10 @@ async def unpin_message(chat_id: Union[int, str], message_id: int) -> str:
|
|||
return log_and_format_error("unpin_message", e, chat_id=chat_id, message_id=message_id)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Mark As Read", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Mark As Read", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
@validate_id("chat_id")
|
||||
async def mark_as_read(chat_id: Union[int, str]) -> str:
|
||||
|
|
@ -3240,8 +3206,8 @@ async def mark_as_read(chat_id: Union[int, str]) -> str:
|
|||
return log_and_format_error("mark_as_read", e, chat_id=chat_id)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(title="Reply To Message", openWorldHint=True, destructiveHint=True)
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(title="Reply To Message", openWorldHint=True, destructiveHint=True)
|
||||
)
|
||||
@validate_id("chat_id")
|
||||
async def reply_to_message(
|
||||
|
|
@ -3387,10 +3353,10 @@ async def resolve_username(username: str) -> str:
|
|||
return log_and_format_error("resolve_username", e, username=username)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Mute Chat", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Mute Chat", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
@validate_id("chat_id")
|
||||
async def mute_chat(chat_id: Union[int, str]) -> str:
|
||||
|
|
@ -3430,10 +3396,10 @@ async def mute_chat(chat_id: Union[int, str]) -> str:
|
|||
return log_and_format_error("mute_chat", e, chat_id=chat_id)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Unmute Chat", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Unmute Chat", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
@validate_id("chat_id")
|
||||
async def unmute_chat(chat_id: Union[int, str]) -> str:
|
||||
|
|
@ -3473,10 +3439,10 @@ async def unmute_chat(chat_id: Union[int, str]) -> str:
|
|||
return log_and_format_error("unmute_chat", e, chat_id=chat_id)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Archive Chat", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Archive Chat", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
@validate_id("chat_id")
|
||||
async def archive_chat(chat_id: Union[int, str]) -> str:
|
||||
|
|
@ -3496,10 +3462,10 @@ async def archive_chat(chat_id: Union[int, str]) -> str:
|
|||
return log_and_format_error("archive_chat", e, chat_id=chat_id)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Unarchive Chat", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Unarchive Chat", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
@validate_id("chat_id")
|
||||
async def unarchive_chat(chat_id: Union[int, str]) -> str:
|
||||
|
|
@ -3533,8 +3499,8 @@ async def get_sticker_sets() -> str:
|
|||
return log_and_format_error("get_sticker_sets", e)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(title="Send Sticker", openWorldHint=True, destructiveHint=True)
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(title="Send Sticker", openWorldHint=True, destructiveHint=True)
|
||||
)
|
||||
@validate_id("chat_id")
|
||||
async def send_sticker(
|
||||
|
|
@ -3623,8 +3589,8 @@ async def get_gif_search(query: str, limit: int = 10) -> str:
|
|||
return log_and_format_error("get_gif_search", e, query=query, limit=limit)
|
||||
|
||||
|
||||
#@mcp.tool(annotations=ToolAnnotations(title="Send Gif", openWorldHint=True, destructiveHint=True))
|
||||
#@validate_id("chat_id")
|
||||
@mcp.tool(annotations=ToolAnnotations(title="Send Gif", openWorldHint=True, destructiveHint=True))
|
||||
@validate_id("chat_id")
|
||||
async def send_gif(chat_id: Union[int, str], gif_id: int) -> str:
|
||||
"""
|
||||
Send a GIF to a chat by Telegram GIF document ID (not a file path).
|
||||
|
|
@ -3643,49 +3609,6 @@ async def send_gif(chat_id: Union[int, str], gif_id: int) -> str:
|
|||
return log_and_format_error("send_gif", e, chat_id=chat_id, gif_id=gif_id)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(title="Send Contact", openWorldHint=True, destructiveHint=True)
|
||||
)
|
||||
@validate_id("chat_id")
|
||||
async def send_contact(
|
||||
chat_id: Union[int, str],
|
||||
phone_number: str,
|
||||
first_name: str,
|
||||
last_name: str = "",
|
||||
vcard: str = "",
|
||||
) -> str:
|
||||
"""
|
||||
Send a contact to a chat.
|
||||
Args:
|
||||
chat_id: The chat ID or username.
|
||||
phone_number: Contact's phone number.
|
||||
first_name: Contact's first name.
|
||||
last_name: Contact's last name (optional).
|
||||
vcard: Additional vCard data (optional).
|
||||
"""
|
||||
try:
|
||||
entity = await resolve_entity(chat_id)
|
||||
from telethon.tl.types import InputMediaContact
|
||||
import random
|
||||
|
||||
await client(
|
||||
functions.messages.SendMediaRequest(
|
||||
peer=entity,
|
||||
media=InputMediaContact(
|
||||
phone_number=phone_number,
|
||||
first_name=first_name,
|
||||
last_name=last_name,
|
||||
vcard=vcard,
|
||||
),
|
||||
message="",
|
||||
random_id=random.randint(0, 2**63 - 1),
|
||||
)
|
||||
)
|
||||
return f"Contact sent to chat {chat_id}."
|
||||
except Exception as e:
|
||||
return log_and_format_error("send_contact", e, chat_id=chat_id, phone_number=phone_number)
|
||||
|
||||
|
||||
@mcp.tool(annotations=ToolAnnotations(title="Get Bot Info", openWorldHint=True, readOnlyHint=True))
|
||||
async def get_bot_info(bot_username: str) -> str:
|
||||
"""
|
||||
|
|
@ -3722,10 +3645,10 @@ async def get_bot_info(bot_username: str) -> str:
|
|||
return log_and_format_error("get_bot_info", e, bot_username=bot_username)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Set Bot Commands", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Set Bot Commands", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
async def set_bot_commands(bot_username: str, commands: list) -> str:
|
||||
"""
|
||||
|
|
@ -3902,8 +3825,8 @@ async def get_pinned_messages(chat_id: Union[int, str]) -> str:
|
|||
return log_and_format_error("get_pinned_messages", e, chat_id=chat_id)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(title="Create Poll", openWorldHint=True, destructiveHint=True)
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(title="Create Poll", openWorldHint=True, destructiveHint=True)
|
||||
)
|
||||
async def create_poll(
|
||||
chat_id: int,
|
||||
|
|
@ -3977,10 +3900,10 @@ async def create_poll(
|
|||
)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Send Reaction", openWorldHint=True, destructiveHint=False, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Send Reaction", openWorldHint=True, destructiveHint=False, idempotentHint=True
|
||||
)
|
||||
)
|
||||
@validate_id("chat_id")
|
||||
async def send_reaction(
|
||||
|
|
@ -4020,10 +3943,10 @@ async def send_reaction(
|
|||
)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Remove Reaction", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Remove Reaction", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
@validate_id("chat_id")
|
||||
async def remove_reaction(
|
||||
|
|
@ -4128,10 +4051,10 @@ async def get_message_reactions(
|
|||
# ============================================================================
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Save Draft", openWorldHint=True, destructiveHint=False, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Save Draft", openWorldHint=True, destructiveHint=False, idempotentHint=True
|
||||
)
|
||||
)
|
||||
@validate_id("chat_id")
|
||||
async def save_draft(
|
||||
|
|
@ -4232,10 +4155,10 @@ async def get_drafts() -> str:
|
|||
return log_and_format_error("get_drafts", e)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Clear Draft", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Clear Draft", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
@validate_id("chat_id")
|
||||
async def clear_draft(chat_id: Union[int, str]) -> str:
|
||||
|
|
@ -4434,10 +4357,10 @@ async def get_folder(folder_id: int) -> str:
|
|||
return log_and_format_error("get_folder", e, ErrorCategory.FOLDER, folder_id=folder_id)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Create Folder", openWorldHint=True, destructiveHint=True, idempotentHint=False
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Create Folder", openWorldHint=True, destructiveHint=True, idempotentHint=False
|
||||
)
|
||||
)
|
||||
async def create_folder(
|
||||
title: str,
|
||||
|
|
@ -4534,10 +4457,10 @@ async def create_folder(
|
|||
return log_and_format_error("create_folder", e, ErrorCategory.FOLDER, title=title)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Add Chat to Folder", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Add Chat to Folder", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
@validate_id("chat_id")
|
||||
async def add_chat_to_folder(
|
||||
|
|
@ -4635,13 +4558,13 @@ async def add_chat_to_folder(
|
|||
)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Remove Chat from Folder",
|
||||
# openWorldHint=True,
|
||||
# destructiveHint=True,
|
||||
# idempotentHint=True,
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Remove Chat from Folder",
|
||||
openWorldHint=True,
|
||||
destructiveHint=True,
|
||||
idempotentHint=True,
|
||||
)
|
||||
)
|
||||
@validate_id("chat_id")
|
||||
async def remove_chat_from_folder(folder_id: int, chat_id: Union[int, str]) -> str:
|
||||
|
|
@ -4745,10 +4668,10 @@ async def remove_chat_from_folder(folder_id: int, chat_id: Union[int, str]) -> s
|
|||
)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Delete Folder", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Delete Folder", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
async def delete_folder(folder_id: int) -> str:
|
||||
"""
|
||||
|
|
@ -4789,10 +4712,10 @@ async def delete_folder(folder_id: int) -> str:
|
|||
return log_and_format_error("delete_folder", e, ErrorCategory.FOLDER, folder_id=folder_id)
|
||||
|
||||
|
||||
#@mcp.tool(
|
||||
# annotations=ToolAnnotations(
|
||||
# title="Reorder Folders", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
# )
|
||||
@mcp.tool(
|
||||
annotations=ToolAnnotations(
|
||||
title="Reorder Folders", openWorldHint=True, destructiveHint=True, idempotentHint=True
|
||||
)
|
||||
)
|
||||
async def reorder_folders(folder_ids: List[int]) -> str:
|
||||
"""
|
||||
|
|
|
|||
Loading…
Reference in a new issue