private async Task <Message> _extractMessage(VkNet.Model.Message msg, bool extractConversation = true) { Conversation conversation = null; Person person = null; IEnumerable <Message> forwarded = null; IEnumerable <Attachment> attachments = null; await Task.WhenAll( Task.Run(async() => { if (extractConversation) { conversation = await _extractConversation(msg); } }), Task.Run(async() => { person = await _extractPerson(msg); }), Task.Run(async() => { if (msg.ForwardedMessages != null && msg.ForwardedMessages.Count > 0) { forwarded = await Task.WhenAll( msg.ForwardedMessages.Select(fwd => _extractMessage(fwd, false))); } else if (msg.ReplyMessage != null) { forwarded = new[] { await _extractMessage(msg.ReplyMessage, false) }; } }), Task.Run(() => { attachments = _extractAttachments(msg); }) ); var body = msg.Text ?? ""; return(new Message(conversation, person, body, forwarded, attachments)); }
public override async Task SendMessage(Conversation conversation, Message message) { Logger.LogTrace("Send message to conversation {0}", conversation.OriginId); var peerId = Convert.ToInt32(conversation.OriginId); #region Get forwarded and attachments var fwd = FlattenForwardedMessages(message); var attachments = GetAllAttachments(message, fwd); #endregion #region Send message var sender = ""; if (message.OriginSender != null) { sender = FormatSender(message.OriginSender) + "\n"; } var body = FormatMessageBody(message, fwd); if (body.Length > 0) { await ApiClient.Messages.SendAsync(new MessagesSendParams { GroupId = _groupId, PeerId = peerId, Message = $"{sender}{body}", RandomId = random.Next() }); } #endregion if (attachments.Any()) { Logger.LogTrace("Sending message with attachments"); try { #region Get upload server urls UploadServerInfo photoUploadServer = null; UploadServerInfo docsUploadServer = null; UploadServerInfo voiceUploadServer = null; await Task.WhenAll(Task.Run(async() => { if (attachments.Any(at => (at is PhotoAttachment || at is StickerAttachment))) { photoUploadServer = await ApiClient.Photo.GetMessagesUploadServerAsync(peerId); } }), Task.Run(async() => { if (attachments.Any(at => !(at is VoiceAttachment || at is PhotoAttachment))) { docsUploadServer = await ApiClient.Docs.GetMessagesUploadServerAsync(peerId, DocMessageType.Doc); } }), Task.Run(async() => { if (attachments.Any(at => at is VoiceAttachment)) { voiceUploadServer = await ApiClient.Docs.GetMessagesUploadServerAsync(peerId, DocMessageType.AudioMessage); } })); #endregion #region Get vk attachments var groupableAttachments = attachments.Where(at => !(at is IVkSpecialAttachment)); Func <Attachment, Task <MediaAttachment> > GroupableAttachmentSelector() { return(async at => { switch (at) { case AnimationAttachment animation: return await _uploadDocument(animation, docsUploadServer); case StickerAttachment sticker: return await _uploadPhoto(sticker, photoUploadServer); case PhotoAttachment albumPhoto: return await _uploadPhoto(albumPhoto, photoUploadServer); case VideoAttachment albumVideo: return await _uploadDocument(albumVideo, docsUploadServer); case VoiceAttachment voice: return await _uploadDocument(voice, voiceUploadServer); case AudioAttachment audio: return await _uploadDocument(audio, docsUploadServer, $"{audio.ToString()}.mp3.txt", "audio/mp3"); case FileAttachment file: return await _uploadDocument(file, docsUploadServer); default: return null; } }); } #endregion #region Send vk attachments by chunks var chunks = groupableAttachments .Select((val, i) => (val, i)) .GroupBy(tuple => tuple.i / 10); foreach (var chunk in chunks) { var vkAttachments = await Task.WhenAll(chunk.Select(x => x.val) .Select(GroupableAttachmentSelector())); await ApiClient.Messages.SendAsync(new MessagesSendParams { GroupId = _groupId, PeerId = peerId, Attachments = vkAttachments.Where(a => a != null), RandomId = random.Next(), Message = $"{sender}{string.Join(" ", vkAttachments.Where(a => a == null).Select(a => "[Unsupported attachment]").ToArray())}" }); } #endregion #region Send special attachments (contacts/urls/places) foreach (var at in attachments) { switch (at) { case ContactAttachment contact: await ApiClient.Messages.SendAsync(new MessagesSendParams { GroupId = _groupId, PeerId = peerId, Attachments = new[] { await _uploadDocument(contact, docsUploadServer) }, Message = $"{sender}{contact.ToString()}", RandomId = random.Next() }); break; case LinkAttachment link: await ApiClient.Messages.SendAsync(new MessagesSendParams { GroupId = _groupId, PeerId = peerId, Message = $"{sender}{link.ToString()}", RandomId = random.Next() }); break; case PlaceAttachment place: await ApiClient.Messages.SendAsync(new MessagesSendParams { GroupId = _groupId, PeerId = peerId, Lat = place.Latitude, Longitude = place.Longitude, // typo in lib Message = $"{sender}{place.ToString()}", RandomId = random.Next() }); break; } } #endregion } catch (Exception e) { Logger.LogError("Attachments upload failed {0}", e); } } }