From 85061a16ce965881c5f48877afcdaf6a9bb11b27 Mon Sep 17 00:00:00 2001 From: Sergey Date: Wed, 14 Oct 2020 16:05:26 +0300 Subject: [PATCH] upd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Добавлено - Ответ об ошибке отправки VK → TG - Повторные попытки отправки TG → VK Фиксы - Гифки VK → TG - Расшифровка войсов - Подарки - Падения при пересланных сообщениях --- bot.py | 6 ++-- telegram.py | 13 +++++--- vk_messages.py | 83 ++++++++++++++++++++++++++++++++------------------ 3 files changed, 65 insertions(+), 37 deletions(-) diff --git a/bot.py b/bot.py index 1bb6d32..ea1e68e 100644 --- a/bot.py +++ b/bot.py @@ -59,11 +59,9 @@ async def get_vk_chat(cid): return VkChat.objects.get_or_create(cid=cid) -max_photo_re = re.compile('photo_([0-9]*)') - - -async def get_max_photo(obj, keyword='photo'): +def get_max_photo(obj, keyword='photo'): maxarr = [] + max_photo_re = re.compile(f'{keyword}_([0-9]*)') for k, v in obj.items(): m = max_photo_re.match(k) if m: diff --git a/telegram.py b/telegram.py index 6fd5013..1406130 100644 --- a/telegram.py +++ b/telegram.py @@ -104,8 +104,13 @@ async def vk_sender(token, tg_message, **kwargs): reply_to_message_id=tg_message.message_id) return except VkAPIError: - log.exception(msg='Error in vk sender', exc_info=True) - return None + await asyncio.sleep(5) + if kwargs.get('retries') > 4: + log.exception(msg='Error in vk sender', exc_info=True) + return None + else: + kwargs['retries'] = kwargs.get('retries', 0) + 1 + await vk_sender(token, tg_message, **kwargs) except Exception: log.exception(msg='Error in vk sender', exc_info=True) return None @@ -357,7 +362,7 @@ async def get_dialog_info(api, vk_chat_id, name_case='nom'): if vk_chat_id >= 2000000000: dialog_info = await api('messages.getChat', chat_id=vk_chat_id - 2000000000) title = dialog_info['title'] - max_photo = await get_max_photo(dialog_info) + max_photo = get_max_photo(dialog_info) if max_photo: photo = dialog_info[max_photo] else: @@ -373,7 +378,7 @@ async def get_dialog_info(api, vk_chat_id, name_case='nom'): elif vk_chat_id < 0: dialog_info = await api('groups.getById', group_ids=abs(vk_chat_id)) title = dialog_info[0]['name'] - max_photo = await get_max_photo(dialog_info[0]) + max_photo = get_max_photo(dialog_info[0]) if max_photo: photo = dialog_info[0][max_photo] else: diff --git a/vk_messages.py b/vk_messages.py index 3a1a5fa..dae2008 100644 --- a/vk_messages.py +++ b/vk_messages.py @@ -560,6 +560,7 @@ async def process_message(msg, token=None, is_multichat=None, vk_chat_id=None, u full_chat = await msg.api('messages.getChat', chat_id=vk_chat_id - 2000000000) if full_msg.get('items'): for vk_msg in full_msg['items']: + vk_msg_url = f'https://vk.com/im?msgid={vk_msg["id"]}&sel=c{vk_msg["peer_id"]}' disable_notify = force_disable_notify or bool(vk_msg.get('push_settings', False)) attaches_scheme = [] if vk_msg.get('attachments'): @@ -675,12 +676,14 @@ async def process_message(msg, token=None, is_multichat=None, vk_chat_id=None, u header_message = tg_message = await bot.send_message(to_tg_chat, header + body, parse_mode=ParseMode.HTML, reply_to_message_id=main_message, - disable_notification=disable_notify) + disable_notification=disable_notify, + vk_msg_url=vk_msg_url) except MessageError: # Надо бы обновить aiogram, чтобы можно было ловить MessageToReplyNotFound header_message = tg_message = await bot.send_message(to_tg_chat, header + body, parse_mode=ParseMode.HTML, reply_to_message_id=None, - disable_notification=disable_notify) + disable_notification=disable_notify, + vk_msg_url=vk_msg_url) if forwarded: main_message = header_message.message_id Message.objects.create( @@ -697,7 +700,7 @@ async def process_message(msg, token=None, is_multichat=None, vk_chat_id=None, u for photo in photo_attachments: media.attach_photo(photo['content']) tg_messages = await tgsend(bot.send_media_group, to_tg_chat, media, reply_to_message_id=main_message, - disable_notification=disable_notify) + disable_notification=disable_notify, vk_msg_url=vk_msg_url) for tg_message in tg_messages: Message.objects.create( vk_chat=vk_chat_id, @@ -708,21 +711,23 @@ async def process_message(msg, token=None, is_multichat=None, vk_chat_id=None, u for attachment in attaches_scheme: if attachment: + tg_message = None if attachment['type'] == 'text': await bot.send_chat_action(to_tg_chat, ChatActions.TYPING) tg_message = await tgsend(bot.send_message, to_tg_chat, attachment['content'], parse_mode=ParseMode.HTML, reply_to_message_id=main_message, - disable_notification=disable_notify) + disable_notification=disable_notify, vk_msg_url=vk_msg_url) elif attachment['type'] == 'photo' and len(photo_attachments) == 1: await bot.send_chat_action(to_tg_chat, ChatActions.UPLOAD_PHOTO) - tg_message = await tgsend(bot.send_photo, to_tg_chat, attachment['content'], - reply_to_message_id=main_message, - disable_notification=disable_notify) + tg_message = await tgsend(bot.send_photo, to_tg_chat, attachment['content'], + reply_to_message_id=main_message, + disable_notification=disable_notify, vk_msg_url=vk_msg_url) elif attachment['type'] == 'document': await bot.send_chat_action(to_tg_chat, ChatActions.UPLOAD_DOCUMENT) tg_message = await tgsend(bot.send_document, to_tg_chat, attachment.get('content', '') or attachment.get('url'), - reply_to_message_id=main_message, disable_notification=disable_notify) + reply_to_message_id=main_message, disable_notification=disable_notify, + vk_msg_url=vk_msg_url) if 'content' in attachment: try: # Иногда тут появляется url, лень проверять откуда растут ноги @@ -738,19 +743,23 @@ async def process_message(msg, token=None, is_multichat=None, vk_chat_id=None, u elif attachment['type'] == 'video': await bot.send_chat_action(to_tg_chat, ChatActions.UPLOAD_VIDEO) tg_message = await tgsend(bot.send_video, to_tg_chat, attachment['content'], - reply_to_message_id=main_message, disable_notification=disable_notify) + reply_to_message_id=main_message, disable_notification=disable_notify, + vk_msg_url=vk_msg_url) elif attachment['type'] == 'sticker': await bot.send_chat_action(to_tg_chat, ChatActions.TYPING) tg_message = await tgsend(bot.send_sticker, to_tg_chat, attachment['content'], - reply_to_message_id=main_message, disable_notification=disable_notify) + reply_to_message_id=main_message, disable_notification=disable_notify, + vk_msg_url=vk_msg_url) elif attachment['type'] == 'location': await bot.send_chat_action(to_tg_chat, ChatActions.FIND_LOCATION) tg_message = await tgsend(bot.send_location, to_tg_chat, *attachment['content'], - reply_to_message_id=main_message, disable_notification=disable_notify) + reply_to_message_id=main_message, disable_notification=disable_notify, + vk_msg_url=vk_msg_url) elif attachment['type'] == 'venue': await bot.send_chat_action(to_tg_chat, ChatActions.FIND_LOCATION) tg_message = await tgsend(bot.send_venue, to_tg_chat, *attachment['content'], - reply_to_message_id=main_message, disable_notification=disable_notify) + reply_to_message_id=main_message, disable_notification=disable_notify, + vk_msg_url=vk_msg_url) elif attachment['type'] == 'audio': await bot.send_chat_action(to_tg_chat, ChatActions.UPLOAD_DOCUMENT) tg_message = await tgsend(bot.send_audio, to_tg_chat, audio=attachment['content'], @@ -758,6 +767,7 @@ async def process_message(msg, token=None, is_multichat=None, vk_chat_id=None, u performer=attachment.get('artist', None), title=attachment.get('title', None), reply_to_message_id=main_message, disable_notification=disable_notify, + vk_msg_url=vk_msg_url, parse_mode='HTML') elif attachment['type'] == 'audio_message': await bot.send_chat_action(to_tg_chat, ChatActions.RECORD_AUDIO) @@ -775,26 +785,31 @@ async def process_message(msg, token=None, is_multichat=None, vk_chat_id=None, u # tg_chat=transcript_message.chat.id, # tg_id=transcript_message.message_id # ) - - Message.objects.create( - vk_chat=vk_chat_id, - vk_id=vk_msg_id, - tg_chat=tg_message.chat.id, - tg_id=tg_message.message_id - ) + if tg_message: + Message.objects.create( + vk_chat=vk_chat_id, + vk_id=vk_msg_id, + tg_chat=tg_message.chat.id, + tg_id=tg_message.message_id + ) if vk_msg.get('fwd_messages'): await bot.send_chat_action(to_tg_chat, ChatActions.TYPING) for fwd_message in vk_msg['fwd_messages']: - fwd_msgs_in_db = Message.objects.filter( - vk_chat=vk_chat_id, - vk_id=fwd_message['id'], - tg_chat=to_tg_chat - ) + # Не у всех сообщений есть уникальный id, похоже надо сохранять conversation_message_id в том числе + # И делать миграции + if fwd_message['id']: + fwd_msgs_in_db = Message.objects.filter( + vk_chat=vk_chat_id, + vk_id=fwd_message['id'], + tg_chat=to_tg_chat + ) + else: + fwd_msg_in_db = None if fwd_msgs_in_db: for fwd_msg_in_db in fwd_msgs_in_db: try: await bot.forward_message(to_tg_chat, to_tg_chat, fwd_msg_in_db.tg_id, - disable_notification=disable_notify) + disable_notification=disable_notify, vk_msg_url=vk_msg_url) except: await process_message(msg, token=token, is_multichat=is_multichat, vk_chat_id=vk_chat_id, @@ -827,6 +842,7 @@ async def get_name(identifier, api): async def tgsend(method, *args, **kwargs): + vk_msg_url = kwargs.pop('vk_msg_url', 0) try: tg_message = await method(*args, **kwargs) return tg_message @@ -836,6 +852,15 @@ async def tgsend(method, *args, **kwargs): except Exception: log.exception(msg='Error in message sending', exc_info=True) + try: + text = 'Ошибка отправки вложения VK → Telegram' + if vk_msg_url: + text += '\n' + f'Сообщение' + await bot.send_message(args[0], text=text, parse_mode='HTML') + except Exception: + log.exception(msg='Error in message sending report', exc_info=True) + pass + async def process_event(msg): pass @@ -876,7 +901,7 @@ async def process_attachment(attachment, token=None): res = {'content': voice_url, 'type': 'audio_message'} if attachment[atype].get('transcript'): - return {'content': f'Войс:{atype[atype]["transcript"]}', 'type': 'text'} + return {'content': f'Войс:{attachment[atype]["transcript"]}', 'type': 'text'} return res elif atype == 'audio': @@ -969,8 +994,8 @@ async def process_attachment(attachment, token=None): elif atype == 'doc': ext = attachment[atype]['ext'] if ext == 'gif': - size = attachment[atype]['file_size'] - gif_url = attachment[atype]['url'] + '&mp4=1' + size = int(attachment[atype]['preview']['video']['file_size']) + gif_url = attachment[atype]['preview']['video']['src'] if size > MAX_FILE_SIZE: return {'content': f'GIF', 'type': 'text'} return {'content': gif_url, 'type': 'document'} @@ -1018,7 +1043,7 @@ async def process_attachment(attachment, token=None): return {'content': file_bytes, 'type': 'sticker'} elif atype == 'gift': - gift_url = attachment[atype][await get_max_photo(attachment[atype], 'thumb')] + gift_url = attachment[atype][get_max_photo(attachment[atype], 'thumb')] return {'content': f'Подарок', 'type': 'text'} elif atype == 'link': link_url = attachment[atype]['url']