mirror of
https://github.com/aiogram/aiogram.git
synced 2026-04-08 16:37:47 +00:00
Bot API 5.0 (#454)
* increased Telegram Bot API version * AIOG-T-64 added logOut method * AIOG-T-64 added logOut method test * AIOG-T-64 logOut type annotation fix * AIOG-T-65 added close (close_bot) method * AIOG-T-65 old `close` method deprecation warn * AIOG-T-65 `close_bot` test added * AIOG-T-67 added ip_address param to set_webhook, updated docs * updated deprecation text Co-authored-by: Martin Winks <mpa@snejugal.ru> * AIOG-T-69 param `drop_pending_updates` added in methods `setWebhook` and `deleteWebhook` * AIOG-T-71 new `ChatLocation` class * AIOG-T-70 updated `Chat` class: bio, linked chats, location * AIOG-T-68 field `ip_address` added to class `WebhookInfo` * AIOG-T-72 param `only_if_banned` added to `unbanChatMember` method * AIOG-T-72 updated Chat.unban shortcut * AIOG-T-73 field `file_name` added to `Audio` and `Video` classes * AIOG-T-74 param `disable_content_type_detection` added in `sendDocument` method and `InputMediaDocument` class * AIOG-T-75 Added the ability to pin messages in private chats (docs update) * AIOG-T-76 Added the parameter message_id to the method unpinChatMessage to allow unpinning of the specific pinned message * AIOG-T-77 Added the method unpinAllChatMessages, which can be used to unpin all pinned messages in a chat. * AIOG-T-78 updated send_media_group description; added media qty check * AIOG-T-80 field `live_period` added to `Location` class * AIOG-T-81 Added support for live location heading * AIOG-T-82 added the field proximity_alert_distance to the classes Location, InlineQueryResultLocation, InputLocationMessageContent; fixed heading in InputLocationMessageContent * AIOG-T-82 added parameter proximity_alert_distance to the methods sendLocation and editMessageLiveLocation * AIOG-T-83 Added the type ProximityAlertTriggered * AIOG-T-83 Added field proximity_alert_triggered to the class Message * AIOG-T-84 Added the field horizontal_accuracy to the classes Location, InlineQueryResultLocation, InputLocationMessageContent * AIOG-T-84 Added the parameter horizontal_accuracy to the methods sendLocation and editMessageLiveLocation. * Added live_period to InputLocationMessageContent (missed?) * AIOG-T-85 Added the field sender_chat to the class Message * AIOG-T-86 Added `is_anonymous` field to `chatMember` class * AIOG-T-87 Added the parameter is_anonymous to the method promoteChatMember * AIOG-T-89 Added the method `copyMessage` * AIOG-T-90 Poll docs update * AIOG-T-91 ability to manually specify text entities * AIOG-T-92 Google Places as a venue API provider * AIOG-T-93 Added the field allow_sending_without_reply to the methods * AIOG-T-94 football and slot machine dice * removed Optional Co-authored-by: Ramzan Bekbulatov <bekbulatov.ramzan@ya.ru> * Apply suggestions from code review removed Optional Co-authored-by: Ramzan Bekbulatov <bekbulatov.ramzan@ya.ru> * Don't use deprecated Bot.close method from dispatcher (Replaced by session.close) * Fix copyMessage method, update alias (with deprecation) Fix imports * AIOG-T-79: Easy way to use custom API server * Update docs * Bump requirements * Rollback email * AIOG-T-93 allow_sending_without_reply to send_message shortcuts * AIOG-T-93 added allow_sending_without_reply to send_photo shortcuts * AIOG-T-93 added allow_sending_without_reply to send_video shortcuts * Union[type, None] -> Optional[type] refactoring * AIOG-T-93 added allow_sending_without_reply to send_animation shortcuts * added type hint to reply field * AIOG-T-93 added allow_sending_without_reply to send_audio shortcuts * AIOG-T-93 added allow_sending_without_reply to send_document shortcuts * AIOG-T-93 added allow_sending_without_reply to send_sticker shortcuts * AIOG-T-93 added allow_sending_without_reply to send_video_note shortcuts * AIOG-T-93 added allow_sending_without_reply to send_voice shortcuts * AIOG-T-93 added allow_sending_without_reply to send_location shortcuts * AIOG-T-93 added allow_sending_without_reply to send_venue shortcuts * AIOG-T-93 added allow_sending_without_reply to send_contact shortcuts * AIOG-T-93 added allow_sending_without_reply to send_poll shortcuts * AIOG-T-93 added allow_sending_without_reply to send_dice shortcuts * AIOG-T-93 added allow_sending_without_reply to send_media_group shortcuts * AIOG-T-92 added google_place_ to send_venue shortcuts * AIOG-T-91 added entities to send_message shortcuts * AIOG-T-91 added caption_entities to send_photo shortcuts * AIOG-T-91 added caption_entities to send_video shortcuts * AIOG-T-91 added caption_entities to send_animation shortcuts * AIOG-T-91 added caption_entities to send_audio shortcuts * AIOG-T-91 added caption_entities to send_document shortcuts * AIOG-T-91 added caption_entities to send_voice shortcuts * AIOG-T-91 added explanation_parse_mode to send_poll shortcuts * AIOG-T-91 added entities to edit_message_text shortcuts * AIOG-T-91 added caption_entities to edit_message_caption shortcuts * fixed types.MessageEntity -> MessageEntity in docs Co-authored-by: Martin Winks <mpa@snejugal.ru> Co-authored-by: Ramzan Bekbulatov <bekbulatov.ramzan@ya.ru> Co-authored-by: Alex Root Junior <jroot.junior@gmail.com>
This commit is contained in:
parent
8c43c209e0
commit
2b060d9ad4
49 changed files with 2847 additions and 1194 deletions
|
|
@ -1,20 +1,57 @@
|
|||
import logging
|
||||
import os
|
||||
from dataclasses import dataclass
|
||||
from http import HTTPStatus
|
||||
|
||||
import aiohttp
|
||||
|
||||
from .. import types
|
||||
from ..utils import exceptions
|
||||
from ..utils import json
|
||||
from ..utils import exceptions, json
|
||||
from ..utils.helper import Helper, HelperMode, Item
|
||||
|
||||
# Main aiogram logger
|
||||
log = logging.getLogger('aiogram')
|
||||
|
||||
# API Url's
|
||||
API_URL = "https://api.telegram.org/bot{token}/{method}"
|
||||
FILE_URL = "https://api.telegram.org/file/bot{token}/{path}"
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class TelegramAPIServer:
|
||||
"""
|
||||
Base config for API Endpoints
|
||||
"""
|
||||
|
||||
base: str
|
||||
file: str
|
||||
|
||||
def api_url(self, token: str, method: str) -> str:
|
||||
"""
|
||||
Generate URL for API methods
|
||||
|
||||
:param token: Bot token
|
||||
:param method: API method name (case insensitive)
|
||||
:return: URL
|
||||
"""
|
||||
return self.base.format(token=token, method=method)
|
||||
|
||||
def file_url(self, token: str, path: str) -> str:
|
||||
"""
|
||||
Generate URL for downloading files
|
||||
|
||||
:param token: Bot token
|
||||
:param path: file path
|
||||
:return: URL
|
||||
"""
|
||||
return self.file.format(token=token, path=path)
|
||||
|
||||
@classmethod
|
||||
def from_base(cls, base: str) -> 'TelegramAPIServer':
|
||||
base = base.rstrip("/")
|
||||
return cls(
|
||||
base=f"{base}/bot{{token}}/{{method}}",
|
||||
file=f"{base}/file/bot{{token}}/{{method}}",
|
||||
)
|
||||
|
||||
|
||||
TELEGRAM_PRODUCTION = TelegramAPIServer.from_base("https://api.telegram.org")
|
||||
|
||||
|
||||
def check_token(token: str) -> bool:
|
||||
|
|
@ -92,11 +129,10 @@ def check_result(method_name: str, content_type: str, status_code: int, body: st
|
|||
raise exceptions.TelegramAPIError(f"{description} [{status_code}]")
|
||||
|
||||
|
||||
async def make_request(session, token, method, data=None, files=None, **kwargs):
|
||||
# log.debug(f"Make request: '{method}' with data: {data} and files {files}")
|
||||
async def make_request(session, server, token, method, data=None, files=None, **kwargs):
|
||||
log.debug('Make request: "%s" with data: "%r" and files "%r"', method, data, files)
|
||||
|
||||
url = Methods.api_url(token=token, method=method)
|
||||
url = server.api_url(token=token, method=method)
|
||||
|
||||
req = compose_data(data, files)
|
||||
try:
|
||||
|
|
@ -153,7 +189,7 @@ class Methods(Helper):
|
|||
"""
|
||||
Helper for Telegram API Methods listed on https://core.telegram.org/bots/api
|
||||
|
||||
List is updated to Bot API 4.9
|
||||
List is updated to Bot API 5.0
|
||||
"""
|
||||
mode = HelperMode.lowerCamelCase
|
||||
|
||||
|
|
@ -165,8 +201,11 @@ class Methods(Helper):
|
|||
|
||||
# Available methods
|
||||
GET_ME = Item() # getMe
|
||||
LOG_OUT = Item() # logOut
|
||||
CLOSE = Item() # close
|
||||
SEND_MESSAGE = Item() # sendMessage
|
||||
FORWARD_MESSAGE = Item() # forwardMessage
|
||||
COPY_MESSAGE = Item() # copyMessage
|
||||
SEND_PHOTO = Item() # sendPhoto
|
||||
SEND_AUDIO = Item() # sendAudio
|
||||
SEND_DOCUMENT = Item() # sendDocument
|
||||
|
|
@ -198,6 +237,7 @@ class Methods(Helper):
|
|||
SET_CHAT_DESCRIPTION = Item() # setChatDescription
|
||||
PIN_CHAT_MESSAGE = Item() # pinChatMessage
|
||||
UNPIN_CHAT_MESSAGE = Item() # unpinChatMessage
|
||||
UNPIN_ALL_CHAT_MESSAGES = Item() # unpinAllChatMessages
|
||||
LEAVE_CHAT = Item() # leaveChat
|
||||
GET_CHAT = Item() # getChat
|
||||
GET_CHAT_ADMINISTRATORS = Item() # getChatAdministrators
|
||||
|
|
@ -242,25 +282,3 @@ class Methods(Helper):
|
|||
SEND_GAME = Item() # sendGame
|
||||
SET_GAME_SCORE = Item() # setGameScore
|
||||
GET_GAME_HIGH_SCORES = Item() # getGameHighScores
|
||||
|
||||
@staticmethod
|
||||
def api_url(token, method):
|
||||
"""
|
||||
Generate API URL with included token and method name
|
||||
|
||||
:param token:
|
||||
:param method:
|
||||
:return:
|
||||
"""
|
||||
return API_URL.format(token=token, method=method)
|
||||
|
||||
@staticmethod
|
||||
def file_url(token, path):
|
||||
"""
|
||||
Generate File URL with included token and file path
|
||||
|
||||
:param token:
|
||||
:param path:
|
||||
:return:
|
||||
"""
|
||||
return FILE_URL.format(token=token, path=path)
|
||||
|
|
|
|||
|
|
@ -12,9 +12,11 @@ import certifi
|
|||
from aiohttp.helpers import sentinel
|
||||
|
||||
from . import api
|
||||
from .api import TelegramAPIServer, TELEGRAM_PRODUCTION
|
||||
from ..types import ParseMode, base
|
||||
from ..utils import json
|
||||
from ..utils.auth_widget import check_integrity
|
||||
from ..utils.deprecated import deprecated
|
||||
|
||||
|
||||
class BaseBot:
|
||||
|
|
@ -33,7 +35,8 @@ class BaseBot:
|
|||
proxy_auth: Optional[aiohttp.BasicAuth] = None,
|
||||
validate_token: Optional[base.Boolean] = True,
|
||||
parse_mode: typing.Optional[base.String] = None,
|
||||
timeout: typing.Optional[typing.Union[base.Integer, base.Float, aiohttp.ClientTimeout]] = None
|
||||
timeout: typing.Optional[typing.Union[base.Integer, base.Float, aiohttp.ClientTimeout]] = None,
|
||||
server: TelegramAPIServer = TELEGRAM_PRODUCTION
|
||||
):
|
||||
"""
|
||||
Instructions how to get Bot token is found here: https://core.telegram.org/bots#3-how-do-i-create-a-bot
|
||||
|
|
@ -54,6 +57,8 @@ class BaseBot:
|
|||
:type parse_mode: :obj:`str`
|
||||
:param timeout: Request timeout
|
||||
:type timeout: :obj:`typing.Optional[typing.Union[base.Integer, base.Float, aiohttp.ClientTimeout]]`
|
||||
:param server: Telegram Bot API Server endpoint.
|
||||
:type server: :obj:`TelegramAPIServer`
|
||||
:raise: when token is invalid throw an :obj:`aiogram.utils.exceptions.ValidationError`
|
||||
"""
|
||||
self._main_loop = loop
|
||||
|
|
@ -64,6 +69,7 @@ class BaseBot:
|
|||
self._token = None
|
||||
self.__token = token
|
||||
self.id = int(token.split(sep=':')[0])
|
||||
self.server = server
|
||||
|
||||
self.proxy = proxy
|
||||
self.proxy_auth = proxy_auth
|
||||
|
|
@ -173,6 +179,8 @@ class BaseBot:
|
|||
finally:
|
||||
self._ctx_token.reset(token)
|
||||
|
||||
@deprecated("This method's behavior will be changed in aiogram v3.0. "
|
||||
"More info: https://core.telegram.org/bots/api#close", stacklevel=3)
|
||||
async def close(self):
|
||||
"""
|
||||
Close all client sessions
|
||||
|
|
@ -197,7 +205,7 @@ class BaseBot:
|
|||
:rtype: Union[List, Dict]
|
||||
:raise: :obj:`aiogram.exceptions.TelegramApiError`
|
||||
"""
|
||||
return await api.make_request(self.session, self.__token, method, data, files,
|
||||
return await api.make_request(self.session, self.server, self.__token, method, data, files,
|
||||
proxy=self.proxy, proxy_auth=self.proxy_auth, timeout=self.timeout, **kwargs)
|
||||
|
||||
async def download_file(self, file_path: base.String,
|
||||
|
|
@ -237,7 +245,7 @@ class BaseBot:
|
|||
return dest
|
||||
|
||||
def get_file_url(self, file_path):
|
||||
return api.Methods.file_url(token=self.__token, path=file_path)
|
||||
return self.server.file_url(token=self.__token, path=file_path)
|
||||
|
||||
async def send_file(self, file_type, method, file, payload) -> Union[Dict, base.Boolean]:
|
||||
"""
|
||||
|
|
|
|||
1455
aiogram/bot/bot.py
1455
aiogram/bot/bot.py
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue