diff --git a/bot.py b/bot.py index 0bebc97..f014708 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): @@ -190,13 +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)) - 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) + 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) @@ -238,21 +271,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 +397,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) @@ -397,9 +426,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'], @@ -411,6 +440,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( @@ -421,7 +452,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') @@ -582,7 +619,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 +647,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 +678,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..4755be0 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,14 +21,14 @@ 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 - logging.warning('Retrying VK Polling in {} seconds.'.format(int(timeout / 10))) + logging.warning('Retrying VK Polling.') + timeout = 0 for i in range(timeout): if self._running: time.sleep(0.1) @@ -36,7 +37,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 +250,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): @@ -282,13 +302,15 @@ class VkMessage: api = vk.API(self.session) try: - new = api.messages.getLongPollHistory(ts=self.ts, pts=self.pts) - except: + ts_pts = ujson.dumps({"ts": self.ts, "pts": self.pts}) + new = api.execute(code='return API.messages.getLongPollHistory({});'.format(ts_pts)) + except vk.api.VkAPIError: timeout = 3 logging.warning('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"]