docs: document server-side rendering pipeline, response timing middleware, and Telegram pairing API
- Add comprehensive documentation for backend content rendering in AGENTS.md, detailing the new `render_content` and `render_title` Jinja globals built on mistune with media processing, emoji shortcodes, and XSS protection
- Document the `X-Response-Time` header and bottom-left render time indicator in README.md
- Update bot token pricing documentation to clarify fallback vs gateway cost headers
- Add `email_accounts` to soft-delete tables and `idx_users_role` composite index in database schema
- Implement `telegram_pairings` and `telegram_links` table creation with column migration and indexes
- Add `/profile/{username}/telegram` endpoint to docs API with request/unpair actions
- Register `TelegramService` in main.py lifespan and add `response_timing` middleware emitting `X-Response-Time` header
- Introduce `TelegramPairForm` model and `guard_public_host_sync` synchronous host validation function
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
# retoor <retoor@molodetz.nl>
|
||||
|
||||
from .controller import TelegramSendController
|
||||
|
||||
__all__ = ["TelegramSendController"]
|
||||
@@ -0,0 +1,54 @@
|
||||
# retoor <retoor@molodetz.nl>
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from typing import Any
|
||||
|
||||
from devplacepy.services.devii.errors import ToolInputError
|
||||
|
||||
|
||||
class TelegramSendController:
|
||||
def __init__(self, owner_kind: str, owner_id: str) -> None:
|
||||
self._owner_kind = owner_kind
|
||||
self._owner_id = owner_id
|
||||
|
||||
async def dispatch(self, name: str, arguments: dict[str, Any]) -> str:
|
||||
if name == "telegram_send":
|
||||
return await self._send(arguments)
|
||||
raise ToolInputError(f"Unknown telegram tool: {name}")
|
||||
|
||||
async def _send(self, arguments: dict[str, Any]) -> str:
|
||||
if self._owner_kind != "user":
|
||||
raise ToolInputError(
|
||||
"Telegram delivery is only available for signed-in users."
|
||||
)
|
||||
text = str(arguments.get("text", "")).strip()
|
||||
if not text:
|
||||
raise ToolInputError("'text' is required and cannot be empty.")
|
||||
from devplacepy.services.telegram import store
|
||||
|
||||
link = store.link_for_user(self._owner_id)
|
||||
if not link:
|
||||
raise ToolInputError(
|
||||
"Your Telegram account is not paired. Ask the user to request a pairing "
|
||||
"code from their profile and connect Telegram first."
|
||||
)
|
||||
from devplacepy.services.manager import service_manager
|
||||
|
||||
service = service_manager.get_service("telegram")
|
||||
if (
|
||||
service is None
|
||||
or not service.is_enabled()
|
||||
or not service_manager.owns_lock()
|
||||
or not service.worker_alive()
|
||||
):
|
||||
raise ToolInputError("The Telegram bot service is not running right now.")
|
||||
delivered = await service.send_markdown(int(link["chat_id"]), text)
|
||||
return json.dumps(
|
||||
{
|
||||
"status": "success" if delivered else "failed",
|
||||
"delivered": delivered,
|
||||
},
|
||||
ensure_ascii=False,
|
||||
)
|
||||
Reference in New Issue
Block a user