Telethon/telethon/_events/inlinequery.py

201 lines
6.3 KiB
Python
Raw Normal View History

2018-07-15 12:31:14 +03:00
import inspect
import re
import asyncio
from .base import EventBuilder
2021-09-12 14:27:13 +03:00
from .._misc import utils
from .. import _tl
2021-09-12 17:58:06 +03:00
from ..types import _custom
2018-07-15 12:31:14 +03:00
class InlineQuery(EventBuilder, _custom.chatgetter.ChatGetter, _custom.sendergetter.SenderGetter):
2018-07-15 12:31:14 +03:00
"""
Occurs whenever you sign in as a bot and a user
sends an inline query such as ``@bot query``.
2018-07-15 12:31:14 +03:00
Members:
query (:tl:`UpdateBotInlineQuery`):
The original :tl:`UpdateBotInlineQuery`.
2018-07-15 12:31:14 +03:00
Make sure to access the `text` property of the query if
you want the text rather than the actual query object.
2018-07-15 12:31:14 +03:00
pattern_match (`obj`, optional):
The resulting object from calling the passed ``pattern``
function, which is ``re.compile(...).match`` by default.
2020-02-20 12:18:26 +03:00
Example
.. code-block:: python
from telethon import events
@client.on(events.InlineQuery)
async def handler(event):
builder = event.builder
# Two options (convert user text to UPPERCASE or lowercase)
await event.answer([
builder.article('UPPERCASE', text=event.text.upper()),
builder.article('lowercase', text=event.text.lower()),
])
2018-07-15 12:31:14 +03:00
"""
@classmethod
def _build(cls, client, update, entities):
if not isinstance(update, _tl.UpdateBotInlineQuery):
return None
self = cls.__new__(cls)
self._client = client
self._sender = entities.get(_tl.PeerUser(update.user_id))
self._chat = entities.get(_tl.PeerUser(update.user_id))
self.query = update
self.pattern_match = None
self._answered = False
return self
2018-07-15 12:31:14 +03:00
@property
def id(self):
"""
Returns the unique identifier for the query ID.
"""
return self.query.query_id
2018-07-15 12:31:14 +03:00
@property
def text(self):
"""
Returns the text the user used to make the inline query.
2018-07-15 12:31:14 +03:00
"""
return self.query.query
2018-07-15 12:31:14 +03:00
@property
def offset(self):
"""
The string the user's client used as an offset for the query.
This will either be empty or equal to offsets passed to `answer`.
"""
return self.query.offset
2018-07-15 12:31:14 +03:00
@property
def geo(self):
"""
If the user location is requested when using inline mode
and the user's device is able to send it, this will return
the :tl:`GeoPoint` with the position of the user.
"""
return self.query.geo
2018-10-12 13:38:46 +03:00
@property
def builder(self):
2018-07-15 12:31:14 +03:00
"""
Returns a new `InlineBuilder
<telethon.tl.custom.inlinebuilder.InlineBuilder>` instance.
See the documentation for `builder` to know what kind of answers
can be given.
"""
return _custom.InlineBuilder(self._client)
async def answer(
self, results=None, cache_time=0, *,
gallery=False, next_offset=None, private=False,
switch_pm=None, switch_pm_param=''):
"""
Answers the inline query with the given results.
Args:
results (`list`, optional):
A list of :tl:`InputBotInlineResult` to use.
You should use `builder` to create these:
2019-05-09 13:24:37 +03:00
.. code-block:: python
builder = inline.builder
r1 = builder.article('Be nice', text='Have a nice day')
r2 = builder.article('Be bad', text="I don't like you")
await inline.answer([r1, r2])
You can send up to 50 results as documented in
https://core.telegram.org/bots/api#answerinlinequery.
Sending more will raise ``ResultsTooMuchError``,
and you should consider using `next_offset` to
paginate them.
cache_time (`int`, optional):
For how long this result should be cached on
the user's client. Defaults to 0 for no cache.
gallery (`bool`, optional):
Whether the results should show as a gallery (grid) or not.
next_offset (`str`, optional):
The offset the client will send when the user scrolls the
results and it repeats the request.
private (`bool`, optional):
Whether the results should be cached by Telegram
(not private) or by the user's client (private).
switch_pm (`str`, optional):
If set, this text will be shown in the results
to allow the user to switch to private messages.
switch_pm_param (`str`, optional):
Optional parameter to start the bot with if
`switch_pm` was used.
Example:
.. code-block:: python
@bot.on(events.InlineQuery)
async def handler(event):
builder = event.builder
rev_text = event.text[::-1]
await event.answer([
builder.article('Reverse text', text=rev_text),
builder.photo('/path/to/photo.jpg')
])
"""
if self._answered:
return
if results:
futures = [self._as_future(x) for x in results]
await asyncio.wait(futures)
# All futures will be in the `done` *set* that `wait` returns.
#
# Precisely because it's a `set` and not a `list`, it
# will not preserve the order, but since all futures
# completed we can use our original, ordered `list`.
results = [x.result() for x in futures]
else:
results = []
if switch_pm:
switch_pm = _tl.InlineBotSwitchPM(switch_pm, switch_pm_param)
return await self._client(
_tl.fn.messages.SetInlineBotResults(
query_id=self.query.query_id,
results=results,
cache_time=cache_time,
gallery=gallery,
next_offset=next_offset,
private=private,
switch_pm=switch_pm
2018-07-15 12:31:14 +03:00
)
)
2018-07-15 12:31:14 +03:00
@staticmethod
def _as_future(obj):
if inspect.isawaitable(obj):
return asyncio.ensure_future(obj)
2018-07-15 12:31:14 +03:00
f = asyncio.get_running_loop().create_future()
f.set_result(obj)
return f