mirror of
https://github.com/eternnoir/pyTelegramBotAPI.git
synced 2023-08-10 21:12:57 +03:00
Compare commits
42 Commits
Author | SHA1 | Date | |
---|---|---|---|
4dce9340b0 | |||
bf79e8341e | |||
dadfdc2f13 | |||
585f627e1f | |||
eead303d47 | |||
14cc15c711 | |||
bf8736e17e | |||
5014ca2459 | |||
f337abe06e | |||
ff35f25211 | |||
2e4280a947 | |||
4a6b5b3d28 | |||
a28af3903d | |||
d1d5b9effb | |||
062fababf2 | |||
946afcc3c1 | |||
6e502cd1c6 | |||
0a7f897f05 | |||
b35f17124f | |||
44b44ac2c5 | |||
39e875c1ea | |||
be7317cc86 | |||
e1c33a1de6 | |||
8149551a15 | |||
ab648ef3db | |||
e721910c0c | |||
9287eced49 | |||
967b94b14f | |||
2df6f00ba5 | |||
beb4f8df44 | |||
92ac5a4166 | |||
716323e56a | |||
cd92d95f91 | |||
9c86ed623d | |||
c6ff9b07df | |||
38cc96d0f3 | |||
82518d8664 | |||
aba2a9e179 | |||
c5c4d081ea | |||
f854163626 | |||
fc31a2d466 | |||
86a0a8cd68 |
21
README.md
21
README.md
@ -121,13 +121,13 @@ This one echoes all incoming text messages back to the sender. It uses a lambda
|
||||
|
||||
We now have a basic bot which replies a static message to "/start" and "/help" commands and which echoes the rest of the sent messages. To start the bot, add the following to our source file:
|
||||
```python
|
||||
bot.polling()
|
||||
bot.infinity_polling()
|
||||
```
|
||||
Alright, that's it! Our source file now looks like this:
|
||||
```python
|
||||
import telebot
|
||||
|
||||
bot = telebot.TeleBot("TOKEN")
|
||||
bot = telebot.TeleBot("YOUR_BOT_TOKEN")
|
||||
|
||||
@bot.message_handler(commands=['start', 'help'])
|
||||
def send_welcome(message):
|
||||
@ -137,7 +137,7 @@ def send_welcome(message):
|
||||
def echo_all(message):
|
||||
bot.reply_to(message, message.text)
|
||||
|
||||
bot.polling()
|
||||
bot.infinity_polling()
|
||||
```
|
||||
To start the bot, simply open up a terminal and enter `python echo_bot.py` to run the bot! Test it by sending commands ('/start' and '/help') and arbitrary text messages.
|
||||
|
||||
@ -242,7 +242,7 @@ Handle edited channel post messages
|
||||
Handle callback queries
|
||||
```python
|
||||
@bot.callback_query_handler(func=lambda call: True)
|
||||
def test_callback(call): # <- passes a CallbackQuery type object to your function
|
||||
def test_callback(call): # <- passes a CallbackQuery type object to your function
|
||||
logger.info(call)
|
||||
```
|
||||
|
||||
@ -381,12 +381,10 @@ TOKEN = '<token_string>'
|
||||
tb = telebot.TeleBot(TOKEN) #create a new Telegram Bot object
|
||||
|
||||
# Upon calling this function, TeleBot starts polling the Telegram servers for new messages.
|
||||
# - none_stop: True/False (default False) - Don't stop polling when receiving an error from the Telegram servers
|
||||
# - interval: True/False (default False) - The interval between polling requests
|
||||
# Note: Editing this parameter harms the bot's response time
|
||||
# - interval: int (default 0) - The interval between polling requests
|
||||
# - timeout: integer (default 20) - Timeout in seconds for long polling.
|
||||
# - allowed_updates: List of Strings (default None) - List of update types to request
|
||||
tb.polling(none_stop=False, interval=0, timeout=20)
|
||||
tb.infinity_polling(interval=0, timeout=20)
|
||||
|
||||
# getMe
|
||||
user = tb.get_me()
|
||||
@ -398,6 +396,7 @@ tb.remove_webhook()
|
||||
|
||||
# getUpdates
|
||||
updates = tb.get_updates()
|
||||
# or
|
||||
updates = tb.get_updates(1234,100,20) #get_Updates(offset, limit, timeout):
|
||||
|
||||
# sendMessage
|
||||
@ -614,7 +613,7 @@ def handle_messages(messages):
|
||||
bot.reply_to(message, 'Hi')
|
||||
|
||||
bot.set_update_listener(handle_messages)
|
||||
bot.polling()
|
||||
bot.infinity_polling()
|
||||
```
|
||||
|
||||
### Using web hooks
|
||||
@ -760,5 +759,9 @@ Get help. Discuss. Chat.
|
||||
* [Anti-Tracking Bot](https://t.me/AntiTrackingBot) by Leon Heess [(source)](https://github.com/leonheess/AntiTrackingBot). Send any link, and the bot tries its best to remove all tracking from the link you sent.
|
||||
* [Developer Bot](https://t.me/IndDeveloper_bot) by [Vishal Singh](https://github.com/vishal2376) [(source code)](https://github.com/vishal2376/telegram-bot) This telegram bot can do tasks like GitHub search & clone,provide c++ learning resources ,Stackoverflow search, Codeforces(profile visualizer,random problems)
|
||||
* [oneIPO bot](https://github.com/aaditya2200/IPO-proj) by [Aadithya](https://github.com/aaditya2200) & [Amol Soans](https://github.com/AmolDerickSoans) This Telegram bot provides live updates , data and documents on current and upcoming IPOs(Initial Public Offerings)
|
||||
* [CoronaGraphsBot](https://t.me/CovidGraph_bot) ([source](https://github.com/TrevorWinstral/CoronaGraphsBot)) by *TrevorWinstral* - Gets live COVID Country data, plots it, and briefs the user
|
||||
* [ETHLectureBot](https://t.me/ETHLectureBot) ([source](https://github.com/TrevorWinstral/ETHLectureBot)) by *TrevorWinstral* - Notifies ETH students when their lectures have been uploaded
|
||||
|
||||
|
||||
|
||||
**Want to have your bot listed here? Just make a pull request. Only bots with public source code are accepted.**
|
||||
|
117
examples/anonymous_bot.py
Normal file
117
examples/anonymous_bot.py
Normal file
@ -0,0 +1,117 @@
|
||||
# This bot is needed to connect two people and their subsequent anonymous communication
|
||||
#
|
||||
# Avaiable commands:
|
||||
# `/start` - Just send you a messsage how to start
|
||||
# `/find` - Find a person you can contact
|
||||
# `/stop` - Stop active conversation
|
||||
|
||||
import telebot
|
||||
from telebot import types
|
||||
|
||||
# Initialize bot with your 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 = {}
|
||||
# The `freeid` variable is needed to contain chat id, that want to start conversation
|
||||
# Or, in other words: chat id of user in the search
|
||||
freeid = None
|
||||
|
||||
# `/start` command handler
|
||||
#
|
||||
# That command only sends you 'Just use /find command!'
|
||||
@bot.message_handler(commands=['start'])
|
||||
def start(message: types.Message):
|
||||
bot.send_message(message.chat.id, 'Just use /find command!')
|
||||
|
||||
# `/find` command handler
|
||||
#
|
||||
# That command finds opponent for you
|
||||
#
|
||||
# That command according to the following principle:
|
||||
# 1. You have written `/find` command
|
||||
# 2. If you are already in the search or have an active dialog, bot sends you 'Shut up!'
|
||||
# 3. If not:
|
||||
# 3.1. Bot sends you 'Finding...'
|
||||
# 3.2. If there is no user in the search:
|
||||
# 3.2.2. `freeid` updated with `your_chat_id`
|
||||
# 3.3. If there is user in the search:
|
||||
# 3.3.1. Both you and the user in the search recieve the message 'Founded!'
|
||||
# 3.3.2. `users` updated with a {user_in_the_search_chat_id, your_chat_id}
|
||||
# 3.3.3. `users` updated with a {your_chat_id, user_in_the_search_id}
|
||||
# 3.3.4. `freeid` updated with `None`
|
||||
@bot.message_handler(commands=['find'])
|
||||
def find(message: types.Message):
|
||||
global freeid
|
||||
|
||||
if message.chat.id not in users:
|
||||
bot.send_message(message.chat.id, 'Finding...')
|
||||
|
||||
if freeid == None:
|
||||
freeid = message.chat.id
|
||||
else:
|
||||
# Question:
|
||||
# Is there any way to simplify this like `bot.send_message([message.chat.id, freeid], 'Founded!')`?
|
||||
bot.send_message(message.chat.id, 'Founded!')
|
||||
bot.send_message(freeid, 'Founded!')
|
||||
|
||||
users[freeid] = message.chat.id
|
||||
users[message.chat.id] = freeid
|
||||
freeid = None
|
||||
|
||||
print(users, freeid) # Debug purpose, you can remove that line
|
||||
else:
|
||||
bot.send_message(message.chat.id, 'Shut up!')
|
||||
|
||||
# `/stop` command handler
|
||||
#
|
||||
# That command stops your current conversation (if it exist)
|
||||
#
|
||||
# That command according to the following principle:
|
||||
# 1. You have written `/stop` command
|
||||
# 2. If you are not have active dialog or you are not in search, bot sends you 'You are not in search!'
|
||||
# 3. If you are in active dialog:
|
||||
# 3.1. Bot sends you 'Stopping...'
|
||||
# 3.2. Bot sends 'Your opponent is leavin`...' to your opponent
|
||||
# 3.3. {your_opponent_chat_id, your_chat_id} removes from `users`
|
||||
# 3.4. {your_chat_id, your_opponent_chat_id} removes from `users`
|
||||
# 4. If you are only in search:
|
||||
# 4.1. Bot sends you 'Stopping...'
|
||||
# 4.2. `freeid` updated with `None`
|
||||
@bot.message_handler(commands=['stop'])
|
||||
def stop(message: types.Message):
|
||||
global freeid
|
||||
|
||||
if message.chat.id in users:
|
||||
bot.send_message(message.chat.id, 'Stopping...')
|
||||
bot.send_message(users[message.chat.id], 'Your opponent is leavin`...')
|
||||
|
||||
del users[users[message.chat.id]]
|
||||
del users[message.chat.id]
|
||||
|
||||
print(users, freeid) # Debug purpose, you can remove that line
|
||||
elif message.chat.id == freeid:
|
||||
bot.send_message(message.chat.id, 'Stopping...')
|
||||
freeid = None
|
||||
|
||||
print(users, freeid) # Debug purpose, you can remove that line
|
||||
else:
|
||||
bot.send_message(message.chat.id, 'You are not in search!')
|
||||
|
||||
# message handler for conversation
|
||||
#
|
||||
# That handler needed to send message from one opponent to another
|
||||
# If you are not in `users`, you will recieve a message 'No one can hear you...'
|
||||
# Otherwise all your messages are sent to your opponent
|
||||
#
|
||||
# Questions:
|
||||
# 1. Is there any way to improve readability like `content_types=['all']`?
|
||||
# 2. Is there any way to register this message handler only when i found the opponent?
|
||||
@bot.message_handler(content_types=['animation', 'audio', 'contact', 'dice', 'document', 'location', 'photo', 'poll', 'sticker', 'text', 'venue', 'video', 'video_note', 'voice'])
|
||||
def chatting(message: types.Message):
|
||||
if message.chat.id in users:
|
||||
bot.copy_message(users[message.chat.id], users[users[message.chat.id]], message.id)
|
||||
else:
|
||||
bot.send_message(message.chat.id, 'No one can hear you...')
|
||||
|
||||
bot.infinity_polling(skip_pending=True)
|
@ -30,4 +30,4 @@ def my_chat_m(message: types.ChatMemberUpdated):
|
||||
@bot.message_handler(content_types=util.content_type_service)
|
||||
def delall(message: types.Message):
|
||||
bot.delete_message(message.chat.id,message.message_id)
|
||||
bot.polling(allowed_updates=util.update_types)
|
||||
bot.infinity_polling(allowed_updates=util.update_types)
|
||||
|
12
examples/custom_filters/admin_filter_example.py
Normal file
12
examples/custom_filters/admin_filter_example.py
Normal file
@ -0,0 +1,12 @@
|
||||
import telebot
|
||||
from telebot import custom_filters
|
||||
bot = telebot.TeleBot('TOKEN')
|
||||
|
||||
# Handler
|
||||
@bot.message_handler(chat_types=['supergroup'], is_chat_admin=True)
|
||||
def answer_for_admin(message):
|
||||
bot.send_message(message.chat.id,"hello my admin")
|
||||
|
||||
# Register filter
|
||||
bot.add_custom_filter(custom_filters.IsAdminFilter(bot))
|
||||
bot.infinity_polling()
|
@ -39,4 +39,4 @@ def bye_user(message):
|
||||
bot.add_custom_filter(MainFilter())
|
||||
bot.add_custom_filter(IsAdmin())
|
||||
|
||||
bot.polling(skip_pending=True,non_stop=True) # Skip old updates
|
||||
bot.infinity_polling(skip_pending=True) # Skip old updates
|
||||
|
@ -13,10 +13,7 @@ def admin_rep(message):
|
||||
def not_admin(message):
|
||||
bot.send_message(message.chat.id, "You are not allowed to use this command")
|
||||
|
||||
|
||||
# Do not forget to register
|
||||
bot.add_custom_filter(custom_filters.ChatFilter())
|
||||
|
||||
|
||||
bot.polling(non_stop=True)
|
||||
|
||||
bot.infinity_polling()
|
||||
|
21
examples/custom_filters/is_filter_example.py
Normal file
21
examples/custom_filters/is_filter_example.py
Normal file
@ -0,0 +1,21 @@
|
||||
import telebot
|
||||
from telebot import custom_filters
|
||||
|
||||
bot = telebot.TeleBot('TOKEN')
|
||||
|
||||
|
||||
# Check if message is a reply
|
||||
@bot.message_handler(is_reply=True)
|
||||
def start_filter(message):
|
||||
bot.send_message(message.chat.id, "Looks like you replied to my message.")
|
||||
|
||||
# Check if message was forwarded
|
||||
@bot.message_handler(is_forwarded=True)
|
||||
def text_filter(message):
|
||||
bot.send_message(message.chat.id, "I do not accept forwarded messages!")
|
||||
|
||||
# Do not forget to register filters
|
||||
bot.add_custom_filter(custom_filters.IsReplyFilter())
|
||||
bot.add_custom_filter(custom_filters.ForwardFilter())
|
||||
|
||||
bot.infinity_polling()
|
@ -18,4 +18,4 @@ def text_filter(message):
|
||||
bot.add_custom_filter(custom_filters.TextMatchFilter())
|
||||
bot.add_custom_filter(custom_filters.TextStartsFilter())
|
||||
|
||||
bot.polling(non_stop=True)
|
||||
bot.infinity_polling()
|
||||
|
64
examples/custom_states.py
Normal file
64
examples/custom_states.py
Normal file
@ -0,0 +1,64 @@
|
||||
import telebot
|
||||
|
||||
from telebot import custom_filters
|
||||
|
||||
bot = telebot.TeleBot("")
|
||||
|
||||
|
||||
|
||||
@bot.message_handler(commands=['start'])
|
||||
def start_ex(message):
|
||||
"""
|
||||
Start command. Here we are starting state
|
||||
"""
|
||||
bot.set_state(message.chat.id, 1)
|
||||
bot.send_message(message.chat.id, 'Hi, write me a name')
|
||||
|
||||
|
||||
|
||||
@bot.message_handler(state="*", commands='cancel')
|
||||
def any_state(message):
|
||||
"""
|
||||
Cancel state
|
||||
"""
|
||||
bot.send_message(message.chat.id, "Your state was cancelled.")
|
||||
bot.delete_state(message.chat.id)
|
||||
|
||||
@bot.message_handler(state=1)
|
||||
def name_get(message):
|
||||
"""
|
||||
State 1. Will process when user's state is 1.
|
||||
"""
|
||||
bot.send_message(message.chat.id, f'Now write me a surname')
|
||||
bot.set_state(message.chat.id, 2)
|
||||
with bot.retrieve_data(message.chat.id) as data:
|
||||
data['name'] = message.text
|
||||
|
||||
|
||||
@bot.message_handler(state=2)
|
||||
def ask_age(message):
|
||||
"""
|
||||
State 2. Will process when user's state is 2.
|
||||
"""
|
||||
bot.send_message(message.chat.id, "What is your age?")
|
||||
bot.set_state(message.chat.id, 3)
|
||||
with bot.retrieve_data(message.chat.id) as data:
|
||||
data['surname'] = message.text
|
||||
|
||||
# result
|
||||
@bot.message_handler(state=3, is_digit=True)
|
||||
def ready_for_answer(message):
|
||||
with bot.retrieve_data(message.chat.id) as data:
|
||||
bot.send_message(message.chat.id, "Ready, take a look:\n<b>Name: {name}\nSurname: {surname}\nAge: {age}</b>".format(name=data['name'], surname=data['surname'], age=message.text), parse_mode="html")
|
||||
bot.delete_state(message.chat.id)
|
||||
|
||||
#incorrect number
|
||||
@bot.message_handler(state=3, is_digit=False)
|
||||
def age_incorrect(message):
|
||||
bot.send_message(message.chat.id, 'Looks like you are submitting a string in the field age. Please enter a number')
|
||||
|
||||
# register filters
|
||||
|
||||
bot.add_custom_filter(custom_filters.StateFilter(bot))
|
||||
bot.add_custom_filter(custom_filters.IsDigitFilter())
|
||||
bot.infinity_polling(skip_pending=True)
|
@ -74,4 +74,4 @@ def send_welcome(message):
|
||||
bot.reply_to(message, reply)
|
||||
|
||||
|
||||
bot.polling()
|
||||
bot.infinity_polling()
|
||||
|
@ -130,4 +130,4 @@ def command_default(m):
|
||||
bot.send_message(m.chat.id, "I don't understand \"" + m.text + "\"\nMaybe try the help page at /help")
|
||||
|
||||
|
||||
bot.polling()
|
||||
bot.infinity_polling()
|
||||
|
@ -25,4 +25,4 @@ def echo_message(message):
|
||||
bot.reply_to(message, message.text)
|
||||
|
||||
|
||||
bot.polling()
|
||||
bot.infinity_polling()
|
||||
|
@ -61,7 +61,7 @@ def default_query(inline_query):
|
||||
|
||||
|
||||
def main_loop():
|
||||
bot.polling(True)
|
||||
bot.infinity_polling()
|
||||
while 1:
|
||||
time.sleep(3)
|
||||
|
||||
|
@ -24,4 +24,4 @@ def callback_query(call):
|
||||
def message_handler(message):
|
||||
bot.send_message(message.chat.id, "Yes/no?", reply_markup=gen_markup())
|
||||
|
||||
bot.polling(none_stop=True)
|
||||
bot.infinity_polling()
|
||||
|
@ -50,4 +50,4 @@ def start(message):
|
||||
bot.send_message(message.chat.id, _('hello'))
|
||||
|
||||
|
||||
bot.polling()
|
||||
bot.infinity_polling()
|
||||
|
@ -58,4 +58,4 @@ def start(message):
|
||||
bot.send_message(message.chat.id, bot.session['state'])
|
||||
|
||||
|
||||
bot.polling()
|
||||
bot.infinity_polling()
|
||||
|
@ -78,5 +78,4 @@ def got_payment(message):
|
||||
parse_mode='Markdown')
|
||||
|
||||
|
||||
bot.skip_pending = True
|
||||
bot.polling(none_stop=True, interval=0)
|
||||
bot.infinity_polling(skip_pending = True)
|
||||
|
21
examples/register_handler.py
Normal file
21
examples/register_handler.py
Normal file
@ -0,0 +1,21 @@
|
||||
import telebot
|
||||
|
||||
api_token = 'token'
|
||||
|
||||
bot = telebot.TeleBot(api_token)
|
||||
|
||||
def start_executor(message):
|
||||
bot.send_message(message.chat.id, 'Hello!')
|
||||
|
||||
bot.register_message_handler(start_executor, commands=['start']) # Start command executor
|
||||
|
||||
# See also
|
||||
# bot.register_callback_query_handler(*args, **kwargs)
|
||||
# bot.register_channel_post_handler(*args, **kwargs)
|
||||
# bot.register_chat_member_handler(*args, **kwargs)
|
||||
# bot.register_inline_handler(*args, **kwargs)
|
||||
# bot.register_my_chat_member_handler(*args, **kwargs)
|
||||
# bot.register_edited_message_handler(*args, **kwargs)
|
||||
# And other functions..
|
||||
|
||||
bot.infinity_polling()
|
@ -10,4 +10,4 @@ def send_welcome(message):
|
||||
def echo_all(message):
|
||||
bot.reply_to(message, message.text)
|
||||
|
||||
bot.polling(skip_pending=True)# Skip pending skips old updates
|
||||
bot.infinity_polling(skip_pending=True)# Skip pending skips old updates
|
||||
|
@ -83,4 +83,4 @@ bot.enable_save_next_step_handlers(delay=2)
|
||||
# WARNING It will work only if enable_save_next_step_handlers was called!
|
||||
bot.load_next_step_handlers()
|
||||
|
||||
bot.polling()
|
||||
bot.infinity_polling()
|
||||
|
@ -81,4 +81,4 @@ def listener(messages):
|
||||
|
||||
|
||||
bot.set_update_listener(listener)
|
||||
bot.polling()
|
||||
bot.infinity_polling()
|
||||
|
@ -27,7 +27,7 @@ logger.addHandler(console_output_handler)
|
||||
logger.setLevel(logging.ERROR)
|
||||
|
||||
from telebot import apihelper, util, types
|
||||
from telebot.handler_backends import MemoryHandlerBackend, FileHandlerBackend
|
||||
from telebot.handler_backends import MemoryHandlerBackend, FileHandlerBackend, State
|
||||
|
||||
|
||||
REPLY_MARKUP_TYPES = Union[
|
||||
@ -186,6 +186,9 @@ class TeleBot:
|
||||
self.my_chat_member_handlers = []
|
||||
self.chat_member_handlers = []
|
||||
self.custom_filters = {}
|
||||
self.state_handlers = []
|
||||
|
||||
self.current_states = State()
|
||||
|
||||
if apihelper.ENABLE_MIDDLEWARE:
|
||||
self.typed_middleware_handlers = {
|
||||
@ -208,6 +211,16 @@ class TeleBot:
|
||||
self.threaded = threaded
|
||||
if self.threaded:
|
||||
self.worker_pool = util.ThreadPool(num_threads=num_threads)
|
||||
|
||||
@property
|
||||
def user(self) -> types.User:
|
||||
"""
|
||||
The User object representing this bot.
|
||||
Equivalent to bot.get_me() but the result is cached so only one API call is needed
|
||||
"""
|
||||
if not hasattr(self, "_user"):
|
||||
self._user = types.User.de_json(self.get_me())
|
||||
return self._user
|
||||
|
||||
def enable_save_next_step_handlers(self, delay=120, filename="./.handler-saves/step.save"):
|
||||
"""
|
||||
@ -549,8 +562,9 @@ class TeleBot:
|
||||
for listener in self.update_listener:
|
||||
self._exec_task(listener, new_messages)
|
||||
|
||||
def infinity_polling(self, timeout=20, skip_pending=False, long_polling_timeout=20, logger_level=logging.ERROR,
|
||||
allowed_updates=None, *args, **kwargs):
|
||||
|
||||
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):
|
||||
"""
|
||||
Wrap polling with infinite loop and exception handling to avoid bot stops polling.
|
||||
|
||||
@ -659,7 +673,10 @@ class TeleBot:
|
||||
# self.worker_pool.clear_exceptions()
|
||||
logger.info("Waiting for {0} seconds until retry".format(error_interval))
|
||||
time.sleep(error_interval)
|
||||
error_interval *= 2
|
||||
if error_interval * 2 < 60:
|
||||
error_interval *= 2
|
||||
else:
|
||||
error_interval = 60
|
||||
else:
|
||||
# polling_thread.clear_exceptions()
|
||||
# self.worker_pool.clear_exceptions()
|
||||
@ -2352,6 +2369,41 @@ class TeleBot:
|
||||
chat_id = message.chat.id
|
||||
self.register_next_step_handler_by_chat_id(chat_id, callback, *args, **kwargs)
|
||||
|
||||
def set_state(self, chat_id, state):
|
||||
"""
|
||||
Sets a new state of a user.
|
||||
:param chat_id:
|
||||
:param state: new state. can be string or integer.
|
||||
"""
|
||||
self.current_states.add_state(chat_id, state)
|
||||
|
||||
def delete_state(self, chat_id):
|
||||
"""
|
||||
Delete the current state of a user.
|
||||
:param chat_id:
|
||||
:return:
|
||||
"""
|
||||
self.current_states.delete_state(chat_id)
|
||||
|
||||
def retrieve_data(self, chat_id):
|
||||
return self.current_states.retrieve_data(chat_id)
|
||||
|
||||
def get_state(self, chat_id):
|
||||
"""
|
||||
Get current state of a user.
|
||||
:param chat_id:
|
||||
:return: state of a user
|
||||
"""
|
||||
return self.current_states.current_state(chat_id)
|
||||
|
||||
def add_data(self, chat_id, **kwargs):
|
||||
"""
|
||||
Add data to states.
|
||||
:param chat_id:
|
||||
"""
|
||||
for key, value in kwargs.items():
|
||||
self.current_states._add_data(chat_id, key, value)
|
||||
|
||||
def register_next_step_handler_by_chat_id(
|
||||
self, chat_id: Union[int, str], callback: Callable, *args, **kwargs) -> None:
|
||||
"""
|
||||
@ -2416,6 +2468,7 @@ class TeleBot:
|
||||
if need_pop:
|
||||
new_messages.pop(i) # removing message that was detected with next_step_handler
|
||||
|
||||
|
||||
@staticmethod
|
||||
def _build_handler_dict(handler, **filters):
|
||||
"""
|
||||
@ -2651,6 +2704,7 @@ class TeleBot:
|
||||
**kwargs)
|
||||
self.add_edited_message_handler(handler_dict)
|
||||
|
||||
|
||||
def channel_post_handler(self, commands=None, regexp=None, func=None, content_types=None, **kwargs):
|
||||
"""
|
||||
Channel post handler decorator
|
||||
|
@ -87,7 +87,7 @@ class ChatFilter(AdvancedCustomFilter):
|
||||
|
||||
class ForwardFilter(SimpleCustomFilter):
|
||||
"""
|
||||
Check whether message was forwarded.
|
||||
Check whether message was forwarded from channel or group.
|
||||
|
||||
Example:
|
||||
|
||||
@ -130,3 +130,47 @@ class LanguageFilter(AdvancedCustomFilter):
|
||||
if type(text) is list:return message.from_user.language_code in text
|
||||
else: return message.from_user.language_code == text
|
||||
|
||||
class IsAdminFilter(SimpleCustomFilter):
|
||||
"""
|
||||
Check whether the user is administrator / owner of the chat.
|
||||
|
||||
Example:
|
||||
@bot.message_handler(chat_types=['supergroup'], is_chat_admin=True)
|
||||
"""
|
||||
|
||||
key = 'is_chat_admin'
|
||||
|
||||
def __init__(self, bot):
|
||||
self._bot = bot
|
||||
|
||||
def check(self, message):
|
||||
return self._bot.get_chat_member(message.chat.id, message.from_user.id).status in ['creator', 'administrator']
|
||||
|
||||
class StateFilter(AdvancedCustomFilter):
|
||||
"""
|
||||
Filter to check state.
|
||||
|
||||
Example:
|
||||
@bot.message_handler(state=1)
|
||||
"""
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
key = 'state'
|
||||
|
||||
def check(self, message, text):
|
||||
if self.bot.current_states.current_state(message.from_user.id) is False:return False
|
||||
elif text == '*':return True
|
||||
elif type(text) is list:return self.bot.current_states.current_state(message.from_user.id) in text
|
||||
return self.bot.current_states.current_state(message.from_user.id) == text
|
||||
|
||||
class IsDigitFilter(SimpleCustomFilter):
|
||||
"""
|
||||
Filter to check whether the string is made up of only digits.
|
||||
|
||||
Example:
|
||||
@bot.message_handler(is_digit=True)
|
||||
"""
|
||||
key = 'is_digit'
|
||||
|
||||
def check(self, message):
|
||||
return message.text.isdigit()
|
||||
|
@ -141,3 +141,79 @@ class RedisHandlerBackend(HandlerBackend):
|
||||
handlers = pickle.loads(value)
|
||||
self.clear_handlers(handler_group_id)
|
||||
return handlers
|
||||
|
||||
|
||||
class State:
|
||||
def __init__(self):
|
||||
self._states = {}
|
||||
|
||||
def add_state(self, chat_id, state):
|
||||
"""
|
||||
Add a state.
|
||||
:param chat_id:
|
||||
:param state: new state
|
||||
"""
|
||||
if chat_id in self._states:
|
||||
|
||||
self._states[chat_id]['state'] = state
|
||||
else:
|
||||
self._states[chat_id] = {'state': state,'data': {}}
|
||||
|
||||
def current_state(self, chat_id):
|
||||
"""Current state"""
|
||||
if chat_id in self._states: return self._states[chat_id]['state']
|
||||
else: return False
|
||||
|
||||
def delete_state(self, chat_id):
|
||||
"""Delete a state"""
|
||||
return self._states.pop(chat_id)
|
||||
|
||||
def _get_data(self, chat_id):
|
||||
return self._states[chat_id]['data']
|
||||
|
||||
def set(self, chat_id, new_state):
|
||||
"""
|
||||
Set a new state for a user.
|
||||
:param chat_id:
|
||||
:param new_state: new_state of a user
|
||||
"""
|
||||
self.add_state(chat_id,new_state)
|
||||
|
||||
def _add_data(self, chat_id, key, value):
|
||||
result = self._states[chat_id]['data'][key] = value
|
||||
return result
|
||||
|
||||
def finish(self, chat_id):
|
||||
"""
|
||||
Finish(delete) state of a user.
|
||||
:param chat_id:
|
||||
"""
|
||||
self.delete_state(chat_id)
|
||||
|
||||
def retrieve_data(self, chat_id):
|
||||
"""
|
||||
Save input text.
|
||||
|
||||
Usage:
|
||||
with state.retrieve_data(message.chat.id) as data:
|
||||
data['name'] = message.text
|
||||
|
||||
Also, at the end of your 'Form' you can get the name:
|
||||
data['name']
|
||||
"""
|
||||
return StateContext(self, chat_id)
|
||||
|
||||
class StateContext:
|
||||
"""
|
||||
Class for data.
|
||||
"""
|
||||
def __init__(self , obj: State, chat_id) -> None:
|
||||
self.obj = obj
|
||||
self.chat_id = chat_id
|
||||
self.data = obj._get_data(chat_id)
|
||||
|
||||
def __enter__(self):
|
||||
return self.data
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
return
|
||||
|
@ -873,7 +873,7 @@ class ForceReply(JsonSerializable):
|
||||
def to_json(self):
|
||||
json_dict = {'force_reply': True}
|
||||
if self.selective is not None:
|
||||
json_dict['selective'] = True
|
||||
json_dict['selective'] = self.selective
|
||||
if self.input_field_placeholder:
|
||||
json_dict['input_field_placeholder'] = self.input_field_placeholder
|
||||
return json.dumps(json_dict)
|
||||
@ -886,7 +886,7 @@ class ReplyKeyboardRemove(JsonSerializable):
|
||||
def to_json(self):
|
||||
json_dict = {'remove_keyboard': True}
|
||||
if self.selective:
|
||||
json_dict['selective'] = True
|
||||
json_dict['selective'] = self.selective
|
||||
return json.dumps(json_dict)
|
||||
|
||||
|
||||
@ -960,11 +960,11 @@ class ReplyKeyboardMarkup(JsonSerializable):
|
||||
"""
|
||||
json_dict = {'keyboard': self.keyboard}
|
||||
if self.one_time_keyboard is not None:
|
||||
json_dict['one_time_keyboard'] = True
|
||||
json_dict['one_time_keyboard'] = self.one_time_keyboard
|
||||
if self.resize_keyboard is not None:
|
||||
json_dict['resize_keyboard'] = True
|
||||
json_dict['resize_keyboard'] = self.resize_keyboard
|
||||
if self.selective is not None:
|
||||
json_dict['selective'] = True
|
||||
json_dict['selective'] = self.selective
|
||||
if self.input_field_placeholder:
|
||||
json_dict['input_field_placeholder'] = self.input_field_placeholder
|
||||
return json.dumps(json_dict)
|
||||
|
@ -1,3 +1,3 @@
|
||||
# Versions should comply with PEP440.
|
||||
# This line is parsed in setup.py:
|
||||
__version__ = '4.0.1'
|
||||
__version__ = '4.1.0'
|
||||
|
Reference in New Issue
Block a user