diff --git a/app/DataBase/hard_link.py b/app/DataBase/hard_link.py
index 22e93f82..cc6ab0d3 100644
--- a/app/DataBase/hard_link.py
+++ b/app/DataBase/hard_link.py
@@ -5,6 +5,7 @@
import xml.etree.ElementTree as ET
from app.log import log
+from app.util.protocbuf.msg_pb2 import MessageBytesExtra
image_db_lock = threading.Lock()
video_db_lock = threading.Lock()
@@ -30,224 +31,47 @@ def get_md5_from_xml(content, type_="img"):
return None
-class tencent_struct:
- def __setVals__(self, data, off):
- if data:
- self.__data = data
- if self.__data:
- self.__size = len(self.__data)
- self.__off = off
-
- def __readString(self):
- try:
- length = self.__readUleb()
- res = self.__data[self.__off: self.__off + length]
- self.__add(length)
- except:
- raise
- return res.decode("utf-8")
-
- def __readUleb(self):
- try:
- i = self.__data[self.__off]
- self.__add()
- if i & 0x80:
- j = self.__data[self.__off]
- i = i & 0x7F
- i = i | (j << 7)
- self.__add()
- if i & 0x4000:
- j = self.__data[self.__off]
- i = i & 0x3FFF
- i = i | (j << 14)
- self.__add()
- if i & 0x200000:
- j = self.__data[self.__off]
- i = i & 0x1FFFFF
- i = i | (j << 21)
- self.__add()
- if i & 0x10000000:
- j = self.__data[self.__off]
- i = i & 0xFFFFFFF
- i = i | (j << 28)
- self.__add()
- return i
- except:
- raise
-
- def __readData(self):
- try:
- length = self.__readUleb()
- data = self.__data[self.__off: self.__off + length]
- self.__add(length)
- return data
- except:
- raise
-
- def __init__(self, data=None, off=0):
- self.__data = data
- self.__off = off
- if self.__data:
- self.__size = len(self.__data)
- else:
- self.__size = 0
-
- def __add(self, value=1):
- self.__off += value
- if self.__off > self.__size:
- raise "偏移量超出size"
-
- def readStruct(self, struct_type):
- current_dict = None
- if isinstance(struct_type, str):
- current_dict = getattr(self, struct_type)
- else:
- current_dict = struct_type
- res = {}
- try:
- while self.__off < self.__size:
- key = self.__readUleb()
- key = key >> 3
- if key == 0:
- break
- op = None
- fieldName = ""
- if key in current_dict:
- op = current_dict[key][1]
- fieldName = current_dict[key][0]
- else:
- break
- if isinstance(op, dict):
- if not key in res:
- res[key] = []
- current_struct = self.__readData()
- recursion = tencent_struct(current_struct)
- res[key].append((fieldName, recursion.readStruct(op)))
- elif op != "":
- res[key] = (fieldName, self.__contenttype__[op](self))
- else:
- break
- except:
- raise
- return res
-
- __struct1__ = {1: ("", "I"), 2: ("", "I")}
-
- __msgInfo__ = {1: ("", "I"), 2: ("msg_info", "s")}
-
- __bytesExtra__ = {
- 1: ("", __struct1__),
- 3: ("msg_info_struct", __msgInfo__),
- }
-
- __struct2__ = {1: ("", "s"), 2: ("", "s")}
-
- __extraBuf__ = {
- 1: ("", __struct2__),
- }
-
- def get_bytesExta_Content(self, data=None, off=0):
- self.__setVals__(data, off)
- try:
- return self.readStruct("__bytesExtra__")
- except:
- raise
-
- def get_extraBuf_Content(self, data=None, off=0):
- self.__setVals__(data, off)
- try:
- return self.readStruct("__extraBuf__")
- except:
- raise
-
- __contenttype__ = {
- "s": __readString,
- "I": __readUleb,
- "P": __readData,
- }
-
-
-def parseBytes(content: bytes):
- try:
- bytesExtra = tencent_struct().get_bytesExta_Content(content)
- return bytesExtra
- except:
- pass
-
-
-def parseExtraBuf(content: bytes):
- try:
- extraBuf = tencent_struct().get_extraBuf_Content(content)
- return extraBuf
- except:
- pass
-
-
def decodeExtraBuf(extra_buf_content: bytes):
- off = 0
- types = [b"\x04", b"\x18", b"\x17", b"\x02", b"\x05"]
trunkName = {
- "46CF10C4": "个性签名",
- "A4D9024A": "国家",
- "E2EAA8D1": "省份",
- "1D025BBF": "市",
- "81AE19B4": "朋友圈背景url",
- "F917BCC0": "公司名称",
- "4EB96D85": "企业微信属性",
- "0E719F13": "备注图片",
- "759378AD": "手机号",
- "74752C06": "性别",
+ b"\x46\xCF\x10\xC4": "个性签名",
+ b"\xA4\xD9\x02\x4A": "国家",
+ b"\xE2\xEA\xA8\xD1": "省份",
+ b"\x1D\x02\x5B\xBF": "市",
+ # b"\x81\xAE\x19\xB4": "朋友圈背景url",
+ # b"\xF9\x17\xBC\xC0": "公司名称",
+ # b"\x4E\xB9\x6D\x85": "企业微信属性",
+ # b"\x0E\x71\x9F\x13": "备注图片",
+ b"\x75\x93\x78\xAD": "手机号",
+ b"\x74\x75\x2C\x06": "性别",
}
- res = {'手机号': {'18': ''}}
- while off < len(extra_buf_content):
- length = 4 # 块头
- trunk_head = extra_buf_content[off: off + length]
- off += length
- trunk_head = binascii.hexlify(trunk_head).decode().upper()
- if trunk_head in trunkName:
- trunk_head = trunkName[trunk_head]
- res[trunk_head] = {}
- char = extra_buf_content[off: off + 1]
+ res = {"手机号": ""}
+ off = 0
+ for key in trunkName:
+ trunk_head = trunkName[key]
+ try:
+ off = extra_buf_content.index(key) + 4
+ except:
+ pass
+ char = extra_buf_content[off : off + 1]
off += 1
- field = binascii.hexlify(char).decode()
if char == b"\x04": # 四个字节的int,小端序
- length = 4
- intContent = extra_buf_content[off: off + length]
+ intContent = extra_buf_content[off : off + 4]
off += 4
intContent = int.from_bytes(intContent, "little")
- res[trunk_head][field] = intContent
+ res[trunk_head] = intContent
elif char == b"\x18": # utf-16字符串
- length = 4
- lengthContent = extra_buf_content[off: off + length]
- off += 4
- lengthContent = int.from_bytes(lengthContent, "little")
- strContent = extra_buf_content[off: off + lengthContent]
- off += lengthContent
- res[trunk_head][field] = strContent.decode("utf-16").rstrip("\x00")
- elif char == b"\x17": # utf-8 protobuf
- length = 4
- lengthContent = extra_buf_content[off: off + length]
+ lengthContent = extra_buf_content[off : off + 4]
off += 4
lengthContent = int.from_bytes(lengthContent, "little")
- strContent = extra_buf_content[off: off + lengthContent]
+ strContent = extra_buf_content[off : off + lengthContent]
off += lengthContent
- res[trunk_head][field] = parseExtraBuf(strContent)
- elif char == b"\x02": # 一个字节的int
- content = extra_buf_content[off: off + 1]
- off += 1
- res[trunk_head][field] = int.from_bytes(content, "little")
- elif char == b"\x05": # 暂时不知道有啥用,固定8个字节,先当int处理
- length = 8
- content = extra_buf_content[off: off + length]
- off += length
- res[trunk_head][field] = int.from_bytes(content, "little")
- # print(res)
+ res[trunk_head] = strContent.decode("utf-16").rstrip("\x00")
return {
- 'region': (res['国家']['18'], res['省份']['18'], res['市']['18']),
- 'signature': res['个性签名']['18'],
- 'telephone': res['手机号']['18'],
- 'gender': res['性别']['04']
+ "region": (res["国家"], res["省份"], res["市"]),
+ "signature": res["个性签名"],
+ "telephone": res["手机号"],
+ "gender": res["性别"],
}
@@ -337,12 +161,14 @@ def get_video_by_md5(self, md5: bytes):
video_db_lock.release()
def get_image(self, content, bytesExtra, thumb=False):
- bytesDict = parseBytes(bytesExtra)
- for msginfo in bytesDict[3]:
- if msginfo[1][1][1] == (3 if thumb else 4):
- pathh = msginfo[1][2][1] # wxid\FileStorage\...
- pathh = "\\".join(pathh.split("\\")[1:])
- return pathh
+ msg_bytes = MessageBytesExtra()
+ msg_bytes.ParseFromString(bytesExtra)
+ for tmp in msg_bytes.message2:
+ if tmp.field1 != (3 if thumb else 4):
+ continue
+ pathh = tmp.field2 # wxid\FileStorage\...
+ pathh = "\\".join(pathh.split("\\")[1:])
+ return pathh
md5 = get_md5_from_xml(content)
if not md5:
return None
@@ -357,12 +183,14 @@ def get_image(self, content, bytesExtra, thumb=False):
return dat_image
def get_video(self, content, bytesExtra, thumb=False):
- bytesDict = parseBytes(bytesExtra)
- for msginfo in bytesDict[3]:
- if msginfo[1][1][1] == (3 if thumb else 4):
- pathh = msginfo[1][2][1] # wxid\FileStorage\...
- pathh = "\\".join(pathh.split("\\")[1:])
- return pathh
+ msg_bytes = MessageBytesExtra()
+ msg_bytes.ParseFromString(bytesExtra)
+ for tmp in msg_bytes.message2:
+ if tmp.field1 != (3 if thumb else 4):
+ continue
+ pathh = tmp.field2 # wxid\FileStorage\...
+ pathh = "\\".join(pathh.split("\\")[1:])
+ return pathh
md5 = get_md5_from_xml(content, type_="video")
if not md5:
return None
diff --git a/app/DataBase/msg.py b/app/DataBase/msg.py
index d1a7c44f..4c67639d 100644
--- a/app/DataBase/msg.py
+++ b/app/DataBase/msg.py
@@ -4,7 +4,6 @@
import threading
import traceback
-from app.DataBase.hard_link import parseBytes
from app.log import logger
from app.util.compress_content import parser_reply
from app.util.protocbuf.msg_pb2 import MessageBytesExtra
@@ -651,12 +650,12 @@ def __del__(self):
else:
show_display_name = appinfo.find('appname').text
print(title, des, url, show_display_name)
- bytesDict = parseBytes(msg[10])
- for msginfo in bytesDict[3]:
- print(msginfo)
- if msginfo[1][1][1] == 3:
- thumb = msginfo[1][2][1]
+ msg_bytes = MessageBytesExtra()
+ msg_bytes.ParseFromString(msg[10])
+ for tmp in msg_bytes.message2:
+ if tmp.field1 == 3:
+ thumb = tmp.field2
print(thumb)
- if msginfo[1][1][1] == 4:
- app_logo = msginfo[1][2][1]
+ if tmp.field2 == 4:
+ app_logo = tmp.field2
print('logo',app_logo)
\ No newline at end of file
diff --git a/app/resources/data/template.html b/app/resources/data/template.html
index 939bb7ac..83c48197 100644
--- a/app/resources/data/template.html
+++ b/app/resources/data/template.html
@@ -173,6 +173,7 @@
width: 42px;
height: 42px;
border-radius: 50%;
+ user-select: none;
}
.chat-video video{
margin-right: 18px;
@@ -465,6 +466,12 @@
margin-left: 5px;
}
}
+
+.system-msg>.emoji_img {
+ width: 18px;
+ height: 18px;
+}
+
.emoji_img {
width: 22px;
height: 22px;
@@ -802,7 +809,7 @@
// 从数据列表中取出对应范围的元素并添加到容器中
for (let i = startIndex; i < endIndex && i < chatMessages.length; i++) {
const message = chatMessages[i];
- if (i == startIndex) { // 判断一下在页面顶部多加一个时间
+ if (i == startIndex && (reachedBottom ? !/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/.test(chatMessages[i - 1].text) : 1)) { // 判断一下在页面顶部多加一个时间
if (!/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/.test(message.text)) {
// 时间戳转成时间
function timestampToTime(timestamp) {
@@ -843,7 +850,7 @@
}
else if (message.type == 0) {
messageElement.className = "item item-center";
- messageElement.innerHTML = `${message.text}`;
+ messageElement.innerHTML = `${replaceEmoji(message.text)}`;
}
else if (message.type == 3) {
// displayname 和 img
diff --git a/app/util/compress_content.py b/app/util/compress_content.py
index f8397e4f..bb6ab148 100644
--- a/app/util/compress_content.py
+++ b/app/util/compress_content.py
@@ -8,7 +8,7 @@
from urllib.parse import urlparse
from bs4 import BeautifulSoup
-from app.DataBase.hard_link import parseBytes
+from app.util.protocbuf.msg_pb2 import MessageBytesExtra
from ..util.file import get_file
@@ -149,15 +149,16 @@ def share_card(bytesExtra, compress_content_):
else:
if appinfo is not None:
show_display_name = appinfo.find('appname').text
- bytesDict = parseBytes(bytesExtra)
+ msg_bytes = MessageBytesExtra()
+ msg_bytes.ParseFromString(bytesExtra)
app_logo = ''
thumbnail = ''
- for msginfo in bytesDict[3]:
- if msginfo[1][1][1] == 3:
- thumbnail = msginfo[1][2][1]
+ for tmp in msg_bytes.message2:
+ if tmp.field1 == 3:
+ thumbnail = tmp.field2
thumbnail = "\\".join(thumbnail.split('\\')[1:])
- if msginfo[1][1][1] == 4:
- app_logo = msginfo[1][2][1]
+ if tmp.field2 == 4:
+ app_logo = tmp.field2
app_logo = "\\".join(app_logo.split('\\')[1:])
if sourceusername is not None:
from app.DataBase import micro_msg_db # 放上面会导致循环依赖