X Tutup
Skip to content

Commit c69cdfd

Browse files
committed
Initial commit for inline bot support
1 parent 71f82d5 commit c69cdfd

File tree

12 files changed

+818
-15
lines changed

12 files changed

+818
-15
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
telegram.choseninlineresult module
2+
==================================
3+
4+
.. automodule:: telegram.choseninlineresult
5+
:members:
6+
:undoc-members:
7+
:show-inheritance:
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
telegram.inlinequery module
2+
===========================
3+
4+
.. automodule:: telegram.inlinequery
5+
:members:
6+
:undoc-members:
7+
:show-inheritance:
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
telegram.inlinequeryresult module
2+
=================================
3+
4+
.. automodule:: telegram.inlinequeryresult
5+
:members:
6+
:undoc-members:
7+
:show-inheritance:

docs/source/telegram.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ Submodules
1212
telegram.updater
1313
telegram.dispatcher
1414
telegram.jobqueue
15+
telegram.inlinequery
16+
telegram.inlinequeryresult
17+
telegram.choseninlineresult
1518
telegram.chataction
1619
telegram.contact
1720
telegram.document

examples/inlinebot.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
#
4+
# Simple Bot to reply to Telegram messages
5+
# This program is dedicated to the public domain under the CC0 license.
6+
7+
"""
8+
This Bot uses the Updater class to handle the bot.
9+
10+
First, a few handler functions are defined. Then, those functions are passed to
11+
the Dispatcher and registered at their respective places.
12+
Then, the bot is started and runs until we press Ctrl-C on the command line.
13+
14+
Usage:
15+
Basic inline bot example. Applies different text transformations.
16+
Press Ctrl-C on the command line or send a signal to the process to stop the
17+
bot.
18+
"""
19+
from random import getrandbits
20+
21+
import re
22+
23+
from telegram import Updater, Update, InlineQueryResultArticle, ParseMode
24+
import logging
25+
26+
# Enable logging
27+
logging.basicConfig(
28+
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
29+
level=logging.INFO)
30+
31+
logger = logging.getLogger(__name__)
32+
33+
34+
# Define a few command handlers. These usually take the two arguments bot and
35+
# update. Error handlers also receive the raised TelegramError object in error.
36+
def start(bot, update):
37+
bot.sendMessage(update.message.chat_id, text='Hi!')
38+
39+
40+
def help(bot, update):
41+
bot.sendMessage(update.message.chat_id, text='Help!')
42+
43+
44+
def escape_markdown(text):
45+
"""Helper function to escape telegram markup symbols"""
46+
escape_chars = '\*_`\['
47+
return re.sub(r'([%s])' % escape_chars, r'\\\1', text)
48+
49+
50+
def inlinequery(bot, update):
51+
if update.inline_query is not None and update.inline_query.query:
52+
query = update.inline_query.query
53+
results = list()
54+
55+
results.append(InlineQueryResultArticle(
56+
id=hex(getrandbits(64))[2:],
57+
title="Caps",
58+
message_text=query.upper()))
59+
60+
results.append(InlineQueryResultArticle(
61+
id=hex(getrandbits(64))[2:],
62+
title="Bold",
63+
message_text="*%s*" % escape_markdown(query),
64+
parse_mode=ParseMode.MARKDOWN))
65+
66+
results.append(InlineQueryResultArticle(
67+
id=hex(getrandbits(64))[2:],
68+
title="Italic",
69+
message_text="_%s_" % escape_markdown(query),
70+
parse_mode=ParseMode.MARKDOWN))
71+
72+
bot.answerInlineQuery(update.inline_query.id, results=results)
73+
74+
75+
76+
def error(bot, update, error):
77+
logger.warn('Update "%s" caused error "%s"' % (update, error))
78+
79+
80+
def main():
81+
# Create the Updater and pass it your bot's token.
82+
updater = Updater("TOKEN")
83+
84+
# Get the dispatcher to register handlers
85+
dp = updater.dispatcher
86+
87+
# on different commands - answer in Telegram
88+
dp.addTelegramCommandHandler("start", start)
89+
dp.addTelegramCommandHandler("help", help)
90+
91+
# on noncommand i.e message - echo the message on Telegram
92+
dp.addTelegramInlineHandler(inlinequery)
93+
94+
# log all errors
95+
dp.addErrorHandler(error)
96+
97+
# Start the Bot
98+
updater.start_polling()
99+
100+
# Block until the user presses Ctrl-C or the process receives SIGINT,
101+
# SIGTERM or SIGABRT. This should be used most of the time, since
102+
# start_polling() is non-blocking and will stop the bot gracefully.
103+
updater.idle()
104+
105+
if __name__ == '__main__':
106+
main()

telegram/__init__.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@
4646
from .emoji import Emoji
4747
from .parsemode import ParseMode
4848
from .message import Message
49+
from .inlinequery import InlineQuery
50+
from .choseninlineresult import ChosenInlineResult
51+
from .inlinequeryresult import InlineQueryResultArticle, InlineQueryResultGif,\
52+
InlineQueryResultMpeg4Gif, InlineQueryResultPhoto, InlineQueryResultVideo
4953
from .update import Update
5054
from .bot import Bot
5155
from .dispatcher import Dispatcher
@@ -57,4 +61,7 @@
5761
'ReplyKeyboardMarkup', 'UserProfilePhotos', 'ChatAction',
5862
'Location', 'Contact', 'Video', 'Sticker', 'Document', 'File',
5963
'Audio', 'PhotoSize', 'Chat', 'Update', 'ParseMode', 'Message',
60-
'User', 'TelegramObject', 'NullHandler', 'Voice', 'JobQueue']
64+
'User', 'TelegramObject', 'NullHandler', 'Voice', 'JobQueue',
65+
'InlineQuery', 'ChosenInlineResult', 'InlineQueryResultArticle',
66+
'InlineQueryResultGif', 'InlineQueryResultPhoto',
67+
'InlineQueryResultMpeg4Gif', 'InlineQueryResultVideo']

telegram/bot.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,56 @@ def sendChatAction(self,
584584

585585
return url, data
586586

587+
@log
588+
def answerInlineQuery(self,
589+
inline_query_id,
590+
results,
591+
cache_time=None,
592+
is_personal=None,
593+
next_offset=None):
594+
"""Use this method to reply to an inline query.
595+
596+
Args:
597+
inline_query_id (int):
598+
Unique identifier for answered query
599+
results (list[InlineQueryResult]):
600+
A list of results for the inline query
601+
602+
Keyword Args:
603+
cache_time (Optional[int]): The maximum amount of time the result
604+
of the inline query may be cached on the server
605+
is_personal (Optional[bool]): Pass True, if results may be cached
606+
on the server side only for the user that sent the query. By
607+
default, results may be returned to any user who sends the same
608+
query
609+
next_offset (Optional[str]): Pass the offset that a client should
610+
send in the next query with the same text to receive more
611+
results. Pass an empty string if there are no more results or
612+
if you don't support pagination. Offset length can't exceed 64
613+
bytes.
614+
615+
Returns:
616+
A boolean if answering was successful
617+
"""
618+
619+
url = '%s/answerInlineQuery' % self.base_url
620+
621+
results = [res.to_dict() for res in results]
622+
623+
data = {'inline_query_id': inline_query_id,
624+
'results': results}
625+
626+
if cache_time is not None:
627+
data['cache_time'] = cache_time
628+
if is_personal is not None:
629+
data['is_personal'] = is_personal
630+
if next_offset is not None:
631+
data['next_offset'] = next_offset
632+
633+
result = request.post(url, data)
634+
635+
return result
636+
587637
@log
588638
def getUserProfilePhotos(self,
589639
user_id,

telegram/choseninlineresult.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#!/usr/bin/env python
2+
# pylint: disable=R0902,R0912,R0913
3+
#
4+
# A library that provides a Python interface to the Telegram Bot API
5+
# Copyright (C) 2015 Leandro Toledo de Souza <devs@python-telegram-bot.org>
6+
#
7+
# This program is free software: you can redistribute it and/or modify
8+
# it under the terms of the GNU Lesser Public License as published by
9+
# the Free Software Foundation, either version 3 of the License, or
10+
# (at your option) any later version.
11+
#
12+
# This program is distributed in the hope that it will be useful,
13+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
# GNU Lesser Public License for more details.
16+
#
17+
# You should have received a copy of the GNU Lesser Public License
18+
# along with this program. If not, see [http://www.gnu.org/licenses/].
19+
20+
"""
21+
This module contains a object that represents a Telegram ChosenInlineResult
22+
"""
23+
24+
25+
from telegram import TelegramObject
26+
27+
28+
class ChosenInlineResult(TelegramObject):
29+
"""This object represents a Telegram ChosenInlineResult.
30+
31+
Note:
32+
* In Python `from` is a reserved word, use `from_user` instead.
33+
34+
Attributes:
35+
result_id (int):
36+
from_user (:class:`telegram.User`):
37+
query (str):
38+
39+
Args:
40+
result_id (int):
41+
from_user (:class:`telegram.User`):
42+
query (str):
43+
44+
"""
45+
46+
def __init__(self,
47+
result_id,
48+
from_user,
49+
query):
50+
# Required
51+
self.result_id = int(result_id)
52+
self.from_user = from_user
53+
self.query = query
54+
55+
@staticmethod
56+
def de_json(data):
57+
"""
58+
Args:
59+
data (dict):
60+
61+
Returns:
62+
telegram.ChosenInlineResult:
63+
"""
64+
if not data:
65+
return None
66+
67+
return ChosenInlineResult(**data)
68+
69+
def to_dict(self):
70+
"""
71+
Returns:
72+
dict:
73+
"""
74+
data = super(ChosenInlineResult, self).to_dict()
75+
76+
# Required
77+
data['from'] = data.pop('from_user', None)
78+
79+
return data

telegram/dispatcher.py

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ def __init__(self, bot, update_queue, workers=4):
130130
self.bot = bot
131131
self.update_queue = update_queue
132132
self.telegram_message_handlers = []
133+
self.telegram_inline_handlers = []
133134
self.telegram_command_handlers = {}
134135
self.telegram_regex_handlers = {}
135136
self.string_regex_handlers = {}
@@ -236,21 +237,23 @@ def processUpdate(self, update):
236237
handled = True
237238

238239
# Telegram update (regex)
239-
if isinstance(update, Update):
240+
if isinstance(update, Update) and update.message is not None:
240241
self.dispatchRegex(update)
241242
handled = True
242243

243-
# Telegram update (command)
244-
if isinstance(update, Update) \
245-
and update.message.text.startswith('/'):
246-
self.dispatchTelegramCommand(update)
247-
handled = True
248-
249-
# Telegram update (message)
250-
elif isinstance(update, Update):
251-
self.dispatchTelegramMessage(update)
252-
handled = True
244+
# Telegram update (command)
245+
if update.message.text.startswith('/'):
246+
self.dispatchTelegramCommand(update)
253247

248+
# Telegram update (message)
249+
else:
250+
self.dispatchTelegramMessage(update)
251+
handled = True
252+
elif isinstance(update, Update) and \
253+
(update.inline_query is not None or
254+
update.chosen_inline_result is not None):
255+
self.dispatchTelegramInline(update)
256+
handled = True
254257
# Update not recognized
255258
if not handled:
256259
self.dispatchError(update, TelegramError(
@@ -268,6 +271,17 @@ def addTelegramMessageHandler(self, handler):
268271

269272
self.telegram_message_handlers.append(handler)
270273

274+
def addTelegramInlineHandler(self, handler):
275+
"""
276+
Registers an inline query handler in the Dispatcher.
277+
278+
Args:
279+
handler (function): A function that takes (Bot, Update, *args) as
280+
arguments.
281+
"""
282+
283+
self.telegram_inline_handlers.append(handler)
284+
271285
def addTelegramCommandHandler(self, command, handler):
272286
"""
273287
Registers a command handler in the Dispatcher.
@@ -397,6 +411,17 @@ def removeTelegramMessageHandler(self, handler):
397411
if handler in self.telegram_message_handlers:
398412
self.telegram_message_handlers.remove(handler)
399413

414+
def removeTelegramInlineHandler(self, handler):
415+
"""
416+
De-registers an inline query handler.
417+
418+
Args:
419+
handler (any):
420+
"""
421+
422+
if handler in self.telegram_inline_handlers:
423+
self.telegram_inline_handlers.remove(handler)
424+
400425
def removeTelegramCommandHandler(self, command, handler):
401426
"""
402427
De-registers a command handler.
@@ -574,6 +599,17 @@ def dispatchTelegramMessage(self, update):
574599

575600
self.dispatchTo(self.telegram_message_handlers, update)
576601

602+
def dispatchTelegramInline(self, update):
603+
"""
604+
Dispatches an update that contains an inline update.
605+
606+
Args:
607+
update (telegram.Update): The Telegram update that contains the
608+
message.
609+
"""
610+
611+
self.dispatchTo(self.telegram_inline_handlers, update)
612+
577613
def dispatchError(self, update, error):
578614
"""
579615
Dispatches an error.

0 commit comments

Comments
 (0)
X Tutup