From ef7bea7f9c22a916fbe7aa4eb9cfc6483b8952ef Mon Sep 17 00:00:00 2001
From: STDquantum <405720329@qq.com>
Date: Sun, 17 Dec 2023 18:33:06 +0800
Subject: [PATCH] =?UTF-8?q?html=E7=BE=A4=E8=81=8A=E5=AF=BC=E5=87=BA?=
=?UTF-8?q?=E6=94=AF=E6=8C=81=E5=A4=B4=E5=83=8F=E5=92=8C=E6=98=B5=E7=A7=B0?=
=?UTF-8?q?=EF=BC=9B=E4=BF=AE=E5=A4=8D=E4=BA=86=E4=B8=80=E4=BA=9B=E5=85=B6?=
=?UTF-8?q?=E4=BB=96=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/DataBase/msg.py | 15 ++
app/DataBase/output_pc.py | 349 ++++++++++++++++++++++++++----------
app/DataBase/package_msg.py | 64 ++++++-
app/util/emoji.py | 91 +++++++++-
main.py | 1 +
5 files changed, 424 insertions(+), 96 deletions(-)
diff --git a/app/DataBase/msg.py b/app/DataBase/msg.py
index 037c5eb..b0ff151 100644
--- a/app/DataBase/msg.py
+++ b/app/DataBase/msg.py
@@ -57,6 +57,21 @@ class Msg:
lock.release()
def get_messages(self, username_):
+ '''
+ return list
+ a[0]: localId,
+ a[1]: talkerId, (和strtalker对应的,不是群聊信息发送人)
+ a[2]: type,
+ a[3]: subType,
+ a[4]: is_sender,
+ a[5]: timestamp,
+ a[6]: status, (没啥用)
+ a[7]: str_content,
+ a[8]: str_time, (格式化的时间)
+ a[9]: msgSvrId,
+ a[10]: BytesExtra,
+ a[11]: CompressContent,
+ '''
if not self.open_flag:
return None
sql = '''
diff --git a/app/DataBase/output_pc.py b/app/DataBase/output_pc.py
index 60569c7..329d5ab 100644
--- a/app/DataBase/output_pc.py
+++ b/app/DataBase/output_pc.py
@@ -27,6 +27,7 @@ def makedirs(path):
os.makedirs(os.path.join(path, 'video'), exist_ok=True)
os.makedirs(os.path.join(path, 'voice'), exist_ok=True)
os.makedirs(os.path.join(path, 'file'), exist_ok=True)
+ os.makedirs(os.path.join(path, 'avatar'), exist_ok=True)
def escape_js_and_html(input_str):
@@ -181,20 +182,32 @@ class ChildThread(QThread):
str_content = message[7]
str_time = message[8]
is_send = message[4]
- avatar = 'myhead.png' if is_send else 'tahead.png'
timestamp = message[5]
+ is_chatroom = 1 if self.contact.is_chatroom else 0
+ if is_chatroom:
+ avatar = f"./avatar/{message[12].wxid}.png"
+ else:
+ avatar = "./avatar/" + ('myhead.png' if is_send else 'tahead.png')
+ if is_chatroom:
+ if is_send:
+ displayname = MePC().name
+ else:
+ displayname = message[12].remark
+ else:
+ displayname = MePC().name if is_send else self.contact.remark
+ displayname = escape_js_and_html(displayname)
if self.output_type == Output.HTML:
str_content = escape_js_and_html(str_content)
if self.is_5_min(timestamp):
doc.write(
- f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:''}},'''
+ f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:'',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
)
emojiText = findall(r"(\[.+?\])", str_content)
for emoji_text in emojiText:
if emoji_text in emoji:
str_content = str_content.replace(emoji_text, emoji[emoji_text])
doc.write(
- f'''{{ type:{1}, text: '{str_content}',is_send:{is_send},avatar_path:'{avatar}'}},'''
+ f'''{{ type:{1}, text: '{str_content}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
)
elif self.output_type == Output.TXT:
name = '你' if is_send else self.contact.remark
@@ -208,9 +221,21 @@ class ChildThread(QThread):
str_content = message[7]
str_time = message[8]
is_send = message[4]
- avatar = 'myhead.png' if is_send else 'tahead.png'
- timestamp = message[5]
BytesExtra = message[10]
+ timestamp = message[5]
+ is_chatroom = 1 if self.contact.is_chatroom else 0
+ if is_chatroom:
+ avatar = f"./avatar/{message[12].wxid}.png"
+ else:
+ avatar = "./avatar/" + ('myhead.png' if is_send else 'tahead.png')
+ if is_chatroom:
+ if is_send:
+ displayname = MePC().name
+ else:
+ displayname = message[12].remark
+ else:
+ displayname = MePC().name if is_send else self.contact.remark
+ displayname = escape_js_and_html(displayname)
if self.output_type == Output.HTML:
str_content = escape_js_and_html(str_content)
image_path = hard_link_db.get_image(str_content, BytesExtra, thumb=False)
@@ -231,10 +256,10 @@ class ChildThread(QThread):
# print(f"tohtml:---{image_path}")
if self.is_5_min(timestamp):
doc.write(
- f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:''}},'''
+ f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:'',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
)
doc.write(
- f'''{{ type:{type_}, text: '{image_path}',is_send:{is_send},avatar_path:'{avatar}'}},'''
+ f'''{{ type:{type_}, text: '{image_path}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
)
elif self.output_type == Output.TXT:
name = '你' if is_send else self.contact.remark
@@ -247,15 +272,26 @@ class ChildThread(QThread):
str_content = message[7]
str_time = message[8]
is_send = message[4]
- avatar = 'myhead.png' if is_send else 'tahead.png'
- creatorName = MePC().name if is_send else self.contact.remark
- timestamp = message[5]
msgSvrId = message[9]
+ timestamp = message[5]
+ is_chatroom = 1 if self.contact.is_chatroom else 0
+ if is_chatroom:
+ avatar = f"./avatar/{message[12].wxid}.png"
+ else:
+ avatar = "./avatar/" + ('myhead.png' if is_send else 'tahead.png')
+ if is_chatroom:
+ if is_send:
+ displayname = MePC().name
+ else:
+ displayname = message[12].remark
+ else:
+ displayname = MePC().name if is_send else self.contact.remark
+ displayname = escape_js_and_html(displayname)
if self.output_type == Output.HTML:
try:
audio_path = media_msg_db.get_audio(msgSvrId, output_path=origin_docx_path + "/voice")
audio_path = audio_path.replace('/', '\\')
- modify_audio_metadata(audio_path, creatorName)
+ modify_audio_metadata(audio_path, displayname)
os.utime(audio_path, (timestamp, timestamp))
audio_path = audio_path.replace('\\', '/')
voice_to_text = escape_js_and_html(media_msg_db.get_audio_text(str_content))
@@ -263,10 +299,10 @@ class ChildThread(QThread):
return
if self.is_5_min(timestamp):
doc.write(
- f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:''}},'''
+ f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:'',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
)
doc.write(
- f'''{{ type:34, text:'{audio_path}',is_send:{is_send},avatar_path:'{avatar}',voice_to_text:'{voice_to_text}'}},'''
+ f'''{{ type:34, text:'{audio_path}',is_send:{is_send},avatar_path:'{avatar}',voice_to_text:'{voice_to_text}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
)
if self.output_type == Output.TXT:
name = '你' if is_send else self.contact.remark
@@ -279,17 +315,33 @@ class ChildThread(QThread):
str_content = message[7]
str_time = message[8]
is_send = message[4]
- avatar = 'myhead.png' if is_send else 'tahead.png'
timestamp = message[5]
+ is_chatroom = 1 if self.contact.is_chatroom else 0
+ if is_chatroom:
+ avatar = f"./avatar/{message[12].wxid}.png"
+ else:
+ avatar = "./avatar/" + ('myhead.png' if is_send else 'tahead.png')
+ if is_chatroom:
+ if is_send:
+ displayname = MePC().name
+ else:
+ displayname = message[12].remark
+ else:
+ displayname = MePC().name if is_send else self.contact.remark
+ displayname = escape_js_and_html(displayname)
if self.output_type == Output.HTML:
emoji_path = get_emoji(str_content, thumb=True, output_path=origin_docx_path + '/emoji')
- emoji_path = './emoji/' + os.path.basename(emoji_path)
+ if emoji_path == "":
+ shutil.copy(f"{os.path.abspath('.')}/app/resources/icons/404.png", origin_docx_path + '/emoji/404.png')
+ emoji_path = "./emoji/404.png"
+ else:
+ emoji_path = './emoji/' + os.path.basename(emoji_path)
if self.is_5_min(timestamp):
doc.write(
- f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:''}},'''
+ f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:'',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
)
doc.write(
- f'''{{ type:{3}, text: '{emoji_path}',is_send:{is_send},avatar_path:'{avatar}'}},'''
+ f'''{{ type:{3}, text: '{emoji_path}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
)
elif self.output_type == Output.TXT:
name = '你' if is_send else self.contact.remark
@@ -317,6 +369,20 @@ class ChildThread(QThread):
avatar = 'myhead.png' if is_send else 'tahead.png'
content = parser_reply(message[11])
refer_msg = content.get('refer')
+ timestamp = message[5]
+ is_chatroom = 1 if self.contact.is_chatroom else 0
+ if is_chatroom:
+ avatar = f"./avatar/{message[12].wxid}.png"
+ else:
+ avatar = "./avatar/" + ('myhead.png' if is_send else 'tahead.png')
+ if is_chatroom:
+ if is_send:
+ displayname = MePC().name
+ else:
+ displayname = message[12].remark
+ else:
+ displayname = MePC().name if is_send else self.contact.remark
+ displayname = escape_js_and_html(displayname)
if self.output_type == Output.HTML:
contentText = content.get('title')
emojiText = findall(r"(\[.+?\])", contentText)
@@ -330,11 +396,11 @@ class ChildThread(QThread):
if emoji_text in emoji:
referText = referText.replace(emoji_text, emoji[emoji_text])
doc.write(
- f'''{{ type:49, text: '{contentText}',is_send:{is_send},sub_type:{content.get('type')},refer_text: '{referText}',avatar_path:'{avatar}'}},'''
+ f'''{{ type:49, text: '{contentText}',is_send:{is_send},sub_type:{content.get('type')},refer_text: '{referText}',avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
)
else:
doc.write(
- f'''{{ type:49, text: '{contentText}',is_send:{is_send},sub_type:{content.get('type')},avatar_path:'{avatar}'}},'''
+ f'''{{ type:49, text: '{contentText}',is_send:{is_send},sub_type:{content.get('type')},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
)
elif self.output_type == Output.TXT:
name = '你' if is_send else self.contact.remark
@@ -351,10 +417,12 @@ class ChildThread(QThread):
str_content = message[7]
is_send = message[4]
str_time = message[8]
+ timestamp = message[5]
+ is_chatroom = 1 if self.contact.is_chatroom else 0
str_content = escape_js_and_html(str_content.lstrip('').rstrip(''))
if self.output_type == Output.HTML:
doc.write(
- f'''{{ type:0, text: '{str_content}',is_send:{is_send},avatar_path:''}},'''
+ f'''{{ type:0, text: '{str_content}',is_send:{is_send},avatar_path:'',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:''}},'''
)
elif self.output_type == Output.TXT:
name = '你' if is_send else self.contact.remark
@@ -369,8 +437,20 @@ class ChildThread(QThread):
str_time = message[8]
is_send = message[4]
BytesExtra = message[10]
- avatar = 'myhead.png' if is_send else 'tahead.png'
timestamp = message[5]
+ is_chatroom = 1 if self.contact.is_chatroom else 0
+ if is_chatroom:
+ avatar = f"./avatar/{message[12].wxid}.png"
+ else:
+ avatar = "./avatar/" + ('myhead.png' if is_send else 'tahead.png')
+ if is_chatroom:
+ if is_send:
+ displayname = MePC().name
+ else:
+ displayname = message[12].remark
+ else:
+ displayname = MePC().name if is_send else self.contact.remark
+ displayname = escape_js_and_html(displayname)
if self.output_type == Output.HTML:
video_path = hard_link_db.get_video(str_content, BytesExtra, thumb=False)
image_path = hard_link_db.get_video(str_content, BytesExtra, thumb=True)
@@ -385,14 +465,14 @@ class ChildThread(QThread):
# print(f"tohtml:---{image_path}")
if self.is_5_min(timestamp):
doc.write(
- f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:''}},'''
+ f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:'',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
)
doc.write(
- f'''{{ type:3, text: '{image_path}',is_send:{is_send},avatar_path:'{avatar}'}},'''
+ f'''{{ type:3, text: '{image_path}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
)
except:
doc.write(
- f'''{{ type:1, text: '视频丢失',is_send:{is_send},avatar_path:'{avatar}'}},'''
+ f'''{{ type:1, text: '视频丢失',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
)
return
if video_path is None and image_path is None:
@@ -407,10 +487,10 @@ class ChildThread(QThread):
video_path = video_path.replace('\\', '/')
if self.is_5_min(timestamp):
doc.write(
- f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:''}},'''
+ f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:'',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
)
doc.write(
- f'''{{ type:{type_}, text: '{video_path}',is_send:{is_send},avatar_path:'{avatar}'}},'''
+ f'''{{ type:{type_}, text: '{video_path}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
)
elif self.output_type == Output.TXT:
name = '你' if is_send else self.contact.remark
@@ -443,12 +523,27 @@ class ChildThread(QThread):
def to_html_(self):
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
makedirs(origin_docx_path)
- messages = msg_db.get_messages(self.contact.wxid)
+ if self.contact.is_chatroom:
+ packagemsg = PackageMsg()
+ messages = packagemsg.get_package_message_by_wxid(self.contact.wxid)
+ else:
+ messages = msg_db.get_messages(self.contact.wxid)
filename = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}/{self.contact.remark}.html"
f = open(filename, 'w', encoding='utf-8')
- f.write(html_head)
- MePC().avatar.save(os.path.join(origin_docx_path, 'myhead.png'))
- self.contact.avatar.save(os.path.join(origin_docx_path, 'tahead.png'))
+ f.write(html_head.replace("
Chat Records", f"{self.contact.remark}"))
+ MePC().avatar.save(os.path.join(f"{origin_docx_path}/avatar/{MePC().wxid}.png"))
+ if self.contact.is_chatroom:
+ for message in messages:
+ if message[4]: # is_send
+ continue
+ try:
+ chatroom_avatar_path = f"{origin_docx_path}/avatar/{message[12].wxid}.png"
+ if not os.path.exists(chatroom_avatar_path):
+ message[12].avatar.save(chatroom_avatar_path)
+ except:
+ pass
+ else:
+ self.contact.avatar.save(os.path.join(f"{origin_docx_path}/avatar/{self.contact.wxid}.png"))
self.rangeSignal.emit(len(messages))
total_steps = len(messages)
for index, message in enumerate(messages):
@@ -467,7 +562,7 @@ class ChildThread(QThread):
self.emoji(f, message)
elif type_ == 10000 and self.message_types.get(type_):
self.system_msg(f, message)
- elif type_ == 49 and sub_type == 57:
+ elif type_ == 49 and sub_type == 57 and self.message_types.get(type_):
self.refermsg(f, message)
f.write(html_end)
f.close()
@@ -562,6 +657,7 @@ emoji = {
'[阴险]': '
',
'[亲亲]': '
',
'[可怜]': '
',
+ '[Whimper]': '
',
'[笑脸]': '
',
'[生病]': '
',
'[脸红]': '
',
@@ -691,7 +787,8 @@ body{
word-wrap:break-word;
word-break:normal;
}
-.chat-refer{
+.chat-refer {
+ margin-top: 5px;
max-width: 400px;
padding: 6px;
border-radius: 5px;
@@ -701,11 +798,11 @@ body{
word-wrap:break-word;
word-break:normal;
}
-.chat-refer-right{
- margin-right:55px;
+.chat-refer-right {
+ margin-right: 55px;
}
.chat-refer-left{
- margin-left:55px;
+ margin-left: 15px;
}
.item-left .bubble{
margin-left: 15px;
@@ -737,8 +834,8 @@ body{
border-bottom: 10px solid transparent;
right: -20px;
}
-.item{
- white-space: pre-line;
+.item {
+ white-space: pre-wrap;
margin-top: 15px;
display: flex;
width: 100%;
@@ -765,6 +862,20 @@ body{
user-select:none;
}
+.content-wrapper {
+ display: flex;
+ flex-direction: column;
+ align-items: baseline;
+}
+
+.displayname {
+ margin-left: 13px;
+ margin-left: 13px;
+ font-size: 13px;
+ margin-bottom: 5px;
+ color: darkgray;
+}
+
.chat-image img{
margin-right: 18px;
margin-left: 18px;
@@ -960,84 +1071,142 @@ html_end = '''
const startIndex = (page - 1) * itemsPerPage;
const endIndex = startIndex + itemsPerPage;
console.log(page);
+
+ // 生成各类标签的函数
+ function messageBubble(message, side) {
+ const messageBubbleTag = document.createElement('div');
+ messageBubbleTag.className = `bubble bubble-${side}`;
+ messageBubbleTag.innerHTML = message.text;
+ return messageBubbleTag;
+ }
+ function displayNameBox(message) {
+ const displayName = document.createElement('div');
+ displayName.className = "displayname";
+ displayName.innerHTML = message.displayname;
+ return displayName;
+ }
+ function avatarBox(message) {
+ const avatarTag = document.createElement('div');
+ avatarTag.className = "avatar";
+ avatarTag.innerHTML = `
`
+ return avatarTag;
+ }
+ function messageImgBox(message) {
+ const messageImgTag = document.createElement('div');
+ messageImgTag.className = `chat-image`;
+ messageImgTag.innerHTML = `
`;
+ return messageImgTag;
+ }
+ function messageVideoBox(message) {
+ const messageVideoTag = document.createElement('div');
+ messageVideoTag.className = `chat-video`;
+ messageVideoTag.innerHTML = ``;
+ return messageVideoTag;
+ }
+ function messageElementReferText(message, side) {
+ const messageElementRefer = document.createElement('div');
+ messageElementRefer.className = `chat-refer chat-refer-${side}`;
+ messageElementRefer.innerHTML = message.refer_text;
+ return messageElementRefer;
+ }
+ function messageVoiceToTextBubble(message, side) {
+ const messageVoiceToTextTag = document.createElement('div');
+ messageVoiceToTextTag.className = `bubble bubble-${side}`;
+ messageVoiceToTextTag.innerHTML = message.voice_to_text;
+ return messageVoiceToTextTag;
+ }
+ function messageAudioBox(message) {
+ const messageAudioTag = document.createElement('div');
+ messageAudioTag.className = `chat-audio`;
+ messageAudioTag.innerHTML = ``;
+ return messageAudioTag;
+ }
+
// 从数据列表中取出对应范围的元素并添加到容器中
for (let i = startIndex; i < endIndex && i < chatMessages.length; i++) {
const message = chatMessages[i];
- const messageElement = document.createElement('div');
- const messageElementRefer = document.createElement('div');
- const formattedText = message.text.replace(/\\n/g, "
");
- var formattedReferText = "";
+ const messageElement = document.createElement('div'); // 下面那俩的合体
+ const avatarTag = avatarBox(message); // 头像
+ const messageContent = document.createElement('div'); // 除了avatar之外的所有
+ const side = message.is_send ? "right" : "left";
if (message.type == 1) {
- if (message.is_send == 1) {
- messageElement.className = "item item-right";
- messageElement.innerHTML = `${formattedText}
`
- }
- else if (message.is_send == 0) {
- messageElement.className = "item item-left";
- messageElement.innerHTML = `${formattedText}
`
+ // displayname 和 bubble
+ messageContent.className = "content-wrapper";
+ if (message.is_chatroom && !message.is_send) {
+ messageContent.appendChild(displayNameBox(message));
}
+ messageContent.appendChild(messageBubble(message, side));
+
+ // 整合
+ messageElement.className = `item item-${side}`;
+ messageElement.appendChild(message.is_send ? messageContent : avatarTag);
+ messageElement.appendChild(message.is_send ? avatarTag : messageContent);
}
else if (message.type == 0) {
messageElement.className = "item item-center";
- messageElement.innerHTML = `${formattedText}`
+ messageElement.innerHTML = `${message.text}`
}
else if (message.type == 3) {
- if (message.is_send == 1) {
- messageElement.className = "item item-right";
- messageElement.innerHTML = ``
- }
- else if (message.is_send == 0) {
- messageElement.className = "item item-left";
- messageElement.innerHTML = ``
+ // displayname 和 img
+ messageContent.className = "content-wrapper";
+ if (message.is_chatroom && !message.is_send) {
+ messageContent.appendChild(displayNameBox(message));
}
+ messageContent.appendChild(messageImgBox(message));
+
+ // 整合
+ messageElement.className = `item item-${side}`;
+ messageElement.appendChild(message.is_send ? messageContent : avatarTag);
+ messageElement.appendChild(message.is_send ? avatarTag : messageContent);
}
else if (message.type == 43) {
- if (message.is_send == 1) {
- messageElement.className = "item item-right";
- messageElement.innerHTML = ``
- }
- else if (message.is_send == 0) {
- messageElement.className = "item item-left";
- messageElement.innerHTML = ``
+ // displayname 和 video
+ messageContent.className = "content-wrapper";
+ if (message.is_chatroom && !message.is_send) {
+ messageContent.appendChild(displayNameBox(message));
}
+ messageContent.appendChild(messageVideoBox(message));
+
+ // 整合
+ messageElement.className = `item item-${side}`;
+ messageElement.appendChild(message.is_send ? messageContent : avatarTag);
+ messageElement.appendChild(message.is_send ? avatarTag : messageContent);
}
else if (message.type == 49) {
- if (message.sub_type == 57){
+ if (message.sub_type == 57) {
+ // displayname 和 bubble 和 refer
+ messageContent.className = "content-wrapper";
+ if (message.is_chatroom && !message.is_send) {
+ messageContent.appendChild(displayNameBox(message));
+ }
+ messageContent.appendChild(messageBubble(message, side));
if (message.refer_text) {
- formattedReferText = message.refer_text.replace(/\\n/g, "
");
- }
- if (message.is_send == 1) {
- messageElement.className = "item item-right";
- messageElement.innerHTML = `${formattedText}
`
- if (message.refer_text) {
- messageElementRefer.className = "item item-right item-refer";
- messageElementRefer.innerHTML = `${formattedReferText}
`
- }
- }
- else if (message.is_send == 0) {
- messageElement.className = "item item-left";
- messageElement.innerHTML = `${formattedText}
`
- if (message.refer_text) {
- messageElementRefer.className = "item item-left item-refer";
- messageElementRefer.innerHTML = `${formattedReferText}
`
- }
+ messageContent.appendChild(messageElementReferText(message, side));
}
+
+ // 整合
+ messageElement.className = `item item-${side}`;
+ messageElement.appendChild(message.is_send ? messageContent : avatarTag);
+ messageElement.appendChild(message.is_send ? avatarTag : messageContent);
}
}
else if (message.type == 34) {
- if (message.is_send == 1) {
- messageElement.className = "item item-right";
- messageElement.innerHTML = `${message.voice_to_text == "" ? "" : `
${message.voice_to_text}
`}
`
+ // displayname 和 转的文字 和 audio
+ messageContent.className = "content-wrapper";
+ if (message.is_chatroom && !message.is_send) {
+ messageContent.appendChild(displayNameBox(message));
}
- else if (message.is_send == 0) {
- messageElement.className = "item item-left";
- messageElement.innerHTML = `${message.voice_to_text == "" ? "" : `
${message.voice_to_text}
`}
`
+ if (message.voice_to_text) {
+ messageContent.appendChild(messageVoiceToTextBubble(message, side));
}
+ messageContent.appendChild(messageAudioBox(message));
+
+ // 整合
+ messageElement.className = `item item-${side}`;
+ messageElement.appendChild(message.is_send ? messageContent : avatarTag);
+ messageElement.appendChild(message.is_send ? avatarTag : messageContent);
}
chatContainer.appendChild(messageElement);
- if (message.type == 49 && message.sub_type == 57 && message.refer_text) {
- chatContainer.appendChild(messageElementRefer);
- }
}
document.querySelector("#chat-container").scrollTop = 0;
updatePaginationInfo();
diff --git a/app/DataBase/package_msg.py b/app/DataBase/package_msg.py
index 59bfd9a..082c93b 100644
--- a/app/DataBase/package_msg.py
+++ b/app/DataBase/package_msg.py
@@ -1,8 +1,9 @@
import threading
-from app.DataBase import msg_db, micro_msg_db
+from app.DataBase import msg_db, micro_msg_db, misc_db
from app.util.protocbuf.msg_pb2 import MessageBytesExtra
from app.util.protocbuf.roomdata_pb2 import ChatRoomData
+from app.person import ContactPC, MePC
lock = threading.Lock()
@@ -76,6 +77,63 @@ class PackageMsg:
row_list.append(sender)
updated_messages.append(tuple(row_list))
return updated_messages
+
+ def get_package_message_by_wxid(self, chatroom_wxid):
+ '''
+ 获取一个群聊的聊天记录
+ return list
+ a[0]: localId,
+ a[1]: talkerId, (和strtalker对应的,不是群聊信息发送人)
+ a[2]: type,
+ a[3]: subType,
+ a[4]: is_sender,
+ a[5]: timestamp,
+ a[6]: status, (没啥用)
+ a[7]: str_content,
+ a[8]: str_time, (格式化的时间)
+ a[9]: msgSvrId,
+ a[10]: BytesExtra,
+ a[11]: CompressContent,
+ a[12]: msg_sender, (ContactPC类型,这个才是群聊里的信息发送人,不是群聊或者自己是发送者没有这个字段)
+ '''
+ updated_messages = [] # 用于存储修改后的消息列表
+
+ messages = msg_db.get_messages(chatroom_wxid)
+
+ for row in messages:
+ message = list(row)
+ if message[4] == 1: # 自己发送的就没必要解析了
+ message.append(MePC())
+ updated_messages.append(message)
+ continue
+ if message[10] is None: # BytesExtra是空的跳过
+ updated_messages.append(message)
+ continue
+ msgbytes = MessageBytesExtra()
+ msgbytes.ParseFromString(message[10])
+ wxid = ''
+ for tmp in msgbytes.message2:
+ if tmp.field1 != 1:
+ continue
+ wxid = tmp.field2
+ if wxid == "": # 系统消息里面 wxid 不存在
+ updated_messages.append(message)
+ continue
+ contact_info_list = micro_msg_db.get_contact_by_username(wxid)
+ contact_info = {
+ 'UserName': contact_info_list[0],
+ 'Alias': contact_info_list[1],
+ 'Type': contact_info_list[2],
+ 'Remark': contact_info_list[3],
+ 'NickName': contact_info_list[4],
+ 'smallHeadImgUrl': contact_info_list[7]
+ }
+ contact = ContactPC(contact_info)
+ contact.smallHeadImgBLOG = misc_db.get_avatar_buffer(contact.wxid)
+ contact.set_avatar(contact.smallHeadImgBLOG)
+ message.append(contact)
+ updated_messages.append(tuple(message))
+ return updated_messages
def get_chatroom_member_list(self, strtalker):
membermap = {}
@@ -101,3 +159,7 @@ class PackageMsg:
finally:
lock.release()
return membermap
+
+if __name__ == "__main__":
+ p = PackageMsg()
+ print(p.get_package_message_by_wxid("44326600419@chatroom"))
diff --git a/app/util/emoji.py b/app/util/emoji.py
index d2a4d7f..3ab73b7 100644
--- a/app/util/emoji.py
+++ b/app/util/emoji.py
@@ -11,6 +11,8 @@ emoji.py
import os
import traceback
import xml.etree.ElementTree as ET
+import sqlite3
+import threading
import requests
@@ -43,7 +45,10 @@ def get_image_format(header):
def parser_xml(xml_string):
assert type(xml_string) == str
# Parse the XML string
- root = ET.fromstring(xml_string)
+ try:
+ root = ET.fromstring(xml_string)
+ except:
+ root = ET.fromstring(xml_string.replace("&", "&"))
emoji = root.find('./emoji')
# Accessing attributes of the 'emoji' element
fromusername = emoji.get('fromusername')
@@ -61,9 +66,66 @@ def parser_xml(xml_string):
'height': height,
'cdnurl': cdnurl,
'thumburl': thumburl if thumburl else cdnurl,
- 'md5': md5 if md5 else androidmd5,
+ 'md5': (md5 if md5 else androidmd5).lower(),
}
+lock = threading.Lock()
+db_path = "./app/Database/Msg/Emotion.db"
+
+class Emotion:
+ def __init__(self):
+ self.DB = None
+ self.cursor: sqlite3.Cursor = None
+ self.open_flag = False
+ self.init_database()
+
+ def init_database(self):
+ if not self.open_flag:
+ if os.path.exists(db_path):
+ self.DB = sqlite3.connect(db_path, check_same_thread=False)
+ # '''创建游标'''
+ self.cursor = self.DB.cursor()
+ self.open_flag = True
+ if lock.locked():
+ lock.release()
+
+ def get_emoji_url(self, md5: str):
+ sql = '''
+ select CDNUrl
+ from CustomEmotion
+ where md5 = ?
+ '''
+ try:
+ lock.acquire(True)
+ self.cursor.execute(sql, [md5])
+ return self.cursor.fetchone()[0]
+ except:
+ md5 = md5.upper()
+ sql = """
+ select Data
+ from EmotionItem
+ where md5 = ?
+ """
+ self.cursor.execute(sql, [md5])
+ try:
+ return self.cursor.fetchone()[0]
+ except:
+ return ""
+ finally:
+ lock.release()
+
+ def close(self):
+ if self.open_flag:
+ try:
+ lock.acquire(True)
+ self.open_flag = False
+ self.DB.close()
+ finally:
+ lock.release()
+
+ def __del__(self):
+ self.close()
+
@log
def download(url, output_dir, name, thumb=False):
if not url:
@@ -95,9 +157,28 @@ def get_emoji(xml_string, thumb=True, output_path=root_path) -> str:
print('表情包已存在')
return file_path
url = emoji_info['thumburl'] if thumb else emoji_info['cdnurl']
- print("下载表情包ing:", url)
- emoji_path = download(url, output_path, md5, thumb)
- return emoji_path
+ if not url or url == "":
+ url = Emotion().get_emoji_url(md5)
+ if type(url) == str and url != "":
+ print("下载表情包ing:", url)
+ emoji_path = download(url, output_path, md5, thumb)
+ return emoji_path
+ elif type(url) == bytes:
+ image_format = get_image_format(url[:8])
+ if image_format:
+ if thumb:
+ output_path = os.path.join(output_path, 'th_' + md5 + '.' + image_format)
+ else:
+ output_path = os.path.join(output_path, md5 + '.' + image_format)
+ else:
+ output_path = os.path.join(output_path, md5)
+ with open(output_path, 'wb') as f:
+ f.write(url)
+ print("表情包数据库加载", output_path)
+ return output_path
+ else:
+ print("!!!未知表情包数据,信息:", xml_string, emoji_info, url)
+ return ""
except:
logger.error(traceback.format_exc())
return ""
diff --git a/main.py b/main.py
index cd73f0b..2dbc7f0 100644
--- a/main.py
+++ b/main.py
@@ -55,6 +55,7 @@ class ViewController(QWidget):
def close(self) -> bool:
close_db()
super().close()
+
if __name__ == '__main__':
app = QApplication(sys.argv)
font = QFont('微软雅黑', 12) # 使用 Times New Roman 字体,字体大小为 14