mirror of
https://github.com/aiogram/aiogram.git
synced 2025-12-12 18:19:34 +00:00
Implemented polls [From test API]
This commit is contained in:
parent
2a6f36b19b
commit
e2e2d9c9fe
10 changed files with 107 additions and 7 deletions
|
|
@ -38,5 +38,5 @@ __all__ = [
|
||||||
'utils'
|
'utils'
|
||||||
]
|
]
|
||||||
|
|
||||||
__version__ = '2.0.2.dev1'
|
__version__ = '2.1.dev1'
|
||||||
__api_version__ = '4.1'
|
__api_version__ = '4.1'
|
||||||
|
|
|
||||||
|
|
@ -229,6 +229,10 @@ class Methods(Helper):
|
||||||
SET_GAME_SCORE = Item() # setGameScore
|
SET_GAME_SCORE = Item() # setGameScore
|
||||||
GET_GAME_HIGH_SCORES = Item() # getGameHighScores
|
GET_GAME_HIGH_SCORES = Item() # getGameHighScores
|
||||||
|
|
||||||
|
# Polls
|
||||||
|
SEND_POLL = Item()
|
||||||
|
STOP_POLL = Item()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def api_url(token, method):
|
def api_url(token, method):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -2056,3 +2056,20 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin):
|
||||||
result = await self.request(api.Methods.GET_GAME_HIGH_SCORES, payload)
|
result = await self.request(api.Methods.GET_GAME_HIGH_SCORES, payload)
|
||||||
|
|
||||||
return [types.GameHighScore(**gamehighscore) for gamehighscore in result]
|
return [types.GameHighScore(**gamehighscore) for gamehighscore in result]
|
||||||
|
|
||||||
|
async def send_poll(self, chat_id: typing.Union[base.Integer, base.String],
|
||||||
|
question: base.String,
|
||||||
|
options: typing.List[base.String],
|
||||||
|
reply_to_message_id: typing.Union[base.Integer, None]):
|
||||||
|
options = prepare_arg(options)
|
||||||
|
payload = generate_payload(**locals())
|
||||||
|
|
||||||
|
result = await self.request(api.Methods.SEND_POLL, payload)
|
||||||
|
return types.Message(**result)
|
||||||
|
|
||||||
|
async def stop_poll(self, chat_id: typing.Union[base.String, base.Integer],
|
||||||
|
message_id: base.Integer) -> types.Poll:
|
||||||
|
payload = generate_payload(**locals())
|
||||||
|
|
||||||
|
result = await self.request(api.Methods.STOP_POLL, payload)
|
||||||
|
return types.Poll(**result)
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ class Dispatcher(DataMixin, ContextInstanceMixin):
|
||||||
self.callback_query_handlers = Handler(self, middleware_key='callback_query')
|
self.callback_query_handlers = Handler(self, middleware_key='callback_query')
|
||||||
self.shipping_query_handlers = Handler(self, middleware_key='shipping_query')
|
self.shipping_query_handlers = Handler(self, middleware_key='shipping_query')
|
||||||
self.pre_checkout_query_handlers = Handler(self, middleware_key='pre_checkout_query')
|
self.pre_checkout_query_handlers = Handler(self, middleware_key='pre_checkout_query')
|
||||||
|
self.poll_handlers = Handler(self, middleware_key='poll')
|
||||||
self.errors_handlers = Handler(self, once=False, middleware_key='error')
|
self.errors_handlers = Handler(self, once=False, middleware_key='error')
|
||||||
|
|
||||||
self.middleware = MiddlewareManager(self)
|
self.middleware = MiddlewareManager(self)
|
||||||
|
|
@ -80,7 +81,8 @@ class Dispatcher(DataMixin, ContextInstanceMixin):
|
||||||
filters_factory = self.filters_factory
|
filters_factory = self.filters_factory
|
||||||
|
|
||||||
filters_factory.bind(StateFilter, exclude_event_handlers=[
|
filters_factory.bind(StateFilter, exclude_event_handlers=[
|
||||||
self.errors_handlers
|
self.errors_handlers,
|
||||||
|
self.poll_handlers
|
||||||
])
|
])
|
||||||
filters_factory.bind(ContentTypeFilter, event_handlers=[
|
filters_factory.bind(ContentTypeFilter, event_handlers=[
|
||||||
self.message_handlers, self.edited_message_handlers,
|
self.message_handlers, self.edited_message_handlers,
|
||||||
|
|
@ -92,7 +94,7 @@ class Dispatcher(DataMixin, ContextInstanceMixin):
|
||||||
filters_factory.bind(Text, event_handlers=[
|
filters_factory.bind(Text, event_handlers=[
|
||||||
self.message_handlers, self.edited_message_handlers,
|
self.message_handlers, self.edited_message_handlers,
|
||||||
self.channel_post_handlers, self.edited_channel_post_handlers,
|
self.channel_post_handlers, self.edited_channel_post_handlers,
|
||||||
self.callback_query_handlers
|
self.callback_query_handlers, self.poll_handlers
|
||||||
])
|
])
|
||||||
filters_factory.bind(HashTag, event_handlers=[
|
filters_factory.bind(HashTag, event_handlers=[
|
||||||
self.message_handlers, self.edited_message_handlers,
|
self.message_handlers, self.edited_message_handlers,
|
||||||
|
|
@ -101,7 +103,7 @@ class Dispatcher(DataMixin, ContextInstanceMixin):
|
||||||
filters_factory.bind(Regexp, event_handlers=[
|
filters_factory.bind(Regexp, event_handlers=[
|
||||||
self.message_handlers, self.edited_message_handlers,
|
self.message_handlers, self.edited_message_handlers,
|
||||||
self.channel_post_handlers, self.edited_channel_post_handlers,
|
self.channel_post_handlers, self.edited_channel_post_handlers,
|
||||||
self.callback_query_handlers
|
self.callback_query_handlers, self.poll_handlers
|
||||||
])
|
])
|
||||||
filters_factory.bind(RegexpCommandsFilter, event_handlers=[
|
filters_factory.bind(RegexpCommandsFilter, event_handlers=[
|
||||||
self.message_handlers, self.edited_message_handlers
|
self.message_handlers, self.edited_message_handlers
|
||||||
|
|
@ -185,6 +187,8 @@ class Dispatcher(DataMixin, ContextInstanceMixin):
|
||||||
if update.pre_checkout_query:
|
if update.pre_checkout_query:
|
||||||
types.User.set_current(update.pre_checkout_query.from_user)
|
types.User.set_current(update.pre_checkout_query.from_user)
|
||||||
return await self.pre_checkout_query_handlers.notify(update.pre_checkout_query)
|
return await self.pre_checkout_query_handlers.notify(update.pre_checkout_query)
|
||||||
|
if update.poll:
|
||||||
|
return await self.poll_handlers.notify(update.poll)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
err = await self.errors_handlers.notify(update, e)
|
err = await self.errors_handlers.notify(update, e)
|
||||||
if err:
|
if err:
|
||||||
|
|
@ -796,6 +800,20 @@ class Dispatcher(DataMixin, ContextInstanceMixin):
|
||||||
|
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
def register_poll_handler(self, callback, *custom_filters, run_task=None, **kwargs):
|
||||||
|
filters_set = self.filters_factory.resolve(self.poll_handlers,
|
||||||
|
*custom_filters,
|
||||||
|
**kwargs)
|
||||||
|
self.poll_handlers.register(self._wrap_async_task(callback, run_task), filters_set)
|
||||||
|
|
||||||
|
def poll_handler(self, *custom_filters, run_task=None, **kwargs):
|
||||||
|
def decorator(callback):
|
||||||
|
self.register_poll_handler(callback, *custom_filters, run_task=run_task,
|
||||||
|
**kwargs)
|
||||||
|
return callback
|
||||||
|
|
||||||
|
return decorator
|
||||||
|
|
||||||
def register_errors_handler(self, callback, *custom_filters, exception=None, run_task=None, **kwargs):
|
def register_errors_handler(self, callback, *custom_filters, exception=None, run_task=None, **kwargs):
|
||||||
"""
|
"""
|
||||||
Register handler for errors
|
Register handler for errors
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ from babel.support import LazyProxy
|
||||||
|
|
||||||
from aiogram import types
|
from aiogram import types
|
||||||
from aiogram.dispatcher.filters.filters import BoundFilter, Filter
|
from aiogram.dispatcher.filters.filters import BoundFilter, Filter
|
||||||
from aiogram.types import CallbackQuery, Message, InlineQuery
|
from aiogram.types import CallbackQuery, Message, InlineQuery, Poll
|
||||||
from aiogram.utils.deprecated import warn_deprecated
|
from aiogram.utils.deprecated import warn_deprecated
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -164,10 +164,14 @@ class Text(Filter):
|
||||||
async def check(self, obj: Union[Message, CallbackQuery, InlineQuery]):
|
async def check(self, obj: Union[Message, CallbackQuery, InlineQuery]):
|
||||||
if isinstance(obj, Message):
|
if isinstance(obj, Message):
|
||||||
text = obj.text or obj.caption or ''
|
text = obj.text or obj.caption or ''
|
||||||
|
if not text and obj.poll:
|
||||||
|
text = obj.poll.question
|
||||||
elif isinstance(obj, CallbackQuery):
|
elif isinstance(obj, CallbackQuery):
|
||||||
text = obj.data
|
text = obj.data
|
||||||
elif isinstance(obj, InlineQuery):
|
elif isinstance(obj, InlineQuery):
|
||||||
text = obj.query
|
text = obj.query
|
||||||
|
elif isinstance(obj, Poll):
|
||||||
|
text = obj.question
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
@ -269,12 +273,16 @@ class Regexp(Filter):
|
||||||
|
|
||||||
async def check(self, obj: Union[Message, CallbackQuery]):
|
async def check(self, obj: Union[Message, CallbackQuery]):
|
||||||
if isinstance(obj, Message):
|
if isinstance(obj, Message):
|
||||||
match = self.regexp.search(obj.text or obj.caption or '')
|
content = obj.text or obj.caption or ''
|
||||||
|
if not content and obj.poll:
|
||||||
|
content = obj.poll.question
|
||||||
elif isinstance(obj, CallbackQuery) and obj.data:
|
elif isinstance(obj, CallbackQuery) and obj.data:
|
||||||
match = self.regexp.search(obj.data)
|
content = obj.data
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
match = self.regexp.search(content)
|
||||||
|
|
||||||
if match:
|
if match:
|
||||||
return {'regexp': match}
|
return {'regexp': match}
|
||||||
return False
|
return False
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ from .passport_element_error import PassportElementError, PassportElementErrorDa
|
||||||
PassportElementErrorSelfie
|
PassportElementErrorSelfie
|
||||||
from .passport_file import PassportFile
|
from .passport_file import PassportFile
|
||||||
from .photo_size import PhotoSize
|
from .photo_size import PhotoSize
|
||||||
|
from .poll import PollOptions, Poll
|
||||||
from .pre_checkout_query import PreCheckoutQuery
|
from .pre_checkout_query import PreCheckoutQuery
|
||||||
from .reply_keyboard import KeyboardButton, ReplyKeyboardMarkup, ReplyKeyboardRemove
|
from .reply_keyboard import KeyboardButton, ReplyKeyboardMarkup, ReplyKeyboardRemove
|
||||||
from .response_parameters import ResponseParameters
|
from .response_parameters import ResponseParameters
|
||||||
|
|
@ -142,6 +143,8 @@ __all__ = (
|
||||||
'PassportElementErrorSelfie',
|
'PassportElementErrorSelfie',
|
||||||
'PassportFile',
|
'PassportFile',
|
||||||
'PhotoSize',
|
'PhotoSize',
|
||||||
|
'Poll',
|
||||||
|
'PollOptions',
|
||||||
'PreCheckoutQuery',
|
'PreCheckoutQuery',
|
||||||
'ReplyKeyboardMarkup',
|
'ReplyKeyboardMarkup',
|
||||||
'ReplyKeyboardRemove',
|
'ReplyKeyboardRemove',
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ from .location import Location
|
||||||
from .message_entity import MessageEntity
|
from .message_entity import MessageEntity
|
||||||
from .passport_data import PassportData
|
from .passport_data import PassportData
|
||||||
from .photo_size import PhotoSize
|
from .photo_size import PhotoSize
|
||||||
|
from .poll import Poll
|
||||||
from .sticker import Sticker
|
from .sticker import Sticker
|
||||||
from .successful_payment import SuccessfulPayment
|
from .successful_payment import SuccessfulPayment
|
||||||
from .user import User
|
from .user import User
|
||||||
|
|
@ -81,6 +82,7 @@ class Message(base.TelegramObject):
|
||||||
successful_payment: SuccessfulPayment = fields.Field(base=SuccessfulPayment)
|
successful_payment: SuccessfulPayment = fields.Field(base=SuccessfulPayment)
|
||||||
connected_website: base.String = fields.Field()
|
connected_website: base.String = fields.Field()
|
||||||
passport_data: PassportData = fields.Field(base=PassportData)
|
passport_data: PassportData = fields.Field(base=PassportData)
|
||||||
|
poll: Poll = fields.Field(base=Poll)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@functools.lru_cache()
|
@functools.lru_cache()
|
||||||
|
|
@ -137,6 +139,8 @@ class Message(base.TelegramObject):
|
||||||
return ContentType.GROUP_CHAT_CREATED
|
return ContentType.GROUP_CHAT_CREATED
|
||||||
elif self.passport_data:
|
elif self.passport_data:
|
||||||
return ContentType.PASSPORT_DATA
|
return ContentType.PASSPORT_DATA
|
||||||
|
elif self.poll:
|
||||||
|
return ContentType.POLL
|
||||||
else:
|
else:
|
||||||
return ContentType.UNKNOWN
|
return ContentType.UNKNOWN
|
||||||
|
|
||||||
|
|
@ -1539,6 +1543,7 @@ class ContentType(helper.Helper):
|
||||||
DELETE_CHAT_PHOTO = helper.Item() # delete_chat_photo
|
DELETE_CHAT_PHOTO = helper.Item() # delete_chat_photo
|
||||||
GROUP_CHAT_CREATED = helper.Item() # group_chat_created
|
GROUP_CHAT_CREATED = helper.Item() # group_chat_created
|
||||||
PASSPORT_DATA = helper.Item() # passport_data
|
PASSPORT_DATA = helper.Item() # passport_data
|
||||||
|
POLL = helper.Item()
|
||||||
|
|
||||||
UNKNOWN = helper.Item() # unknown
|
UNKNOWN = helper.Item() # unknown
|
||||||
ANY = helper.Item() # any
|
ANY = helper.Item() # any
|
||||||
|
|
@ -1600,6 +1605,7 @@ class ContentTypes(helper.Helper):
|
||||||
DELETE_CHAT_PHOTO = helper.ListItem() # delete_chat_photo
|
DELETE_CHAT_PHOTO = helper.ListItem() # delete_chat_photo
|
||||||
GROUP_CHAT_CREATED = helper.ListItem() # group_chat_created
|
GROUP_CHAT_CREATED = helper.ListItem() # group_chat_created
|
||||||
PASSPORT_DATA = helper.ListItem() # passport_data
|
PASSPORT_DATA = helper.ListItem() # passport_data
|
||||||
|
POLL = helper.ListItem()
|
||||||
|
|
||||||
UNKNOWN = helper.ListItem() # unknown
|
UNKNOWN = helper.ListItem() # unknown
|
||||||
ANY = helper.ListItem() # any
|
ANY = helper.ListItem() # any
|
||||||
|
|
|
||||||
16
aiogram/types/poll.py
Normal file
16
aiogram/types/poll.py
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
import typing
|
||||||
|
|
||||||
|
from . import base
|
||||||
|
from . import fields
|
||||||
|
|
||||||
|
|
||||||
|
class PollOptions(base.TelegramObject):
|
||||||
|
text: base.String = fields.Field()
|
||||||
|
voter_count: base.Integer = fields.Field()
|
||||||
|
|
||||||
|
|
||||||
|
class Poll(base.TelegramObject):
|
||||||
|
id: base.String = fields.Field()
|
||||||
|
question: base.String = fields.Field()
|
||||||
|
options: typing.List[PollOptions] = fields.ListField(base=PollOptions)
|
||||||
|
is_closed: base.Boolean = fields.Field()
|
||||||
|
|
@ -6,6 +6,7 @@ from .callback_query import CallbackQuery
|
||||||
from .chosen_inline_result import ChosenInlineResult
|
from .chosen_inline_result import ChosenInlineResult
|
||||||
from .inline_query import InlineQuery
|
from .inline_query import InlineQuery
|
||||||
from .message import Message
|
from .message import Message
|
||||||
|
from .poll import Poll
|
||||||
from .pre_checkout_query import PreCheckoutQuery
|
from .pre_checkout_query import PreCheckoutQuery
|
||||||
from .shipping_query import ShippingQuery
|
from .shipping_query import ShippingQuery
|
||||||
from ..utils import helper
|
from ..utils import helper
|
||||||
|
|
@ -28,6 +29,7 @@ class Update(base.TelegramObject):
|
||||||
callback_query: CallbackQuery = fields.Field(base=CallbackQuery)
|
callback_query: CallbackQuery = fields.Field(base=CallbackQuery)
|
||||||
shipping_query: ShippingQuery = fields.Field(base=ShippingQuery)
|
shipping_query: ShippingQuery = fields.Field(base=ShippingQuery)
|
||||||
pre_checkout_query: PreCheckoutQuery = fields.Field(base=PreCheckoutQuery)
|
pre_checkout_query: PreCheckoutQuery = fields.Field(base=PreCheckoutQuery)
|
||||||
|
poll: Poll = fields.Field(base=Poll)
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return self.update_id
|
return self.update_id
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,16 @@ TelegramAPIError
|
||||||
MessageNotModified
|
MessageNotModified
|
||||||
MessageToForwardNotFound
|
MessageToForwardNotFound
|
||||||
MessageToDeleteNotFound
|
MessageToDeleteNotFound
|
||||||
|
MessageWithPollNotFound
|
||||||
|
MessageIsNotAPoll
|
||||||
MessageIdentifierNotSpecified
|
MessageIdentifierNotSpecified
|
||||||
MessageTextIsEmpty
|
MessageTextIsEmpty
|
||||||
MessageCantBeEdited
|
MessageCantBeEdited
|
||||||
MessageCantBeDeleted
|
MessageCantBeDeleted
|
||||||
MessageToEditNotFound
|
MessageToEditNotFound
|
||||||
ToMuchMessages
|
ToMuchMessages
|
||||||
|
PollCantBeStopped
|
||||||
|
PollHasAlreadyClosed
|
||||||
ObjectExpectedAsReplyMarkup
|
ObjectExpectedAsReplyMarkup
|
||||||
InlineKeyboardExpected
|
InlineKeyboardExpected
|
||||||
ChatNotFound
|
ChatNotFound
|
||||||
|
|
@ -164,6 +168,20 @@ class MessageToDeleteNotFound(MessageError):
|
||||||
match = 'message to delete not found'
|
match = 'message to delete not found'
|
||||||
|
|
||||||
|
|
||||||
|
class MessageWithPollNotFound(MessageError):
|
||||||
|
"""
|
||||||
|
Will be raised when you try to stop poll with message without poll
|
||||||
|
"""
|
||||||
|
match = 'message with poll to stop not found'
|
||||||
|
|
||||||
|
|
||||||
|
class MessageIsNotAPoll(MessageError):
|
||||||
|
"""
|
||||||
|
Will be raised when you try to stop poll with message without poll
|
||||||
|
"""
|
||||||
|
match = 'message is not a poll'
|
||||||
|
|
||||||
|
|
||||||
class MessageIdentifierNotSpecified(MessageError):
|
class MessageIdentifierNotSpecified(MessageError):
|
||||||
match = 'message identifier is not specified'
|
match = 'message identifier is not specified'
|
||||||
|
|
||||||
|
|
@ -203,6 +221,14 @@ class InlineKeyboardExpected(BadRequest):
|
||||||
match = 'inline keyboard expected'
|
match = 'inline keyboard expected'
|
||||||
|
|
||||||
|
|
||||||
|
class PollCantBeStopped(BadRequest):
|
||||||
|
match = "poll can't be stopped"
|
||||||
|
|
||||||
|
|
||||||
|
class PollHasAlreadyBeenClosed(BadRequest):
|
||||||
|
match = 'poll has already been closed'
|
||||||
|
|
||||||
|
|
||||||
class ChatNotFound(BadRequest):
|
class ChatNotFound(BadRequest):
|
||||||
match = 'chat not found'
|
match = 'chat not found'
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue