From 25e81c46df571fe107f513646e9bfdd60816dac4 Mon Sep 17 00:00:00 2001 From: Kylmakalle Date: Thu, 6 Jul 2017 00:51:41 +0300 Subject: [PATCH 1/6] exceptions test --- bot.py | 6 +++--- vk_messages.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bot.py b/bot.py index 0bebc97..c44896a 100644 --- a/bot.py +++ b/bot.py @@ -582,7 +582,7 @@ def reply_sticker(message): except Exception: bot.reply_to(message, '*Произошла неизвестная ошибка при отправке*', parse_mode='Markdown').wait() # TODO?: Bugreport system - logging.exception('Error: {}'.format(traceback.format_exc())) + print('Error: {}'.format(traceback.format_exc())) @bot.message_handler(content_types=['photo']) @@ -610,7 +610,7 @@ def reply_contact(message): except Exception: bot.reply_to(message, '*Произошла неизвестная ошибка при отправке*', parse_mode='Markdown').wait() - logging.exception('Error: {}'.format(traceback.format_exc())) + print('Error: {}'.format(traceback.format_exc())) @bot.message_handler(content_types=['text']) @@ -641,7 +641,7 @@ def reply_text(message): except Exception: bot.reply_to(message, 'Произошла неизвестная ошибка при отправке', parse_mode='Markdown').wait() - logging.exception('Error: {}'.format(traceback.format_exc())) + print('Error: {}'.format(traceback.format_exc())) # bot.polling(none_stop=True) diff --git a/vk_messages.py b/vk_messages.py index df37641..8205110 100644 --- a/vk_messages.py +++ b/vk_messages.py @@ -27,7 +27,7 @@ class VkPolling: handle_updates(vk_user, bot, chat_id, updates) except requests.exceptions.ReadTimeout: timeout *= 2 - logging.warning('Retrying VK Polling in {} seconds.'.format(int(timeout / 10))) + print('Retrying VK Polling in {} seconds.'.format(int(timeout / 10))) for i in range(timeout): if self._running: time.sleep(0.1) @@ -283,9 +283,9 @@ class VkMessage: api = vk.API(self.session) try: new = api.messages.getLongPollHistory(ts=self.ts, pts=self.pts) - except: + except vk.api.VkAPIError: timeout = 3 - logging.warning('Retrying getLongPollHistory in {} seconds'.format(timeout)) + print('Retrying getLongPollHistory in {} seconds'.format(timeout)) time.sleep(timeout) self.ts, self.pts = get_tses(self.session) new = api.messages.getLongPollHistory(ts=self.ts, pts=self.pts) From f88ac8bfafb04801dd929c565da7ca28a3741ed9 Mon Sep 17 00:00:00 2001 From: Kylmakalle Date: Thu, 6 Jul 2017 19:33:31 +0300 Subject: [PATCH 2/6] Support for groups and big stability improvemnts --- bot.py | 63 +++++++++++++++++++++++++++++++++----------------- vk_messages.py | 33 ++++++++++++++++++++------ 2 files changed, 68 insertions(+), 28 deletions(-) diff --git a/bot.py b/bot.py index c44896a..ae5887f 100644 --- a/bot.py +++ b/bot.py @@ -70,6 +70,8 @@ def replace_shields(text): def request_user_dialogs(session, userid): order = [] users_ids = [] + group_ids = [] + positive_group_ids = [] dialogs = vk.API(session).messages.getDialogs(count=200) for chat in dialogs[1:]: if 'chat_id' in chat: @@ -80,14 +82,28 @@ def request_user_dialogs(session, userid): elif chat['uid'] > 0: order.append({'title': None, 'id': chat['uid']}) users_ids.append(chat['uid']) + elif chat['uid'] < 0: + order.append({'title': None, 'id': chat['uid']}) + group_ids.append(chat['uid']) + + for g in group_ids: + positive_group_ids.append(str(g)[1:]) + users = vk.API(session).users.get(user_ids=users_ids, fields=['first_name', 'last_name', 'uid']) + groups = vk.API(session).groups.getById(group_ids=positive_group_ids, fields=[]) for output in order: if output['title'] == ' ... ' or not output['title']: - for x in users: - if x['uid'] == output['id']: - current_user = x - break - output['title'] = '{} {}'.format(current_user['first_name'], current_user['last_name']) + if output['id'] > 0: + for x in users: + if x['uid'] == output['id']: + output['title'] = '{} {}'.format(x['first_name'], x['last_name']) + break + + else: + for f in groups: + if str(f['gid']) == str(output['id'])[1:]: + output['title'] = '{}'.format(f['name']) + break for button in range(len(order)): order[button] = types.InlineKeyboardButton(order[button]['title'], callback_data=str(order[button]['id'])) rows = [order[x:x + 2] for x in range(0, len(order), 2)] @@ -139,8 +155,13 @@ def search_users(message, text): def callback_buttons(call): if call.message: if 'page' in call.data: + try: + create_markup(call.message, call.from_user.id, int(call.data.split('page')[1]), True) + except: + session = VkMessage(vk_tokens.get(str(call.from_user.id))).session + request_user_dialogs(session, call.from_user.id) + create_markup(call.message, call.from_user.id, int(call.data.split('page')[1]), True) bot.answer_callback_query(call.id).wait() - create_markup(call.message, call.from_user.id, int(call.data.split('page')[1]), True) elif 'search' in call.data: markup = types.ForceReply(selective=False) bot.answer_callback_query(call.id, 'Поиск беседы 🔍').wait() @@ -157,15 +178,20 @@ def callback_buttons(call): 'Вы в беседе {}'.format(chat['title']), parse_mode='HTML').wait() currentchat[str(call.from_user.id)] = call.data - elif call.data.isdigit(): + elif call.data.lstrip('-').isdigit(): session = VkMessage(vk_tokens.get(str(call.from_user.id))).session - user = vk.API(session).users.get(user_ids=call.data, fields=[])[0] + if '-' in call.data: + user = vk.API(session).groups.getById(group_id=call.data.lstrip('-'), fields=[])[0] + user = {'first_name': user['name'], 'last_name': ''} + else: + user = vk.API(session).users.get(user_ids=call.data, fields=[])[0] bot.answer_callback_query(call.id, 'Вы в чате с {} {}'.format(user['first_name'], user['last_name'])).wait() bot.send_message(call.from_user.id, 'Вы в чате с {} {}'.format(user['first_name'], user['last_name']), parse_mode='HTML').wait() - currentchat[str(call.from_user.id)] = call.data + currentchat[str(call.from_user.id)] = {'title': user['first_name'] + ' ' + user['last_name'], + 'id': call.data} def create_thread(uid, vk_token): @@ -193,7 +219,6 @@ def thread_supervisor(): if check_thread(uid.decode("utf-8")): try: create_thread(uid.decode("utf-8"), vk_tokens.get(uid)) - request_user_dialogs(VkMessage(vk_tokens.get(uid.decode("utf-8"))).session, uid.decode("utf-8")) except requests.exceptions.ReadTimeout as e: time.sleep(10) time.sleep(120) @@ -238,21 +263,17 @@ def info_extractor(info): def chat_command(message): if logged(message): if str(message.from_user.id) in currentchat: - if 'group' in currentchat[str(message.from_user.id)]: - session = VkMessage(vk_tokens.get(str(message.from_user.id))).session - chat = vk.API(session).messages.getChat( - chat_id=currentchat[str(message.from_user.id)].split('group')[1], - fields=[]) + if 'group' in currentchat[str(message.from_user.id)]['id']: + chat = currentchat[str(message.from_user.id)] if chat['title'].replace('\\', ''): chat['title'] = chat['title'].replace('\\', '') bot.send_message(message.from_user.id, 'Вы в беседе {}'.format(chat['title']), parse_mode='HTML').wait() else: - session = VkMessage(vk_tokens.get(str(message.from_user.id))).session - user = vk.API(session).users.get(user_ids=currentchat[str(message.from_user.id)], fields=[])[0] + chat = currentchat[str(message.from_user.id)] bot.send_message(message.from_user.id, - 'Вы в чате с {} {}'.format(user['first_name'], user['last_name']), + 'Вы в чате с {}'.format(chat['title']), parse_mode='HTML').wait() else: bot.send_message(message.from_user.id, @@ -368,12 +389,12 @@ def vk_sender(message, method): elif str(message.from_user.id) in currentchat: info = [] - if 'group' in currentchat[str(message.from_user.id)]: + if 'group' in currentchat[str(message.from_user.id)]['id']: info.append('0') - info.append(currentchat[str(message.from_user.id)].split('group')[1]) + info.append(currentchat[str(message.from_user.id)]['id'].split('group')[1]) info.append('1') else: - info.append(currentchat[str(message.from_user.id)]) + info.append(currentchat[str(message.from_user.id)]['id']) info.append('0') info.append('0') form_request(message, method, info) diff --git a/vk_messages.py b/vk_messages.py index 8205110..9df8463 100644 --- a/vk_messages.py +++ b/vk_messages.py @@ -36,7 +36,12 @@ class VkPolling: def handle_messages(m, vk_user, bot, chat_id, mainmessage=None): - user = vk.API(vk_user.session).users.get(user_ids=m["uid"], fields=[])[0] + if m['uid'] > 0: + user = vk.API(vk_user.session).users.get(user_ids=m["uid"], fields=[])[0] + else: + group = vk.API(vk_user.session).groups.getById(group_ids=str(m['uid'])[1:])[0] + user = {'first_name': group['name'], 'last_name': None} + if 'body' in m and not 'attachment' in m and not 'geo' in m and not 'fwd_messages' in m: data = add_user_info(m, user["first_name"], user["last_name"])[:-1] + add_reply_info(m) bot.send_message(chat_id, data, parse_mode='HTML', disable_web_page_preview=False, @@ -244,15 +249,29 @@ def add_reply_info(m): def add_user_info(m, first_name, last_name): if 'body' in m and m['body']: - if 'chat_id' in m: - return '{} {} @ {}:\n{}\n'.format(first_name, last_name, m['title'], m['body'].replace('
', '\n')) + if last_name: + if 'chat_id' in m: + return '{} {} @ {}:\n{}\n'.format(first_name, last_name, m['title'], + m['body'].replace('
', '\n')) + else: + return '{} {}:\n{}\n'.format(first_name, last_name, m['body'].replace('
', '\n')) else: - return '{} {}:\n{}\n'.format(first_name, last_name, m['body'].replace('
', '\n')) + if 'chat_id' in m: + return '{} @ {}:\n{}\n'.format(first_name, m['title'], + m['body'].replace('
', '\n')) + else: + return '{}:\n{}\n'.format(first_name, m['body'].replace('
', '\n')) else: - if 'chat_id' in m: - return '{} {} @ {}:\n'.format(first_name, last_name, m['title']) + if last_name: + if 'chat_id' in m: + return '{} {} @ {}:\n'.format(first_name, last_name, m['title']) + else: + return '{} {}:\n'.format(first_name, last_name) else: - return '{} {}:\n'.format(first_name, last_name) + if 'chat_id' in m: + return '{} @ {}:\n'.format(first_name, m['title']) + else: + return '{}:\n'.format(first_name) def check_notification(value): From fa57f787b0b09cb825a7745459b7f42a56259b6e Mon Sep 17 00:00:00 2001 From: Kylmakalle Date: Sat, 8 Jul 2017 01:24:13 +0300 Subject: [PATCH 3/6] Sending TG gifs as VK videos --- bot.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/bot.py b/bot.py index ae5887f..65cbfad 100644 --- a/bot.py +++ b/bot.py @@ -418,9 +418,9 @@ def send_text(message, userid, group, forward_messages=None): def send_doc(message, userid, group, forward_messages=None): filetype = message.content_type session = VkMessage(vk_tokens.get(str(message.from_user.id))).session - file = wget.download( - FILE_URL.format(token, bot.get_file(getattr(message, filetype).file_id).wait().file_path)) - if filetype == 'document': + if filetype == 'document' and 'video' not in message.document.mime_type: + file = wget.download( + FILE_URL.format(token, bot.get_file(getattr(message, filetype).file_id).wait().file_path)) openedfile = open(file, 'rb') files = {'file': openedfile} fileonserver = ujson.loads(requests.post(vk.API(session).docs.getUploadServer()['upload_url'], @@ -432,6 +432,8 @@ def send_doc(message, userid, group, forward_messages=None): os.remove(file) elif filetype == 'voice': + file = wget.download( + FILE_URL.format(token, bot.get_file(getattr(message, filetype).file_id).wait().file_path)) openedfile = open(file, 'rb') files = {'file': openedfile} fileonserver = ujson.loads( @@ -442,7 +444,13 @@ def send_doc(message, userid, group, forward_messages=None): openedfile.close() os.remove(file) + elif filetype == 'document' and 'video' in message.document.mime_type: + vk_sender(message, send_video) + return + else: # filetype == 'audio': + file = wget.download( + FILE_URL.format(token, bot.get_file(getattr(message, filetype).file_id).wait().file_path)) newfile = file.split('.')[0] + '.aac' os.rename(file, newfile) openedfile = open(newfile, 'rb') From 87af6c9b8dd18add0cb578fffcb09b00728bef89 Mon Sep 17 00:00:00 2001 From: Kylmakalle Date: Sat, 8 Jul 2017 01:24:53 +0300 Subject: [PATCH 4/6] timeout fixes --- vk_messages.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/vk_messages.py b/vk_messages.py index 9df8463..aed8310 100644 --- a/vk_messages.py +++ b/vk_messages.py @@ -4,6 +4,7 @@ import redis import requests import time import vk +import ujson import wget logging.basicConfig(format='%(levelname)-8s [%(asctime)s] %(message)s', level=logging.WARNING, filename='vk.log') @@ -20,13 +21,13 @@ class VkPolling: def run(self, vk_user, bot, chat_id): while self._running: - timeout = 50 + timeout = 30 try: updates = vk_user.get_new_messages() if updates: handle_updates(vk_user, bot, chat_id, updates) - except requests.exceptions.ReadTimeout: - timeout *= 2 + except requests.exceptions.ReadTimeout as e: + print('Error', e) print('Retrying VK Polling in {} seconds.'.format(int(timeout / 10))) for i in range(timeout): if self._running: @@ -301,13 +302,15 @@ class VkMessage: api = vk.API(self.session) try: - new = api.messages.getLongPollHistory(ts=self.ts, pts=self.pts) + ts_pts = ujson.dumps({"ts": self.ts, "pts": self.pts}) + new = api.execute(code='return API.messages.getLongPollHistory({});'.format(ts_pts)) # api.messages.getLongPollHistory(ts=self.ts, pts=self.pts) except vk.api.VkAPIError: timeout = 3 print('Retrying getLongPollHistory in {} seconds'.format(timeout)) time.sleep(timeout) self.ts, self.pts = get_tses(self.session) - new = api.messages.getLongPollHistory(ts=self.ts, pts=self.pts) + ts_pts = ujson.dumps({"ts": self.ts, "pts": self.pts}) + new = api.execute(code='return API.messages.getLongPollHistory({});'.format(ts_pts)) msgs = new['messages'] self.pts = new["new_pts"] From 336b84436cc30a474e60bc3d78c3ed61dd516be8 Mon Sep 17 00:00:00 2001 From: Kylmakalle Date: Sun, 9 Jul 2017 14:48:31 +0300 Subject: [PATCH 5/6] Exceptions logging (debug) --- vk_messages.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/vk_messages.py b/vk_messages.py index aed8310..fb9566c 100644 --- a/vk_messages.py +++ b/vk_messages.py @@ -27,8 +27,7 @@ class VkPolling: if updates: handle_updates(vk_user, bot, chat_id, updates) except requests.exceptions.ReadTimeout as e: - print('Error', e) - print('Retrying VK Polling in {} seconds.'.format(int(timeout / 10))) + logging.warning('Retrying VK Polling in {} seconds.'.format(int(timeout / 10))) for i in range(timeout): if self._running: time.sleep(0.1) @@ -303,10 +302,10 @@ class VkMessage: api = vk.API(self.session) try: ts_pts = ujson.dumps({"ts": self.ts, "pts": self.pts}) - new = api.execute(code='return API.messages.getLongPollHistory({});'.format(ts_pts)) # api.messages.getLongPollHistory(ts=self.ts, pts=self.pts) + new = api.execute(code='return API.messages.getLongPollHistory({});'.format(ts_pts)) except vk.api.VkAPIError: timeout = 3 - print('Retrying getLongPollHistory in {} seconds'.format(timeout)) + logging.warning('Retrying getLongPollHistory in {} seconds'.format(timeout)) time.sleep(timeout) self.ts, self.pts = get_tses(self.session) ts_pts = ujson.dumps({"ts": self.ts, "pts": self.pts}) From faa580e86114a76b8f312bf396572dd18cd40ee2 Mon Sep 17 00:00:00 2001 From: Kylmakalle Date: Sun, 9 Jul 2017 22:47:05 +0300 Subject: [PATCH 6/6] Final version of stability update --- bot.py | 20 ++++++++++++++------ vk_messages.py | 5 +++-- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/bot.py b/bot.py index 65cbfad..f014708 100644 --- a/bot.py +++ b/bot.py @@ -216,12 +216,20 @@ def check_thread(uid): def thread_supervisor(): while True: for uid in vk_tokens.scan_iter(): - if check_thread(uid.decode("utf-8")): - try: - create_thread(uid.decode("utf-8"), vk_tokens.get(uid)) - except requests.exceptions.ReadTimeout as e: - time.sleep(10) - time.sleep(120) + tries = 0 + while check_thread(uid.decode("utf-8")): + if tries < 6: + try: + create_thread(uid.decode("utf-8"), vk_tokens.get(uid)) + except: + tries = tries + 1 + else: + mark = types.InlineKeyboardMarkup() + login = types.InlineKeyboardButton('ВХОД', url=link) + mark.add(login) + bot.send_message(uid.decode("utf-8"), 'Непредвиденная ошибка, требуется повторный логин ВК!', + parse_mode='HTML', reply_markup=mark) + time.sleep(60) supervisor = threading.Thread(name='supervisor', target=thread_supervisor) diff --git a/vk_messages.py b/vk_messages.py index fb9566c..4755be0 100644 --- a/vk_messages.py +++ b/vk_messages.py @@ -26,8 +26,9 @@ class VkPolling: updates = vk_user.get_new_messages() if updates: handle_updates(vk_user, bot, chat_id, updates) - except requests.exceptions.ReadTimeout as e: - logging.warning('Retrying VK Polling in {} seconds.'.format(int(timeout / 10))) + except requests.exceptions.ReadTimeout: + logging.warning('Retrying VK Polling.') + timeout = 0 for i in range(timeout): if self._running: time.sleep(0.1)