mirror of
https://github.com/LC044/WeChatMsg
synced 2024-11-14 22:01:54 +08:00
导出csv文件时,增加发送人名称、接受者名称、备注名字段
This commit is contained in:
parent
4a357dca24
commit
0aa1ac964f
@ -63,6 +63,37 @@ class MicroMsg:
|
|||||||
lock.release()
|
lock.release()
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def get_contact_by_username(self, username):
|
||||||
|
if not self.open_flag:
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
lock.acquire(True)
|
||||||
|
sql = '''SELECT UserName, Alias, Type, Remark, NickName, PYInitial, RemarkPYInitial, ContactHeadImgUrl.smallHeadImgUrl, ContactHeadImgUrl.bigHeadImgUrl
|
||||||
|
FROM Contact
|
||||||
|
INNER JOIN ContactHeadImgUrl ON Contact.UserName = ContactHeadImgUrl.usrName
|
||||||
|
WHERE UserName = ?
|
||||||
|
'''
|
||||||
|
self.cursor.execute(sql, [username])
|
||||||
|
result = self.cursor.fetchone()
|
||||||
|
finally:
|
||||||
|
lock.release()
|
||||||
|
return result
|
||||||
|
|
||||||
|
def get_chatroom_info(self, chatroomname):
|
||||||
|
'''
|
||||||
|
获取群聊信息
|
||||||
|
'''
|
||||||
|
if not self.open_flag:
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
lock.acquire(True)
|
||||||
|
sql = '''SELECT ChatRoomName, RoomData FROM ChatRoom WHERE ChatRoomName = ?'''
|
||||||
|
self.cursor.execute(sql, [chatroomname])
|
||||||
|
result = self.cursor.fetchone()
|
||||||
|
finally:
|
||||||
|
lock.release()
|
||||||
|
return result
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
if self.open_flag:
|
if self.open_flag:
|
||||||
try:
|
try:
|
||||||
|
@ -72,7 +72,7 @@ class Msg:
|
|||||||
|
|
||||||
def get_messages_all(self):
|
def get_messages_all(self):
|
||||||
sql = '''
|
sql = '''
|
||||||
select localId,TalkerId,Type,SubType,IsSender,CreateTime,Status,StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime,MsgSvrID
|
select localId,TalkerId,Type,SubType,IsSender,CreateTime,Status,StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime,MsgSvrID,BytesExtra,StrTalker,Reserved1
|
||||||
from MSG
|
from MSG
|
||||||
order by CreateTime
|
order by CreateTime
|
||||||
'''
|
'''
|
||||||
|
@ -5,6 +5,7 @@ import os
|
|||||||
from PyQt5.QtCore import pyqtSignal, QThread
|
from PyQt5.QtCore import pyqtSignal, QThread
|
||||||
|
|
||||||
from . import msg_db
|
from . import msg_db
|
||||||
|
from .package_msg import PackageMsg
|
||||||
from ..DataBase import hard_link_db
|
from ..DataBase import hard_link_db
|
||||||
from ..person_pc import MePC
|
from ..person_pc import MePC
|
||||||
from ..util import get_abs_path
|
from ..util import get_abs_path
|
||||||
@ -65,8 +66,10 @@ class Output(QThread):
|
|||||||
# columns = ["用户名", "消息内容", "发送时间", "发送状态", "消息类型", "isSend", "msgId"]
|
# columns = ["用户名", "消息内容", "发送时间", "发送状态", "消息类型", "isSend", "msgId"]
|
||||||
columns = ['localId', 'TalkerId', 'Type', 'SubType',
|
columns = ['localId', 'TalkerId', 'Type', 'SubType',
|
||||||
'IsSender', 'CreateTime', 'Status', 'StrContent',
|
'IsSender', 'CreateTime', 'Status', 'StrContent',
|
||||||
'StrTime']
|
'StrTime', 'Remark', 'NickName', 'Sender']
|
||||||
messages = msg_db.get_messages_all()
|
# messages = msg_db.get_messages_all()
|
||||||
|
packagemsg = PackageMsg()
|
||||||
|
messages = packagemsg.get_package_message_all()
|
||||||
# 写入CSV文件
|
# 写入CSV文件
|
||||||
with open(filename, mode='w', newline='', encoding='utf-8') as file:
|
with open(filename, mode='w', newline='', encoding='utf-8') as file:
|
||||||
writer = csv.writer(file)
|
writer = csv.writer(file)
|
||||||
@ -165,8 +168,10 @@ class ChildThread(QThread):
|
|||||||
# columns = ["用户名", "消息内容", "发送时间", "发送状态", "消息类型", "isSend", "msgId"]
|
# columns = ["用户名", "消息内容", "发送时间", "发送状态", "消息类型", "isSend", "msgId"]
|
||||||
columns = ['localId', 'TalkerId', 'Type', 'SubType',
|
columns = ['localId', 'TalkerId', 'Type', 'SubType',
|
||||||
'IsSender', 'CreateTime', 'Status', 'StrContent',
|
'IsSender', 'CreateTime', 'Status', 'StrContent',
|
||||||
'StrTime']
|
'StrTime', 'Remark', 'NickName', 'Sender']
|
||||||
messages = msg_db.get_messages_all()
|
# messages = msg_db.get_messages_all()
|
||||||
|
packagemsg = PackageMsg()
|
||||||
|
messages = packagemsg.get_package_message_all()
|
||||||
# 写入CSV文件
|
# 写入CSV文件
|
||||||
with open(filename, mode='w', newline='', encoding='utf-8') as file:
|
with open(filename, mode='w', newline='', encoding='utf-8') as file:
|
||||||
writer = csv.writer(file)
|
writer = csv.writer(file)
|
||||||
|
103
app/DataBase/package_msg.py
Normal file
103
app/DataBase/package_msg.py
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
import threading
|
||||||
|
|
||||||
|
from app.DataBase import msg_db, micro_msg_db
|
||||||
|
from app.util.protocbuf.msg_pb2 import MessageBytesExtra
|
||||||
|
from app.util.protocbuf.roomdata_pb2 import ChatRoomData
|
||||||
|
|
||||||
|
lock = threading.Lock()
|
||||||
|
|
||||||
|
|
||||||
|
def singleton(cls):
|
||||||
|
_instance = {}
|
||||||
|
|
||||||
|
def inner():
|
||||||
|
if cls not in _instance:
|
||||||
|
_instance[cls] = cls()
|
||||||
|
return _instance[cls]
|
||||||
|
|
||||||
|
return inner
|
||||||
|
|
||||||
|
|
||||||
|
@singleton
|
||||||
|
class PackageMsg:
|
||||||
|
def __init__(self):
|
||||||
|
self.ChatRoomMap = {}
|
||||||
|
|
||||||
|
def get_package_message_all(self):
|
||||||
|
'''
|
||||||
|
获取完整的聊天记录
|
||||||
|
'''
|
||||||
|
updated_messages = [] # 用于存储修改后的消息列表
|
||||||
|
|
||||||
|
messages = msg_db.get_messages_all()
|
||||||
|
for row in messages:
|
||||||
|
row_list = list(row)
|
||||||
|
# 删除不使用的几个字段
|
||||||
|
del row_list[12]
|
||||||
|
del row_list[11]
|
||||||
|
del row_list[10]
|
||||||
|
|
||||||
|
strtalker = row[11]
|
||||||
|
info = micro_msg_db.get_contact_by_username(strtalker)
|
||||||
|
if info is not None:
|
||||||
|
row_list.append(info[3])
|
||||||
|
row_list.append(info[4])
|
||||||
|
# 判断是否是群聊
|
||||||
|
if strtalker.__contains__('@chatroom'):
|
||||||
|
# 自己发送
|
||||||
|
if row[12] == 1:
|
||||||
|
row_list.append('我')
|
||||||
|
else:
|
||||||
|
# 存在BytesExtra为空的情况,此时消息类型应该为提示性消息。跳过不处理
|
||||||
|
if row[10] is None:
|
||||||
|
continue
|
||||||
|
# 解析BytesExtra
|
||||||
|
msgbytes = MessageBytesExtra()
|
||||||
|
msgbytes.ParseFromString(row[10])
|
||||||
|
wxid = ''
|
||||||
|
for tmp in msgbytes.message2:
|
||||||
|
if tmp.field1 != 1:
|
||||||
|
continue
|
||||||
|
wxid = tmp.field2
|
||||||
|
sender = ''
|
||||||
|
# 获取群聊成员列表
|
||||||
|
membersMap = self.get_chatroom_member_list(strtalker)
|
||||||
|
if membersMap is not None:
|
||||||
|
if wxid in membersMap:
|
||||||
|
sender = membersMap.get(wxid)
|
||||||
|
else:
|
||||||
|
senderinfo = micro_msg_db.get_contact_by_username(wxid)
|
||||||
|
if senderinfo is not None:
|
||||||
|
sender = senderinfo[4]
|
||||||
|
membersMap[wxid] = senderinfo[4]
|
||||||
|
if len(senderinfo[3]) > 0:
|
||||||
|
sender = senderinfo[3]
|
||||||
|
membersMap[wxid] = senderinfo[3]
|
||||||
|
row_list.append(sender)
|
||||||
|
updated_messages.append(tuple(row_list))
|
||||||
|
return updated_messages
|
||||||
|
|
||||||
|
def get_chatroom_member_list(self, strtalker):
|
||||||
|
membermap = {}
|
||||||
|
'''
|
||||||
|
获取群聊成员
|
||||||
|
'''
|
||||||
|
try:
|
||||||
|
lock.acquire(True)
|
||||||
|
if strtalker in self.ChatRoomMap:
|
||||||
|
membermap = self.ChatRoomMap.get(strtalker)
|
||||||
|
else:
|
||||||
|
chatroom = micro_msg_db.get_chatroom_info(strtalker)
|
||||||
|
if chatroom is None:
|
||||||
|
return None
|
||||||
|
# 解析RoomData数据
|
||||||
|
parsechatroom = ChatRoomData()
|
||||||
|
parsechatroom.ParseFromString(chatroom[1])
|
||||||
|
# 群成员数据放入字典存储
|
||||||
|
for mem in parsechatroom.members:
|
||||||
|
if mem.displayName is not None and len(mem.displayName) > 0:
|
||||||
|
membermap[mem.wxID] = mem.displayName
|
||||||
|
self.ChatRoomMap[strtalker] = membermap
|
||||||
|
finally:
|
||||||
|
lock.release()
|
||||||
|
return membermap
|
0
app/util/protocbuf/__init__.py
Normal file
0
app/util/protocbuf/__init__.py
Normal file
18
app/util/protocbuf/msg.proto
Normal file
18
app/util/protocbuf/msg.proto
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package app.protobuf;
|
||||||
|
option go_package=".;proto";
|
||||||
|
|
||||||
|
message SubMessage1 {
|
||||||
|
int32 field1 = 1;
|
||||||
|
int32 field2 = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SubMessage2 {
|
||||||
|
int32 field1 = 1;
|
||||||
|
string field2 = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MessageBytesExtra {
|
||||||
|
SubMessage1 message1 = 1;
|
||||||
|
repeated SubMessage2 message2 = 3;
|
||||||
|
}
|
54
app/util/protocbuf/msg_pb2.py
Normal file
54
app/util/protocbuf/msg_pb2.py
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||||
|
# source: msg.proto
|
||||||
|
"""Generated protocol buffer code."""
|
||||||
|
from google.protobuf import descriptor as _descriptor
|
||||||
|
from google.protobuf import descriptor_pool as _descriptor_pool
|
||||||
|
from google.protobuf import message as _message
|
||||||
|
from google.protobuf import reflection as _reflection
|
||||||
|
from google.protobuf import symbol_database as _symbol_database
|
||||||
|
# @@protoc_insertion_point(imports)
|
||||||
|
|
||||||
|
_sym_db = _symbol_database.Default()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\tmsg.proto\x12\x0c\x61pp.protobuf\"-\n\x0bSubMessage1\x12\x0e\n\x06\x66ield1\x18\x01 \x01(\x05\x12\x0e\n\x06\x66ield2\x18\x02 \x01(\x05\"-\n\x0bSubMessage2\x12\x0e\n\x06\x66ield1\x18\x01 \x01(\x05\x12\x0e\n\x06\x66ield2\x18\x02 \x01(\t\"m\n\x11MessageBytesExtra\x12+\n\x08message1\x18\x01 \x01(\x0b\x32\x19.app.protobuf.SubMessage1\x12+\n\x08message2\x18\x03 \x03(\x0b\x32\x19.app.protobuf.SubMessage2b\x06proto3')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
_SUBMESSAGE1 = DESCRIPTOR.message_types_by_name['SubMessage1']
|
||||||
|
_SUBMESSAGE2 = DESCRIPTOR.message_types_by_name['SubMessage2']
|
||||||
|
_MESSAGEBYTESEXTRA = DESCRIPTOR.message_types_by_name['MessageBytesExtra']
|
||||||
|
SubMessage1 = _reflection.GeneratedProtocolMessageType('SubMessage1', (_message.Message,), {
|
||||||
|
'DESCRIPTOR' : _SUBMESSAGE1,
|
||||||
|
'__module__' : 'msg_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:app.protobuf.SubMessage1)
|
||||||
|
})
|
||||||
|
_sym_db.RegisterMessage(SubMessage1)
|
||||||
|
|
||||||
|
SubMessage2 = _reflection.GeneratedProtocolMessageType('SubMessage2', (_message.Message,), {
|
||||||
|
'DESCRIPTOR' : _SUBMESSAGE2,
|
||||||
|
'__module__' : 'msg_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:app.protobuf.SubMessage2)
|
||||||
|
})
|
||||||
|
_sym_db.RegisterMessage(SubMessage2)
|
||||||
|
|
||||||
|
MessageBytesExtra = _reflection.GeneratedProtocolMessageType('MessageBytesExtra', (_message.Message,), {
|
||||||
|
'DESCRIPTOR' : _MESSAGEBYTESEXTRA,
|
||||||
|
'__module__' : 'msg_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:app.protobuf.MessageBytesExtra)
|
||||||
|
})
|
||||||
|
_sym_db.RegisterMessage(MessageBytesExtra)
|
||||||
|
|
||||||
|
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||||
|
|
||||||
|
DESCRIPTOR._options = None
|
||||||
|
_SUBMESSAGE1._serialized_start=27
|
||||||
|
_SUBMESSAGE1._serialized_end=72
|
||||||
|
_SUBMESSAGE2._serialized_start=74
|
||||||
|
_SUBMESSAGE2._serialized_end=119
|
||||||
|
_MESSAGEBYTESEXTRA._serialized_start=121
|
||||||
|
_MESSAGEBYTESEXTRA._serialized_end=230
|
||||||
|
# @@protoc_insertion_point(module_scope)
|
34
app/util/protocbuf/readme.md
Normal file
34
app/util/protocbuf/readme.md
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# 说明
|
||||||
|
|
||||||
|
## 解析
|
||||||
|
```shell
|
||||||
|
protoc --decode_raw < msg_data.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
## 根据解析结果,设置.proto文件
|
||||||
|
```shell
|
||||||
|
1 {
|
||||||
|
1: 16
|
||||||
|
2: 0
|
||||||
|
}
|
||||||
|
3 {
|
||||||
|
1: 1
|
||||||
|
2: "wxid_4b1t09d63spw22"
|
||||||
|
}
|
||||||
|
3 {
|
||||||
|
1: 7
|
||||||
|
2: "<msgsource>\n\t<alnode>\n\t\t<fr>2</fr>\n\t</alnode>\n\t<sec_msg_node>\n\t\t<uuid>c6680ab2c57499a1a22e44a7eada76e8_</uuid>\n\t</sec_msg_node>\n\t<silence>1</silence>\n\t<membercount>198</membercount>\n\t<signature>v1_Gj7hfmi5</signature>\n\t<tmp_node>\n\t\t<publisher-id></publisher-id>\n\t</tmp_node>\n</msgsource>\n"
|
||||||
|
}
|
||||||
|
3 {
|
||||||
|
1: 2
|
||||||
|
2: "c13acbc95512d1a59bb686d684fd64d8"
|
||||||
|
}
|
||||||
|
3 {
|
||||||
|
1: 4
|
||||||
|
2: "yiluoAK_47\\FileStorage\\Cache\\2023-08\\2286b5852db82f6cbd9c2084ccd52358"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
## 生成python文件
|
||||||
|
```shell
|
||||||
|
protoc --python_out=. msg.proto
|
||||||
|
```
|
19
app/util/protocbuf/roomdata.proto
Normal file
19
app/util/protocbuf/roomdata.proto
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package app.protobuf;
|
||||||
|
option go_package=".;proto";
|
||||||
|
|
||||||
|
message ChatRoomData {
|
||||||
|
message ChatRoomMember {
|
||||||
|
string wxID = 1;
|
||||||
|
string displayName = 2;
|
||||||
|
int32 state = 3;
|
||||||
|
}
|
||||||
|
repeated ChatRoomMember members = 1;
|
||||||
|
int32 field_2 = 2;
|
||||||
|
int32 field_3 = 3;
|
||||||
|
int32 field_4 = 4;
|
||||||
|
int32 room_capacity = 5;
|
||||||
|
int32 field_6 = 6;
|
||||||
|
int64 field_7 = 7;
|
||||||
|
int64 field_8 = 8;
|
||||||
|
}
|
45
app/util/protocbuf/roomdata_pb2.py
Normal file
45
app/util/protocbuf/roomdata_pb2.py
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||||
|
# source: roomdata.proto
|
||||||
|
"""Generated protocol buffer code."""
|
||||||
|
from google.protobuf import descriptor as _descriptor
|
||||||
|
from google.protobuf import descriptor_pool as _descriptor_pool
|
||||||
|
from google.protobuf import message as _message
|
||||||
|
from google.protobuf import reflection as _reflection
|
||||||
|
from google.protobuf import symbol_database as _symbol_database
|
||||||
|
# @@protoc_insertion_point(imports)
|
||||||
|
|
||||||
|
_sym_db = _symbol_database.Default()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0eroomdata.proto\x12\x0c\x61pp.protobuf\"\x8b\x02\n\x0c\x43hatRoomData\x12:\n\x07members\x18\x01 \x03(\x0b\x32).app.protobuf.ChatRoomData.ChatRoomMember\x12\x0f\n\x07\x66ield_2\x18\x02 \x01(\x05\x12\x0f\n\x07\x66ield_3\x18\x03 \x01(\x05\x12\x0f\n\x07\x66ield_4\x18\x04 \x01(\x05\x12\x15\n\rroom_capacity\x18\x05 \x01(\x05\x12\x0f\n\x07\x66ield_6\x18\x06 \x01(\x05\x12\x0f\n\x07\x66ield_7\x18\x07 \x01(\x03\x12\x0f\n\x07\x66ield_8\x18\x08 \x01(\x03\x1a\x42\n\x0e\x43hatRoomMember\x12\x0c\n\x04wxID\x18\x01 \x01(\t\x12\x13\n\x0b\x64isplayName\x18\x02 \x01(\t\x12\r\n\x05state\x18\x03 \x01(\x05\x62\x06proto3')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
_CHATROOMDATA = DESCRIPTOR.message_types_by_name['ChatRoomData']
|
||||||
|
_CHATROOMDATA_CHATROOMMEMBER = _CHATROOMDATA.nested_types_by_name['ChatRoomMember']
|
||||||
|
ChatRoomData = _reflection.GeneratedProtocolMessageType('ChatRoomData', (_message.Message,), {
|
||||||
|
|
||||||
|
'ChatRoomMember' : _reflection.GeneratedProtocolMessageType('ChatRoomMember', (_message.Message,), {
|
||||||
|
'DESCRIPTOR' : _CHATROOMDATA_CHATROOMMEMBER,
|
||||||
|
'__module__' : 'roomdata_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:app.protobuf.ChatRoomData.ChatRoomMember)
|
||||||
|
})
|
||||||
|
,
|
||||||
|
'DESCRIPTOR' : _CHATROOMDATA,
|
||||||
|
'__module__' : 'roomdata_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:app.protobuf.ChatRoomData)
|
||||||
|
})
|
||||||
|
_sym_db.RegisterMessage(ChatRoomData)
|
||||||
|
_sym_db.RegisterMessage(ChatRoomData.ChatRoomMember)
|
||||||
|
|
||||||
|
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||||
|
|
||||||
|
DESCRIPTOR._options = None
|
||||||
|
_CHATROOMDATA._serialized_start=33
|
||||||
|
_CHATROOMDATA._serialized_end=300
|
||||||
|
_CHATROOMDATA_CHATROOMMEMBER._serialized_start=234
|
||||||
|
_CHATROOMDATA_CHATROOMMEMBER._serialized_end=300
|
||||||
|
# @@protoc_insertion_point(module_scope)
|
BIN
requirements.txt
BIN
requirements.txt
Binary file not shown.
Loading…
Reference in New Issue
Block a user