1
0
mirror of https://github.com/eternnoir/pyTelegramBotAPI.git synced 2023-08-10 21:12:57 +03:00

Compare commits

...

51 Commits
2.0.5 ... 2.1.3

Author SHA1 Message Date
25ad3f055f Update version.
Change log:
- Added new methods: getChat, leaveChat, getChatAdministrators,
  getChatMember, getChatMembersCount.
- New fields: edited_message in Update, edit_date in Message, user in
  MessageEntity. New value text_mention for the type field in
MessageEntity.
2016-06-07 19:57:40 +08:00
cdb6d6760d Add some comment. 2016-06-07 19:44:30 +08:00
5bd8e9d3f5 Update readme. 2016-06-07 19:40:35 +08:00
fab2f324d0 Fix test case. 2016-06-07 19:34:46 +08:00
9bf4be2caf fix test case. 2016-06-07 19:32:12 +08:00
d701fd6e1d Merge remote-tracking branch 'origin/feature-changes20160522' into api2.1 2016-06-07 19:30:01 +08:00
8e3c9d8d24 Add edited message handler. 2016-06-07 19:29:12 +08:00
0b9f91c6fb Add new method test case. 2016-06-07 19:16:17 +08:00
468a535257 Fix de_json. 2016-06-07 19:08:52 +08:00
d2e7f4d8f2 Add 2.1 new method. 2016-06-07 19:00:44 +08:00
ddd3664329 Merge pull request #192 from alejandrocq/comedoresugrbot
Add ComedoresUGRbot to bots list.
2016-06-06 01:32:45 +08:00
9e397c41cf ComedoresUGRbot added to bots list. 2016-06-05 19:20:17 +02:00
b528b0bcf0 Merge pull request #191 from Ledokol/uni-json
unicode strings for check_json
2016-06-05 18:36:36 +08:00
2f20d70e89 unicode strings for check_json 2016-06-04 21:18:09 +05:00
ac740e4755 Change public link to invite link. 2016-06-03 17:21:33 +08:00
2cf8ffcbc0 Update group link. 2016-06-03 14:45:25 +08:00
87ad4a62ff Merge pull request #187 from GabrielRF/master
Added Send2KindleBot
2016-06-03 00:06:10 +08:00
6b255deed7 Added Send2KindleBot
Also added description of urlprobot and lmgtfy_bot
2016-06-02 12:04:04 -03:00
ce24aa25f2 Fix #179. 2016-06-02 13:25:50 +08:00
a0f25089e0 Merge pull request #177 from qwidim/master
heroku webhook example
2016-06-02 13:17:12 +08:00
1bfdf7cf35 Merge pull request #173 from dmcelectrico/master
Added optional connection (aka sending) timeouts to methods that may …
2016-05-31 02:11:31 +08:00
5b1de9f339 Merge pull request #181 from PowerInside/patch-1
Fix inline demo code in readme.md
2016-05-29 22:29:21 +08:00
e956800e34 Fix inline demo code in readme.md 2016-05-29 19:25:36 +05:30
b9a57f630a Merge pull request #178 from Kondra007/patch-5
Update Readme.md
2016-05-26 11:02:30 +08:00
851d76888b Update Readme.md
Added `user` to attributes list
2016-05-26 00:44:39 +03:00
05f1c87c7d Update webhook_flask_heroku_echo.py 2016-05-25 19:25:46 +06:00
59b19fbbc1 Update webhook_flask_heroku_echo.py 2016-05-25 19:15:13 +06:00
e87907f0b8 Update webhook_flask_heroku_echo.py 2016-05-25 01:44:09 +06:00
d84aa796c0 Add files via upload 2016-05-25 01:42:25 +06:00
8c20f63022 Add user to MessageEntity. 2016-05-23 11:12:20 +08:00
f9c7497c5c Merge branch 'Kondra007-patch-3' into feature-changes20160522 2016-05-23 11:05:14 +08:00
3413669a23 Added optional connection (aka sending) timeouts to methods that may upload big chunks of data: send_audio, send_voice, send_document, send_sticker and send_video. 2016-05-22 18:35:20 +02:00
1a45b4844a Fixed Travis build (again)
Yeah, I'm really sorry for all this errors, maybe tired a little bit.
2016-05-22 15:47:44 +03:00
8a9d89591b Fixed Travis build errors 2016-05-22 15:44:04 +03:00
234dd8cf9f Edited edit_date field
It's integer, not `Message`
2016-05-22 13:55:54 +03:00
6a98d27f1a Added edited_message to Update object
As of Bot API update 2.1, Update object now has optional edited_message field.
2016-05-22 13:35:21 +03:00
04df139efb Added edit_date to Message object
As of Bot API update 2.1, `Message` object now has optional `edit_date` field.
2016-05-22 13:32:53 +03:00
747f14216b Merge pull request #166 from Kondra007/patch-1
Changed "Process_new_message" to "Process_new_update"
2016-05-20 23:23:10 +08:00
aee9255568 Changed "Process_new_message" to "Process_new_update"
This way all types of queries (Message, Inline query, Callback query) are supported.
2016-05-20 17:40:22 +03:00
fbaf88c237 Update version. 2016-05-20 14:41:00 +08:00
3ebc47de8b Add missing title in InlineQueryResultVenue. #165 2016-05-20 14:39:34 +08:00
8017c8d919 Fix failing build for python 3.3, 3.4 and pypy3 2016-05-19 10:18:00 +02:00
2545724a6f Fix #164 2016-05-19 10:02:59 +02:00
b8770e2c04 Merge pull request #163 from agentik-007/patch-1
Update webhook_flask_echo_bot.py
2016-05-17 08:41:34 +08:00
1da5d1e0e2 Update webhook_flask_echo_bot.py 2016-05-16 14:31:36 +03:00
bc73f345b2 Update README.md 2016-05-15 09:40:56 +08:00
a824ff967b Version update. 2016-05-12 11:39:50 +08:00
0c420ee5e4 Add missing title to InlineQueryResultLocation to_json.
Fix #160
2016-05-12 11:09:21 +08:00
16838c30b6 Update version.
Change log:
- Added the field emoji to the Sticker.
- Added the field forward_from_chat to the Message object for messages
  forwarded from channels.
2016-05-08 18:45:21 +08:00
022cdada49 Merge pull request #157 from Kondra007/patch-6
Added 06.05.16 updates
2016-05-08 10:45:28 +08:00
fb1052824c Added 06.05.16 updates
* Added the field emoji to the Sticker object. Your bot can now know the emoji a sticker corresponds to.
* Added the field forwarded_from_chat to the Message object for messages forwarded from channels.
2016-05-07 20:24:16 +03:00
9 changed files with 282 additions and 38 deletions

View File

@ -197,6 +197,10 @@ def send_something(message):
```
**Important: all handlers are tested in the order in which they were declared**
#### Edited Message handlers
Same as Message handlers
#### Callback Query Handler
In bot2.0 update. You can get `callback_query` in update object. In telebot use `callback_query_handler` to process callback_querys.
@ -379,13 +383,28 @@ def test_chosen(chosen_inline_result):
@bot.inline_handler(lambda query: query.query == 'text')
def query_text(inline_query):
try:
r = types.InlineQueryResultArticle('1', 'Result', 'Result message.')
r2 = types.InlineQueryResultArticle('2', 'Result2', 'Result message2.')
r = types.InlineQueryResultArticle('1', 'Result', types.InputTextMessageContent('Result message.'))
r2 = types.InlineQueryResultArticle('2', 'Result2', types.InputTextMessageContent('Result message2.'))
bot.answer_inline_query(inline_query.id, [r, r2])
except Exception as e:
print(e)
```
###Working with entities:
This object represents one special entity in a text message. For example, hashtags, usernames, URLs, etc.
Attributes:
* `type`
* `url`
* `offset`
* `length`
* `user`
**Here's an Example:**`message.entities[num].<attribute>`<br>
Here `num` is the entity number or order of entity in a reply, for if incase there are multiple entities in the reply/message.<br>
`message.entities` returns a list of entities object. <br>
`message.entities[0].type` would give the type of the first entity<br>
Refer [Bot Api](https://core.telegram.org/bots/api#messageentity) for extra details
## Advanced use of the API
@ -490,8 +509,7 @@ if message.chat.type == “channel”:
Get help. Discuss. Chat.
* Join the pyTelegramBotAPI Telegram Chat Group
* Messge to @eternnoir by telegram for Invitation.
* Join the [pyTelegramBotAPI Telegram Chat Group](https://telegram.me/joinchat/Bn4ixj84FIZVkwhk2jag6A)
* We now have a Telegram Channel as well! Keep yourself up to date with API changes, and [join it](https://telegram.me/pytelegrambotapi).
## More examples
@ -503,13 +521,15 @@ Get help. Discuss. Chat.
## Bots using this API
* [SiteAlert bot](https://telegram.me/SiteAlert_bot) ([source](https://github.com/ilteoood/SiteAlert-Python)) by *ilteoood* - Monitors websites and sends a notification on changes
* [TelegramLoggingBot](https://github.com/aRandomStranger/TelegramLoggingBot) by *aRandomStranger*
* [Telegram LMGTFY_bot](https://github.com/GabrielRF/telegram-lmgtfy_bot) by *GabrielRF*
* [Telegram UrlProBot](https://github.com/GabrielRF/telegram-urlprobot) by *GabrielRF*
* [Send to Kindle Bot](https://telegram.me/Send2KindleBot) by *GabrielRF* - Send to Kindle files or links to files.
* [Telegram LMGTFY_bot](https://github.com/GabrielRF/telegram-lmgtfy_bot) ([source](https://github.com/GabrielRF/telegram-lmgtfy_bot)) by *GabrielRF* - Let me Google that for you.
* [Telegram UrlProBot](https://github.com/GabrielRF/telegram-urlprobot) ([source](https://github.com/GabrielRF/telegram-urlprobot)) by *GabrielRF* - URL shortener and URL expander.
* [Telegram Proxy Bot](https://bitbucket.org/master_groosha/telegram-proxy-bot) by *Groosha* - A simple BITM (bot-in-the-middle) for Telegram acting as some kind of "proxy".
* [Telegram Proxy Bot](https://github.com/mrgigabyte/proxybot) by *mrgigabyte* - `Credits for the original version of this bot goes to` **Groosha** `, simply added certain features which I thought were needed`.
* [RadRetroRobot](https://github.com/Tronikart/RadRetroRobot) by *Tronikart* - Multifunctional Telegram Bot RadRetroRobot.
* [League of Legends bot](https://telegram.me/League_of_Legends_bot) ([source](https://github.com/i32ropie/lol)) by *i32ropie*
* [NeoBot](https://github.com/neoranger/NeoBot) by *neoranger*
* [TagAlertBot](https://github.com/pitasi/TagAlertBot) by *pitasi*
* [ComedoresUGRbot](http://telegram.me/ComedoresUGRbot) ([source](https://github.com/alejandrocq/ComedoresUGRbot)) by [*alejandrocq*](https://github.com/alejandrocq) - Telegram bot to check the menu of Universidad de Granada dining hall.
Want to have your bot listed here? Send a Telegram message to @eternnoir or @pevdh.

View File

@ -46,7 +46,7 @@ class WebhookServer(object):
length = int(cherrypy.request.headers['content-length'])
json_string = cherrypy.request.body.read(length).decode("utf-8")
update = telebot.types.Update.de_json(json_string)
bot.process_new_messages([update.message])
bot.process_new_updates([update])
return ''
else:
raise cherrypy.HTTPError(403)

View File

@ -48,7 +48,7 @@ def index():
@app.route(WEBHOOK_URL_PATH, methods=['POST'])
def webhook():
if flask.request.headers.get('content-type') == 'application/json':
json_string = flask.request.get_data().decode('utf-8')
json_string = flask.request.get_data().encode('utf-8')
update = telebot.types.Update.de_json(json_string)
bot.process_new_messages([update.message])
return ''

View File

@ -0,0 +1,30 @@
import telebot
import os
from flask import Flask, request
bot = telebot.TeleBot('<api_token>')
server = Flask(__name__)
@bot.message_handler(commands=['start'])
def start(message):
bot.reply_to(message, 'Hello, ' + message.from_user.first_name)
@bot.message_handler(func=lambda message: True, content_types=['text'])
def echo_message(message):
bot.reply_to(message, message.text)
@server.route("/bot", methods=['POST'])
def getMessage():
bot.process_new_messages(
[telebot.types.Update.de_json(request.stream.read().decode("utf-8")).message])
return "!", 200
@server.route("/")
def webhook():
bot.remove_webhook()
bot.set_webhook(url="https://herokuProject_url/bot")
return "!", 200
server.run(host="0.0.0.0", port=os.environ.get('PORT', 5000))
server = Flask(__name__)

View File

@ -7,7 +7,7 @@ def readme():
return f.read()
setup(name='pyTelegramBotAPI',
version='2.0.5',
version='2.1.3',
description='Python Telegram bot api. ',
long_description=readme(),
author='eternnoir',

View File

@ -66,6 +66,7 @@ class TeleBot:
self.pre_message_subscribers_next_step = {}
self.message_handlers = []
self.edited_message_handlers = []
self.inline_handlers = []
self.chosen_inline_handlers = []
self.callback_query_handlers = []
@ -123,6 +124,7 @@ class TeleBot:
def process_new_updates(self, updates):
new_messages = []
edited_new_messages = []
new_inline_querys = []
new_chosen_inline_results = []
new_callback_querys = []
@ -131,6 +133,8 @@ class TeleBot:
self.last_update_id = update.update_id
if update.message:
new_messages.append(update.message)
if update.edited_message:
edited_new_messages.append(update.edited_message)
if update.inline_query:
new_inline_querys.append(update.inline_query)
if update.chosen_inline_result:
@ -140,6 +144,8 @@ class TeleBot:
logger.debug('Received {0} new updates'.format(len(updates)))
if len(new_messages) > 0:
self.process_new_messages(new_messages)
if len(edited_new_messages) > 0:
self.process_new_edited_messages(edited_new_messages)
if len(new_inline_querys) > 0:
self.process_new_inline_query(new_inline_querys)
if len(new_chosen_inline_results) > 0:
@ -154,6 +160,9 @@ class TeleBot:
self._notify_message_subscribers(new_messages)
self._notify_message_next_handler(new_messages)
def process_new_edited_messages(self, edited_message):
self._notify_command_handlers(self.edited_message_handlers, edited_message)
def process_new_inline_query(self, new_inline_querys):
self._notify_command_handlers(self.inline_handlers, new_inline_querys)
@ -285,6 +294,57 @@ class TeleBot:
result = apihelper.get_user_profile_photos(self.token, user_id, offset, limit)
return types.UserProfilePhotos.de_json(result)
def get_chat(self, chat_id):
"""
Use this method to get up to date information about the chat (current name of the user for one-on-one
conversations, current username of a user, group or channel, etc.). Returns a Chat object on success.
:param chat_id:
:return:
"""
result = apihelper.get_chat(self.token, chat_id)
return types.Chat.de_json(result)
def leave_chat(self, chat_id):
"""
Use this method for your bot to leave a group, supergroup or channel. Returns True on success.
:param chat_id:
:return:
"""
result = apihelper.leave_chat(self.token, chat_id)
return result
def get_chat_administrators(self, chat_id):
"""
Use this method to get a list of administrators in a chat. On success, returns an Array of ChatMember objects
that contains information about all chat administrators except other bots.
:param chat_id:
:return:
"""
result = apihelper.get_chat_administrators(self.token, chat_id)
ret = []
for r in result:
ret.append(types.ChatMember.de_json(r))
return ret
def get_chat_members_count(self, chat_id):
"""
Use this method to get the number of members in a chat. Returns Int on success.
:param chat_id:
:return:
"""
result = apihelper.get_chat_members_count(self.token, chat_id)
return result
def get_chat_member(self, chat_id, user_id):
"""
Use this method to get information about a member of a chat. Returns a ChatMember object on success.
:param chat_id:
:param user_id:
:return:
"""
result = apihelper.get_chat_member(self.token, chat_id, user_id)
return types.ChatMember.de_json(result)
def send_message(self, chat_id, text, disable_web_page_preview=None, reply_to_message_id=None, reply_markup=None,
parse_mode=None, disable_notification=None):
"""
@ -334,7 +394,7 @@ class TeleBot:
disable_notification))
def send_audio(self, chat_id, audio, duration=None, performer=None, title=None, reply_to_message_id=None,
reply_markup=None, disable_notification=None):
reply_markup=None, disable_notification=None, timeout=None):
"""
Use this method to send audio files, if you want Telegram clients to display them in the music player. Your audio must be in the .mp3 format.
:param chat_id:Unique identifier for the message recipient
@ -348,10 +408,10 @@ class TeleBot:
"""
return types.Message.de_json(
apihelper.send_audio(self.token, chat_id, audio, duration, performer, title, reply_to_message_id,
reply_markup, disable_notification))
reply_markup, disable_notification, timeout))
def send_voice(self, chat_id, voice, duration=None, reply_to_message_id=None, reply_markup=None,
disable_notification=None):
disable_notification=None, timeout=None):
"""
Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message.
:param chat_id:Unique identifier for the message recipient.
@ -363,9 +423,10 @@ class TeleBot:
"""
return types.Message.de_json(
apihelper.send_voice(self.token, chat_id, voice, duration, reply_to_message_id, reply_markup,
disable_notification))
disable_notification, timeout))
def send_document(self, chat_id, data, reply_to_message_id=None, reply_markup=None, disable_notification=None):
def send_document(self, chat_id, data, reply_to_message_id=None, caption=None, reply_markup=None,
disable_notification=None, timeout=None):
"""
Use this method to send general files.
:param chat_id:
@ -376,9 +437,10 @@ class TeleBot:
"""
return types.Message.de_json(
apihelper.send_data(self.token, chat_id, data, 'document', reply_to_message_id, reply_markup,
disable_notification))
disable_notification, timeout, caption=caption))
def send_sticker(self, chat_id, data, reply_to_message_id=None, reply_markup=None, disable_notification=None):
def send_sticker(self, chat_id, data, reply_to_message_id=None, reply_markup=None, disable_notification=None,
timeout=None):
"""
Use this method to send .webp stickers.
:param chat_id:
@ -389,10 +451,10 @@ class TeleBot:
"""
return types.Message.de_json(
apihelper.send_data(self.token, chat_id, data, 'sticker', reply_to_message_id, reply_markup,
disable_notification))
disable_notification, timeout))
def send_video(self, chat_id, data, duration=None, caption=None, reply_to_message_id=None, reply_markup=None,
disable_notification=None):
disable_notification=None, timeout=None):
"""
Use this method to send video files, Telegram clients support mp4 videos.
:param chat_id: Integer : Unique identifier for the message recipient — User or GroupChat id
@ -405,7 +467,7 @@ class TeleBot:
"""
return types.Message.de_json(
apihelper.send_video(self.token, chat_id, data, duration, caption, reply_to_message_id, reply_markup,
disable_notification))
disable_notification, timeout))
def send_location(self, chat_id, latitude, longitude, reply_to_message_id=None, reply_markup=None,
disable_notification=None):
@ -479,8 +541,8 @@ class TeleBot:
def edit_message_text(self, text, chat_id=None, message_id=None, inline_message_id=None, parse_mode=None,
disable_web_page_preview=None, reply_markup=None):
result = apihelper.edit_message_text(self.token, text, chat_id, message_id, inline_message_id, parse_mode,
disable_web_page_preview, reply_markup)
if type(result) == bool: # if edit inline message return is bool not Message.
disable_web_page_preview, reply_markup)
if type(result) == bool: # if edit inline message return is bool not Message.
return result
return types.Message.de_json(result)
@ -647,6 +709,32 @@ class TeleBot:
self.message_handlers.append(handler_dict)
def edited_message_handler(self, commands=None, regexp=None, func=None, content_types=['text']):
def decorator(handler):
self.add_edited_message_handler(handler, commands, regexp, func, content_types)
return handler
return decorator
def add_edited_message_handler(self, handler, commands=None, regexp=None, func=None, content_types=None):
if content_types is None:
content_types = ['text']
filters = {'content_types': content_types}
if regexp:
filters['regexp'] = regexp
if func:
filters['lambda'] = func
if commands:
filters['commands'] = commands
handler_dict = {
'function': handler,
'filters': filters
}
self.edited_message_handlers.append(handler_dict)
def inline_handler(self, func):
def decorator(handler):
self.add_inline_handler(handler, func)

View File

@ -27,9 +27,11 @@ def _make_request(token, method_name, method='get', params=None, files=None, bas
request_url = base_url.format(token, method_name)
logger.debug("Request: method={0} url={1} params={2} files={3}".format(method, request_url, params, files))
read_timeout = READ_TIMEOUT
connect_timeout = CONNECT_TIMEOUT
if params:
if 'timeout' in params: read_timeout = params['timeout'] + 10
result = requests.request(method, request_url, params=params, files=files, timeout=(CONNECT_TIMEOUT, read_timeout))
if 'connect-timeout' in params: connect_timeout = params['connect-timeout'] + 10
result = requests.request(method, request_url, params=params, files=files, timeout=(connect_timeout, read_timeout))
logger.debug("The server returned: '{0}'".format(result.text.encode('utf8')))
return _check_result(method_name, result)['result']
@ -147,6 +149,36 @@ def get_user_profile_photos(token, user_id, offset=None, limit=None):
return _make_request(token, method_url, params=payload)
def get_chat(token, chat_id):
method_url = r'getChat'
payload = {'chat_id': chat_id}
return _make_request(token, method_url, params=payload)
def leave_chat(token, chat_id):
method_url = r'leaveChat'
payload = {'chat_id': chat_id}
return _make_request(token, method_url, params=payload)
def get_chat_administrators(token, chat_id):
method_url = r'getChatAdministrators'
payload = {'chat_id': chat_id}
return _make_request(token, method_url, params=payload)
def get_chat_members_count(token, chat_id):
method_url = r'getChatMembersCount'
payload = {'chat_id': chat_id}
return _make_request(token, method_url, params=payload)
def get_chat_member(token, chat_id, user_id):
method_url = r'getChatMember'
payload = {'chat_id': chat_id, 'user_id': user_id}
return _make_request(token, method_url, params=payload)
def forward_message(token, chat_id, from_chat_id, message_id, disable_notification=None):
method_url = r'forwardMessage'
payload = {'chat_id': chat_id, 'from_chat_id': from_chat_id, 'message_id': message_id}
@ -225,7 +257,7 @@ def send_chat_action(token, chat_id, action):
def send_video(token, chat_id, data, duration=None, caption=None, reply_to_message_id=None, reply_markup=None,
disable_notification=None):
disable_notification=None, timeout=None):
method_url = r'sendVideo'
payload = {'chat_id': chat_id}
files = None
@ -243,11 +275,13 @@ def send_video(token, chat_id, data, duration=None, caption=None, reply_to_messa
payload['reply_markup'] = _convert_markup(reply_markup)
if disable_notification:
payload['disable_notification'] = disable_notification
if timeout:
payload['connect-timeout'] = timeout
return _make_request(token, method_url, params=payload, files=files, method='post')
def send_voice(token, chat_id, voice, duration=None, reply_to_message_id=None, reply_markup=None,
disable_notification=None):
disable_notification=None, timeout=None):
method_url = r'sendVoice'
payload = {'chat_id': chat_id}
files = None
@ -263,11 +297,13 @@ def send_voice(token, chat_id, voice, duration=None, reply_to_message_id=None, r
payload['reply_markup'] = _convert_markup(reply_markup)
if disable_notification:
payload['disable_notification'] = disable_notification
if timeout:
payload['connect-timeout'] = timeout
return _make_request(token, method_url, params=payload, files=files, method='post')
def send_audio(token, chat_id, audio, duration=None, performer=None, title=None, reply_to_message_id=None,
reply_markup=None, disable_notification=None):
reply_markup=None, disable_notification=None, timeout=None):
method_url = r'sendAudio'
payload = {'chat_id': chat_id}
files = None
@ -287,10 +323,13 @@ def send_audio(token, chat_id, audio, duration=None, performer=None, title=None,
payload['reply_markup'] = _convert_markup(reply_markup)
if disable_notification:
payload['disable_notification'] = disable_notification
if timeout:
payload['connect-timeout'] = timeout
return _make_request(token, method_url, params=payload, files=files, method='post')
def send_data(token, chat_id, data, data_type, reply_to_message_id=None, reply_markup=None, disable_notification=None):
def send_data(token, chat_id, data, data_type, reply_to_message_id=None, reply_markup=None, disable_notification=None,
timeout=None, caption=None):
method_url = get_method_by_type(data_type)
payload = {'chat_id': chat_id}
files = None
@ -304,6 +343,10 @@ def send_data(token, chat_id, data, data_type, reply_to_message_id=None, reply_m
payload['reply_markup'] = _convert_markup(reply_markup)
if disable_notification:
payload['disable_notification'] = disable_notification
if timeout:
payload['connect-timeout'] = timeout
if caption:
payload['caption'] = caption
return _make_request(token, method_url, params=payload, files=files, method='post')

View File

@ -3,6 +3,8 @@
import json
import six
from telebot import util
class JsonSerializable:
"""
@ -60,9 +62,14 @@ class JsonDeserializable:
:param json_type:
:return:
"""
try:
str_types = (str, unicode)
except NameError:
str_types = (str,)
if type(json_type) == dict:
return json_type
elif type(json_type) == str:
elif type(json_type) in str_types:
return json.loads(json_type)
else:
raise ValueError("json_type should be a json dict or string.")
@ -84,22 +91,27 @@ class Update(JsonDeserializable):
obj = cls.check_json(json_type)
update_id = obj['update_id']
message = None
edited_message = None
inline_query = None
chosen_inline_result = None
callback_query = None
if 'message' in obj:
message = Message.de_json(obj['message'])
if 'edited_message' in obj:
edited_message = Message.de_json(obj['edited_message'])
if 'inline_query' in obj:
inline_query = InlineQuery.de_json(obj['inline_query'])
if 'chosen_inline_result' in obj:
chosen_inline_result = ChosenInlineResult.de_json(obj['chosen_inline_result'])
if 'callback_query' in obj:
callback_query = CallbackQuery.de_json(obj['callback_query'])
return cls(update_id, message, inline_query, chosen_inline_result, callback_query)
return cls(update_id, message, edited_message, inline_query, chosen_inline_result, callback_query)
def __init__(self, update_id, message, inline_query, chosen_inline_result, callback_query):
def __init__(self, update_id, message, edited_message, inline_query, chosen_inline_result, callback_query):
self.update_id = update_id
self.edited_message = edited_message
self.message = message
self.edited_message = edited_message
self.inline_query = inline_query
self.chosen_inline_result = chosen_inline_result
self.callback_query = callback_query
@ -170,10 +182,14 @@ class Message(JsonDeserializable):
opts = {}
if 'forward_from' in obj:
opts['forward_from'] = User.de_json(obj['forward_from'])
if 'forward_from_chat' in obj:
opts['forward_from_chat'] = Chat.de_json(obj['forward_from_chat'])
if 'forward_date' in obj:
opts['forward_date'] = obj['forward_date']
if 'reply_to_message' in obj:
opts['reply_to_message'] = Message.de_json(obj['reply_to_message'])
if 'edit_date' in obj:
opts['edit_date'] = obj.get('edit_date')
if 'text' in obj:
opts['text'] = obj['text']
content_type = 'text'
@ -261,9 +277,11 @@ class Message(JsonDeserializable):
self.from_user = from_user
self.date = date
self.chat = chat
self.forward_from_chat = None
self.forward_from = None
self.forward_date = None
self.reply_to_message = None
self.edit_date = None
self.text = None
self.entities = None
self.audio = None
@ -299,13 +317,17 @@ class MessageEntity(JsonDeserializable):
offset = obj['offset']
length = obj['length']
url = obj.get('url')
return cls(type, offset, length, url)
user = None
if 'user' in obj:
user = User.de_json(obj['user'])
return cls(type, offset, length, url, user)
def __init__(self, type, offset, length, url=None):
def __init__(self, type, offset, length, url=None, user=None):
self.type = type
self.offset = offset
self.length = length
self.url = url
self.user = user
class PhotoSize(JsonDeserializable):
@ -394,14 +416,16 @@ class Sticker(JsonDeserializable):
thumb = None
if 'thumb' in obj:
thumb = PhotoSize.de_json(obj['thumb'])
emoji = obj.get('emoji')
file_size = obj.get('file_size')
return cls(file_id, width, height, thumb, file_size)
return cls(file_id, width, height, thumb, emoji, file_size)
def __init__(self, file_id, width, height, thumb, file_size=None):
def __init__(self, file_id, width, height, thumb, emoji=None, file_size=None):
self.file_id = file_id
self.width = width
self.height = height
self.thumb = thumb
self.emoji = emoji
self.file_size = file_size
@ -548,7 +572,7 @@ class ReplyKeyboardMarkup(JsonSerializable):
i = 1
row = []
for button in args:
if isinstance(button, str):
if util.is_string(button):
row.append({'text': button})
else:
row.append(button.to_dic())
@ -569,7 +593,7 @@ class ReplyKeyboardMarkup(JsonSerializable):
"""
btn_array = []
for button in args:
if isinstance(button, str):
if util.is_string(button):
btn_array.append({'text': button})
else:
btn_array.append(button.to_dic())
@ -709,6 +733,19 @@ class CallbackQuery(JsonDeserializable):
self.inline_message_id = inline_message_id
class ChatMember(JsonDeserializable):
@classmethod
def de_json(cls, json_type):
obj = cls.check_json(json_type)
user = User.de_json(obj['user'])
status = obj['status']
return cls(user, status)
def __init__(self, user, status):
self.user = user
self.status = status
# InlineQuery
class InlineQuery(JsonDeserializable):
@ -1157,7 +1194,8 @@ class InlineQueryResultLocation(JsonSerializable):
self.thumb_height = thumb_height
def to_json(self):
json_dict = {'type': self.type, 'id': self.id, 'latitude': self.latitude, 'longitude': self.longitude}
json_dict = {'type': self.type, 'id': self.id, 'latitude': self.latitude, 'longitude': self.longitude,
'title': self.title}
if self.thumb_url:
json_dict['thumb_url'] = self.thumb_url
if self.thumb_width:
@ -1188,8 +1226,8 @@ class InlineQueryResultVenue(JsonSerializable):
self.thumb_height = thumb_height
def to_json(self):
json_dict = {'type': self.type, 'id': self.id, 'latitude': self.latitude, 'longitude': self.longitude,
'address': self.address}
json_dict = {'type': self.type, 'id': self.id, 'title': self.title, 'latitude': self.latitude,
'longitude': self.longitude, 'address': self.address}
if self.foursquare_id:
json_dict['foursquare_id'] = self.foursquare_id
if self.thumb_url:

View File

@ -16,6 +16,7 @@ should_skip = 'TOKEN' and 'CHAT_ID' not in os.environ
if not should_skip:
TOKEN = os.environ['TOKEN']
CHAT_ID = os.environ['CHAT_ID']
GROUP_ID = os.environ['GROUP_ID']
@pytest.mark.skipif(should_skip, reason="No environment variables configured")
@ -129,6 +130,15 @@ class TestTeleBot:
ret_msg = tb.send_document(CHAT_ID, ret_msg.document.file_id)
assert ret_msg.message_id
def test_send_file_caption(self):
file_data = open('../examples/detailed_example/kitten.jpg', 'rb')
tb = telebot.TeleBot(TOKEN)
ret_msg = tb.send_document(CHAT_ID, file_data, caption="Test")
assert ret_msg.message_id
ret_msg = tb.send_document(CHAT_ID, ret_msg.document.file_id)
assert ret_msg.message_id
def test_send_video(self):
file_data = open('./test_data/test_video.mp4', 'rb')
tb = telebot.TeleBot(TOKEN)
@ -342,6 +352,21 @@ class TestTeleBot:
new_msg = tb.edit_message_text('Edit test', chat_id=CHAT_ID, message_id=msg.message_id)
assert new_msg.text == 'Edit test'
def test_get_chat(self):
tb = telebot.TeleBot(TOKEN)
ch = tb.get_chat(GROUP_ID)
assert str(ch.id) == GROUP_ID
def test_get_chat_administrators(self):
tb = telebot.TeleBot(TOKEN)
cas = tb.get_chat_administrators(GROUP_ID)
assert len(cas) > 0
def test_get_chat_members_count(self):
tb = telebot.TeleBot(TOKEN)
cn = tb.get_chat_members_count(GROUP_ID)
assert cn > 1
def test_edit_markup(self):
text = 'CI Test Message'
tb = telebot.TeleBot(TOKEN)