public static Richtext Parse(BinaryReader reader) { var result = new Richtext(); // TODO: 解析富文本 try { var messageType = reader.ReadByte(); var dataLength = reader.BeReadChar(); while (reader.BaseStream.Position + dataLength < reader.BaseStream.Length) { reader.ReadByte(); switch (messageType) { case 0x01: //文本消息 { var messageStr = Encoding.UTF8.GetString(reader.ReadBytes(reader.BeReadChar())); if (messageStr.Contains("@")) { //Reader.ReadBytes(10); //var AtQQ = Util.GetQQNumRetUint(Util.ToHex(Reader.ReadBytes(4)));//被At人的QQ号 result.Snippets.Add(new TextSnippet(messageStr, MessageType.At)); } else { result.Snippets.Add(messageStr); } break; } case 0x02: //小黄豆表情 { result.Snippets.Add(new TextSnippet( Util.GetQQNumRetUint(Util.ToHex(reader.ReadBytes(reader.BeReadChar()))).ToString(), MessageType.Emoji)); break; } case 0x03: //图片 { result.Snippets.Add(new TextSnippet( Encoding.UTF8.GetString(reader.ReadBytes(reader.BeReadChar())), MessageType.Picture)); break; } case 0x0A: //音频 { result.Snippets.Add(new TextSnippet(Encoding.UTF8.GetString(reader.ReadBytes(reader.BeReadChar())), MessageType.Audio)); break; } case 0x0E: //未知 { break; } case 0x14: //XML { reader.ReadByte(); result.Snippets.Add(new TextSnippet(GZipByteArray.DecompressString(reader.ReadBytes((int)(reader.BaseStream.Length - 1))), MessageType.Xml)); break; } case 0x18: //群文件 { reader.ReadBytes(3); var fileName = reader.ReadBytes(reader.ReadByte()); //文件名称 reader.ReadByte(); reader.ReadBytes(reader.ReadByte()); //文件大小 result.Snippets.Add(new TextSnippet(Encoding.UTF8.GetString(fileName), MessageType.OfflineFile)); break; } case 0x19: //红包秘钥段 { if (reader.ReadByte() != 0xC2) { break; } reader.ReadBytes(19); reader.ReadBytes(reader.ReadByte()); //恭喜发财 reader.ReadByte(); reader.ReadBytes(reader.ReadByte()); //赶紧点击拆开吧 reader.ReadByte(); reader.ReadBytes(reader.ReadByte()); //QQ红包 reader.ReadBytes(5); reader.ReadBytes(reader.ReadByte()); //[QQ红包]恭喜发财 reader.ReadBytes(22); var redId = Encoding.UTF8.GetString(reader.ReadBytes(32)); //redid reader.ReadBytes(12); reader.ReadBytes(reader.BeReadChar()); reader.ReadBytes(0x10); var key1 = Encoding.UTF8.GetString(reader.ReadBytes(reader.ReadByte())); //Key1 reader.BeReadChar(); var key2 = Encoding.UTF8.GetString(reader.ReadBytes(reader.ReadByte())); //Key2 result.Snippets.Add(new TextSnippet("", MessageType.RedBag, new Tuple <string, object>("RedId", redId), new Tuple <string, object>("Key1", key1), new Tuple <string, object>("Key2", key2))); break; } } messageType = reader.ReadByte(); dataLength = reader.BeReadChar(); } } catch (Exception ex) { } return(result); }
public static Richtext Parse(BinaryReader reader) { var result = new Richtext(); // TODO: 解析富文本 try { var messageType = reader.ReadByte(); var dataLength = reader.BeReadUInt16(); var pos = reader.BaseStream.Position; while (pos + dataLength < reader.BaseStream.Length) { reader.ReadByte(); switch (messageType) { case 0x01: // 纯文本消息、@ { var messageStr = reader.BeReadString(); if (messageStr.StartsWith("@") && pos + dataLength - reader.BaseStream.Position == 16) { reader.ReadBytes(10); result.Snippets.Add(new TextSnippet(messageStr, MessageType.At, ("Target", reader.BeReadLong32()))); } else { result.Snippets.Add(messageStr); } break; } case 0x02: // Emoji(系统表情) { reader.BeReadUInt16(); // 这里的数字貌似总是1:系统表情只有208个。 result.Snippets.Add(new TextSnippet("", MessageType.Emoji, ("Type", reader.ReadByte()))); break; } case 0x03: // 图片 { result.Snippets.Add(new TextSnippet(reader.BeReadString(), MessageType.Picture)); break; } case 0x0A: // 音频 { result.Snippets.Add(new TextSnippet(reader.BeReadString(), MessageType.Audio)); break; } case 0x0E: // 未知 { break; } case 0x12: // 群名片 { break; } case 0x14: // XML { reader.ReadByte(); result.Snippets.Add(new TextSnippet( GZipByteArray.DecompressString(reader.ReadBytes((int)(reader.BaseStream.Length - 1))), MessageType.Xml)); break; } case 0x18: // 群文件 { reader.ReadBytes(5); var fileName = reader.BeReadString(); // 文件名称... 长度总是一个byte reader.ReadByte(); reader.ReadBytes(reader.ReadByte()); // 文件大小 result.Snippets.Add(new TextSnippet(fileName, MessageType.OfflineFile)); break; } case 0x19: // 红包秘钥段 { if (reader.ReadByte() != 0xC2) { break; } reader.ReadBytes(19); reader.ReadBytes(reader.ReadByte()); // 恭喜发财 reader.ReadByte(); reader.ReadBytes(reader.ReadByte()); // 赶紧点击拆开吧 reader.ReadByte(); reader.ReadBytes(reader.ReadByte()); // QQ红包 reader.ReadBytes(5); reader.ReadBytes(reader.ReadByte()); // [QQ红包]恭喜发财 reader.ReadBytes(22); var redId = Encoding.UTF8.GetString(reader.ReadBytes(32)); //redid reader.ReadBytes(12); reader.ReadBytes(reader.BeReadUInt16()); reader.ReadBytes(0x10); var key1 = Encoding.UTF8.GetString(reader.ReadBytes(reader.ReadByte())); //Key1 reader.BeReadUInt16(); var key2 = Encoding.UTF8.GetString(reader.ReadBytes(reader.ReadByte())); //Key2 result.Snippets.Add(new TextSnippet("", MessageType.RedBag, ("RedId", redId), ("Key1", key1), ("Key2", key2))); break; } } reader.ReadBytes((int)(pos + dataLength - reader.BaseStream.Position)); messageType = reader.ReadByte(); dataLength = reader.BeReadUInt16(); pos = reader.BaseStream.Position; } } catch (Exception ex) { } // 移除所有空白的片段 result.Snippets.RemoveAll(s => s.Type == MessageType.Normal && string.IsNullOrEmpty(s.Content)); // 若长度大于1,那么应该只含有普通文本、At、表情、图片。 // 虽然我看着别人好像视频也能通过转发什么的弄进来,但是反正我们现在不支持接收音视频,所以不管了 return(result.Snippets.Count > 1 && result.Snippets.Any(s => s.Type != MessageType.Normal && s.Type != MessageType.At && s.Type != MessageType.Emoji && s.Type != MessageType.Picture) ? throw new NotSupportedException("富文本中包含多个非聊天代码") : result); }