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

Compare commits

..

46 Commits
3.7.5 ... 3.7.7

Author SHA1 Message Date
4024490249 Merge pull request #1121 from Badiboy/master
Minor release
Heroku example update
2021-03-28 11:57:49 +03:00
209d9b27b4 Minor release 2021-03-28 11:57:05 +03:00
96e0be8942 Heroku example update 2021-03-28 11:54:46 +03:00
87bce0bce1 Merge pull request #1113 from barbax7/master
Added Price Tracker bot
2021-03-18 17:43:43 +03:00
f23059d7ec Added Price Tracker bot 2021-03-18 08:38:47 +01:00
cc08fe32c6 Merge pull request #1107 from MasterGroosha/patch-1
Removed my bot from README
2021-03-09 10:35:06 +03:00
07e93f95a1 Removed my bot from list
The link is now dead, and so is that bot
2021-03-09 02:05:44 +03:00
a10e8afa5c Merge pull request #1096 from anvaari/master
Add my bot to Readme.md
2021-02-16 13:25:07 +03:00
b39244f827 Add my bot to Readme.md 2021-02-16 13:41:56 +03:30
af4d986a13 Merge pull request #1090 from Badiboy/master
Custom logging level for infinity_polling
2021-02-05 00:43:22 +03:00
8790f26e68 Custom logging level for infinity_polling 2021-01-30 14:41:19 +03:00
f01412a996 Merge pull request #1086 from dexpiper/patch-1
README list of bots update
2021-01-22 16:56:02 +03:00
20d0ab229f README list of bots update
Add another bot to the list below
2021-01-21 17:19:54 +03:00
2dec4f1ffc Merge pull request #1083 from ModischFabrications/patch-1
Add MineGramBot to readme
2021-01-20 13:31:05 +03:00
a7d1dbf0e9 add MineGramBot 2021-01-20 11:04:55 +01:00
eace25d9d2 Merge pull request #1082 from Badiboy/master
Minor update to copyMessage
2021-01-19 01:28:16 +03:00
fdf2838669 Minor update to copyMessage 2021-01-19 01:27:39 +03:00
74fb8258b6 Merge pull request #1067 from Aazerra/copyMessage_method
Added copyMessage method
2021-01-19 01:16:09 +03:00
cc299fe4da Merge pull request #1081 from ModischFabrications/patch-1
Extend readme with more usage hints
2021-01-18 02:26:02 +03:00
cd31c8db5c fix example 2021-01-17 23:47:03 +01:00
6d7116d521 document SESSION_TIME_TO_LIVE 2021-01-17 23:45:23 +01:00
f93916372e document edit_message_text in readme 2021-01-17 23:34:54 +01:00
80c9e17fd4 add apihelper.ENABLE_MIDDLEWARE = True to readme 2021-01-17 23:22:45 +01:00
003a92f466 Merge pull request #1080 from Badiboy/master
Release v.3.7.6
2021-01-18 01:02:45 +03:00
d57aa04bfb Release v.3.7.6 2021-01-18 01:02:19 +03:00
9c2d279806 Merge pull request #1078 from ModischFabrications/patch-1
Hide token from debug logs
2021-01-17 12:21:42 +03:00
3109e35bb4 show bot id 2021-01-17 01:26:38 +01:00
ea51b1e95e hide token from debug logs
prevent leaks of the bot token by hiding it from the log
2021-01-17 01:06:47 +01:00
3799a1e99a Merge pull request #1077 from Badiboy/master
Added short live sessions
2021-01-17 00:46:01 +03:00
ec8714ad3a Short live sessions u1 2021-01-17 00:43:52 +03:00
bc54a5379c Added short live sessions 2021-01-16 23:50:25 +03:00
a7587057bf Merge pull request #1076 from Badiboy/master
Polling timeout fix
2021-01-16 02:15:26 +03:00
e9ba2fd8bb Polling timeout fix 2021-01-16 02:14:29 +03:00
8203fa588f Merge pull request #1074 from Badiboy/master
Version update to previous commit
2021-01-14 15:49:01 +03:00
2e5250ec98 Version update to previous commit 2021-01-14 15:48:30 +03:00
1f910745f1 Merge pull request #1073 from Badiboy/master
Fix restrict_chat_member until_date bug
2021-01-14 15:47:21 +03:00
f56da17741 Fix restrict_chat_member until_date bug 2021-01-14 15:45:47 +03:00
a0d86977b0 Merge pull request #1072 from Badiboy/master
Infinity polling fall down fixed
2021-01-14 03:57:00 +03:00
82838e1d26 Infinity polling fall down fixed 2021-01-14 03:44:37 +03:00
bb8bc7672a Merge pull request #1070 from dgarcoe/patch-1
Update README.md
2021-01-13 20:03:10 +03:00
6e3e159109 Update README.md
I included my bot in the README. Thanks for the library!
2021-01-13 17:55:08 +01:00
b561e35330 Update __init__.py 2021-01-12 11:19:57 +03:30
b684c4f60d Fix Things on copyMessage 2021-01-12 11:17:53 +03:30
58281f0a10 Added copyMessage method 2021-01-11 02:50:17 +03:30
87574a7613 Merge pull request #1066 from Badiboy/master
drop_pending_updates in set_webhook
2021-01-09 21:23:55 +03:00
52ebb5a1a7 drop_pending_updates in set_webhook 2021-01-09 21:22:49 +03:00
8 changed files with 199 additions and 36 deletions

View File

@ -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.

View File

@ -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

View File

@ -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)

View File

@ -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()

View File

@ -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

View File

@ -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:

View File

@ -1,3 +1,3 @@
# Versions should comply with PEP440.
# This line is parsed in setup.py:
__version__ = '3.7.5'
__version__ = '3.7.7'

View File

@ -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)