mirror of
https://github.com/eternnoir/pyTelegramBotAPI.git
synced 2023-08-10 21:12:57 +03:00
Merge branch 'master' into patch-2
This commit is contained in:
commit
f8e7c0f819
22
README.md
22
README.md
@ -26,6 +26,7 @@
|
||||
* [Using web hooks](#using-web-hooks)
|
||||
* [Logging](#logging)
|
||||
* [Proxy](#proxy)
|
||||
* [New in library](#new-in-library)
|
||||
* [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)
|
||||
@ -510,6 +511,10 @@ apihelper.proxy = {'https':'socks5://userproxy:password@proxy_address:port'}
|
||||
```
|
||||
|
||||
|
||||
## New in library
|
||||
|
||||
06.06.2019 - Добавленна поддержка опросов (Poll). Добавлены функции send_poll, stop_poll
|
||||
|
||||
## F.A.Q.
|
||||
|
||||
### Bot 2.0
|
||||
@ -524,16 +529,16 @@ Telegram Bot API support new type Chat for message.chat.
|
||||
- Check the ```type``` attribute in ```Chat``` object:
|
||||
-
|
||||
```python
|
||||
if message.chat.type == “private”:
|
||||
if message.chat.type == "private":
|
||||
# private chat message
|
||||
|
||||
if message.chat.type == “group”:
|
||||
if message.chat.type == "group":
|
||||
# group chat message
|
||||
|
||||
if message.chat.type == “supergroup”:
|
||||
if message.chat.type == "supergroup":
|
||||
# supergroup chat message
|
||||
|
||||
if message.chat.type == “channel”:
|
||||
if message.chat.type == "channel":
|
||||
# channel message
|
||||
|
||||
```
|
||||
@ -576,7 +581,6 @@ Get help. Discuss. Chat.
|
||||
* [EmaProject](https://github.com/halkliff/emaproject) by [*halkliff*](https://github.com/halkliff) - Ema - Eastern Media Assistant was made thinking on the ease-to-use feature. Coding here is simple, as much as is fast and powerful.
|
||||
* [filmratingbot](http://t.me/filmratingbot)([source](https://github.com/jcolladosp/film-rating-bot)) by [*jcolladosp*](https://github.com/jcolladosp) - Telegram bot using the Python API that gets films rating from IMDb and metacritic
|
||||
* [you2mp3bot](http://t.me/you2mp3bot)([link](https://storebot.me/bot/you2mp3bot)) - This bot can convert a Youtube video to Mp3. All you need is send the URL video.
|
||||
* [areajugonesbot](http://t.me/areajugonesbot)([link](http://t.me/areajugonesbot)) - The areajugonesbot sends news published on the videogames blog Areajugones to Telegram.
|
||||
* [Send2Kindlebot](http://t.me/Send2KindleBot) ([source](https://github.com/GabrielRF/Send2KindleBot)) by *GabrielRF* - Send to Kindle service.
|
||||
* [RastreioBot](http://t.me/RastreioBot) ([source](https://github.com/GabrielRF/RastreioBot)) by *GabrielRF* - Bot used to track packages on the Brazilian Mail Service.
|
||||
* [filex_bot](http://t.me/filex_bot)([link](https://github.com/victor141516/FileXbot-telegram))
|
||||
@ -588,6 +592,12 @@ Get help. Discuss. Chat.
|
||||
* [Bot-Telegram-Shodan ](https://github.com/rubenleon/Bot-Telegram-Shodan) by [rubenleon](https://github.com/rubenleon)
|
||||
* [MandangoBot](https://t.me/MandangoBot) by @Alvaricias - Bot for managing Marvel Strike Force alliances (only in spanish, atm).
|
||||
* [ManjaroBot](https://t.me/ManjaroBot) by [@NeoRanger](https://github.com/neoranger) - Bot for Manjaro Linux Spanish group with a lot of info for Manjaro Newbies.
|
||||
|
||||
* [VigoBusTelegramBot](https://t.me/vigobusbot) ([GitHub](https://github.com/Pythoneiro/VigoBus-TelegramBot)) - Bot that provides buses coming to a certain stop and their remaining time for the city of Vigo (Galicia - Spain)
|
||||
* [kaishnik-bot](https://t.me/kaishnik_bot) ([source](https://github.com/airatk/kaishnik-bot)) by *airatk* - bot which shows all the necessary information to KNTRU-KAI students.
|
||||
* [Creation Date](https://t.me/creationdatebot) by @karipov - interpolates account creation dates based on telegram given ID’s
|
||||
* [m0xbot](https://t.me/m0xbot) by [kor0p](https://github.com/kor0p) - tic-tac-toe.
|
||||
* [kboardbot](https://t.me/kboardbot) by [kor0p](https://github.com/kor0p) - inline switches keyboard layout (English, Hebrew, Ukrainian, Russian).
|
||||
* [Robbie](https://t.me/romdeliverybot) ([source](https://github.com/FacuM/romdeliverybot_support)) by @FacuM - Support Telegram bot for developers and maintainers.
|
||||
* [AsadovBot](https://t.me/asadov_bot) ([source])(https://github.com/desexcile/BotApi)) by @DesExcile - Сatalog of poems by Eduard Asadov.
|
||||
|
||||
Want to have your bot listed here? Send a Telegram message to @eternnoir or @pevdh.
|
||||
|
@ -9,8 +9,8 @@ bot = telebot.TeleBot(TELEGRAM_TOKEN)
|
||||
def gen_markup():
|
||||
markup = InlineKeyboardMarkup()
|
||||
markup.row_width = 2
|
||||
markup.add(InlineKeyboardButton("Yes", callback_data=f"cb_yes"),
|
||||
InlineKeyboardButton("No", callback_data=f"cb_no"))
|
||||
markup.add(InlineKeyboardButton("Yes", callback_data="cb_yes"),
|
||||
InlineKeyboardButton("No", callback_data="cb_no"))
|
||||
return markup
|
||||
|
||||
@bot.callback_query_handler(func=lambda call: True)
|
||||
|
@ -86,11 +86,13 @@ def echo_message(message):
|
||||
|
||||
|
||||
# Remove webhook, it fails sometimes the set if there is a previous webhook
|
||||
bot.remove_webhook()
|
||||
#bot.remove_webhook()
|
||||
|
||||
# Set webhook
|
||||
bot.set_webhook(url=WEBHOOK_URL_BASE + WEBHOOK_URL_PATH,
|
||||
certificate=open(WEBHOOK_SSL_CERT, 'r'))
|
||||
# Beacuse telegram bot api server will check webhook server is alive.
|
||||
# Here we need set webhook after server started manually.
|
||||
#bot.set_webhook(url=WEBHOOK_URL_BASE + WEBHOOK_URL_PATH,
|
||||
# certificate=open(WEBHOOK_SSL_CERT, 'r'))
|
||||
|
||||
# Start server
|
||||
httpd = HTTPServer((WEBHOOK_LISTEN, WEBHOOK_PORT),
|
||||
|
@ -113,6 +113,7 @@ class TeleBot:
|
||||
getUserProfilePhotos
|
||||
getUpdates
|
||||
getFile
|
||||
sendPoll
|
||||
kickChatMember
|
||||
unbanChatMember
|
||||
restrictChatMember
|
||||
@ -364,12 +365,12 @@ class TeleBot:
|
||||
for listener in self.update_listener:
|
||||
self._exec_task(listener, new_messages)
|
||||
|
||||
def infinity_polling(self, *args, **kwargs):
|
||||
def infinity_polling(self, timeout=20, *args, **kwargs):
|
||||
while not self.__stop_polling.is_set():
|
||||
try:
|
||||
self.polling(*args, **kwargs)
|
||||
self.polling(timeout=timeout, *args, **kwargs)
|
||||
except Exception as e:
|
||||
time.sleep(5)
|
||||
time.sleep(timeout)
|
||||
pass
|
||||
logger.info("Break infinity polling")
|
||||
|
||||
@ -1044,6 +1045,12 @@ class TeleBot:
|
||||
disable_notification, reply_to_message_id, reply_markup, provider_data)
|
||||
return types.Message.de_json(result)
|
||||
|
||||
def send_poll(self, chat_id, poll, disable_notifications=False, reply_to_message=None, reply_markup=None):
|
||||
return types.Message.de_json(apihelper.send_poll(self.token, chat_id, poll.question, poll.options, disable_notifications, reply_to_message, reply_markup))
|
||||
|
||||
def stop_poll(self, chat_id, message_id):
|
||||
return types.Poll.de_json(apihelper.stop_poll(self.token, chat_id, message_id))
|
||||
|
||||
def answer_shipping_query(self, shipping_query_id, ok, shipping_options=None, error_message=None):
|
||||
return apihelper.answer_shipping_query(self.token, shipping_query_id, ok, shipping_options, error_message)
|
||||
|
||||
@ -1333,7 +1340,7 @@ class TeleBot:
|
||||
bot.send_message(message.chat.id, 'Document received, sir!')
|
||||
|
||||
# Handle all other commands.
|
||||
@bot.message_handler(func=lambda message: True, content_types=['audio', 'video', 'document', 'text', 'location', 'contact', 'sticker'])
|
||||
@bot.message_handler(func=lambda message: True, content_types=['audio', 'photo', 'voice', 'video', 'document', 'text', 'location', 'contact', 'sticker'])
|
||||
def default_command(message):
|
||||
bot.send_message(message.chat.id, "This is the default command handler.")
|
||||
|
||||
@ -1750,3 +1757,11 @@ class AsyncTeleBot(TeleBot):
|
||||
@util.async_dec()
|
||||
def delete_sticker_from_set(self, *args, **kwargs):
|
||||
return TeleBot.delete_sticker_from_set(self, *args, **kwargs)
|
||||
|
||||
@util.async_dec()
|
||||
def send_poll(self, *args, **kwargs):
|
||||
return TeleBot.send_poll(self, *args, **kwargs)
|
||||
|
||||
@util.async_dec()
|
||||
def stop_poll(self, *args, **kwargs):
|
||||
return TeleBot.stop_poll(self, *args, **kwargs)
|
||||
|
@ -619,7 +619,7 @@ def edit_message_text(token, text, chat_id=None, message_id=None, inline_message
|
||||
payload['disable_web_page_preview'] = disable_web_page_preview
|
||||
if reply_markup:
|
||||
payload['reply_markup'] = _convert_markup(reply_markup)
|
||||
return _make_request(token, method_url, params=payload)
|
||||
return _make_request(token, method_url, params=payload, method='post')
|
||||
|
||||
|
||||
def edit_message_caption(token, caption, chat_id=None, message_id=None, inline_message_id=None,
|
||||
@ -636,7 +636,7 @@ def edit_message_caption(token, caption, chat_id=None, message_id=None, inline_m
|
||||
payload['parse_mode'] = parse_mode
|
||||
if reply_markup:
|
||||
payload['reply_markup'] = _convert_markup(reply_markup)
|
||||
return _make_request(token, method_url, params=payload)
|
||||
return _make_request(token, method_url, params=payload, method='post')
|
||||
|
||||
|
||||
def edit_message_media(token, media, chat_id=None, message_id=None, inline_message_id=None, reply_markup=None):
|
||||
@ -665,13 +665,13 @@ def edit_message_reply_markup(token, chat_id=None, message_id=None, inline_messa
|
||||
payload['inline_message_id'] = inline_message_id
|
||||
if reply_markup:
|
||||
payload['reply_markup'] = _convert_markup(reply_markup)
|
||||
return _make_request(token, method_url, params=payload)
|
||||
return _make_request(token, method_url, params=payload, method='post')
|
||||
|
||||
|
||||
def delete_message(token, chat_id, message_id):
|
||||
method_url = r'deleteMessage'
|
||||
payload = {'chat_id': chat_id, 'message_id': message_id}
|
||||
return _make_request(token, method_url, params=payload)
|
||||
return _make_request(token, method_url, params=payload, method='post')
|
||||
|
||||
|
||||
# Game
|
||||
@ -938,6 +938,26 @@ def delete_sticker_from_set(token, sticker):
|
||||
return _make_request(token, method_url, params=payload, method='post')
|
||||
|
||||
|
||||
def send_poll(token, chat_id, question, options, disable_notifications=False, reply_to_message_id=None, reply_markup=None):
|
||||
method_url = r'sendPoll'
|
||||
payload = {'chat_id': str(chat_id), 'question': question, 'options': _convert_list_json_serializable(options)}
|
||||
if disable_notifications:
|
||||
payload['disable_notification'] = disable_notifications
|
||||
if reply_to_message_id:
|
||||
payload['reply_to_message_id'] = reply_to_message_id
|
||||
if reply_markup:
|
||||
payload['reply_markup'] = _convert_markup(reply_markup)
|
||||
return _make_request(token, method_url, params=payload)
|
||||
|
||||
|
||||
def stop_poll(token, chat_id, message_id, reply_markup=None):
|
||||
method_url = r'stopPoll'
|
||||
payload = {'chat_id': str(chat_id), 'message_id': message_id}
|
||||
if reply_markup:
|
||||
payload['reply_markup'] = _convert_markup(reply_markup)
|
||||
return _make_request(token, method_url, params=payload)
|
||||
|
||||
|
||||
def _convert_list_json_serializable(results):
|
||||
ret = ''
|
||||
for r in results:
|
||||
|
@ -368,6 +368,9 @@ class Message(JsonDeserializable):
|
||||
if 'connected_website' in obj:
|
||||
opts['connected_website'] = obj['connected_website']
|
||||
content_type = 'connected_website'
|
||||
if 'poll' in obj:
|
||||
opts['poll'] = Poll.de_json(obj['poll'])
|
||||
content_type = 'poll'
|
||||
return cls(message_id, from_user, date, chat, content_type, opts, json_string)
|
||||
|
||||
@classmethod
|
||||
@ -885,9 +888,30 @@ class InlineKeyboardMarkup(Dictionaryable, JsonSerializable):
|
||||
return json_dict
|
||||
|
||||
|
||||
class LoginUrl(JsonSerializable):
|
||||
def __init__(self, url, forward_text=None, bot_username=None, request_write_access=None):
|
||||
self.url = url
|
||||
self.forward_text = forward_text
|
||||
self.bot_username = bot_username
|
||||
self.request_write_access = request_write_access
|
||||
|
||||
def to_json(self):
|
||||
return json.dumps(self.to_dic())
|
||||
|
||||
def to_dic(self):
|
||||
json_dic = {'url': self.url}
|
||||
if self.forward_text:
|
||||
json_dic['forward_text'] = self.forward_text
|
||||
if self.bot_username:
|
||||
json_dic['bot_username'] = self.bot_username
|
||||
if self.request_write_access:
|
||||
json_dic['request_write_access'] = self.request_write_access
|
||||
return json_dic
|
||||
|
||||
|
||||
class InlineKeyboardButton(JsonSerializable):
|
||||
def __init__(self, text, url=None, callback_data=None, switch_inline_query=None,
|
||||
switch_inline_query_current_chat=None, callback_game=None, pay=None):
|
||||
switch_inline_query_current_chat=None, callback_game=None, pay=None, login_url=None):
|
||||
self.text = text
|
||||
self.url = url
|
||||
self.callback_data = callback_data
|
||||
@ -895,6 +919,7 @@ class InlineKeyboardButton(JsonSerializable):
|
||||
self.switch_inline_query_current_chat = switch_inline_query_current_chat
|
||||
self.callback_game = callback_game
|
||||
self.pay = pay
|
||||
self.login_url = login_url
|
||||
|
||||
def to_json(self):
|
||||
return json.dumps(self.to_dic())
|
||||
@ -913,6 +938,8 @@ class InlineKeyboardButton(JsonSerializable):
|
||||
json_dic['callback_game'] = self.callback_game
|
||||
if self.pay is not None:
|
||||
json_dic['pay'] = self.pay
|
||||
if self.login_url is not None:
|
||||
json_dic['login_url'] = self.login_url.to_dic()
|
||||
return json_dic
|
||||
|
||||
|
||||
@ -2173,3 +2200,48 @@ class InputMediaDocument(InputMedia):
|
||||
if self.thumb:
|
||||
ret['thumb'] = self.thumb
|
||||
return ret
|
||||
|
||||
|
||||
class PollOption(JsonSerializable, JsonDeserializable):
|
||||
@classmethod
|
||||
def de_json(cls, json_type):
|
||||
obj = cls.check_json(json_type)
|
||||
text = obj['text']
|
||||
voter_count = int(obj['voter_count'])
|
||||
option = cls(text)
|
||||
option.voter_count = voter_count
|
||||
return option
|
||||
|
||||
def __init__(self, text):
|
||||
self.text = text
|
||||
self.voter_count = 0
|
||||
|
||||
def to_json(self):
|
||||
return json.dumps(self.text)
|
||||
|
||||
|
||||
class Poll(JsonDeserializable):
|
||||
@classmethod
|
||||
def de_json(cls, json_type):
|
||||
obj = cls.check_json(json_type)
|
||||
poll_id = obj['id']
|
||||
question = obj['question']
|
||||
poll = cls(question)
|
||||
options = []
|
||||
for opt in obj['options']:
|
||||
options.append(PollOption.de_json(opt))
|
||||
poll.options = options
|
||||
is_closed = obj['is_closed']
|
||||
poll.id = poll_id
|
||||
poll.is_closed = is_closed
|
||||
return poll
|
||||
|
||||
def __init__(self, question):
|
||||
self.options = []
|
||||
self.question = question
|
||||
|
||||
def add(self, option):
|
||||
if type(option) is PollOption:
|
||||
self.options.append(option)
|
||||
else:
|
||||
self.options.append(PollOption(option))
|
||||
|
Loading…
x
Reference in New Issue
Block a user