School/IKEA_scraper/.venv/Lib/site-packages/aiogram/bot/api.py
Kristofers Solo dca634b9b9 Changed name
2021-09-12 18:39:57 +03:00

291 lines
10 KiB
Python

import logging
import os
from dataclasses import dataclass
from http import HTTPStatus
import aiohttp
from .. import types
from ..utils import exceptions, json
from ..utils.helper import Helper, HelperMode, Item
# Main aiogram logger
log = logging.getLogger('aiogram')
@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}}/{{path}}",
)
TELEGRAM_PRODUCTION = TelegramAPIServer.from_base("https://api.telegram.org")
def check_token(token: str) -> bool:
"""
Validate BOT token
:param token:
:return:
"""
if not isinstance(token, str):
message = (f"Token is invalid! "
f"It must be 'str' type instead of {type(token)} type.")
raise exceptions.ValidationError(message)
if any(x.isspace() for x in token):
message = "Token is invalid! It can't contains spaces."
raise exceptions.ValidationError(message)
left, sep, right = token.partition(':')
if (not sep) or (not left.isdigit()) or (not right):
raise exceptions.ValidationError('Token is invalid!')
return True
def check_result(method_name: str, content_type: str, status_code: int, body: str):
"""
Checks whether `result` is a valid API response.
A result is considered invalid if:
- The server returned an HTTP response code other than 200
- The content of the result is invalid JSON.
- The method call was unsuccessful (The JSON 'ok' field equals False)
:param method_name: The name of the method called
:param status_code: status code
:param content_type: content type of result
:param body: result body
:return: The result parsed to a JSON dictionary
:raises ApiException: if one of the above listed cases is applicable
"""
log.debug('Response for %s: [%d] "%r"', method_name, status_code, body)
if content_type != 'application/json':
raise exceptions.NetworkError(f"Invalid response with content type {content_type}: \"{body}\"")
try:
result_json = json.loads(body)
except ValueError:
result_json = {}
description = result_json.get('description') or body
parameters = types.ResponseParameters(**result_json.get('parameters', {}) or {})
if HTTPStatus.OK <= status_code <= HTTPStatus.IM_USED:
return result_json.get('result')
elif parameters.retry_after:
raise exceptions.RetryAfter(parameters.retry_after)
elif parameters.migrate_to_chat_id:
raise exceptions.MigrateToChat(parameters.migrate_to_chat_id)
elif status_code == HTTPStatus.BAD_REQUEST:
exceptions.BadRequest.detect(description)
elif status_code == HTTPStatus.NOT_FOUND:
exceptions.NotFound.detect(description)
elif status_code == HTTPStatus.CONFLICT:
exceptions.ConflictError.detect(description)
elif status_code in (HTTPStatus.UNAUTHORIZED, HTTPStatus.FORBIDDEN):
exceptions.Unauthorized.detect(description)
elif status_code == HTTPStatus.REQUEST_ENTITY_TOO_LARGE:
raise exceptions.NetworkError('File too large for uploading. '
'Check telegram api limits https://core.telegram.org/bots/api#senddocument')
elif status_code >= HTTPStatus.INTERNAL_SERVER_ERROR:
if 'restart' in description:
raise exceptions.RestartingTelegram()
raise exceptions.TelegramAPIError(description)
raise exceptions.TelegramAPIError(f"{description} [{status_code}]")
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 = server.api_url(token=token, method=method)
req = compose_data(data, files)
try:
async with session.post(url, data=req, **kwargs) as response:
return check_result(method, response.content_type, response.status, await response.text())
except aiohttp.ClientError as e:
raise exceptions.NetworkError(f"aiohttp client throws an error: {e.__class__.__name__}: {e}")
def guess_filename(obj):
"""
Get file name from object
:param obj:
:return:
"""
name = getattr(obj, 'name', None)
if name and isinstance(name, str) and name[0] != '<' and name[-1] != '>':
return os.path.basename(name)
def compose_data(params=None, files=None):
"""
Prepare request data
:param params:
:param files:
:return:
"""
data = aiohttp.formdata.FormData(quote_fields=False)
if params:
for key, value in params.items():
data.add_field(key, str(value))
if files:
for key, f in files.items():
if isinstance(f, tuple):
if len(f) == 2:
filename, fileobj = f
else:
raise ValueError('Tuple must have exactly 2 elements: filename, fileobj')
elif isinstance(f, types.InputFile):
filename, fileobj = f.filename, f.file
else:
filename, fileobj = guess_filename(f) or key, f
data.add_field(key, fileobj, filename=filename)
return data
class Methods(Helper):
"""
Helper for Telegram API Methods listed on https://core.telegram.org/bots/api
List is updated to Bot API 5.3
"""
mode = HelperMode.lowerCamelCase
# Getting Updates
GET_UPDATES = Item() # getUpdates
SET_WEBHOOK = Item() # setWebhook
DELETE_WEBHOOK = Item() # deleteWebhook
GET_WEBHOOK_INFO = Item() # getWebhookInfo
# 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
SEND_VIDEO = Item() # sendVideo
SEND_ANIMATION = Item() # sendAnimation
SEND_VOICE = Item() # sendVoice
SEND_VIDEO_NOTE = Item() # sendVideoNote
SEND_MEDIA_GROUP = Item() # sendMediaGroup
SEND_LOCATION = Item() # sendLocation
EDIT_MESSAGE_LIVE_LOCATION = Item() # editMessageLiveLocation
STOP_MESSAGE_LIVE_LOCATION = Item() # stopMessageLiveLocation
SEND_VENUE = Item() # sendVenue
SEND_CONTACT = Item() # sendContact
SEND_POLL = Item() # sendPoll
SEND_DICE = Item() # sendDice
SEND_CHAT_ACTION = Item() # sendChatAction
GET_USER_PROFILE_PHOTOS = Item() # getUserProfilePhotos
GET_FILE = Item() # getFile
KICK_CHAT_MEMBER = Item() # kickChatMember
BAN_CHAT_MEMBER = Item() # banChatMember
UNBAN_CHAT_MEMBER = Item() # unbanChatMember
RESTRICT_CHAT_MEMBER = Item() # restrictChatMember
PROMOTE_CHAT_MEMBER = Item() # promoteChatMember
SET_CHAT_ADMINISTRATOR_CUSTOM_TITLE = Item() # setChatAdministratorCustomTitle
SET_CHAT_PERMISSIONS = Item() # setChatPermissions
EXPORT_CHAT_INVITE_LINK = Item() # exportChatInviteLink
CREATE_CHAT_INVITE_LINK = Item() # createChatInviteLink
EDIT_CHAT_INVITE_LINK = Item() # editChatInviteLink
REVOKE_CHAT_INVITE_LINK = Item() # revokeChatInviteLink
SET_CHAT_PHOTO = Item() # setChatPhoto
DELETE_CHAT_PHOTO = Item() # deleteChatPhoto
SET_CHAT_TITLE = Item() # setChatTitle
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
GET_CHAT_MEMBER_COUNT = Item() # getChatMemberCount
GET_CHAT_MEMBERS_COUNT = Item() # getChatMembersCount (renamed to getChatMemberCount)
GET_CHAT_MEMBER = Item() # getChatMember
SET_CHAT_STICKER_SET = Item() # setChatStickerSet
DELETE_CHAT_STICKER_SET = Item() # deleteChatStickerSet
ANSWER_CALLBACK_QUERY = Item() # answerCallbackQuery
SET_MY_COMMANDS = Item() # setMyCommands
DELETE_MY_COMMANDS = Item() # deleteMyCommands
GET_MY_COMMANDS = Item() # getMyCommands
# Updating messages
EDIT_MESSAGE_TEXT = Item() # editMessageText
EDIT_MESSAGE_CAPTION = Item() # editMessageCaption
EDIT_MESSAGE_MEDIA = Item() # editMessageMedia
EDIT_MESSAGE_REPLY_MARKUP = Item() # editMessageReplyMarkup
STOP_POLL = Item() # stopPoll
DELETE_MESSAGE = Item() # deleteMessage
# Stickers
SEND_STICKER = Item() # sendSticker
GET_STICKER_SET = Item() # getStickerSet
UPLOAD_STICKER_FILE = Item() # uploadStickerFile
CREATE_NEW_STICKER_SET = Item() # createNewStickerSet
ADD_STICKER_TO_SET = Item() # addStickerToSet
SET_STICKER_POSITION_IN_SET = Item() # setStickerPositionInSet
DELETE_STICKER_FROM_SET = Item() # deleteStickerFromSet
SET_STICKER_SET_THUMB = Item() # setStickerSetThumb
# Inline mode
ANSWER_INLINE_QUERY = Item() # answerInlineQuery
# Payments
SEND_INVOICE = Item() # sendInvoice
ANSWER_SHIPPING_QUERY = Item() # answerShippingQuery
ANSWER_PRE_CHECKOUT_QUERY = Item() # answerPreCheckoutQuery
# Telegram Passport
SET_PASSPORT_DATA_ERRORS = Item() # setPassportDataErrors
# Games
SEND_GAME = Item() # sendGame
SET_GAME_SCORE = Item() # setGameScore
GET_GAME_HIGH_SCORES = Item() # getGameHighScores