mirror of
https://github.com/eternnoir/pyTelegramBotAPI.git
synced 2023-08-10 21:12:57 +03:00
Compare commits
46 Commits
Author | SHA1 | Date | |
---|---|---|---|
4024490249 | |||
209d9b27b4 | |||
96e0be8942 | |||
87bce0bce1 | |||
f23059d7ec | |||
cc08fe32c6 | |||
07e93f95a1 | |||
a10e8afa5c | |||
b39244f827 | |||
af4d986a13 | |||
8790f26e68 | |||
f01412a996 | |||
20d0ab229f | |||
2dec4f1ffc | |||
a7d1dbf0e9 | |||
eace25d9d2 | |||
fdf2838669 | |||
74fb8258b6 | |||
cc299fe4da | |||
cd31c8db5c | |||
6d7116d521 | |||
f93916372e | |||
80c9e17fd4 | |||
003a92f466 | |||
d57aa04bfb | |||
9c2d279806 | |||
3109e35bb4 | |||
ea51b1e95e | |||
3799a1e99a | |||
ec8714ad3a | |||
bc54a5379c | |||
a7587057bf | |||
e9ba2fd8bb | |||
8203fa588f | |||
2e5250ec98 | |||
1f910745f1 | |||
f56da17741 | |||
a0d86977b0 | |||
82838e1d26 | |||
bb8bc7672a | |||
6e3e159109 | |||
b561e35330 | |||
b684c4f60d | |||
58281f0a10 | |||
87574a7613 | |||
52ebb5a1a7 |
19
README.md
19
README.md
@ -34,6 +34,7 @@
|
||||
* [F.A.Q.](#faq)
|
||||
* [Bot 2.0](#bot-20)
|
||||
* [How can I distinguish a User and a GroupChat in message.chat?](#how-can-i-distinguish-a-user-and-a-groupchat-in-messagechat)
|
||||
* [How can I handle reocurring ConnectionResetErrors?](#how-can-i-handle-reocurring-connectionreseterrors)
|
||||
* [The Telegram Chat Group](#the-telegram-chat-group)
|
||||
* [More examples](#more-examples)
|
||||
* [Bots using this API](#bots-using-this-api)
|
||||
@ -231,9 +232,11 @@ def test_callback(call):
|
||||
|
||||
A middleware handler is a function that allows you to modify requests or the bot context as they pass through the
|
||||
Telegram to the bot. You can imagine middleware as a chain of logic connection handled before any other handlers are
|
||||
executed.
|
||||
executed. Middleware processing is disabled by default, enable it by setting `apihelper.ENABLE_MIDDLEWARE = True`.
|
||||
|
||||
```python
|
||||
apihelper.ENABLE_MIDDLEWARE = True
|
||||
|
||||
@bot.middleware_handler(update_types=['message'])
|
||||
def modify_message(bot_instance, message):
|
||||
# modifying the message before it reaches any other handler
|
||||
@ -275,6 +278,9 @@ updates = tb.get_updates(1234,100,20) #get_Updates(offset, limit, timeout):
|
||||
# sendMessage
|
||||
tb.send_message(chat_id, text)
|
||||
|
||||
# editMessageText
|
||||
tb.edit_message_text(new_text, chat_id, message_id)
|
||||
|
||||
# forwardMessage
|
||||
tb.forward_message(to_chat_id, from_chat_id, message_id)
|
||||
|
||||
@ -598,6 +604,10 @@ if message.chat.type == "channel":
|
||||
|
||||
```
|
||||
|
||||
### How can I handle reocurring ConnectionResetErrors?
|
||||
|
||||
Bot instances that were idle for a long time might be rejected by the server when sending a message due to a timeout of the last used session. Add `apihelper.SESSION_TIME_TO_LIVE = 5 * 60` to your initialisation to force recreation after 5 minutes without any activity.
|
||||
|
||||
## The Telegram Chat Group
|
||||
|
||||
Get help. Discuss. Chat.
|
||||
@ -617,7 +627,6 @@ Get help. Discuss. Chat.
|
||||
* [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*
|
||||
@ -670,5 +679,9 @@ Get help. Discuss. Chat.
|
||||
* [Bot Hour](https://t.me/roadtocode_bot) a little bot that say the time in different countries by [@diegop384](https://github.com/diegop384) [repo](https://github.com/diegop384/telegrambothour)
|
||||
* [moodforfood_bot](https://t.me/moodforfood_bot) This bot will provide you with a list of food place(s) near your current Telegram location, which you are prompted to share. The API for all this info is from https://foursquare.com/. by [@sophiamarani](https://github.com/sophiamarani)
|
||||
* [Donation with Amazon](https://t.me/donamazonbot) by [@barbax7](https://github.com/barbax7) This bot donates amazon advertising commissions to the non-profit organization chosen by the user.
|
||||
|
||||
* [COVID-19 Galicia Bot](https://t.me/covid19_galicia_bot) by [@dgarcoe](https://github.com/dgarcoe) This bot provides daily data related to the COVID19 crisis in Galicia (Spain) obtained from official government sources.
|
||||
* [MineGramBot](https://github.com/ModischFabrications/MineGramBot) by [ModischFabrications](https://github.com/ModischFabrications). This bot can start, stop and monitor a minecraft server.
|
||||
* [Tabletop DiceBot](https://github.com/dexpiper/tabletopdicebot) by [dexpiper](https://github.com/dexpiper). This bot can roll multiple dices for RPG-like games, add positive and negative modifiers and show short descriptions to the rolls.
|
||||
* [BarnameKon](https://t.me/BarnameKonBot) by [Anvaari](https://github.com/anvaari). This Bot make "Add to google calendar" link for your events. It give information about event and return link. It work for Jalali calendar and in Tehran Time. [Source code](https://github.com/anvaari/BarnameKon)
|
||||
* [Price Tracker](https://t.me/trackokbot) by [@barbax7](https://github.com/barbax7). This bot tracks amazon.it product's prices the user is interested to and notify him when one price go down.
|
||||
Want to have your bot listed here? Just make a pull requet.
|
||||
|
@ -21,7 +21,9 @@ def echo_message(message):
|
||||
|
||||
@server.route('/' + TOKEN, methods=['POST'])
|
||||
def getMessage():
|
||||
bot.process_new_updates([telebot.types.Update.de_json(request.stream.read().decode("utf-8"))])
|
||||
json_string = request.get_data().decode('utf-8')
|
||||
update = telebot.types.Update.de_json(json_string)
|
||||
bot.process_new_updates([update])
|
||||
return "!", 200
|
||||
|
||||
|
||||
|
@ -6,6 +6,7 @@ import re
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
import traceback
|
||||
|
||||
logger = logging.getLogger('TeleBot')
|
||||
formatter = logging.Formatter(
|
||||
@ -45,6 +46,7 @@ class ExceptionHandler:
|
||||
Class for handling exceptions while Polling
|
||||
"""
|
||||
|
||||
# noinspection PyMethodMayBeStatic,PyUnusedLocal
|
||||
def handle(self, exception):
|
||||
return False
|
||||
|
||||
@ -235,7 +237,8 @@ class TeleBot:
|
||||
"""
|
||||
self.reply_backend.load_handlers(filename, del_file_after_loading)
|
||||
|
||||
def set_webhook(self, url=None, certificate=None, max_connections=None, allowed_updates=None, ip_address=None, timeout=None):
|
||||
def set_webhook(self, url=None, certificate=None, max_connections=None, allowed_updates=None, ip_address=None,
|
||||
drop_pending_updates = None, timeout=None):
|
||||
"""
|
||||
Use this method to specify a url and receive incoming updates via an outgoing webhook. Whenever there is an
|
||||
update for the bot, we will send an HTTPS POST request to the specified url, containing a JSON-serialized Update.
|
||||
@ -246,10 +249,11 @@ class TeleBot:
|
||||
:param max_connections: Maximum allowed number of simultaneous HTTPS connections to the webhook for update delivery, 1-100. Defaults to 40. Use lower values to limit the load on your bot's server, and higher values to increase your bot's throughput.
|
||||
:param allowed_updates: A JSON-serialized list of the update types you want your bot to receive. For example, specify [“message”, “edited_channel_post”, “callback_query”] to only receive updates of these types. See Update for a complete list of available update types. Specify an empty list to receive all updates regardless of type (default). If not specified, the previous setting will be used.
|
||||
:param ip_address: The fixed IP address which will be used to send webhook requests instead of the IP address resolved through DNS
|
||||
:param drop_pending_updates: Pass True to drop all pending updates
|
||||
:param timeout: Integer. Request connection timeout
|
||||
:return:
|
||||
"""
|
||||
return apihelper.set_webhook(self.token, url, certificate, max_connections, allowed_updates, ip_address, timeout)
|
||||
return apihelper.set_webhook(self.token, url, certificate, max_connections, allowed_updates, ip_address, drop_pending_updates, timeout)
|
||||
|
||||
def delete_webhook(self, drop_pending_updates=None, timeout=None):
|
||||
"""
|
||||
@ -451,16 +455,28 @@ class TeleBot:
|
||||
for listener in self.update_listener:
|
||||
self._exec_task(listener, new_messages)
|
||||
|
||||
def infinity_polling(self, timeout=20, long_polling_timeout=20, *args, **kwargs):
|
||||
def infinity_polling(self, timeout=20, long_polling_timeout=20, logger_level=logging.ERROR, *args, **kwargs):
|
||||
"""
|
||||
Wrap polling with infinite loop and exception handling to avoid bot stops polling.
|
||||
|
||||
:param timeout: Request connection timeout
|
||||
:param long_polling_timeout: Timeout in seconds for long polling (see API docs)
|
||||
:param logger_level: Custom logging level for infinity_polling logging. Use logger levels from logging as a value. None/NOTSET = no error logging
|
||||
"""
|
||||
while not self.__stop_polling.is_set():
|
||||
try:
|
||||
self.polling(none_stop=True, timeout=timeout, long_polling_timeout=long_polling_timeout, *args, **kwargs)
|
||||
except Exception as e:
|
||||
logger.error("Infinity polling exception: {}".format(e))
|
||||
if logger_level and logger_level >= logging.ERROR:
|
||||
logger.error("Infinity polling exception: %s", str(e))
|
||||
if logger_level and logger_level >= logging.DEBUG:
|
||||
logger.error("Exception traceback:\n%s", traceback.format_exc())
|
||||
time.sleep(3)
|
||||
continue
|
||||
logger.info("Infinity polling: polling exited")
|
||||
logger.info("Break infinity polling")
|
||||
if logger_level and logger_level >= logging.INFO:
|
||||
logger.error("Infinity polling: polling exited")
|
||||
if logger_level and logger_level >= logging.INFO:
|
||||
logger.error("Break infinity polling")
|
||||
|
||||
def polling(self, none_stop=False, interval=0, timeout=20, long_polling_timeout=20):
|
||||
"""
|
||||
@ -470,10 +486,10 @@ class TeleBot:
|
||||
Warning: Do not call this function more than once!
|
||||
|
||||
Always get updates.
|
||||
:param interval:
|
||||
:param interval: Delay between two update retrivals
|
||||
:param none_stop: Do not stop polling when an ApiException occurs.
|
||||
:param timeout: Integer. Request connection timeout
|
||||
:param long_polling_timeout. Timeout in seconds for long polling.
|
||||
:param timeout: Request connection timeout
|
||||
:param long_polling_timeout: Timeout in seconds for long polling (see API docs)
|
||||
:return:
|
||||
"""
|
||||
if self.threaded:
|
||||
@ -747,6 +763,29 @@ class TeleBot:
|
||||
return types.Message.de_json(
|
||||
apihelper.forward_message(self.token, chat_id, from_chat_id, message_id, disable_notification, timeout))
|
||||
|
||||
def copy_message(self, chat_id, from_chat_id, message_id, caption=None, parse_mode=None, caption_entities=None,
|
||||
disable_notification=None, reply_to_message_id=None, allow_sending_without_reply=None,
|
||||
reply_markup=None, timeout=None):
|
||||
"""
|
||||
Use this method to copy messages of any kind.
|
||||
:param chat_id: which chat to forward
|
||||
:param from_chat_id: which chat message from
|
||||
:param message_id: message id
|
||||
:param caption:
|
||||
:param parse_mode:
|
||||
:param caption_entities:
|
||||
:param disable_notification:
|
||||
:param reply_to_message_id:
|
||||
:param allow_sending_without_reply:
|
||||
:param reply_markup:
|
||||
:param timeout:
|
||||
:return: API reply.
|
||||
"""
|
||||
return types.MessageID.de_json(
|
||||
apihelper.copy_message(self.token, chat_id, from_chat_id, message_id, caption, parse_mode, caption_entities,
|
||||
disable_notification, reply_to_message_id, allow_sending_without_reply, reply_markup,
|
||||
timeout))
|
||||
|
||||
def delete_message(self, chat_id, message_id, timeout=None):
|
||||
"""
|
||||
Use this method to delete message. Returns True on success.
|
||||
@ -860,7 +899,7 @@ class TeleBot:
|
||||
"""
|
||||
parse_mode = self.parse_mode if (parse_mode is None) else parse_mode
|
||||
|
||||
return types.Message.de_json(
|
||||
return types.Message.de_json(
|
||||
apihelper.send_data(self.token, chat_id, data, 'document', reply_to_message_id, reply_markup,
|
||||
parse_mode, disable_notification, timeout, caption, thumb))
|
||||
|
||||
@ -2264,6 +2303,11 @@ class AsyncTeleBot(TeleBot):
|
||||
def forward_message(self, *args, **kwargs):
|
||||
return TeleBot.forward_message(self, *args, **kwargs)
|
||||
|
||||
@util.async_dec()
|
||||
def copy_message(self, *args, **kwargs):
|
||||
return TeleBot.copy_message(self, *args, **kwargs)
|
||||
|
||||
|
||||
@util.async_dec()
|
||||
def delete_message(self, *args):
|
||||
return TeleBot.delete_message(self, *args)
|
||||
|
@ -1,5 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import time
|
||||
from datetime import datetime
|
||||
|
||||
try:
|
||||
import ujson as json
|
||||
@ -28,6 +29,7 @@ FILE_URL = None
|
||||
|
||||
CONNECT_TIMEOUT = 3.5
|
||||
READ_TIMEOUT = 9999
|
||||
SESSION_TIME_TO_LIVE = None # In seconds. None - live forever, 0 - one-time
|
||||
|
||||
RETRY_ON_ERROR = False
|
||||
RETRY_TIMEOUT = 2
|
||||
@ -39,7 +41,21 @@ ENABLE_MIDDLEWARE = False
|
||||
|
||||
|
||||
def _get_req_session(reset=False):
|
||||
return util.per_thread('req_session', lambda: session if session else requests.session(), reset)
|
||||
if SESSION_TIME_TO_LIVE:
|
||||
# If session TTL is set - check time passed
|
||||
creation_date = util.per_thread('req_session_time', lambda: datetime.now(), reset)
|
||||
if (datetime.now() - creation_date).total_seconds() > SESSION_TIME_TO_LIVE:
|
||||
# Force session reset
|
||||
reset = True
|
||||
# Save reset time
|
||||
util.per_thread('req_session_time', lambda: datetime.now(), True)
|
||||
|
||||
if SESSION_TIME_TO_LIVE == 0:
|
||||
# Session is one-time use
|
||||
return requests.sessions.Session()
|
||||
else:
|
||||
# Session lives some time or forever once created. Default
|
||||
return util.per_thread('req_session', lambda: session if session else requests.sessions.Session(), reset)
|
||||
|
||||
|
||||
def _make_request(token, method_name, method='get', params=None, files=None):
|
||||
@ -57,7 +73,7 @@ def _make_request(token, method_name, method='get', params=None, files=None):
|
||||
else:
|
||||
request_url = "https://api.telegram.org/bot{0}/{1}".format(token, method_name)
|
||||
|
||||
logger.debug("Request: method={0} url={1} params={2} files={3}".format(method, request_url, params, files))
|
||||
logger.debug("Request: method={0} url={1} params={2} files={3}".format(method, request_url, params, files).replace(token, token.split(':')[0] + ":{TOKEN}"))
|
||||
read_timeout = READ_TIMEOUT
|
||||
connect_timeout = CONNECT_TIMEOUT
|
||||
if files and format_header_param:
|
||||
@ -68,8 +84,11 @@ def _make_request(token, method_name, method='get', params=None, files=None):
|
||||
if 'connect-timeout' in params:
|
||||
connect_timeout = params.pop('connect-timeout') + 10
|
||||
if 'long_polling_timeout' in params:
|
||||
# For getUpdates: the only function with timeout on the BOT API side
|
||||
# For getUpdates
|
||||
# The only function with timeout on the BOT API side
|
||||
params['timeout'] = params.pop('long_polling_timeout')
|
||||
# Long polling hangs for given time. Read timeout should be greater that long_polling_timeout
|
||||
read_timeout = max(params['timeout'] + 10, read_timeout)
|
||||
|
||||
|
||||
result = None
|
||||
@ -206,7 +225,8 @@ def send_message(
|
||||
return _make_request(token, method_url, params=payload, method='post')
|
||||
|
||||
|
||||
def set_webhook(token, url=None, certificate=None, max_connections=None, allowed_updates=None, ip_address=None, timeout=None):
|
||||
def set_webhook(token, url=None, certificate=None, max_connections=None, allowed_updates=None, ip_address=None,
|
||||
drop_pending_updates = None, timeout=None):
|
||||
method_url = r'setWebhook'
|
||||
payload = {
|
||||
'url': url if url else "",
|
||||
@ -216,10 +236,12 @@ def set_webhook(token, url=None, certificate=None, max_connections=None, allowed
|
||||
files = {'certificate': certificate}
|
||||
if max_connections:
|
||||
payload['max_connections'] = max_connections
|
||||
if allowed_updates is not None: # Empty lists should pass
|
||||
if allowed_updates is not None: # Empty lists should pass
|
||||
payload['allowed_updates'] = json.dumps(allowed_updates)
|
||||
if ip_address is not None: # Empty string should pass
|
||||
if ip_address is not None: # Empty string should pass
|
||||
payload['ip_address'] = ip_address
|
||||
if drop_pending_updates is not None: # Any bool value should pass
|
||||
payload['drop_pending_updates'] = drop_pending_updates
|
||||
if timeout:
|
||||
payload['connect-timeout'] = timeout
|
||||
return _make_request(token, method_url, params=payload, files=files)
|
||||
@ -228,7 +250,7 @@ def set_webhook(token, url=None, certificate=None, max_connections=None, allowed
|
||||
def delete_webhook(token, drop_pending_updates=None, timeout=None):
|
||||
method_url = r'deleteWebhook'
|
||||
payload = {}
|
||||
if drop_pending_updates is not None: # None / True / False
|
||||
if drop_pending_updates is not None: # Any bool value should pass
|
||||
payload['drop_pending_updates'] = drop_pending_updates
|
||||
if timeout:
|
||||
payload['connect-timeout'] = timeout
|
||||
@ -251,7 +273,7 @@ def get_updates(token, offset=None, limit=None, timeout=None, allowed_updates=No
|
||||
if limit:
|
||||
payload['limit'] = limit
|
||||
if timeout:
|
||||
payload['timeout'] = timeout
|
||||
payload['connect-timeout'] = timeout
|
||||
if long_polling_timeout:
|
||||
payload['long_polling_timeout'] = long_polling_timeout
|
||||
if allowed_updates is not None: # Empty lists should pass
|
||||
@ -323,6 +345,30 @@ def forward_message(
|
||||
return _make_request(token, method_url, params=payload)
|
||||
|
||||
|
||||
def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_mode=None, caption_entities=None,
|
||||
disable_notification=None, reply_to_message_id=None, allow_sending_without_reply=None,
|
||||
reply_markup=None, timeout=None):
|
||||
method_url = r'copyMessage'
|
||||
payload = {'chat_id': chat_id, 'from_chat_id': from_chat_id, 'message_id': message_id}
|
||||
if caption is not None:
|
||||
payload['caption'] = caption
|
||||
if parse_mode:
|
||||
payload['parse_mode'] = parse_mode
|
||||
if caption_entities is not None:
|
||||
payload['caption_entities'] = _convert_entites(caption_entities)
|
||||
if disable_notification is not None:
|
||||
payload['disable_notification'] = disable_notification
|
||||
if reply_to_message_id:
|
||||
payload['reply_to_message_id'] = reply_to_message_id
|
||||
if reply_markup is not None:
|
||||
payload['reply_markup'] = _convert_markup(reply_markup)
|
||||
if allow_sending_without_reply is not None:
|
||||
payload['allow_sending_without_reply'] = allow_sending_without_reply
|
||||
if timeout:
|
||||
payload['connect-timeout'] = timeout
|
||||
return _make_request(token, method_url, params=payload)
|
||||
|
||||
|
||||
def send_dice(
|
||||
token, chat_id,
|
||||
emoji=None, disable_notification=None, reply_to_message_id=None,
|
||||
@ -706,7 +752,9 @@ def get_method_by_type(data_type):
|
||||
def kick_chat_member(token, chat_id, user_id, until_date=None):
|
||||
method_url = 'kickChatMember'
|
||||
payload = {'chat_id': chat_id, 'user_id': user_id}
|
||||
if until_date:
|
||||
if isinstance(until_date, datetime):
|
||||
payload['until_date'] = until_date.timestamp()
|
||||
else:
|
||||
payload['until_date'] = until_date
|
||||
return _make_request(token, method_url, params=payload, method='post')
|
||||
|
||||
@ -727,8 +775,6 @@ def restrict_chat_member(
|
||||
can_invite_users=None, can_pin_messages=None):
|
||||
method_url = 'restrictChatMember'
|
||||
permissions = {}
|
||||
if until_date is not None:
|
||||
permissions['until_date'] = until_date
|
||||
if can_send_messages is not None:
|
||||
permissions['can_send_messages'] = can_send_messages
|
||||
if can_send_media_messages is not None:
|
||||
@ -747,6 +793,11 @@ def restrict_chat_member(
|
||||
permissions['can_pin_messages'] = can_pin_messages
|
||||
permissions_json = json.dumps(permissions)
|
||||
payload = {'chat_id': chat_id, 'user_id': user_id, 'permissions': permissions_json}
|
||||
if until_date is not None:
|
||||
if isinstance(until_date, datetime):
|
||||
payload['until_date'] = until_date.timestamp()
|
||||
else:
|
||||
payload['until_date'] = until_date
|
||||
return _make_request(token, method_url, params=payload, method='post')
|
||||
|
||||
|
||||
@ -1243,7 +1294,10 @@ def send_poll(
|
||||
if open_period is not None:
|
||||
payload['open_period'] = open_period
|
||||
if close_date is not None:
|
||||
payload['close_date'] = close_date
|
||||
if isinstance(close_date, datetime):
|
||||
payload['close_date'] = close_date.timestamp()
|
||||
else:
|
||||
payload['close_date'] = close_date
|
||||
if is_closed is not None:
|
||||
payload['is_closed'] = is_closed
|
||||
|
||||
@ -1282,6 +1336,17 @@ def _convert_markup(markup):
|
||||
return markup
|
||||
|
||||
|
||||
def _convert_entites(entites):
|
||||
if entites is None:
|
||||
return None
|
||||
elif len(entites) == 0:
|
||||
return []
|
||||
elif isinstance(entites[0], types.JsonSerializable):
|
||||
return [entity.to_json() for entity in entites]
|
||||
else:
|
||||
return entites
|
||||
|
||||
|
||||
def convert_input_media(media):
|
||||
if isinstance(media, types.InputMedia):
|
||||
return media.convert_input_media()
|
||||
|
@ -261,6 +261,19 @@ class Chat(JsonDeserializable):
|
||||
self.location = location
|
||||
|
||||
|
||||
class MessageID(JsonDeserializable):
|
||||
@classmethod
|
||||
def de_json(cls, json_string):
|
||||
if(json_string is None):
|
||||
return None
|
||||
obj = cls.check_json(json_string)
|
||||
message_id = obj['message_id']
|
||||
return cls(message_id)
|
||||
|
||||
def __init__(self, message_id):
|
||||
self.message_id = message_id
|
||||
|
||||
|
||||
class Message(JsonDeserializable):
|
||||
@classmethod
|
||||
def de_json(cls, json_string):
|
||||
@ -548,7 +561,7 @@ class Message(JsonDeserializable):
|
||||
return self.__html_text(self.caption, self.caption_entities)
|
||||
|
||||
|
||||
class MessageEntity(JsonDeserializable):
|
||||
class MessageEntity(Dictionaryable, JsonSerializable, JsonDeserializable):
|
||||
@classmethod
|
||||
def de_json(cls, json_string):
|
||||
if (json_string is None): return None
|
||||
@ -569,6 +582,17 @@ class MessageEntity(JsonDeserializable):
|
||||
self.user = user
|
||||
self.language = language
|
||||
|
||||
def to_json(self):
|
||||
return json.dumps(self.to_dict())
|
||||
|
||||
def to_dict(self):
|
||||
return {"type": self.type,
|
||||
"offset": self.offset,
|
||||
"length": self.length,
|
||||
"url": self.url,
|
||||
"user": self.user,
|
||||
"language": self.language}
|
||||
|
||||
|
||||
class Dice(JsonSerializable, Dictionaryable, JsonDeserializable):
|
||||
@classmethod
|
||||
|
@ -235,8 +235,10 @@ def or_clear(self):
|
||||
|
||||
|
||||
def orify(e, changed_callback):
|
||||
e._set = e.set
|
||||
e._clear = e.clear
|
||||
if not hasattr(e, "_set"):
|
||||
e._set = e.set
|
||||
if not hasattr(e, "_clear"):
|
||||
e._clear = e.clear
|
||||
e.changed = changed_callback
|
||||
e.set = lambda: or_set(e)
|
||||
e.clear = lambda: or_clear(e)
|
||||
@ -244,7 +246,7 @@ def orify(e, changed_callback):
|
||||
def OrEvent(*events):
|
||||
or_event = threading.Event()
|
||||
def changed():
|
||||
bools = [e.is_set() for e in events]
|
||||
bools = [ev.is_set() for ev in events]
|
||||
if any(bools):
|
||||
or_event.set()
|
||||
else:
|
||||
|
@ -1,3 +1,3 @@
|
||||
# Versions should comply with PEP440.
|
||||
# This line is parsed in setup.py:
|
||||
__version__ = '3.7.5'
|
||||
__version__ = '3.7.7'
|
||||
|
@ -48,6 +48,7 @@ class TestTeleBot:
|
||||
bot = telebot.TeleBot('')
|
||||
msg = self.create_text_message(r'https://web.telegram.org/')
|
||||
|
||||
# noinspection PyUnusedLocal
|
||||
@bot.message_handler(regexp=r'((https?):((//)|(\\\\))+([\w\d:#@%/;$()~_?\+-=\\\.&](#!)?)*)')
|
||||
def command_url(message):
|
||||
msg.text = 'got'
|
||||
@ -60,6 +61,7 @@ class TestTeleBot:
|
||||
bot = telebot.TeleBot('')
|
||||
msg = self.create_text_message(r'lambda_text')
|
||||
|
||||
# noinspection PyUnusedLocal
|
||||
@bot.message_handler(func=lambda message: r'lambda' in message.text)
|
||||
def command_url(message):
|
||||
msg.text = 'got'
|
||||
@ -72,6 +74,7 @@ class TestTeleBot:
|
||||
bot = telebot.TeleBot('')
|
||||
msg = self.create_text_message(r'text')
|
||||
|
||||
# noinspection PyUnusedLocal
|
||||
@bot.message_handler(func=lambda message: r'lambda' in message.text)
|
||||
def command_url(message):
|
||||
msg.text = 'got'
|
||||
@ -84,6 +87,7 @@ class TestTeleBot:
|
||||
bot = telebot.TeleBot('')
|
||||
msg = self.create_text_message(r'web.telegram.org/')
|
||||
|
||||
# noinspection PyUnusedLocal
|
||||
@bot.message_handler(regexp=r'((https?):((//)|(\\\\))+([\w\d:#@%/;$()~_?\+-=\\\.&](#!)?)*)')
|
||||
def command_url(message):
|
||||
msg.text = 'got'
|
||||
@ -289,6 +293,13 @@ class TestTeleBot:
|
||||
ret_msg = tb.forward_message(CHAT_ID, CHAT_ID, msg.message_id)
|
||||
assert ret_msg.forward_from
|
||||
|
||||
def test_copy_message(self):
|
||||
text = 'CI copy_message Test Message'
|
||||
tb = telebot.TeleBot(TOKEN)
|
||||
msg = tb.send_message(CHAT_ID, text)
|
||||
ret_msg = tb.copy_message(CHAT_ID, CHAT_ID, msg.message_id)
|
||||
assert ret_msg
|
||||
|
||||
def test_forward_message_dis_noti(self):
|
||||
text = 'CI forward_message Test Message'
|
||||
tb = telebot.TeleBot(TOKEN)
|
||||
@ -522,6 +533,7 @@ class TestTeleBot:
|
||||
tb = telebot.TeleBot('')
|
||||
update = self.create_message_update('/help')
|
||||
|
||||
# noinspection PyUnusedLocal
|
||||
@tb.middleware_handler(update_types=['message'])
|
||||
def middleware(tb_instance, message):
|
||||
message.text = 'got'
|
||||
@ -542,9 +554,10 @@ class TestTeleBot:
|
||||
tb = telebot.TeleBot('')
|
||||
update = self.create_message_update('/help')
|
||||
|
||||
# noinspection PyUnusedLocal
|
||||
@tb.middleware_handler()
|
||||
def middleware(tb_instance, update):
|
||||
update.message.text = 'got'
|
||||
def middleware(tb_instance, mw_update):
|
||||
mw_update.message.text = 'got'
|
||||
|
||||
@tb.message_handler(func=lambda m: m.text == 'got')
|
||||
def command_handler(message):
|
||||
@ -556,6 +569,6 @@ class TestTeleBot:
|
||||
|
||||
def test_chat_permissions(self):
|
||||
return # CHAT_ID is private chat, no permissions can be set
|
||||
tb = telebot.TeleBot(TOKEN)
|
||||
permissions = types.ChatPermissions(can_send_messages=True, can_send_polls=False)
|
||||
msg = tb.set_chat_permissions(CHAT_ID, permissions)
|
||||
#tb = telebot.TeleBot(TOKEN)
|
||||
#permissions = types.ChatPermissions(can_send_messages=True, can_send_polls=False)
|
||||
#msg = tb.set_chat_permissions(CHAT_ID, permissions)
|
||||
|
Reference in New Issue
Block a user