def _check_ssl_cert(self, cert, key):
# Check SSL-Certificate with openssl, if possible
try:
exit_code = subprocess.call(
["openssl", "x509", "-text", "-noout", "-in", cert],
stdout=open(os.devnull, 'wb'),
stderr=subprocess.STDOUT)
except OSError:
exit_code = 0
if exit_code is 0:
try:
self.httpd.socket = ssl.wrap_socket(
self.httpd.socket, certfile=cert, keyfile=key, server_side=True)
except ssl.SSLError as error:
self.logger.exception('Failed to init SSL socket')
raise TelegramError(str(error))
else:
raise TelegramError('SSL Certificate invalid')
python类TelegramError()的实例源码
def get_telegram_bot():
"""
Creates a telegram bot instance.
Returns:
telegram.Bot: The bot instance.
Raises:
TelegramConfigurationError: If the telegram bot was not properly
configured.
"""
logger = logging.getLogger()
try:
return Bot(Config().telegram_token)
except (FileNotFoundError, ValueError, TelegramError) as exc:
logger.error("Telegram token not present or invalid: '%s'", str(exc))
raise TelegramConfigurationError("Telegram token not "
"present or invalid.")
def botupdated_message(bot, job):
"""
Defining a command to notify the user and tell them what updates have been released
It is called at every execution ONLY if there are documents in a specific db collection
"""
messages = list(DATABASE.messages.find())
DATABASE.messages.remove()
invalid_chatid = []
for message in messages:
for chat_id in USERS['telegramID']:
try:
bot.sendMessage(chat_id, parse_mode='HTML',
text=message['text'])
except TelegramError:
invalid_chatid.append(chat_id)
for chat_id in invalid_chatid:
USERS['telegramID'].remove(chat_id)
unsubscribe_user(chat_id, 'telegramID')
def test_editMessageCaption(self):
self.mockbot.editMessageCaption(chat_id=12, message_id=23)
data = self.mockbot.sent_messages[-1]
self.assertEqual(data['method'], "editMessageCaption")
self.assertEqual(data['chat_id'], 12)
self.mockbot.editMessageCaption(
inline_message_id=23, caption="new cap", photo=True)
data = self.mockbot.sent_messages[-1]
self.assertEqual(data['method'], "editMessageCaption")
with self.assertRaises(TelegramError):
self.mockbot.editMessageCaption()
with self.assertRaises(TelegramError):
self.mockbot.editMessageCaption(chat_id=12)
with self.assertRaises(TelegramError):
self.mockbot.editMessageCaption(message_id=12)
def process_update(obj, update):
if isinstance(update, TelegramError):
obj.dispatch_error(None, update)
else:
for group in obj.groups:
for handler in obj.handlers[group]:
try:
if handler.check_update(update):
handler.handle_update(update, obj)
except Exception as e:
try:
obj.dispatch_error(update, e)
except Exception:
obj.logger.exception(
'An uncaught error was raised while '
'handling the error')
def updateChatList(bot, job):
logger.debug("-----------------------updatedChatList--------------------")
logger.info("Updating the chat list")
results = mDatabase.groups.find()
for doc in results:
try:
chat = bot.getChat(chat_id = doc['_id'])
logger.info("Chat %s (%s) responded." % (chat.title, chat.id))
mDatabase.groups.find_one_and_update({'_id':doc['_id']},
{ '$set' : {'title':chat.title}})
except TelegramError:
logger.info("Not yet removing %s (%s) from the database, it is not responding" % (doc['title'],doc['_id']))
#mDatabase.groups.remove({'_id':doc['_id']})
except:
logger.info("Other error when checking %s (%s), check networking" % (doc['title'],doc['_id']))
def updateChatList(bot, job):
logger.debug("-----------------------updatedChatList--------------------")
logger.info("Updating the chat list")
results = MDB.groups.find()
for doc in results:
try:
chat = bot.getChat(chat_id = doc['_id'])
logger.info("Chat %s (%s) responded." % (chat.title, chat.id))
admins = [chatmember.user.id for chatmember in bot.getChatAdministrators(chat_id=doc['_id'])]
MDB.groups.find_one_and_update({'_id':doc['_id']},
{ '$set' : {'title':chat.title, "admins":admins}})
except TelegramError as te:
logger.warning("Removing %s (%s) from the database, it is not responding, re-add the bot if this is incorrect." % (doc['title'],doc['_id']))
logger.debug("Error received: %s" % (str(te)))
MDB.groups.remove({'_id':doc['_id']})
except:
logger.info("Other error when checking %s (%s), check networking" % (doc['title'],doc['_id']))
def respondToMessageQuery(self, message):
senderId = message.from_user.id
chatId = message.chat.id
messageId = message.message_id
expression = message.text
errorMessage = None
try:
imageStream, pdfStream = self._latexConverter.convertExpressionToPng(expression, senderId, str(messageId)+str(senderId), returnPdf=True)
self._bot.sendDocument(chatId, pdfStream, filename="expression.pdf")
self._bot.sendPhoto(chatId, imageStream)
except ValueError as err:
errorMessage = self.getWrongSyntaxResult(expression, err.args[0])
except TelegramError as err:
errorMessage = self._resourceManager.getString("telegram_error")+str(err)
self.logger.warn(errorMessage)
finally:
if not errorMessage is None:
self._bot.sendMessage(chatId, errorMessage)
self.logger.debug("Answered to message from %d, chatId %d, expression: %s",
senderId, chatId, expression)
def _check_ssl_cert(self, cert, key):
# Check SSL-Certificate with openssl, if possible
try:
exit_code = subprocess.call(
["openssl", "x509", "-text", "-noout", "-in", cert],
stdout=open(os.devnull, 'wb'),
stderr=subprocess.STDOUT)
except OSError:
exit_code = 0
if exit_code is 0:
try:
self.httpd.socket = ssl.wrap_socket(
self.httpd.socket, certfile=cert, keyfile=key, server_side=True)
except ssl.SSLError as error:
self.logger.exception('Failed to init SSL socket')
raise TelegramError(str(error))
else:
raise TelegramError('SSL Certificate invalid')
def send_tg(self, msg: str):
for i in self.chat_ids:
attempt = 1
sleep_tm = 1
while 1:
try:
self.bot.sendMessage(i, msg, parse_mode='Markdown')
except telegram.error.NetworkError:
self._logger.warning(
'telegram servers in trouble; attempt={} sleep={}'.format(
attempt, sleep_tm))
time.sleep(sleep_tm)
attempt += 1
if sleep_tm < 60:
sleep_tm *= 2
continue
except telegram.TelegramError:
self._logger.exception('failed sending telegram')
break
def delete_message(self, chat=None, message_id=None, message=None):
"""Deletes message
Args:
chat(Optional[int|str]): chat ID or '@channel_name'
message_id(Optional[int]): ID of message to be deleted
message(Optional[:class:`telegram.Message`]): message to be deleted
Returns:
bool: ``True`` on success, ``False`` otherwise
Raises:
ValueError: if ``chat``, ``message_id`` and ``message`` are ``None``
"""
if (chat is None or message_id is None) and message is None:
raise ValueError('Either `chat` and `message_id` or `message` must be given')
if message is not None:
chat = message.chat_id
message_id = message.message_id
try:
return self._bot.delete_message(chat, message_id)
except TelegramError as e:
logger.exception('Exception was raised while deleting message', exc_info=e)
return False
def ban_member(self, chat, user_id=None, user=None):
"""Bans chat member
Args:
chat(int|str): chat ID or '@channel_name'
user_id(Optional[int]): user ID to be banned
user(Optional[:class:`telegram.User`]): user to be banned
Returns:
bool: ``True`` on success, ``False`` otherwise
Raises:
ValueError: if both ``user_id`` and ``user`` were (not) given
"""
if (user_id is None and user is None) or (user_id is not None and user is not None):
raise ValueError('Either `user_id` or `user` must be given')
if user is not None:
user_id = user.id
try:
self._bot.kick_chat_member(chat, user_id)
except TelegramError as e:
logger.exception('Exception was raised while kicking member', exc_info=e)
return False
return True
def unban_member(self, chat, user_id=None, user=None):
"""Unbans chat member
Args:
chat(int|str): chat ID or '@channel_name'
user_id(Optional[int]): user ID to be unbanned
user(Optional[:class:`telegram.User`]): user to be unbanned
Returns:
bool: ``True`` on success, ``False`` otherwise
Raises:
ValueError: if both ``user_id`` and ``user`` were (not) given
"""
if (user_id is None and user is None) or (user_id is not None and user is not None):
raise ValueError('Either `user_id` or `user` must be given')
if user is not None:
user_id = user.id
try:
self._bot.unban_chat_member(chat, user_id)
except TelegramError as e:
logger.exception('Exception was raised while unbanning member', exc_info=e)
return False
return True
def is_image(stream):
"""Check if the content file is an image by analyzing its headers.
Args:
stream (str): A str representing the content of a file.
Returns:
str: The str mimetype of an image.
"""
image = imghdr.what(None, stream)
if image:
return 'image/%s' % image
raise TelegramError('Could not parse file content')
def _bootstrap(self, max_retries, clean, webhook_url, allowed_updates, cert=None):
retries = 0
while 1:
try:
if clean:
# Disable webhook for cleaning
self.bot.deleteWebhook()
self._clean_updates()
sleep(1)
self.bot.setWebhook(
url=webhook_url, certificate=cert, allowed_updates=allowed_updates)
except (Unauthorized, InvalidToken):
raise
except TelegramError:
msg = 'error in bootstrap phase; try={0} max_retries={1}'.format(retries,
max_retries)
if max_retries < 0 or retries < max_retries:
self.logger.warning(msg)
retries += 1
else:
self.logger.exception(msg)
raise
else:
break
sleep(1)
def process_update(self, update):
"""
Processes a single update.
Args:
update (object):
"""
# An error happened while polling
if isinstance(update, TelegramError):
self.dispatch_error(None, update)
else:
for group in self.groups:
for handler in self.handlers[group]:
try:
if handler.check_update(update):
handler.handle_update(update, self)
break
# Dispatch any errors
except TelegramError as te:
self.logger.warn('A TelegramError was raised while processing the '
'Update.')
try:
self.dispatch_error(update, te)
except Exception:
self.logger.exception('An uncaught error was raised while '
'handling the error')
finally:
break
# Errors should not stop the thread
except Exception:
self.logger.exception('An uncaught error was raised while '
'processing the update')
break
def add_error_handler(self, callback):
"""
Registers an error handler in the Dispatcher.
Args:
handler (function): A function that takes ``Bot, Update,
TelegramError`` as arguments.
"""
self.error_handlers.append(callback)
def dispatch_error(self, update, error):
"""
Dispatches an error.
Args:
update (object): The update that caused the error
error (telegram.TelegramError): The Telegram error that was raised.
"""
for callback in self.error_handlers:
callback(self.bot, update, error)
def filter_by_hashtag(bot, update, db, users_state):
user_id = update.message.from_user.id
users_state[user_id] = dict()
users_state[user_id]['channels'] = dict()
keyboard = []
keyboard_row = []
for channel in db.query(Channel).filter(Channel.owner_id == str(user_id)).order_by(Channel.created_at.desc()):
try:
channel_chat = bot.get_chat(chat_id=channel.channel_id)
users_state[user_id]['channels'][channel_chat.title] = channel.channel_id
keyboard_row.append(channel_chat.title)
if len(keyboard_row) == 2:
keyboard.append(keyboard_row)
keyboard_row = []
except telegram.TelegramError:
logger.warning('filter_by_hashtag: cannot get title of channel {}'.format(channel.channel_id))
traceback.print_exc()
if len(keyboard_row) != 0:
keyboard.append(keyboard_row)
update.message.reply_text('???????? ?????', reply_markup=ReplyKeyboardMarkup(keyboard, one_time_keyboard=True))
return ASKED_CHANNEL_ID_IN_FILTER_BY_HASHTAG
def test_editMessageReplyMarkup(self):
self.mockbot.editMessageReplyMarkup(chat_id=1, message_id=1)
data = self.mockbot.sent_messages[-1]
self.assertEqual(data['method'], "editMessageReplyMarkup")
self.assertEqual(data['chat_id'], 1)
self.mockbot.editMessageReplyMarkup(inline_message_id=1)
data = self.mockbot.sent_messages[-1]
self.assertEqual(data['method'], "editMessageReplyMarkup")
self.assertEqual(data['inline_message_id'], 1)
with self.assertRaises(TelegramError):
self.mockbot.editMessageReplyMarkup()
with self.assertRaises(TelegramError):
self.mockbot.editMessageReplyMarkup(chat_id=12)
with self.assertRaises(TelegramError):
self.mockbot.editMessageReplyMarkup(message_id=12)
def broadcast(bot, update):
to_send = update.effective_message.text.split(None, 1)
if len(to_send) >= 2:
chats = sql.get_all_chats() or []
for chat in chats:
try:
bot.sendMessage(int(chat.chat_id), to_send[1])
sleep(0.1)
except TelegramError:
print("Couldn't send broadcast to {}, group name {}".format(chat.chat_id, chat.chat_name),
file=sys.stderr)
def registerMe(bot, update):
if not checkValidCommand(update.message.text, bot.username):
return
if not checkTypeGroup(update):
update.message.reply_text("This only works in groups the bot is in. If you would like to add the bot to a group, do so and then send /registerme")
return
#userDict = createUserDict(update.message.from_user)
userDict = update.message.from_user.id
logger.debug("New User: %s" % str(userDict))
mDatabase.groups.update({'_id':update.message.chat.id},
{'$addToSet':{'users':userDict},
'$set':{'title':update.message.chat.title}},
upsert=True)
logger.info("Register Me called for %s (%s)" % (update.message.chat.title, update.message.chat.id))
keyboard = [[InlineKeyboardButton("Register Me!",
callback_data="RegisterMe")]]
markup = InlineKeyboardMarkup(keyboard)
reply_text = "If you would like to register with this bot for this group, send /registerme, or click the button below."
try:
bot.sendMessage(chat_id = update.message.chat.id,
text = reply_text,
reply_markup = markup)
except TelegramError as TE:
logger.error("Caught this from registerMe: %s" % str(TE))
def forwardToAll(bot, list_of_chats, from_chat_id, message_id):
logger.debug("List of chats to forward a message to: %s" % list_of_chats)
if not list_of_chats: #If there are no chats to foward to.
return
for chat in list_of_chats:
try:
bot.forward_message(chat_id=chat,
from_chat_id=from_chat_id,
message_id=message_id)
except TelegramError as te:
logger.debug("Unable to send message to %s from %s. May want to remove it, or resolve the thread." %(chat, from_chat_id))
logger.debug("Error from forward to all: %s" % te)
def alertAdmins(bot, username):
admins = []
logger.debug('alerting admins:')
for group in MDB.groups.find():
logger.debug("Admins in group %s: %s" %(group['title'], group['admins']))
admins += group['admins']
admins = set(admins)
for admin in admins:
try:
bot.send_message(chat_id=admin,
text="%s is sending feedback, send /cancel to select and respond to them." % username)
except TelegramError as te:
logger.debug("Not all admins are interacting with the bot.")
logger.debug("Error in alert Admins: %s" % te)
def _bootstrap(self, max_retries, clean, webhook_url, allowed_updates, cert=None):
retries = 0
while 1:
try:
if clean:
# Disable webhook for cleaning
self.bot.delete_webhook()
self._clean_updates()
sleep(1)
self.bot.set_webhook(
url=webhook_url, certificate=cert, allowed_updates=allowed_updates)
except (Unauthorized, InvalidToken):
raise
except TelegramError:
msg = 'error in bootstrap phase; try={0} max_retries={1}'.format(retries,
max_retries)
if max_retries < 0 or retries < max_retries:
self.logger.warning(msg)
retries += 1
else:
self.logger.exception(msg)
raise
else:
break
sleep(1)
def start(self):
"""Thread target of thread 'dispatcher'.
Runs in background and processes the update queue.
"""
if self.running:
self.logger.warning('already running')
return
if self.__exception_event.is_set():
msg = 'reusing dispatcher after exception event is forbidden'
self.logger.error(msg)
raise TelegramError(msg)
self._init_async_threads(uuid4(), self.workers)
self.running = True
self.logger.debug('Dispatcher started')
while 1:
try:
# Pop update from update queue.
update = self.update_queue.get(True, 1)
except Empty:
if self.__stop_event.is_set():
self.logger.debug('orderly stopping')
break
elif self.__exception_event.is_set():
self.logger.critical('stopping due to exception in another thread')
break
continue
self.logger.debug('Processing Update: %s' % update)
self.process_update(update)
self.running = False
self.logger.debug('Dispatcher thread stopped')
def dispatch_error(self, update, error):
"""Dispatches an error.
Args:
update (:obj:`str` | :class:`telegram.Update` | None): The update that caused the error
error (:class:`telegram.TelegramError`): The Telegram error that was raised.
"""
for callback in self.error_handlers:
callback(self.bot, update, error)
def __init__(self, data):
self.data = data
self.boundary = choose_boundary()
for t in FILE_TYPES:
if t in data:
self.input_name = t
self.input_file = data.pop(t)
break
else:
raise TelegramError('Unknown inputfile type')
if hasattr(self.input_file, 'read'):
self.filename = None
self.input_file_content = self.input_file.read()
if 'filename' in data:
self.filename = self.data.pop('filename')
elif hasattr(self.input_file, 'name'):
# on py2.7, pylint fails to understand this properly
# pylint: disable=E1101
self.filename = os.path.basename(self.input_file.name)
try:
self.mimetype = self.is_image(self.input_file_content)
if not self.filename or '.' not in self.filename:
self.filename = self.mimetype.replace('/', '.')
except TelegramError:
if self.filename:
self.mimetype = mimetypes.guess_type(
self.filename)[0] or DEFAULT_MIME_TYPE
else:
self.mimetype = DEFAULT_MIME_TYPE
def is_image(stream):
"""Check if the content file is an image by analyzing its headers.
Args:
stream (:obj:`str`): A str representing the content of a file.
Returns:
:obj:`str`: The str mime-type of an image.
"""
image = imghdr.what(None, stream)
if image:
return 'image/%s' % image
raise TelegramError('Could not parse file content')
def send_text_message(self, chat, text, markdown=False, html=False, reply_to=None,
force_reply_to=False, **kwargs):
"""Sends message
Notes:
For now, this method supports only sending message with markdown or HTML parsing
Args:
chat(int|str): chat ID or '@channel_name'
text(str): text to send
markdown(Optional[bool]): parse text as markdown
html(Optional[bool]): parse text as html
reply_to(Optional[int]): ID of message to reply to
force_reply_to(Optional[bool]): Replies to message even in private chats
Returns:
int|bool: message_id if message was sent, ``False`` otherwise
Raises:
ValueError: if ``markdown`` and ``html`` are both ``True``
"""
if markdown and html:
raise ValueError('`markdown` and `html` are self-exclusive')
if markdown:
parse_mode = ParseMode.MARKDOWN
elif html:
parse_mode = ParseMode.HTML
else:
parse_mode = None
if reply_to and self.is_private_chat(chat) and not force_reply_to:
reply_to = None
try:
msg = self._bot.send_message(chat, text, parse_mode=parse_mode,
reply_to_message_id=reply_to, **kwargs)
except TelegramError as e:
logger.exception('Exception was raised while sending message', exc_info=e)
return False
return msg.message_id