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

Compare commits

..

No commits in common. "8d380b49138d95dc02ebebbe68a30f749a346fcd" and "2e9947277a0ae642f3894fc6ffdbe9be386317df" have entirely different histories.

18 changed files with 99 additions and 63 deletions

View File

@ -20,7 +20,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [ '3.6','3.7','3.8','3.9', 'pypy-3.7', 'pypy-3.8' ] #'pypy-3.9' NOT SUPPORTED NOW
python-version: [ '3.6','3.7','3.8','3.9', 'pypy-3.6', 'pypy-3.7' ] #'pypy-3.8', 'pypy-3.9' NOT SUPPORTED NOW
name: ${{ matrix.python-version }} and tests
steps:
- uses: actions/checkout@v2

View File

@ -60,7 +60,6 @@
* [The Telegram Chat Group](#the-telegram-chat-group)
* [Telegram Channel](#telegram-channel)
* [More examples](#more-examples)
* [Code Template](#code-template)
* [Bots using this API](#bots-using-this-api)
## Getting started
@ -750,7 +749,7 @@ Asynchronous tasks depend on processor performance. Many asynchronous tasks can
AsyncTeleBot has different middlewares. See example on [middlewares](https://github.com/coder2020official/pyTelegramBotAPI/tree/master/examples/asynchronous_telebot/middleware)
### Examples
See more examples in our [examples](https://github.com/eternnoir/pyTelegramBotAPI/tree/master/examples/asynchronous_telebot) folder
See more examples in our [examples](https://github.com/coder2020official/pyTelegramBotAPI/tree/master/examples/asynchronous_telebot) folder
## F.A.Q.
@ -795,14 +794,6 @@ Join the [News channel](https://t.me/pyTelegramBotAPI). Here we will post releas
* [Deep Linking](https://github.com/eternnoir/pyTelegramBotAPI/blob/master/examples/deep_linking.py)
* [next_step_handler Example](https://github.com/eternnoir/pyTelegramBotAPI/blob/master/examples/step_example.py)
## Code Template
Template is a ready folder that contains architecture of basic project.
Here are some examples of template:
* [AsyncTeleBot template](https://github.com/coder2020official/asynctelebot_template)
* [TeleBot template](https://github.com/coder2020official/telebot_template)
## 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*

View File

@ -9,7 +9,7 @@ import telebot
from telebot import types
# Initialize bot with your token
bot = telebot.TeleBot('TOKEN')
bot = telebot.TeleBot(TOKEN)
# The `users` variable is needed to contain chat ids that are either in the search or in the active dialog, like {chat_id, chat_id}
users = {}
@ -47,7 +47,7 @@ def find(message: types.Message):
if message.chat.id not in users:
bot.send_message(message.chat.id, 'Finding...')
if freeid is None:
if freeid == None:
freeid = message.chat.id
else:
# Question:

View File

@ -1,8 +1,9 @@
import telebot
from telebot import asyncio_filters
from telebot.async_telebot import AsyncTeleBot
# list of storages, you can use any storage
from telebot.asyncio_storage import StateMemoryStorage
from telebot.asyncio_storage import StateRedisStorage,StateMemoryStorage,StatePickleStorage
# new feature for states.
from telebot.asyncio_handler_backends import State, StatesGroup

View File

@ -1,5 +1,6 @@
# Just a little example of middleware handlers
import telebot
from telebot.asyncio_handler_backends import BaseMiddleware
from telebot.async_telebot import AsyncTeleBot
from telebot.async_telebot import CancelUpdate

View File

@ -4,7 +4,7 @@ from telebot import custom_filters
from telebot.handler_backends import State, StatesGroup #States
# States storage
from telebot.storage import StateMemoryStorage
from telebot.storage import StateRedisStorage, StatePickleStorage, StateMemoryStorage
# Beginning from version 4.4.0+, we support storages.

View File

@ -18,6 +18,7 @@ def send_welcome(message):
def beep(chat_id) -> None:
"""Send the beep message."""
bot.send_message(chat_id, text='Beep!')
return schedule.CancelJob # Run a job once
@bot.message_handler(commands=['set'])

View File

@ -5,7 +5,6 @@
# Documenation to Tornado: http://tornadoweb.org
import signal
from typing import Optional, Awaitable
import tornado.httpserver
import tornado.ioloop
@ -34,18 +33,12 @@ bot = telebot.TeleBot(API_TOKEN)
class Root(tornado.web.RequestHandler):
def data_received(self, chunk: bytes) -> Optional[Awaitable[None]]:
pass
def get(self):
self.write("Hi! This is webhook example!")
self.finish()
class WebhookServ(tornado.web.RequestHandler):
def data_received(self, chunk: bytes) -> Optional[Awaitable[None]]:
pass
class webhook_serv(tornado.web.RequestHandler):
def get(self):
self.write("What are you doing here?")
self.finish()
@ -100,7 +93,7 @@ tornado.options.parse_command_line()
signal.signal(signal.SIGINT, signal_handler)
application = tornado.web.Application([
(r"/", Root),
(r"/" + WEBHOOK_SECRET, WebhookServ)
(r"/" + WEBHOOK_SECRET, webhook_serv)
])
http_server = tornado.httpserver.HTTPServer(application, ssl_options={

View File

@ -9,7 +9,7 @@ import time
import traceback
from typing import Any, Callable, List, Optional, Union
# these imports are used to avoid circular import error
# this imports are used to avoid circular import error
import telebot.util
import telebot.types
@ -33,11 +33,13 @@ from telebot.handler_backends import MemoryHandlerBackend, FileHandlerBackend
from telebot.custom_filters import SimpleCustomFilter, AdvancedCustomFilter
REPLY_MARKUP_TYPES = Union[
types.InlineKeyboardMarkup, types.ReplyKeyboardMarkup,
types.ReplyKeyboardRemove, types.ForceReply]
"""
Module : telebot
"""
@ -154,6 +156,7 @@ class TeleBot:
:param parse_mode: default parse_mode
:return: Telebot object.
"""
self.token = token
self.parse_mode = parse_mode
self.update_listener = []
@ -193,6 +196,7 @@ class TeleBot:
self.current_states = state_storage
if apihelper.ENABLE_MIDDLEWARE:
self.typed_middleware_handlers = {
'message': [],
@ -247,7 +251,8 @@ class TeleBot:
:param filename: Filename of saving file
"""
self.current_states = StatePickleStorage(file_path=filename)
self.current_states = StatePickleStorage(filename=filename)
self.current_states.create_dir()
def enable_save_reply_handlers(self, delay=120, filename="./.handler-saves/reply.save"):
@ -514,6 +519,7 @@ class TeleBot:
self.process_new_chat_member(new_chat_members)
if chat_join_request:
self.process_new_chat_join_request(chat_join_request)
def process_new_messages(self, new_messages):
self._notify_next_handlers(new_messages)
@ -584,6 +590,7 @@ class TeleBot:
for listener in self.update_listener:
self._exec_task(listener, new_messages)
def infinity_polling(self, timeout: int=20, skip_pending: bool=False, long_polling_timeout: int=20, logger_level=logging.ERROR,
allowed_updates: Optional[List[str]]=None, *args, **kwargs):
"""
@ -771,7 +778,7 @@ class TeleBot:
logger.info('Stopped polling.')
def _exec_task(self, task, *args, **kwargs):
if kwargs and kwargs.get('task_type') == 'handler':
if kwargs.get('task_type') == 'handler':
pass_bot = kwargs.get('pass_bot')
kwargs.pop('pass_bot')
kwargs.pop('task_type')
@ -949,6 +956,7 @@ class TeleBot:
"""
Use this method to send text messages.
Warning: Do not send more than about 4000 characters each message, otherwise you'll risk an HTTP 414 error.
If you must send more than 4000 characters,
use the `split_string` or `smart_split` function in util.py.
@ -1411,6 +1419,7 @@ class TeleBot:
allow_sending_without_reply, protect_content)
return [types.Message.de_json(msg) for msg in result]
# TODO: Rewrite this method like in API.
def send_location(
self, chat_id: Union[int, str],
@ -1425,6 +1434,8 @@ class TeleBot:
proximity_alert_radius: Optional[int]=None,
allow_sending_without_reply: Optional[bool]=None,
protect_content: Optional[bool]=None) -> types.Message:
"""
Use this method to send point on the map.
:param chat_id:
@ -1724,6 +1735,7 @@ class TeleBot:
:return: True on success.
"""
return apihelper.set_chat_administrator_custom_title(self.token, chat_id, user_id, custom_title)
def ban_chat_sender_chat(self, chat_id: Union[int, str], sender_chat_id: Union[int, str]) -> bool:
"""
@ -1755,6 +1767,7 @@ class TeleBot:
"""
return apihelper.unban_chat_sender_chat(self.token, chat_id, sender_chat_id)
def set_chat_permissions(
self, chat_id: Union[int, str], permissions: types.ChatPermissions) -> bool:
"""
@ -2249,6 +2262,7 @@ class TeleBot:
:param protect_content:
:return:
"""
if isinstance(question, types.Poll):
raise RuntimeError("The send_poll signature was changed, please see send_poll function details.")
@ -2431,6 +2445,7 @@ class TeleBot:
self.token, user_id, name, title, emojis, png_sticker, tgs_sticker,
contains_masks, mask_position)
def add_sticker_to_set(
self, user_id: int, name: str, emojis: str,
png_sticker: Optional[Union[Any, str]]=None,
@ -2451,6 +2466,7 @@ class TeleBot:
return apihelper.add_sticker_to_set(
self.token, user_id, name, emojis, png_sticker, tgs_sticker, mask_position)
def set_sticker_position_in_set(self, sticker: str, position: int) -> bool:
"""
Use this method to move a sticker in a set created by the bot to a specific position . Returns True on success.
@ -2526,9 +2542,8 @@ class TeleBot:
def set_state(self, user_id: int, state: Union[int, str], chat_id: int=None) -> None:
"""
Sets a new state of a user.
:param user_id:
:param state: new state. can be string or integer.
:param chat_id:
:param state: new state. can be string or integer.
"""
if chat_id is None:
chat_id = user_id
@ -2542,12 +2557,10 @@ class TeleBot:
"""
if chat_id is None:
chat_id = user_id
self.current_states.reset_data(chat_id, user_id)
def delete_state(self, user_id: int, chat_id: int=None) -> None:
"""
Delete the current state of a user.
:param user_id:
:param chat_id:
:return:
"""
@ -2563,7 +2576,6 @@ class TeleBot:
def get_state(self, user_id: int, chat_id: int=None) -> Optional[Union[int, str]]:
"""
Get current state of a user.
:param user_id:
:param chat_id:
:return: state of a user
"""
@ -2574,7 +2586,6 @@ class TeleBot:
def add_data(self, user_id: int, chat_id:int=None, **kwargs):
"""
Add data to states.
:param user_id:
:param chat_id:
"""
if chat_id is None:
@ -2644,8 +2655,8 @@ class TeleBot:
need_pop = True
self._exec_task(handler["callback"], message, *handler["args"], **handler["kwargs"])
if need_pop:
# removing message that was detected with next_step_handler
new_messages.pop(i)
new_messages.pop(i) # removing message that was detected with next_step_handler
@staticmethod
def _build_handler_dict(handler, pass_bot=False, **filters):
@ -2686,7 +2697,9 @@ class TeleBot:
print(update.update_id)
:param update_types: Optional list of update types that can be passed into the middleware handler.
"""
def decorator(handler):
self.add_middleware_handler(handler, update_types)
return handler
@ -2724,9 +2737,10 @@ class TeleBot:
bot.register_middleware_handler(print_channel_post_text, update_types=['channel_post', 'edited_channel_post'])
:param callback:
:param update_types: Optional list of update types that can be passed into the middleware handler.
"""
self.add_middleware_handler(callback, update_types)
def message_handler(self, commands=None, regexp=None, func=None, content_types=None, chat_types=None, **kwargs):
@ -2768,6 +2782,7 @@ class TeleBot:
:param content_types: Supported message content types. Must be a list. Defaults to ['text'].
:param chat_types: list of chat types
"""
if content_types is None:
content_types = ["text"]
@ -2841,6 +2856,7 @@ class TeleBot:
:param kwargs:
:return:
"""
if content_types is None:
content_types = ["text"]
@ -3049,6 +3065,7 @@ class TeleBot:
:param kwargs:
:return:
"""
def decorator(handler):
handler_dict = self._build_handler_dict(handler, func=func, **kwargs)
self.add_inline_handler(handler_dict)
@ -3082,6 +3099,7 @@ class TeleBot:
:param kwargs:
:return:
"""
def decorator(handler):
handler_dict = self._build_handler_dict(handler, func=func, **kwargs)
self.add_chosen_inline_handler(handler_dict)
@ -3115,6 +3133,7 @@ class TeleBot:
:param kwargs:
:return:
"""
def decorator(handler):
handler_dict = self._build_handler_dict(handler, func=func, **kwargs)
self.add_callback_query_handler(handler_dict)
@ -3148,6 +3167,7 @@ class TeleBot:
:param kwargs:
:return:
"""
def decorator(handler):
handler_dict = self._build_handler_dict(handler, func=func, **kwargs)
self.add_shipping_query_handler(handler_dict)
@ -3181,6 +3201,7 @@ class TeleBot:
:param kwargs:
:return:
"""
def decorator(handler):
handler_dict = self._build_handler_dict(handler, func=func, **kwargs)
self.add_pre_checkout_query_handler(handler_dict)
@ -3214,6 +3235,7 @@ class TeleBot:
:param kwargs:
:return:
"""
def decorator(handler):
handler_dict = self._build_handler_dict(handler, func=func, **kwargs)
self.add_poll_handler(handler_dict)
@ -3247,6 +3269,7 @@ class TeleBot:
:param kwargs:
:return:
"""
def decorator(handler):
handler_dict = self._build_handler_dict(handler, func=func, **kwargs)
self.add_poll_answer_handler(handler_dict)
@ -3280,6 +3303,7 @@ class TeleBot:
:param kwargs:
:return:
"""
def decorator(handler):
handler_dict = self._build_handler_dict(handler, func=func, **kwargs)
self.add_my_chat_member_handler(handler_dict)
@ -3313,6 +3337,7 @@ class TeleBot:
:param kwargs:
:return:
"""
def decorator(handler):
handler_dict = self._build_handler_dict(handler, func=func, **kwargs)
self.add_chat_member_handler(handler_dict)
@ -3346,6 +3371,7 @@ class TeleBot:
:param kwargs:
:return:
"""
def decorator(handler):
handler_dict = self._build_handler_dict(handler, func=func, **kwargs)
self.add_chat_join_request_handler(handler_dict)
@ -3403,6 +3429,14 @@ class TeleBot:
:param message: Message to test
:return: True if filter conforms
"""
# test_cases = {
# 'content_types': lambda msg: msg.content_type in filter_value,
# 'regexp': lambda msg: msg.content_type == 'text' and re.search(filter_value, msg.text, re.IGNORECASE),
# 'commands': lambda msg: msg.content_type == 'text' and util.extract_command(msg.text) in filter_value,
# 'func': lambda msg: filter_value(msg)
# }
# return test_cases.get(message_filter, lambda msg: False)(message)
if message_filter == 'content_types':
return message.content_type in filter_value
elif message_filter == 'regexp':
@ -3444,3 +3478,8 @@ class TeleBot:
if self._test_message_handler(message_handler, message):
self._exec_task(message_handler['function'], message, pass_bot=message_handler['pass_bot'], task_type='handler')
break

View File

@ -3,6 +3,7 @@ from datetime import datetime
import logging
import re
import sys
import time
import traceback
from typing import Any, List, Optional, Union
@ -21,14 +22,17 @@ from telebot import logger
from telebot import util, types, asyncio_helper
import asyncio
from telebot import asyncio_handler_backends
from telebot import asyncio_filters
REPLY_MARKUP_TYPES = Union[
types.InlineKeyboardMarkup, types.ReplyKeyboardMarkup,
types.ReplyKeyboardRemove, types.ForceReply]
"""
Module : telebot
"""
@ -38,6 +42,7 @@ class Handler:
"""
Class for (next step|reply) handlers
"""
def __init__(self, callback, *args, **kwargs):
self.callback = callback
self.args = args
@ -305,6 +310,7 @@ class AsyncTeleBot:
return
except asyncio.CancelledError:
return
except asyncio_helper.RequestTimeout as e:
logger.error(str(e))
if non_stop:
@ -312,12 +318,16 @@ class AsyncTeleBot:
continue
else:
return
except asyncio_helper.ApiTelegramException as e:
logger.error(str(e))
if non_stop:
continue
else:
break
except KeyboardInterrupt:
return
except Exception as e:
logger.error('Cause exception while getting updates.')
if non_stop:
@ -325,12 +335,14 @@ class AsyncTeleBot:
await asyncio.sleep(3)
continue
else:
raise e
raise e
finally:
self._polling = False
await self.close_session()
logger.warning('Polling is stopped.')
def _loop_create_task(self, coro):
return asyncio.create_task(coro)
@ -345,7 +357,8 @@ class AsyncTeleBot:
for message in messages:
middleware = await self.process_middlewares(message, update_type)
tasks.append(self._run_middlewares_and_handlers(handlers, message, middleware))
await asyncio.gather(*tasks)
asyncio.gather(*tasks)
async def _run_middlewares_and_handlers(self, handlers, message, middleware):
handler_error = None
@ -777,7 +790,6 @@ class AsyncTeleBot:
def register_edited_message_handler(self, callback, content_types=None, commands=None, regexp=None, func=None, chat_types=None, pass_bot=False, **kwargs):
"""
Registers edited message handler.
:param pass_bot:
:param callback: function to be called
:param content_types: list of content_types
:param commands: list of commands
@ -849,7 +861,6 @@ class AsyncTeleBot:
def register_channel_post_handler(self, callback, content_types=None, commands=None, regexp=None, func=None, pass_bot=False, **kwargs):
"""
Registers channel post message handler.
:param pass_bot:
:param callback: function to be called
:param content_types: list of content_types
:param commands: list of commands
@ -918,7 +929,6 @@ class AsyncTeleBot:
def register_edited_channel_post_handler(self, callback, content_types=None, commands=None, regexp=None, func=None, pass_bot=False, **kwargs):
"""
Registers edited channel post message handler.
:param pass_bot:
:param callback: function to be called
:param content_types: list of content_types
:param commands: list of commands
@ -969,7 +979,6 @@ class AsyncTeleBot:
def register_inline_handler(self, callback, func, pass_bot=False, **kwargs):
"""
Registers inline handler.
:param pass_bot:
:param callback: function to be called
:param func:
:return: decorated function
@ -1003,7 +1012,6 @@ class AsyncTeleBot:
def register_chosen_inline_handler(self, callback, func, pass_bot=False, **kwargs):
"""
Registers chosen inline handler.
:param pass_bot:
:param callback: function to be called
:param func:
:return: decorated function
@ -1037,7 +1045,6 @@ class AsyncTeleBot:
def register_callback_query_handler(self, callback, func, pass_bot=False, **kwargs):
"""
Registers callback query handler..
:param pass_bot:
:param callback: function to be called
:param func:
:return: decorated function
@ -1071,7 +1078,6 @@ class AsyncTeleBot:
def register_shipping_query_handler(self, callback, func, pass_bot=False, **kwargs):
"""
Registers shipping query handler.
:param pass_bot:
:param callback: function to be called
:param func:
:return: decorated function
@ -1105,7 +1111,6 @@ class AsyncTeleBot:
def register_pre_checkout_query_handler(self, callback, func, pass_bot=False, **kwargs):
"""
Registers pre-checkout request handler.
:param pass_bot:
:param callback: function to be called
:param func:
:return: decorated function
@ -1139,7 +1144,6 @@ class AsyncTeleBot:
def register_poll_handler(self, callback, func, pass_bot=False, **kwargs):
"""
Registers poll handler.
:param pass_bot:
:param callback: function to be called
:param func:
:return: decorated function
@ -1173,7 +1177,6 @@ class AsyncTeleBot:
def register_poll_answer_handler(self, callback, func, pass_bot=False, **kwargs):
"""
Registers poll answer handler.
:param pass_bot:
:param callback: function to be called
:param func:
:return: decorated function
@ -1207,7 +1210,6 @@ class AsyncTeleBot:
def register_my_chat_member_handler(self, callback, func=None, pass_bot=False, **kwargs):
"""
Registers my chat member handler.
:param pass_bot:
:param callback: function to be called
:param func:
:return: decorated function
@ -1241,7 +1243,6 @@ class AsyncTeleBot:
def register_chat_member_handler(self, callback, func=None, pass_bot=False, **kwargs):
"""
Registers chat member handler.
:param pass_bot:
:param callback: function to be called
:param func:
:return: decorated function
@ -1275,7 +1276,6 @@ class AsyncTeleBot:
def register_chat_join_request_handler(self, callback, func=None, pass_bot=False, **kwargs):
"""
Registers chat join request handler.
:param pass_bot:
:param callback: function to be called
:param func:
:return: decorated function
@ -1403,7 +1403,7 @@ class AsyncTeleBot:
"""
Alternative for delete_webhook but uses set_webhook
"""
await self.set_webhook()
self.set_webhook()
async def get_webhook_info(self, timeout=None):
"""
@ -3061,7 +3061,6 @@ class AsyncTeleBot:
async def set_state(self, user_id: int, state: str, chat_id: int=None):
"""
Sets a new state of a user.
:param user_id:
:param chat_id:
:param state: new state. can be string or integer.
"""
@ -3082,7 +3081,6 @@ class AsyncTeleBot:
async def delete_state(self, user_id: int, chat_id:int=None):
"""
Delete the current state of a user.
:param user_id:
:param chat_id:
:return:
"""
@ -3098,7 +3096,6 @@ class AsyncTeleBot:
async def get_state(self, user_id, chat_id: int=None):
"""
Get current state of a user.
:param user_id:
:param chat_id:
:return: state of a user
"""
@ -3109,7 +3106,6 @@ class AsyncTeleBot:
async def add_data(self, user_id: int, chat_id: int=None, **kwargs):
"""
Add data to states.
:param user_id:
:param chat_id:
"""
if not chat_id:

View File

@ -1,3 +1,8 @@
import os
import pickle
class BaseMiddleware:
"""
Base class for middleware.
@ -27,3 +32,4 @@ class StatesGroup:
if not name.startswith('__') and not callable(value) and isinstance(value, State):
# change value of that variable
value.name = ':'.join((cls.__name__, name))

View File

@ -43,7 +43,6 @@ class SessionManager:
if self.session.closed:
self.session = await self.create_session()
# noinspection PyProtectedMember
if not self.session._loop.is_running():
await self.session.close()
self.session = await self.create_session()

View File

@ -43,10 +43,11 @@ class StateStorageBase:
async def get_state(self, chat_id, user_id):
raise NotImplementedError
async def save(self, chat_id, user_id, data):
async def save(chat_id, user_id, data):
raise NotImplementedError
class StateContext:
"""
Class for data.

View File

@ -1,3 +1,4 @@
from pickle import FALSE
from telebot.asyncio_storage.base_storage import StateStorageBase, StateContext
import json
@ -92,6 +93,7 @@ class StateRedisStorage(StateStorageBase):
return True
return False
async def get_value(self, chat_id, user_id, key):
"""
Get value for a data of a user in a chat.
@ -103,6 +105,7 @@ class StateRedisStorage(StateStorageBase):
if key in response[user_id]['data']:
return response[user_id]['data'][key]
return None
async def get_state(self, chat_id, user_id):
"""
@ -116,6 +119,7 @@ class StateRedisStorage(StateStorageBase):
return None
async def get_data(self, chat_id, user_id):
"""
Get data of particular user in a particular chat.
@ -127,6 +131,7 @@ class StateRedisStorage(StateStorageBase):
return response[user_id]['data']
return None
async def reset_data(self, chat_id, user_id):
"""
Reset data of a user in a chat.
@ -139,6 +144,9 @@ class StateRedisStorage(StateStorageBase):
await self.set_record(chat_id, response)
return True
async def set_data(self, chat_id, user_id, key, value):
"""
Set data without interactive data.
@ -167,3 +175,4 @@ class StateRedisStorage(StateStorageBase):
response[user_id]['data'] = dict(data, **response[user_id]['data'])
await self.set_record(chat_id, response)
return True

View File

@ -42,7 +42,7 @@ class StateStorageBase:
def get_state(self, chat_id, user_id):
raise NotImplementedError
def save(self, chat_id, user_id, data):
def save(chat_id, user_id, data):
raise NotImplementedError

View File

@ -6,7 +6,6 @@ import pickle
class StatePickleStorage(StateStorageBase):
# noinspection PyMissingConstructor
def __init__(self, file_path="./.state-save/states.pkl") -> None:
self.file_path = file_path
self.create_dir()
@ -110,4 +109,4 @@ class StatePickleStorage(StateStorageBase):
def save(self, chat_id, user_id, data):
self.data[chat_id][user_id]['data'] = data
self.update_data()
self.update_data()

View File

@ -4,6 +4,7 @@ import re
import string
import threading
import traceback
import warnings
from typing import Any, Callable, List, Dict, Optional, Union
# noinspection PyPep8Naming
@ -407,7 +408,6 @@ def OrEvent(*events):
def busy_wait():
while not or_event.is_set():
# noinspection PyProtectedMember
or_event._wait(3)
for e in events:

View File

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