Repository: QQBackup/QQ-History-Backup
Branch: master
Commit: edc6653a7043
Files: 14
Total size: 133.5 KB
Directory structure:
gitextract_56qtarj0/
├── .gitignore
├── GUI.py
├── GUI.spec
├── LICENSE
├── QQ_History.py
├── README.md
├── emoticon/
│ └── face_config.json
├── icon.py
├── install.ps1
├── proto/
│ ├── RichMsg.proto
│ ├── RichMsg_pb2.py
│ ├── __init__.py
│ └── compile
└── requirements.txt
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
*.txt
!requirements.txt
*.db
*.html
*.db-shm
*.db-wal
*.zip
*.exe
*.spec
!GUI.spec
build/
dist/
__pycache__/
qq/
QQ*/
com.tencent.mobileqq/
chatimg/
output_*
test_qq_files/
================================================
FILE: GUI.py
================================================
import tkinter as tk
from tkinter import filedialog
import tkinter.ttk as ttk
from icon import qq_icon_png, github_mark
# 防止加载不出图标
import base64
import QQ_History
import os
import webbrowser
from time import sleep
class GUI_CONST:
TITLE = "QQ聊天记录导出"
URL = "https://github.com/Young-Lord/QQ_History_Backup"
def Enter():
base_path, qq_self, qq = e1.get(), e2.get(), e3.get()
for i in (e4, e5, e6, e7, e8):
if i.get() not in i['values']:
info.set(f"某个输入框的值{i.get()}不在允许的取值{i['values']}内!")
return ()
group = 1 if e4.get() == '私聊' else 2
emoji = 1 if e5.get() == '新' else 2
dump_all = True if e8.get() == '是' else False
with_img = True if e6.get() == '是' else False
combine_img = True if e7.get() == '是' else False
if (base_path == "" or qq_self == "") or (qq == "" and (not dump_all)):
info.set("信息不完整!")
return ()
# info.set("开始导出……")
# if dump_all:
# info.set("批量导出较慢,请耐心等待……")
# 只要界面未更新 用户就看不到
try:
config = (base_path, qq_self, qq, group,
emoji, with_img, combine_img, dump_all)
QQ_History.main(base_path, qq_self, qq, group,
emoji, with_img, combine_img, dump_all=dump_all)
info.set("导出完成。")
except Exception as e:
info.set(str(config)+"\r\n"+str(repr(e)))
return ()
def SelectDBPath():
dir = filedialog.askdirectory()
base_path_get.set(dir)
def SelectImgPath():
dir = filedialog.askdirectory()
img_path_get.set(dir)
def url():
webbrowser.open_new(GUI_CONST.URL)
root = tk.Tk()
base_path_get, img_path_get, key_get, info = tk.StringVar(
), tk.StringVar(), tk.StringVar(), tk.StringVar()
tmp = open("tmp.png", "wb+")
tmp.write(base64.b64decode(qq_icon_png))
tmp.close()
root.call('wm', 'iconphoto', root._w,tk.PhotoImage(file='tmp.png'))
os.remove("tmp.png")
root.title(GUI_CONST.TITLE)
ttk.Label(root, text="*com.tencent.mobileqq:").grid(row=0, column=0, sticky="e")
e1 = ttk.Entry(root, textvariable=base_path_get)
e1.grid(row=0, column=1, columnspan=2, sticky="ew", pady=3)
ttk.Button(root, text="选择", command=SelectDBPath,
width=5).grid(row=0, column=3)
ttk.Label(root, text="*自己QQ号:").grid(row=1, column=0, sticky="e")
e2 = ttk.Entry(root)
e2.grid(row=1, column=1, columnspan=3, sticky="ew", pady=3)
ttk.Label(root, text="导出所有记录:").grid(
row=2, column=0, sticky="e") # 每个row属性都得更改,什么离谱布局
e8 = ttk.Combobox(root)
e8['values'] = ('是', '否')
e8.current(1)
e8.grid(row=2, column=1, columnspan=3, sticky="ew", pady=3)
ttk.Label(root, text="QQ号/群号:").grid(row=3, column=0, sticky="e")
e3 = ttk.Entry(root)
e3.grid(row=3, column=1, columnspan=3, sticky="ew", pady=3)
ttk.Label(root, text="私聊/群聊:").grid(row=4, column=0, sticky="e")
e4 = ttk.Combobox(root)
e4['values'] = ('私聊', '群聊')
e4.current(0)
e4.grid(row=4, column=1, columnspan=3, sticky="ew", pady=3)
ttk.Label(root, text="表情版本:").grid(row=5, column=0, sticky="e")
e5 = ttk.Combobox(root)
e5['values'] = ('新', '旧')
e5.current(0)
e5.grid(row=5, column=1, columnspan=3, sticky="ew", pady=3)
ttk.Label(root, text="导出图片:").grid(row=6, column=0, sticky="e")
e6 = ttk.Combobox(root)
e6['values'] = ('是', '否')
e6.current(0)
e6.grid(row=6, column=1, columnspan=3, sticky="ew", pady=3)
ttk.Label(root, text="合并图片:").grid(row=7, column=0, sticky="e")
e7 = ttk.Combobox(root)
e7['values'] = ('是', '否')
e7.current(1)
e7.grid(row=7, column=1, columnspan=3, sticky="ew", pady=3)
root.grid_columnconfigure(2, weight=1)
info.set("开始")
ttk.Button(root, textvariable=info, command=Enter).grid(row=8, column=1)
tmp = open("tmp.png", "wb+")
tmp.write(base64.b64decode(github_mark))
tmp.close()
github = tk.PhotoImage(file='tmp.png')
os.remove("tmp.png")
button_img = tk.Button(root, image=github, text='b', command=url, bd=0)
button_img.grid(row=9, rowspan=7, column=0, sticky="ws")
root.mainloop()
================================================
FILE: GUI.spec
================================================
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(
['GUI.py'],
pathex=[],
binaries=[],
datas=[],
hiddenimports=[],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='GUI',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=False,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon=['icon.ico'],
)
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2023 Young-Lord
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: QQ_History.py
================================================
import hashlib
import sqlite3
import time
import os
import traceback
import json
import base64
from proto.RichMsg_pb2 import PicRec
from proto.RichMsg_pb2 import Elem
from proto.RichMsg_pb2 import Msg
from proto.RichMsg_pb2 import PttRec
from html import escape
from tempfile import NamedTemporaryFile
_crc64_init = False
_crc64_table = [0] * 256
def crc64(s):
global _crc64_init
if not _crc64_init:
for i in range(256):
bf = i
for j in range(8):
if bf & 1 != 0:
bf = bf >> 1 ^ -7661587058870466123
else:
bf >>= 1
_crc64_table[i] = bf
_crc64_init = True
v = -1
for i in range(len(s)):
v = _crc64_table[(ord(s[i]) ^ v) & 255] ^ v >> 8
return v
def tempFilename() -> str:
f = NamedTemporaryFile(delete=False)
f.close()
return f.name
def isEmpty(s):
if s is None:
return True
if type(s) == int and s == 0:
return True
if type(s) == str and s == '':
return True
return False
class QQoutput():
def __init__(self, base_path: str, qq_self: str, emoji: int = 1, with_img: bool = True, combine_img: bool = False):
# 真正用到的文件只有[f"{QQ}.db", f"slowtable_{QQ}.db", "kc"],这里我直接合并到一个层级下了
self.IS_TIM = False # TIM会缺少一些字段
self.base_path = base_path
if type(qq_self) == int:
qq_self = str(qq_self)
assert(type(qq_self) == str)
self.qq_self: str = qq_self # 自己的QQ号
self.uin_to_username = {}
self.troopuin_to_troopname = {}
self.troopuin_to_troopmembers = {}
self.init_paths()
self.init_key() # 解密用的密钥
self.c1 = sqlite3.connect(self.db_main_path).cursor()
try:
self.c2 = sqlite3.connect(self.db_slow_path).cursor()
except:
pass
self.detect_TIM()
self.init_friend_list()
self.init_troop_list()
# self.qq: str = qq # 导出对象的QQ号
# self.mode = mode # 1为私聊,2为群聊
assert(emoji in (1, 2))
self.emoji = emoji # 1为新表情,2为旧表情
assert(type(with_img) == bool)
self.with_img = with_img # True为生成图片,False为不生成图片
assert(type(combine_img) == bool)
self.combine_img = combine_img # True为将图片嵌入HTML文件中,False为在HTML中存储图片的相对路径
# self.num_to_name = {}
# 双重映射,即self.troop_members_name[群号][发言人QQ号]
self.troop_members_name = {}
self.emoji_map = self.map_new_emoji()
@staticmethod
def getDisplayName(friend: list) -> str:
if isEmpty(friend[1]):
ans = friend[2]
else:
ans = friend[1]
return ans
@staticmethod
def getSafePath(ans: str) -> str:
ban_words = "\\ / : * ? \" ' < > | $ \r \n".replace(
' ', '')
ban_strips = "#/~"
while True:
ans_bak = ans
for i in ban_words:
ans = ans.replace(i, "")
for i in ban_strips:
ans = ans.strip(i)
if ans == ans_bak: # 多次匹配
break
return ans
def detect_TIM(self):
try:
self.fill_cursor("select troopRemark from TroopInfoV2")
except sqlite3.OperationalError:
self.IS_TIM = True
print("检测到 TIM,部分功能可能缺失!")
else:
self.IS_TIM = False
return self.IS_TIM
def mydecrypt(self, data):
# 综合一下
s = self.fix(data, 1)
if s != "":
return s
return self.decrypt(data)
def fix(self, data, mode):
# msgdata mode=0
# other mode=1
# https://github.com/roadwide/qqmessageoutput/blob/master/q.py
# decrypt处理Emoji时会出问题,而这个不会
if (mode == 0):
rowbyte = []
# 这么做是为了解决汉字的utf-8是三字节
for i in range(0, len(data)):
rowbyte.append(data[i] ^ ord(self.key[i % len(self.key)]))
rowbyte = bytes(rowbyte)
try:
msg = rowbyte.decode(encoding='utf-8')
except:
msg = ""
return msg
elif (mode == 1):
str = ''
try:
j = 0
for i in range(0, len(data)):
# 获取unicode码
unicode = ord(data[i])
# 如果大于ffff 处理emoji
if (unicode > 0xffff):
# 分为2个10位二进制与两个密码进行异或
code = unicode ^ (
(ord(self.key[i+j % len(self.key)]) << 10) + ord(self.key[i+j+1 % len(self.key)]))
str += chr(code)
j = j + 1
else:
str += chr(ord(data[i]) ^
ord(self.key[i+j % len(self.key)]))
except:
str = ""
return str
def decrypt(self, data, msg_type=-1000):
# fix处理**一些东西**会出问题,这个不会
try:
msg = b''
if type(data) == bytes:
msg = b''
for i in range(0, len(data)):
msg += bytes([data[i] ^ ord(self.key[i % len(self.key)])])
elif type(data) == str:
msg = ''
for i in range(0, len(data)):
msg += chr(ord(data[i]) ^ ord(self.key[i % len(self.key)]))
return msg
if msg_type == -1000 or msg_type == -1049 or msg_type == -1051:
try:
return escape(msg.decode('utf-8'))
except:
# print(msg)
pass
return '[decode error]'
if not self.with_img:
return None
elif msg_type == -2000:
return self.decode_pic(msg)
elif msg_type == -1035:
return self.decode_mix_msg(msg)
elif msg_type == -5008:
return self.decode_share_url(msg)
elif msg_type == -5012 or msg_type == -5018:
return '[戳一戳]'
elif msg_type == -2002: # 语音消息
return self.decode_silk(msg)
except:
return f'[解码失败({msg_type})]'
# for debug
return '[unknown msg_type {}]'.format(msg_type)
# return ''
def add_emoji(self, msg):
pos = msg.find('\x14')
while pos != -1:
lastpos = pos
num = ord(msg[pos + 1])
if str(num) in self.emoji_map:
index = self.emoji_map[str(num)]
if self.emoji == 1:
filename = "new/s" + index + ".png"
else:
filename = "old/" + index + ".gif"
emoticon_path = os.path.join('emoticon', filename)
if self.combine_img:
try:
emoticon_path = self.get_base64_from_pic(emoticon_path)
except:
pass
msg = msg.replace(
msg[pos:pos + 2], '<img src="{}" alt="{}" />'.format(emoticon_path, index))
else:
msg = msg.replace(msg[pos:pos + 2],
'[emoji:{}]'.format(str(num)))
pos = msg.find('\x14')
if pos == lastpos:
break
return msg
def message(self, qq: str, mode: int):
# mode=1 friend
# mode=2 troop
num = qq.encode("utf-8")
md5num = hashlib.md5(num).hexdigest().upper()
if mode == 1:
cmd = "select msgData,senderuin,time,msgtype from mr_friend_{}_New order by time".format(
md5num)
# self.get_friends()
else:
cmd = "select msgData,senderuin,time,msgtype from mr_troop_{}_New order by time".format(
md5num)
# print('Groups {} -> {}'.format(num, md5num))
self.get_troop_members(qq)
cursor = self.fill_cursor(cmd)
allmsg = []
for row in cursor:
msgdata: bytes = row[0]
if not msgdata:
continue
uin = row[1]
ltime = time.localtime(row[2])
sendtime = time.strftime("%Y-%m-%d %H:%M:%S", ltime)
msg_type = row[3]
msg_final = self.decrypt(msgdata, msg_type)
if msg_final is None:
continue
allmsg.append(
[sendtime, msg_type, self.decrypt(uin), msg_final])
return allmsg
def get_friends(self):
raise NotImplementedError
def get_troop_members(self, qq: str):
self.troopuin_to_troopmembers[qq] = {}
cmd = "SELECT troopuin, memberuin, autoremark, troopnick, friendnick, recommendRemark, mUniqueTitle FROM TroopMemberInfo"
cursor = self.fill_cursor(cmd)
for row in cursor:
if self.fix(row[0], 1) != qq:
continue
num = self.fix(row[1], 1)
names = [self.fix(i, 1) for i in row[2:6]]
# 2是你给好友的备注,3是好友的群昵称,4是好友名字,5是好友的群昵称,mUniqueTitle是群头衔
# xxx 我不知道这个顺序怎么搞的 一部分是猜
try:
final_name = [i for i in names[1:] if not isEmpty(i)][0]
except IndexError:
try:
final_name = names[0]
except IndexError:
print(f"{qq}群中{num}好友无法匹配名字。names={names}")
print("开Issue!")
if num in self.uin_to_username: # 是你对话过的人
if not isEmpty(names[0]):
final_name = names[0]
else:
# print(names)
# print("↑你这个好友怎么没有备注的?开Issue!")
pass
self.troopuin_to_troopmembers[qq][num] = final_name
# print([self.fix(i, 1) for i in row[2:6]])
if not isEmpty(row[6]): # 添加头衔
self.troopuin_to_troopmembers[qq][num] = f"【{row[6]}】" + \
self.troopuin_to_troopmembers[qq][num]
def _fill_cursors(self, cmd):
cursors = []
# slowtable might not contain related message, so just skip it
try:
cursors.append(self.c2.execute(cmd))
except:
pass
try:
cursors.append(self.c1.execute(cmd))
except sqlite3.OperationalError:
pass
return cursors
def fill_cursor(self, cmd):
cursors = self._fill_cursors(cmd)
ans = []
for cs in cursors:
for row in cs:
ans.append(row)
return ans
def output(self, qq: str, mode: int, output_path: str = "."):
self.outut_path = output_path
if type(qq) == int:
qq = str(qq)
assert(type(qq) == str)
assert(mode in (1, 2))
name1 = "我"
fileprefix = ""
if mode == 1:
fileprefix = "私聊"
filebasename = self.getSafePath(self.uin_to_username.get(qq, str(qq)))
if qq not in self.uin_to_username:
print(f"警告:{qq}无法在好友列表内找到,请检查聊天类型是否填写正确")
else:
fileprefix = "群聊"
filebasename = self.getSafePath(self.troopuin_to_troopname.get(qq, str(qq)))
if qq not in self.troopuin_to_troopname:
print(f"警告:{qq}无法在群聊列表内找到,请检查聊天类型是否填写正确")
file = f"{fileprefix}-{filebasename}-{qq}.html"
file = os.path.join(output_path, file)
allmsg = self.message(qq, mode)
if len(allmsg) == 0:
print(f"{qq}_{mode}没有聊天记录,跳过。")
return
f2 = open(file, "w", encoding="utf-8")
f2.write(
"<head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /></head>"
)
f2.write("<div style='white-space: pre-line'>")
if mode == 1:
table = self.uin_to_username
else:
table = self.troopuin_to_troopmembers.get(qq, {})
for ts, _, uid, msg in allmsg:
if not msg:
continue
if uid == str(self.qq_self):
f2.write("<p align='right'>")
f2.write("<font color=\"green\">")
f2.write(ts)
f2.write("</font>-----<font color=\"blue\"><b>")
f2.write(name1)
f2.write("</font></b></br>")
else:
f2.write("<p align='left'>")
f2.write("<font color=\"blue\"><b>")
f2.write(escape("{}({})".format(
table.get(uid, "???未知???"), uid)))
f2.write("</b></font>-----<font color=\"green\">")
f2.write(ts)
f2.write("</font></br>")
f2.write(self.add_emoji(msg))
f2.write("</br></br>")
f2.write("</p>")
f2.write("</div>")
f2.close()
print("导出已完成。文件目录:" + file)
def init_key(self):
kc_file = open(self.kc_path, "r")
self.key = kc_file.read().strip('\r \n')
kc_file.close()
def init_paths(self):
join = os.path.join
mainb = self.qq_self + ".db"
slowb = "slowtable_" + self.qq_self + ".db"
db_main_paths = [mainb, join("databases", mainb), join("db", mainb)]
db_slow_paths = [slowb, join("databases", slowb), join("db", slowb)]
kc_paths = ["kc", join("files", "kc"), join("f", "kc")]
self.kc_path = self.db_main_path = self.db_slow_path = None
for i in db_main_paths:
current_file = join(self.base_path, i)
if os.path.isfile(current_file):
self.db_main_path = current_file
for i in db_slow_paths:
current_file = join(self.base_path, i)
if os.path.isfile(current_file):
self.db_slow_path = current_file
for i in kc_paths:
current_file = join(self.base_path, i)
if os.path.isfile(current_file):
self.kc_path = current_file
if self.kc_path is None or self.db_main_path is None: # 很少记录的号没有slowtable,故不判断
raise FileNotFoundError(
f"无法找到目标文件!\n路径:{self.base_path}\n当前匹配列表:{[self.kc_path, self.db_main_path, self.db_slow_path]}")
def init_friend_list(self):
self.FriendsData = []
# uin-QQ号,remark-备注,name-昵称
execute = "select uin,remark,name from Friends"
cursor = self.fill_cursor(execute)
for i in cursor:
uin, remark, name = i[0], i[1], i[2]
decode_uin = self.mydecrypt(uin)
decode_remark = self.mydecrypt(remark)
decode_name = self.mydecrypt(name)
friend = [decode_uin, decode_remark, decode_name]
self.FriendsData.append(friend)
self.uin_to_username[decode_uin] = self.getDisplayName(friend)
def init_troop_list(self):
self.TroopsData = []
# troopuin-群号,troopRemark-群备注,troopname-群名
execute = "select troopuin,troopRemark,troopname from TroopInfoV2"
if self.IS_TIM:
execute = execute.replace(
"troopRemark", "troopname") # TIM无法给群聊设备注
cursor = self.fill_cursor(execute)
for i in cursor:
uin, remark, name = i[0], i[1], i[2]
# print([self.fix(ii,1) for ii in i])
decode_uin = self.mydecrypt(uin)
decode_remark = self.mydecrypt(remark)
decode_name = self.mydecrypt(name)
troop = [decode_uin, decode_remark, decode_name]
self.TroopsData.append(troop)
# print(troop)
self.troopuin_to_troopname[decode_uin] = self.getDisplayName(troop)
def map_new_emoji(self):
with open(os.path.join(os.path.dirname(os.path.abspath(__file__)), './emoticon/face_config.json'), encoding='utf-8') as f:
# 这个地方可能会在打包的时候出问题
emojis = json.load(f)
new_emoji_map = {}
for e in emojis['sysface']:
if self.emoji == 1:
new_emoji_map[e["AQLid"]] = e["QSid"]
else:
if len(e["EMCode"]) == 3:
new_emoji_map[e["AQLid"]] = str(int(e["EMCode"]) - 100)
return new_emoji_map
def get_base64_from_pic(self, path):
with open(path, "rb") as image_file:
return (b'data:image/png;base64,' + base64.b64encode(image_file.read())).decode("utf-8")
def decode_pic(self, data):
try:
doc = PicRec()
doc.ParseFromString(data)
url = 'chatimg:' + doc.md5
filename = hex(crc64(url))
filename = 'Cache_' + filename.replace('0x', '')
chatimg_basepath = os.path.join(self.base_path, "chatimg")
if not os.path.isdir(chatimg_basepath):
chatimg_basepath = "chatimg"
rel_path = os.path.join(chatimg_basepath, filename[-3:], filename)
if os.path.exists(rel_path):
print(rel_path)
w = 'auto' if doc.uint32_thumb_width == 0 else str(
doc.uint32_thumb_width)
h = 'auto' if doc.uint32_thumb_height == 0 else str(
doc.uint32_thumb_height)
if self.combine_img:
rel_path = self.get_base64_from_pic(rel_path)
return '<img src="{}" width="{}" height="{}" />'.format(rel_path, w, h)
# 最后这里必须用相对路径
except Exception as e:
pass
return '[图片]'
def decode_mix_msg(self, data):
try:
doc = Msg()
doc.ParseFromString(data)
message = ''
for elem in doc.elems:
if elem.picMsg:
message += self.decode_pic(elem.picMsg)
else:
message += escape(elem.textMsg.decode('utf-8'))
return message
except:
pass
return '[混合消息]'
def decode_silk(self, data):
# TODO
try:
import pilk
import av
av.logging.set_level(av.logging.ERROR)
doc = PttRec()
doc.ParseFromString(data)
print(doc.sttText)
voiceLength = doc.voiceLength # 以秒为单位
filename = doc.localPath[doc.localPath.find("/ptt/")+5:]
ptt_basepath = os.path.join(self.base_path, "ptt")
if not os.path.isdir(ptt_basepath):
ptt_basepath = "ptt"
if not os.path.isdir(ptt_basepath):
return '[语音消息](目录不存在)'
rel_path = os.path.join(ptt_basepath, filename)
if not os.path.exists(rel_path):
p = [".amr", ".slk"]
if rel_path.endswith(p[0]) and os.path.exists(rel_path[:-4]+p[1]): # 试着更改后缀匹配
filename = filename[:-4]+p[1]
rel_path = rel_path[:-4]+p[1]
elif rel_path.endswith(p[1]) and os.path.exists(rel_path[:-4]+p[0]):
filename = filename[:-4]+p[0]
rel_path = rel_path[:-4]+p[0]
else:
# 摆了!
return f"[语音消息](文件{rel_path}不存在)"
voice_path = os.path.join(self.outut_path, "voice")
if not os.path.exists(voice_path):
os.makedirs(voice_path)
pcm = tempFilename()
pilk.decode(rel_path, pcm)
absolute_output = os.path.join(voice_path, filename[:-4]+".mp3")
relative_output = os.path.join("voice", filename[:-4]+".mp3")
rate=24000# pilk源码写的,不管了
with av.open(pcm,format='s16le',options={'ar':str(rate),'ac':'1'}) as in_container:
in_stream = in_container.streams.audio[0]
with av.open(absolute_output, 'w') as out_container:
out_stream = out_container.add_stream(
'mp3',
rate=rate,
layout='mono'
)
try:
for frame in in_container.decode(in_stream):
frame.pts = None
for packet in out_stream.encode(frame):
out_container.mux(packet)
except Exception as ee:
raise ee
pass
os.remove(pcm)
return '<audio src="{}" controls title="{}"/>'.format(relative_output, f"时长 {voiceLength} 秒的语音消息")
# 最后这里必须用相对路径
except Exception as e:
print(traceback.format_exc())
return '[语音消息]'
def decode_share_url(self, msg):
# TODO
return '[分享卡片]'
def main(base_path, qq_self, qq, mode, emoji, with_img, combine_img, dump_all):
try:
f = open('log.txt', 'w', encoding="utf-8")
except:
class ff:
def write(): pass
def close(): pass
f = ff()
global print
print_bak = print
def print(*arg, **kwarg):
print_bak(*arg, **kwarg)
f.write("[PRINT]: "+' '.join([str(i) for i in arg])+"\n")
try:
q = QQoutput(base_path, str(qq_self), emoji, with_img, combine_img)
if dump_all:
print("正在批量导出……")
dest = "output_" + \
time.strftime("%Y%m%d-%H%M%S", time.localtime(time.time()))
try:
os.mkdir(dest)
except:
raise ValueError("目录创建失败,退出。")
for i in q.FriendsData:
try:
q.output(i[0], 1, dest)
except Exception as e:
f.write(repr(e))
f.write(traceback.format_exc())
for i in q.TroopsData:
try:
q.output(i[0], 2, dest)
except Exception as e:
f.write(repr(e))
f.write(traceback.format_exc())
print("")
print("="*30)
print("所有记录导出完成。")
print("="*30)
else:
q.output(qq, mode)
except Exception as e:
f.write(repr(e))
f.write(traceback.format_exc())
print(traceback.format_exc())
if repr(e).split(":")[0] == "OperationalError('no such table":
raise ValueError("信息填入错误")
else:
raise BaseException("Error! See log.txt")
def run_directly():
base_path = r"修改这里!" # com.tencent.mobileqq 路径
qq_self = "修改这里!" # 自己的QQ号
batch = True # 是否导出所有记录
q = QQoutput(base_path, str(qq_self))
f = open('log.txt', 'w', encoding="utf-8")
if batch:
print("正在批量导出……")
dest = "output_" + \
time.strftime("%Y%m%d-%H%M%S", time.localtime(time.time()))
try:
os.mkdir(dest)
except:
raise ValueError("目录创建失败,退出。")
for i in q.FriendsData:
try:
q.output(i[0], 1, dest)
except Exception as e:
f.write(repr(e))
f.write(traceback.format_exc())
for i in q.TroopsData:
try:
q.output(i[0], 2, dest)
except Exception as e:
f.write(repr(e))
f.write(traceback.format_exc())
print("")
print("="*30)
print("所有记录导出完成。")
print("="*30)
else:
qq = "修改这里!"
mode = 1 # 修改这里!私聊为1,群聊为2
q.output(qq, mode)
f.close()
if __name__ == '__main__':
run_directly()
================================================
FILE: README.md
================================================
# QQ聊天记录导出
本项目用于将 **非 QQNT** 的 Android 端 QQ/TIM 的聊天记录数据库转换为 HTML 文件,并转换图片、语音等部分特殊消息。
## 关于其他平台(Windows, MacOS, iOS…)
请看 [QQBackup/qq-win-db-key](https://github.com/QQBackup/qq-win-db-key)。
## 维护情况
省流:没时间维护,欢迎新 maintainer 与 PR(或者可以自行开个fork)。请提交到`dev`分支。
同时,请参看[qq-win-db-key 中列出的改进版](https://github.com/QQBackup/qq-win-db-key/blob/master/%E6%95%99%E7%A8%8B%20-%20%E5%AE%89%E5%8D%93%E7%89%88QQ%E5%8F%8ATIM.md#%E8%A7%A3%E5%AF%86%E8%BD%AC%E6%8D%A2)。
## 运行方式
1. 一切操作之前,你需要先安装 Python 3.x(建议使用可下载的最高版本,已知支持`3.12`),可参考[此文章(Windows)](https://zhuanlan.zhihu.com/p/458428159)。
2. 然后,在当前目录打开终端,Windows 用户若不懂可以看[这篇博文](https://blog.csdn.net/Lzy410992/article/details/105937780)
3. 输入以下命令永久加速相关依赖的下载(换源):`pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple`
3. 安装依赖:`pip install -r requirements.txt`
4. 若是运行 GUI,就`python GUI.py`
5. 若是直接运行命令行版,就修改好`QQ_History.py`最下面的内容,并运行:`python QQ_History.py`
## 声明
本项目仅供学习交流使用,严禁用于任何违反中国大陆法律法规、您所在地区法律法规、[QQ软件许可及服务协议](https://rule.tencent.com/rule/preview/46a15f24-e42c-4cb6-a308-2347139b1201)的行为,本人不承担任何相关行为导致的直接或间接责任。
本项目理论仅能将可以通过正常方法查看的聊天记录**导出**,而不能进行包括但不限于已删除聊天记录恢复在内的操作。
本项目不对生成内容的完整性、准确性作任何担保,因此生成的一切内容**没有法律效力**,您不应当将其用于学习与交流外的任何用途。
## 简介
作为国内最常用的聊天工具之一,QQ 为了用户留存度,默认聊天记录备份无法脱离 QQ 被独立打开。
目前版本往往需要通过命令行运行,本方法在之前版本的基础上简化了操作,制作了GUI方便使用;并且不再需要提供密钥,自动填入备注/昵称,添加了QQ表情、图片和语音的一并导出。
如果你不使用打包后的版本,请首先运行以下命令以安装依赖:`pip install -r requirements.txt`
## 获取聊天记录文件夹方法
> 注:以下提到的“电脑”泛指一切可以运行此程序的环境,如安卓手机上的 Termux 也属于此列
> 注:以下内容假设您使用的是 QQ 而非 TIM,如果您在使用 TIM,请将`com.tencent.mobileqq`改为`com.tencent.tim`,将`MobileQQ`改为`Tim`
如果手机已获得 root 权限,聊天记录可在以下路径找到。
```
/data/data/com.tencent.mobileqq/
```
我们需要的文件只有`databases/<QQ号>.db`,`databases/slowtable_<QQ号>.db`,`files/kc`,因此您可以将整个文件夹压缩后传输到电脑上,亦或将这三个文件单独放在同一个目录中传输。本程序会自动识别这两种不同的目录结构。
如果没有 root 权限,可以通过手机自带的备份工具备份整个 QQ,拷贝备份文件到电脑,解压找到 `com.tencent.mobileqq`。
具体方法可以参见
> 怎样导出手机中的QQ聊天记录? - 益新软件的回答 - 知乎
> <https://www.zhihu.com/question/28574047/answer/964813560>
关于苹果设备导出,参见[此讨论](https://github.com/Yiyiyimu/QQ-History-Backup/issues/42);对于安卓系统导出内容的提取,请自行在互联网查询。
如果同时需要在聊天记录中显示图片,拷贝手机中 `/sdcard/Android/data/com.tencent.mobileqq/Tencent/MobileQQ/chatpic/chatimg` 至 `GUI.exe` 同一文件夹中或者拷贝过来的`com.tencent.mobileqq`目录下。
(QQ)如果同时需要在聊天记录中显示语音,拷贝手机中 `/sdcard/Android/data/com.tencent.mobileqq/Tencent/MobileQQ/<QQ号>/ptt` 至 `GUI.exe` 同一文件夹中或者拷贝过来的`com.tencent.mobileqq`目录下。
(TIM)如果同时需要在聊天记录中显示语音,拷贝手机中 `/sdcard/Android/data/com.tencent.tim/Tencent/Tim/ptt/<QQ号>` 至 `GUI.exe` 同一文件夹中或者拷贝过来的`com.tencent.mobileqq`目录下,并重命名为`ptt`。
## GUI使用方法

- `com.tencent.mobileqq`:选择导出的相应文件夹,对于备份方式,一般为`apps/com.tencent.mobileqq`
- 表情版本:默认为新版QQ表情。如果你的聊天记录来自很早以前,可以切换为旧版的表情
- 导出所有记录:若此项选择“是”,则`QQ号/群号:`与`私聊/群聊:`选项会被忽略。
- 导出图片:若此项与前一项均选择“是”,必须把`chatimg`目录复制到生成的`output_xxx`目录下,图片才能正常显示
- 合并图片:默认为否
- 不启用合并图片好处在于:1. 使导出的 HTML 文件具有可读性;2. 减小 HTML 文件体积方便打开
- 启用合并图片好处:拷贝时不需要和 `emoticon` 以及 `chatimg` 文件夹一起拷贝,更加方便
## 输出截图


如果没有启用合并图片,拷贝生成的聊天记录时需要一起拷贝 `emoticon` 以及 `chatimg` 文件夹.
有 bug 的话提 issue,记得附上 log.txt 里的内容以及终端的报错内容。
## TODO
- [x] 支持群聊导出
- [x] 支持自动查找密钥
- [x] 使用好友/群聊昵称作为默认用户名
- [x] 自动合并 db 和 slow-table
- [x] 支持新 QQ emoji
- [x] 支持单一文件导出
- [x] 支持音频导出
- [ ] 支持视频导出
- [ ] 支持合并转发消息导出
- [ ] 支持戳一戳导出
- [ ] 支持缩略图
- [ ] 支持卡片分享
- [ ] 重构代码
- [ ] 加入 i18n 与自定义翻译支持
- [ ] 支持使用[silk-v3-decoder](https://github.com/ZhangJun2017/QQChatHistoryExporter)转换音频文件
- [ ] 使用 Jinja2 生成 HTML 文件
- [ ] 允许插入自定义 CSS 与 自定义 JS
- [ ] 分析并试图优化解密相关函数
- [ ] 更新预览图
- [ ] 基于 GitHub Actions 以 PyInstaller 生成在 Windows 下的可执行文件
## FAQ
- **聊天记录中显示 `[图片]` 是因为什么?**
解码出的图片路径在 `chatimg` 找不到相应文件。可能原因为在手机中没有加载过该文件,导致图片没有存在手机里。
## CHANGELOG
### v2
- 直接从 `files/kc` 提取明文的密钥,不用再手动输入或解密
- 支持群聊记录导出
- 支持 私聊/群聊 的 备注/昵称 自动填入
- 支持 slowtable 的直接整合
- 支持新版 QQ 表情
### v2.2
- 支持导出图片至聊天记录
- 支持合并图片至单一文件方便传输
### v2.3
- 支持读取不同的目录结构
- 支持单独导出一个私聊对话或群聊对话
- 部分修复解密函数存在的 bug
- 支持批量导出
- 修复导出的 HTML 中的字符转义
### v2.4
- 支持读取音频
## 致谢
1. [roadwide/qqmessageoutput](https://github.com/roadwide/qqmessageoutput)
2. [WincerChan/export.py](https://gist.github.com/WincerChan/362331456a6e0417c5aa1cf3ff7be2b7)
3. [Yiyiyimu/QQ-History-Backup](https://github.com/Yiyiyimu/QQ-History-Backup) (本仓库的来源,致敬!同时,源代码基于 MIT 协议使用。)
4. [ZhangJun2017/QQChatHistoryExporter](https://github.com/ZhangJun2017/QQChatHistoryExporter) (参考了 Protobuf 相关内容)
## 适配新类型笔记
1. 下载 [protoc](https://github.com/protocolbuffers/protobuf/releases) 这一可执行文件,设置可执行权限(仅 Linux 类系统)并移动到适当位置(位于 PATH 环境变量中的目录)
2. 编辑`proto/RichMsg.proto`,增加新类型(可以参照[此项目](https://github.com/ZhangJun2017/QQChatHistoryExporter/blob/f97eb64581229a30514d55aa0a8423b138b09437/src/RawMessage.java#L41))
3. 切换到目录`proto`中,运行`compile`,在 Windows 下需先将其改名为`compile.bat`
4. 编辑`QQ_History.py`中的`decrypt`,加入`msgtype`对应判断与处理代码
5. **记得写文档**
================================================
FILE: emoticon/face_config.json
================================================
{
"sysface": [
{
"QSid": "14",
"QDes": "/微笑",
"IQLid": "23",
"AQLid": "23",
"EMCode": "100"
},
{
"QSid": "1",
"QDes": "/撇嘴",
"IQLid": "40",
"AQLid": "40",
"EMCode": "101"
},
{
"QSid": "2",
"QDes": "/色",
"IQLid": "19",
"AQLid": "19",
"EMCode": "102"
},
{
"QSid": "3",
"QDes": "/发呆",
"IQLid": "43",
"AQLid": "43",
"EMCode": "103"
},
{
"QSid": "4",
"QDes": "/得意",
"IQLid": "21",
"AQLid": "21",
"EMCode": "104"
},
{
"QSid": "5",
"QDes": "/流泪",
"IQLid": "9",
"AQLid": "9",
"EMCode": "105"
},
{
"QSid": "6",
"QDes": "/害羞",
"IQLid": "20",
"AQLid": "20",
"EMCode": "106"
},
{
"QSid": "7",
"QDes": "/闭嘴",
"IQLid": "104",
"AQLid": "106",
"EMCode": "107"
},
{
"QSid": "8",
"QDes": "/睡",
"IQLid": "35",
"AQLid": "35",
"EMCode": "108"
},
{
"QSid": "9",
"QDes": "/大哭",
"IQLid": "10",
"AQLid": "10",
"EMCode": "109"
},
{
"QSid": "10",
"QDes": "/尴尬",
"IQLid": "25",
"AQLid": "25",
"EMCode": "110"
},
{
"QSid": "11",
"QDes": "/发怒",
"IQLid": "24",
"AQLid": "24",
"EMCode": "111"
},
{
"QSid": "12",
"QDes": "/调皮",
"IQLid": "1",
"AQLid": "1",
"EMCode": "112"
},
{
"QSid": "13",
"QDes": "/呲牙",
"IQLid": "0",
"AQLid": "0",
"EMCode": "113"
},
{
"QSid": "0",
"QDes": "/惊讶",
"IQLid": "33",
"AQLid": "33",
"EMCode": "114"
},
{
"QSid": "15",
"QDes": "/难过",
"isStatic": "1",
"IQLid": "32",
"AQLid": "32",
"EMCode": "115"
},
{
"QSid": "16",
"QDes": "/酷",
"IQLid": "12",
"AQLid": "12",
"EMCode": "116"
},
{
"QSid": "96",
"QDes": "/冷汗",
"IQLid": "27",
"AQLid": "27",
"EMCode": "117"
},
{
"QSid": "18",
"QDes": "/抓狂",
"IQLid": "13",
"AQLid": "13",
"EMCode": "118"
},
{
"QSid": "19",
"QDes": "/吐",
"IQLid": "22",
"AQLid": "22",
"EMCode": "119"
},
{
"QSid": "20",
"QDes": "/偷笑",
"IQLid": "3",
"AQLid": "3",
"EMCode": "120"
},
{
"QSid": "21",
"QDes": "/可爱",
"IQLid": "18",
"AQLid": "18",
"EMCode": "121"
},
{
"QSid": "22",
"QDes": "/白眼",
"IQLid": "30",
"AQLid": "30",
"EMCode": "122"
},
{
"QSid": "23",
"QDes": "/傲慢",
"IQLid": "31",
"AQLid": "31",
"EMCode": "123"
},
{
"QSid": "24",
"QDes": "/饥饿",
"IQLid": "79",
"AQLid": "81",
"EMCode": "124"
},
{
"QSid": "25",
"QDes": "/困",
"IQLid": "80",
"AQLid": "82",
"EMCode": "125"
},
{
"QSid": "26",
"QDes": "/惊恐",
"IQLid": "26",
"AQLid": "26",
"EMCode": "126"
},
{
"QSid": "27",
"QDes": "/流汗",
"IQLid": "2",
"AQLid": "2",
"EMCode": "127"
},
{
"QSid": "28",
"QDes": "/憨笑",
"IQLid": "37",
"AQLid": "37",
"EMCode": "128"
},
{
"QSid": "29",
"QDes": "/悠闲",
"IQLid": "50",
"AQLid": "50",
"EMCode": "129"
},
{
"QSid": "30",
"QDes": "/奋斗",
"IQLid": "42",
"AQLid": "42",
"EMCode": "130"
},
{
"QSid": "31",
"QDes": "/咒骂",
"IQLid": "81",
"AQLid": "83",
"EMCode": "131"
},
{
"QSid": "32",
"QDes": "/疑问",
"IQLid": "34",
"AQLid": "34",
"EMCode": "132"
},
{
"QSid": "33",
"QDes": "/嘘",
"IQLid": "11",
"AQLid": "11",
"EMCode": "133"
},
{
"QSid": "34",
"QDes": "/晕",
"IQLid": "49",
"AQLid": "49",
"EMCode": "134"
},
{
"QSid": "35",
"QDes": "/折磨",
"IQLid": "82",
"AQLid": "84",
"EMCode": "135"
},
{
"QSid": "36",
"QDes": "/衰",
"isStatic": "1",
"IQLid": "39",
"AQLid": "39",
"EMCode": "136"
},
{
"QSid": "37",
"QDes": "/骷髅",
"isStatic": "1",
"IQLid": "76",
"AQLid": "78",
"EMCode": "137"
},
{
"QSid": "38",
"QDes": "/敲打",
"IQLid": "5",
"AQLid": "5",
"EMCode": "138"
},
{
"QSid": "39",
"QDes": "/再见",
"IQLid": "4",
"AQLid": "4",
"EMCode": "139"
},
{
"QSid": "97",
"QDes": "/擦汗",
"IQLid": "6",
"AQLid": "6",
"EMCode": "140"
},
{
"QSid": "98",
"QDes": "/抠鼻",
"IQLid": "83",
"AQLid": "85",
"EMCode": "141"
},
{
"QSid": "99",
"QDes": "/鼓掌",
"IQLid": "84",
"AQLid": "86",
"EMCode": "142"
},
{
"QSid": "100",
"QDes": "/糗大了",
"IQLid": "85",
"AQLid": "87",
"EMCode": "143"
},
{
"QSid": "101",
"QDes": "/坏笑",
"IQLid": "46",
"AQLid": "46",
"EMCode": "144"
},
{
"QSid": "102",
"QDes": "/左哼哼",
"IQLid": "86",
"AQLid": "88",
"EMCode": "145"
},
{
"QSid": "103",
"QDes": "/右哼哼",
"IQLid": "44",
"AQLid": "44",
"EMCode": "146"
},
{
"QSid": "104",
"QDes": "/哈欠",
"IQLid": "87",
"AQLid": "89",
"EMCode": "147"
},
{
"QSid": "105",
"QDes": "/鄙视",
"IQLid": "48",
"AQLid": "48",
"EMCode": "148"
},
{
"QSid": "106",
"QDes": "/委屈",
"IQLid": "14",
"AQLid": "14",
"EMCode": "149"
},
{
"QSid": "107",
"QDes": "/快哭了",
"IQLid": "88",
"AQLid": "90",
"EMCode": "150"
},
{
"QSid": "108",
"QDes": "/阴险",
"IQLid": "41",
"AQLid": "41",
"EMCode": "151"
},
{
"QSid": "109",
"QDes": "/亲亲",
"IQLid": "36",
"AQLid": "36",
"EMCode": "152"
},
{
"QSid": "110",
"QDes": "/吓",
"IQLid": "89",
"AQLid": "91",
"EMCode": "153"
},
{
"QSid": "111",
"QDes": "/可怜",
"IQLid": "51",
"AQLid": "51",
"EMCode": "154"
},
{
"QSid": "172",
"QDes": "/眨眼睛",
"IQLid": "142",
"AQLid": "164",
"EMCode": "242"
},
{
"QSid": "182",
"QDes": "/笑哭",
"IQLid": "152",
"AQLid": "174",
"EMCode": "252"
},
{
"QSid": "179",
"QDes": "/doge",
"IQLid": "149",
"AQLid": "171",
"EMCode": "249"
},
{
"QSid": "173",
"QDes": "/泪奔",
"IQLid": "143",
"AQLid": "165",
"EMCode": "243"
},
{
"QSid": "174",
"QDes": "/无奈",
"IQLid": "144",
"AQLid": "166",
"EMCode": "244"
},
{
"QSid": "212",
"QDes": "/托腮",
"IQLid": "182",
"AQLid": "161",
"EMCode": "282"
},
{
"QSid": "175",
"QDes": "/卖萌",
"IQLid": "145",
"AQLid": "167",
"EMCode": "245"
},
{
"QSid": "178",
"QDes": "/斜眼笑",
"IQLid": "148",
"AQLid": "170",
"EMCode": "248"
},
{
"QSid": "177",
"QDes": "/喷血",
"IQLid": "147",
"AQLid": "169",
"EMCode": "247"
},
{
"QSid": "180",
"QDes": "/惊喜",
"IQLid": "150",
"AQLid": "172",
"EMCode": "250"
},
{
"QSid": "181",
"QDes": "/骚扰",
"IQLid": "151",
"AQLid": "173",
"EMCode": "251"
},
{
"QSid": "176",
"QDes": "/小纠结",
"IQLid": "146",
"AQLid": "168",
"EMCode": "246"
},
{
"QSid": "183",
"QDes": "/我最美",
"IQLid": "153",
"AQLid": "175",
"EMCode": "253"
},
{
"QSid": "245",
"QDes": "/加油必胜",
"IQLid": "245",
"AQLid": "217",
"EMCode": "202001"
},
{
"QSid": "246",
"QDes": "/加油抱抱",
"IQLid": "246",
"AQLid": "218",
"EMCode": "202002"
},
{
"QSid": "247",
"QDes": "/口罩护体",
"IQLid": "247",
"AQLid": "219",
"EMCode": "202003"
},
{
"QSid": "260",
"QDes": "/搬砖中",
"isStatic": "1",
"IQLid": "260",
"AQLid": "260",
"EMCode": "10260"
},
{
"QSid": "261",
"QDes": "/忙到飞起",
"IQLid": "261",
"AQLid": "261",
"EMCode": "10261"
},
{
"QSid": "262",
"QDes": "/脑阔疼",
"IQLid": "262",
"AQLid": "262",
"EMCode": "10262"
},
{
"QSid": "263",
"QDes": "/沧桑",
"IQLid": "263",
"AQLid": "263",
"EMCode": "10263"
},
{
"QSid": "264",
"QDes": "/捂脸",
"IQLid": "264",
"AQLid": "264",
"EMCode": "10264"
},
{
"QSid": "265",
"QDes": "/辣眼睛",
"IQLid": "265",
"AQLid": "265",
"EMCode": "10265"
},
{
"QSid": "266",
"QDes": "/哦哟",
"IQLid": "266",
"AQLid": "266",
"EMCode": "10266"
},
{
"QSid": "267",
"QDes": "/头秃",
"IQLid": "267",
"AQLid": "267",
"EMCode": "10267"
},
{
"QSid": "268",
"QDes": "/问号脸",
"IQLid": "268",
"AQLid": "268",
"EMCode": "10268"
},
{
"QSid": "269",
"QDes": "/暗中观察",
"IQLid": "269",
"AQLid": "269",
"EMCode": "10269"
},
{
"QSid": "270",
"QDes": "/emm",
"IQLid": "270",
"AQLid": "270",
"EMCode": "10270"
},
{
"QSid": "271",
"QDes": "/吃瓜",
"IQLid": "271",
"AQLid": "271",
"EMCode": "10271"
},
{
"QSid": "272",
"QDes": "/呵呵哒",
"IQLid": "272",
"AQLid": "272",
"EMCode": "10272"
},
{
"QSid": "277",
"QDes": "/汪汪",
"isStatic": "1",
"IQLid": "277",
"AQLid": "277",
"EMCode": "10277"
},
{
"QSid": "281",
"QDes": "/无眼笑",
"IQLid": "281",
"AQLid": "281",
"EMCode": "10281"
},
{
"QSid": "282",
"QDes": "/敬礼",
"IQLid": "282",
"AQLid": "282",
"EMCode": "10282"
},
{
"QSid": "283",
"QDes": "/狂笑",
"IQLid": "283",
"AQLid": "283",
"EMCode": "10283"
},
{
"QSid": "284",
"QDes": "/面无表情",
"IQLid": "284",
"AQLid": "284",
"EMCode": "10284"
},
{
"QSid": "285",
"QDes": "/摸鱼",
"IQLid": "285",
"AQLid": "285",
"EMCode": "10285"
},
{
"QSid": "286",
"QDes": "/魔鬼笑",
"IQLid": "286",
"AQLid": "286",
"EMCode": "10286"
},
{
"QSid": "287",
"QDes": "/哦",
"IQLid": "287",
"AQLid": "287",
"EMCode": "10287"
},
{
"QSid": "288",
"QDes": "/请",
"IQLid": "288",
"AQLid": "288",
"EMCode": "10288"
},
{
"QSid": "289",
"QDes": "/睁眼",
"IQLid": "289",
"AQLid": "289",
"EMCode": "10289"
},
{
"QSid": "273",
"QDes": "/我酸了",
"isStatic": "1",
"IQLid": "273",
"AQLid": "273",
"EMCode": "10273"
},
{
"QSid": "274",
"QDes": "/太南了",
"isStatic": "1",
"IQLid": "274",
"AQLid": "274",
"EMCode": "10274"
},
{
"QSid": "112",
"QDes": "/菜刀",
"IQLid": "17",
"AQLid": "17",
"EMCode": "155"
},
{
"QSid": "89",
"QDes": "/西瓜",
"isStatic": "1",
"IQLid": "60",
"AQLid": "60",
"EMCode": "156"
},
{
"QSid": "276",
"QDes": "/辣椒酱",
"isStatic": "1",
"IQLid": "276",
"AQLid": "276",
"QHide": "1",
"EMCode": "10276"
},
{
"QSid": "113",
"QDes": "/啤酒",
"IQLid": "61",
"AQLid": "61",
"EMCode": "157"
},
{
"QSid": "114",
"QDes": "/篮球",
"IQLid": "90",
"AQLid": "92",
"EMCode": "158"
},
{
"QSid": "115",
"QDes": "/乒乓",
"IQLid": "91",
"AQLid": "93",
"EMCode": "159"
},
{
"QSid": "171",
"QDes": "/茶",
"IQLid": "141",
"AQLid": "163",
"EMCode": "241"
},
{
"QSid": "60",
"QDes": "/咖啡",
"IQLid": "66",
"AQLid": "66",
"EMCode": "160"
},
{
"QSid": "61",
"QDes": "/饭",
"isStatic": "1",
"IQLid": "58",
"AQLid": "58",
"EMCode": "161"
},
{
"QSid": "46",
"QDes": "/猪头",
"isStatic": "1",
"IQLid": "7",
"AQLid": "7",
"EMCode": "162"
},
{
"QSid": "63",
"QDes": "/玫瑰",
"isStatic": "1",
"IQLid": "8",
"AQLid": "8",
"EMCode": "163"
},
{
"QSid": "64",
"QDes": "/凋谢",
"isStatic": "1",
"IQLid": "57",
"AQLid": "57",
"EMCode": "164"
},
{
"QSid": "116",
"QDes": "/示爱",
"IQLid": "29",
"AQLid": "29",
"EMCode": "165"
},
{
"QSid": "66",
"QDes": "/爱心",
"IQLid": "28",
"AQLid": "28",
"EMCode": "166"
},
{
"QSid": "67",
"QDes": "/心碎",
"IQLid": "72",
"AQLid": "74",
"EMCode": "167"
},
{
"QSid": "53",
"QDes": "/蛋糕",
"IQLid": "59",
"AQLid": "59",
"EMCode": "168"
},
{
"QSid": "54",
"QDes": "/闪电",
"isStatic": "1",
"IQLid": "78",
"AQLid": "80",
"EMCode": "169"
},
{
"QSid": "55",
"QDes": "/炸弹",
"isStatic": "1",
"IQLid": "16",
"AQLid": "16",
"EMCode": "170"
},
{
"QSid": "56",
"QDes": "/刀",
"IQLid": "68",
"AQLid": "70",
"EMCode": "171"
},
{
"QSid": "145",
"QDes": "/祈祷",
"isStatic": "1",
"IQLid": "115",
"AQLid": "117",
"EMCode": "121010"
},
{
"QSid": "57",
"QDes": "/足球",
"IQLid": "75",
"AQLid": "77",
"EMCode": "172"
},
{
"QSid": "117",
"QDes": "/瓢虫",
"IQLid": "62",
"AQLid": "62",
"EMCode": "173"
},
{
"QSid": "59",
"QDes": "/便便",
"IQLid": "15",
"AQLid": "15",
"EMCode": "174"
},
{
"QSid": "75",
"QDes": "/月亮",
"isStatic": "1",
"IQLid": "67",
"AQLid": "68",
"EMCode": "175"
},
{
"QSid": "74",
"QDes": "/太阳",
"isStatic": "1",
"IQLid": "73",
"AQLid": "75",
"EMCode": "176"
},
{
"QSid": "69",
"QDes": "/礼物",
"isStatic": "1",
"IQLid": "74",
"AQLid": "76",
"EMCode": "177"
},
{
"QSid": "49",
"QDes": "/拥抱",
"IQLid": "45",
"AQLid": "45",
"EMCode": "178"
},
{
"QSid": "76",
"QDes": "/赞",
"IQLid": "52",
"AQLid": "52",
"EMCode": "179"
},
{
"QSid": "77",
"QDes": "/踩",
"IQLid": "53",
"AQLid": "53",
"EMCode": "180"
},
{
"QSid": "78",
"QDes": "/握手",
"IQLid": "54",
"AQLid": "54",
"EMCode": "181"
},
{
"QSid": "79",
"QDes": "/胜利",
"IQLid": "55",
"AQLid": "55",
"EMCode": "182"
},
{
"QSid": "118",
"QDes": "/抱拳",
"IQLid": "56",
"AQLid": "56",
"EMCode": "183"
},
{
"QSid": "119",
"QDes": "/勾引",
"IQLid": "63",
"AQLid": "63",
"EMCode": "184"
},
{
"QSid": "120",
"QDes": "/拳头",
"IQLid": "71",
"AQLid": "73",
"EMCode": "185"
},
{
"QSid": "121",
"QDes": "/差劲",
"IQLid": "70",
"AQLid": "72",
"EMCode": "186"
},
{
"QSid": "122",
"QDes": "/爱你",
"IQLid": "65",
"AQLid": "65",
"EMCode": "187"
},
{
"QSid": "123",
"QDes": "/NO",
"IQLid": "92",
"AQLid": "94",
"EMCode": "188"
},
{
"QSid": "124",
"QDes": "/OK",
"isStatic": "1",
"IQLid": "64",
"AQLid": "64",
"EMCode": "189"
},
{
"QSid": "42",
"QDes": "/爱情",
"IQLid": "38",
"AQLid": "38",
"EMCode": "190"
},
{
"QSid": "85",
"QDes": "/飞吻",
"isStatic": "1",
"IQLid": "47",
"AQLid": "47",
"EMCode": "191"
},
{
"QSid": "43",
"QDes": "/跳跳",
"IQLid": "93",
"AQLid": "95",
"EMCode": "192"
},
{
"QSid": "41",
"QDes": "/发抖",
"isStatic": "1",
"IQLid": "69",
"AQLid": "71",
"EMCode": "193"
},
{
"QSid": "86",
"QDes": "/怄火",
"IQLid": "94",
"AQLid": "96",
"EMCode": "194"
},
{
"QSid": "125",
"QDes": "/转圈",
"IQLid": "95",
"AQLid": "97",
"EMCode": "195"
},
{
"QSid": "126",
"QDes": "/磕头",
"IQLid": "96",
"AQLid": "98",
"EMCode": "196"
},
{
"QSid": "127",
"QDes": "/回头",
"IQLid": "97",
"AQLid": "99",
"EMCode": "197"
},
{
"QSid": "128",
"QDes": "/跳绳",
"IQLid": "98",
"AQLid": "100",
"EMCode": "198"
},
{
"QSid": "129",
"QDes": "/挥手",
"IQLid": "77",
"AQLid": "79",
"EMCode": "199"
},
{
"QSid": "130",
"QDes": "/激动",
"IQLid": "99",
"AQLid": "101",
"EMCode": "200"
},
{
"QSid": "131",
"QDes": "/街舞",
"IQLid": "100",
"AQLid": "102",
"EMCode": "201"
},
{
"QSid": "132",
"QDes": "/献吻",
"IQLid": "101",
"AQLid": "103",
"EMCode": "202"
},
{
"QSid": "133",
"QDes": "/左太极",
"IQLid": "102",
"AQLid": "104",
"EMCode": "203"
},
{
"QSid": "134",
"QDes": "/右太极",
"IQLid": "103",
"AQLid": "105",
"EMCode": "204"
},
{
"QSid": "136",
"QDes": "/双喜",
"isStatic": "1",
"IQLid": "106",
"AQLid": "108",
"EMCode": "121001"
},
{
"QSid": "137",
"QDes": "/鞭炮",
"isStatic": "1",
"IQLid": "107",
"AQLid": "109",
"EMCode": "121002"
},
{
"QSid": "138",
"QDes": "/灯笼",
"isStatic": "1",
"IQLid": "108",
"AQLid": "110",
"EMCode": "121003"
},
{
"QSid": "140",
"QDes": "/K歌",
"isStatic": "1",
"IQLid": "110",
"AQLid": "112",
"EMCode": "121005"
},
{
"QSid": "144",
"QDes": "/喝彩",
"isStatic": "1",
"IQLid": "114",
"AQLid": "116",
"EMCode": "121009"
},
{
"QSid": "146",
"QDes": "/爆筋",
"isStatic": "1",
"IQLid": "116",
"AQLid": "118",
"EMCode": "121011"
},
{
"QSid": "147",
"QDes": "/棒棒糖",
"isStatic": "1",
"IQLid": "117",
"AQLid": "119",
"EMCode": "121012"
},
{
"QSid": "148",
"QDes": "/喝奶",
"isStatic": "1",
"IQLid": "118",
"AQLid": "120",
"EMCode": "121013"
},
{
"QSid": "151",
"QDes": "/飞机",
"isStatic": "1",
"IQLid": "121",
"AQLid": "123",
"EMCode": "121016"
},
{
"QSid": "158",
"QDes": "/钞票",
"isStatic": "1",
"IQLid": "128",
"AQLid": "130",
"EMCode": "121023"
},
{
"QSid": "168",
"QDes": "/药",
"isStatic": "1",
"IQLid": "138",
"AQLid": "140",
"EMCode": "121033"
},
{
"QSid": "169",
"QDes": "/手枪",
"isStatic": "1",
"IQLid": "139",
"AQLid": "141",
"EMCode": "121034"
},
{
"QSid": "188",
"QDes": "/蛋",
"IQLid": "158",
"AQLid": "180",
"EMCode": "258"
},
{
"QSid": "192",
"QDes": "/红包",
"IQLid": "162",
"AQLid": "184",
"EMCode": "262"
},
{
"QSid": "184",
"QDes": "/河蟹",
"IQLid": "154",
"AQLid": "176",
"EMCode": "254"
},
{
"QSid": "185",
"QDes": "/羊驼",
"IQLid": "155",
"AQLid": "177",
"EMCode": "255"
},
{
"QSid": "190",
"QDes": "/菊花",
"IQLid": "160",
"AQLid": "182",
"EMCode": "260"
},
{
"QSid": "187",
"QDes": "/幽灵",
"IQLid": "157",
"AQLid": "179",
"EMCode": "257"
},
{
"QSid": "193",
"QDes": "/大笑",
"IQLid": "163",
"AQLid": "185",
"EMCode": "263"
},
{
"QSid": "194",
"QDes": "/不开心",
"IQLid": "164",
"AQLid": "143",
"EMCode": "264"
},
{
"QSid": "197",
"QDes": "/冷漠",
"IQLid": "167",
"AQLid": "146",
"EMCode": "267"
},
{
"QSid": "198",
"QDes": "/呃",
"IQLid": "168",
"AQLid": "147",
"EMCode": "268"
},
{
"QSid": "199",
"QDes": "/好棒",
"IQLid": "169",
"AQLid": "148",
"EMCode": "269"
},
{
"QSid": "200",
"QDes": "/拜托",
"IQLid": "170",
"AQLid": "149",
"EMCode": "270"
},
{
"QSid": "201",
"QDes": "/点赞",
"IQLid": "171",
"AQLid": "150",
"EMCode": "271"
},
{
"QSid": "202",
"QDes": "/无聊",
"IQLid": "172",
"AQLid": "151",
"EMCode": "272"
},
{
"QSid": "203",
"QDes": "/托脸",
"IQLid": "173",
"AQLid": "152",
"EMCode": "273"
},
{
"QSid": "204",
"QDes": "/吃",
"IQLid": "174",
"AQLid": "153",
"EMCode": "274"
},
{
"QSid": "205",
"QDes": "/送花",
"IQLid": "175",
"AQLid": "154",
"EMCode": "275"
},
{
"QSid": "206",
"QDes": "/害怕",
"IQLid": "176",
"AQLid": "155",
"EMCode": "276"
},
{
"QSid": "207",
"QDes": "/花痴",
"IQLid": "177",
"AQLid": "156",
"EMCode": "277"
},
{
"QSid": "208",
"QDes": "/小样儿",
"IQLid": "178",
"AQLid": "157",
"EMCode": "278"
},
{
"QSid": "210",
"QDes": "/飙泪",
"IQLid": "180",
"AQLid": "159",
"EMCode": "280"
},
{
"QSid": "211",
"QDes": "/我不看",
"IQLid": "181",
"AQLid": "160",
"EMCode": "281"
},
{
"QSid": "278",
"QDes": "/汗",
"IQLid": "278",
"isCMEmoji": "1",
"AQLid": "278",
"EMCode": "20237"
},
{
"QSid": "279",
"QDes": "/打脸",
"IQLid": "279",
"isCMEmoji": "1",
"AQLid": "279",
"EMCode": "20238"
},
{
"QSid": "280",
"QDes": "/击掌",
"IQLid": "280",
"isCMEmoji": "1",
"AQLid": "280",
"EMCode": "20239"
},
{
"QSid": "242",
"QDes": "/头撞击",
"IQLid": "212",
"isCMEmoji": "1",
"AQLid": "214",
"EMCode": "314"
},
{
"QSid": "243",
"QDes": "/甩头",
"IQLid": "213",
"isCMEmoji": "1",
"AQLid": "215",
"EMCode": "313"
},
{
"QSid": "244",
"QDes": "/扔狗",
"IQLid": "214",
"isCMEmoji": "1",
"AQLid": "216",
"EMCode": "312"
},
{
"QSid": "215",
"QDes": "/糊脸",
"IQLid": "185",
"isCMEmoji": "1",
"AQLid": "187",
"EMCode": "285"
},
{
"QSid": "237",
"QDes": "/偷看",
"IQLid": "207",
"isCMEmoji": "1",
"AQLid": "209",
"EMCode": "307"
},
{
"QSid": "226",
"QDes": "/拍桌",
"IQLid": "196",
"isCMEmoji": "1",
"AQLid": "198",
"EMCode": "297"
},
{
"QSid": "214",
"QDes": "/啵啵",
"IQLid": "184",
"isCMEmoji": "1",
"AQLid": "186",
"EMCode": "284"
},
{
"QSid": "217",
"QDes": "/扯一扯",
"IQLid": "187",
"isCMEmoji": "1",
"AQLid": "189",
"EMCode": "287"
},
{
"QSid": "240",
"QDes": "/喷脸",
"IQLid": "210",
"isCMEmoji": "1",
"AQLid": "212",
"EMCode": "310"
},
{
"QSid": "216",
"QDes": "/拍头",
"IQLid": "186",
"isCMEmoji": "1",
"AQLid": "188",
"EMCode": "286"
},
{
"QSid": "218",
"QDes": "/舔一舔",
"IQLid": "188",
"isCMEmoji": "1",
"AQLid": "190",
"EMCode": "288"
},
{
"QSid": "229",
"QDes": "/干杯",
"IQLid": "199",
"isCMEmoji": "1",
"AQLid": "201",
"EMCode": "299"
},
{
"QSid": "238",
"QDes": "/扇脸",
"IQLid": "208",
"isCMEmoji": "1",
"AQLid": "210",
"EMCode": "308"
},
{
"QSid": "219",
"QDes": "/蹭一蹭",
"IQLid": "189",
"isCMEmoji": "1",
"AQLid": "191",
"EMCode": "289"
},
{
"QSid": "225",
"QDes": "/撩一撩",
"IQLid": "195",
"isCMEmoji": "1",
"AQLid": "197",
"EMCode": "296"
},
{
"QSid": "231",
"QDes": "/哼",
"IQLid": "201",
"isCMEmoji": "1",
"AQLid": "203",
"EMCode": "301"
},
{
"QSid": "233",
"QDes": "/掐一掐",
"IQLid": "203",
"isCMEmoji": "1",
"AQLid": "205",
"EMCode": "303"
},
{
"QSid": "221",
"QDes": "/顶呱呱",
"IQLid": "191",
"isCMEmoji": "1",
"AQLid": "193",
"EMCode": "291"
},
{
"QSid": "222",
"QDes": "/抱抱",
"IQLid": "192",
"isCMEmoji": "1",
"AQLid": "194",
"EMCode": "292"
},
{
"QSid": "239",
"QDes": "/原谅",
"IQLid": "209",
"isCMEmoji": "1",
"AQLid": "211",
"EMCode": "309"
},
{
"QSid": "232",
"QDes": "/佛系",
"IQLid": "202",
"isCMEmoji": "1",
"AQLid": "204",
"EMCode": "302"
},
{
"QSid": "220",
"QDes": "/拽炸天",
"IQLid": "190",
"isCMEmoji": "1",
"AQLid": "192",
"EMCode": "290"
},
{
"QSid": "235",
"QDes": "/颤抖",
"IQLid": "205",
"isCMEmoji": "1",
"AQLid": "207",
"EMCode": "305"
},
{
"QSid": "241",
"QDes": "/生日快乐",
"IQLid": "211",
"isCMEmoji": "1",
"AQLid": "213",
"EMCode": "311"
},
{
"QSid": "230",
"QDes": "/嘲讽",
"IQLid": "200",
"isCMEmoji": "1",
"AQLid": "202",
"EMCode": "300"
},
{
"QSid": "224",
"QDes": "/开枪",
"IQLid": "194",
"isCMEmoji": "1",
"AQLid": "196",
"EMCode": "295"
},
{
"QSid": "236",
"QDes": "/啃头",
"IQLid": "206",
"isCMEmoji": "1",
"AQLid": "208",
"EMCode": "306"
},
{
"QSid": "228",
"QDes": "/恭喜",
"IQLid": "198",
"isCMEmoji": "1",
"AQLid": "200",
"EMCode": "298"
},
{
"QSid": "234",
"QDes": "/惊呆",
"IQLid": "204",
"isCMEmoji": "1",
"AQLid": "206",
"EMCode": "304"
},
{
"QSid": "223",
"QDes": "/暴击",
"IQLid": "193",
"isCMEmoji": "1",
"AQLid": "195",
"EMCode": "293"
},
{
"QSid": "227",
"QDes": "/拍手",
"IQLid": "197",
"isCMEmoji": "1",
"AQLid": "199",
"EMCode": "294"
}
],
"emoji": [
{
"QSid": "😊",
"QCid": "128522",
"AQLid": "0",
"QDes": "/嘿嘿",
"EMCode": "400832"
},
{
"QSid": "😌",
"QCid": "128524",
"AQLid": "1",
"QDes": "/羞涩",
"EMCode": "400834"
},
{
"QSid": "😚",
"QCid": "128538",
"AQLid": "2",
"QDes": "/亲亲",
"EMCode": "400848"
},
{
"QSid": "😓",
"QCid": "128531",
"AQLid": "3",
"QDes": "/汗",
"EMCode": "400841"
},
{
"QSid": "😰",
"QCid": "128560",
"AQLid": "4",
"QDes": "/紧张",
"EMCode": "400870"
},
{
"QSid": "😝",
"QCid": "128541",
"AQLid": "5",
"QDes": "/吐舌",
"EMCode": "400851"
},
{
"QSid": "😁",
"QCid": "128513",
"AQLid": "6",
"QDes": "/呲牙",
"EMCode": "400823"
},
{
"QSid": "😜",
"QCid": "128540",
"AQLid": "7",
"QDes": "/淘气",
"EMCode": "400850"
},
{
"QSid": "☺",
"QCid": "9786",
"AQLid": "8",
"QDes": "/可爱",
"EMCode": "401181"
},
{
"QSid": "😉",
"QCid": "128521",
"AQLid": "9",
"QDes": "/媚眼",
"EMCode": "400831"
},
{
"QSid": "😍",
"QCid": "128525",
"AQLid": "10",
"QDes": "/花痴",
"EMCode": "400835"
},
{
"QSid": "😔",
"QCid": "128532",
"AQLid": "11",
"QDes": "/失落",
"EMCode": "400842"
},
{
"QSid": "😄",
"QCid": "128516",
"AQLid": "12",
"QDes": "/高兴",
"EMCode": "400826"
},
{
"QSid": "😏",
"QCid": "128527",
"AQLid": "13",
"QDes": "/哼哼",
"EMCode": "400837"
},
{
"QSid": "😒",
"QCid": "128530",
"AQLid": "14",
"QDes": "/不屑",
"EMCode": "400840"
},
{
"QSid": "😳",
"QCid": "128563",
"AQLid": "15",
"QDes": "/瞪眼",
"EMCode": "400873"
},
{
"QSid": "😘",
"QCid": "128536",
"AQLid": "16",
"QDes": "/飞吻",
"EMCode": "400846"
},
{
"QSid": "😭",
"QCid": "128557",
"AQLid": "17",
"QDes": "/大哭",
"EMCode": "400867"
},
{
"QSid": "😱",
"QCid": "128561",
"AQLid": "18",
"QDes": "/害怕",
"EMCode": "400871"
},
{
"QSid": "😂",
"QCid": "128514",
"AQLid": "19",
"QDes": "/激动",
"EMCode": "400824"
},
{
"QSid": "💪",
"QCid": "128170",
"AQLid": "20",
"QDes": "/肌肉",
"EMCode": "400644"
},
{
"QSid": "👊",
"QCid": "128074",
"AQLid": "21",
"QDes": "/拳头",
"EMCode": "400390"
},
{
"QSid": "👍",
"QCid": "128077",
"AQLid": "22",
"QDes": "/厉害",
"EMCode": "400408"
},
{
"QSid": "☝",
"QCid": "9757",
"AQLid": "23",
"QDes": "/向上",
"EMCode": "401203"
},
{
"QSid": "👏",
"QCid": "128079",
"AQLid": "24",
"QDes": "/鼓掌",
"EMCode": "400420"
},
{
"QSid": "✌",
"QCid": "9996",
"AQLid": "25",
"QDes": "/胜利",
"EMCode": "401210"
},
{
"QSid": "👎",
"QCid": "128078",
"AQLid": "26",
"QDes": "/鄙视",
"EMCode": "400414"
},
{
"QSid": "🙏",
"QCid": "128591",
"AQLid": "27",
"QDes": "/合十",
"EMCode": "400396"
},
{
"QSid": "👌",
"QCid": "128076",
"AQLid": "28",
"QDes": "/好的",
"EMCode": "400402"
},
{
"QSid": "👈",
"QCid": "128072",
"AQLid": "29",
"QDes": "/向左",
"EMCode": "400378"
},
{
"QSid": "👉",
"QCid": "128073",
"AQLid": "30",
"QDes": "/向右",
"EMCode": "400384"
},
{
"QSid": "👆",
"QCid": "128070",
"AQLid": "31",
"QDes": "/向上",
"EMCode": "400366"
},
{
"QSid": "👇",
"QCid": "128071",
"AQLid": "32",
"QDes": "/向下",
"EMCode": "400372"
},
{
"QSid": "👀",
"QCid": "128064",
"AQLid": "33",
"QDes": "/眼睛",
"EMCode": "400351"
},
{
"QSid": "👃",
"QCid": "128067",
"AQLid": "34",
"QDes": "/鼻子",
"EMCode": "400358"
},
{
"QSid": "👄",
"QCid": "128068",
"AQLid": "35",
"QDes": "/嘴唇",
"EMCode": "400364"
},
{
"QSid": "👂",
"QCid": "128066",
"AQLid": "36",
"QDes": "/耳朵",
"EMCode": "400352"
},
{
"QSid": "🍚",
"QCid": "127834",
"AQLid": "37",
"QDes": "/米饭",
"EMCode": "400149"
},
{
"QSid": "🍝",
"QCid": "127837",
"AQLid": "38",
"QDes": "/意面",
"EMCode": "400152"
},
{
"QSid": "🍜",
"QCid": "127836",
"AQLid": "39",
"QDes": "/拉面",
"EMCode": "400151"
},
{
"QSid": "🍙",
"QCid": "127833",
"AQLid": "40",
"QDes": "/饭团",
"EMCode": "400148"
},
{
"QSid": "🍧",
"QCid": "127847",
"AQLid": "41",
"QDes": "/刨冰",
"EMCode": "400162"
},
{
"QSid": "🍣",
"QCid": "127843",
"AQLid": "42",
"QDes": "/寿司",
"EMCode": "400158"
},
{
"QSid": "🎂",
"QCid": "127874",
"AQLid": "43",
"QDes": "/蛋糕",
"EMCode": "400186"
},
{
"QSid": "🍞",
"QCid": "127838",
"AQLid": "44",
"QDes": "/面包",
"EMCode": "400153"
},
{
"QSid": "🍔",
"QCid": "127828",
"AQLid": "45",
"QDes": "/汉堡",
"EMCode": "400143"
},
{
"QSid": "🍳",
"QCid": "127859",
"AQLid": "46",
"QDes": "/煎蛋",
"EMCode": "400174"
},
{
"QSid": "🍟",
"QCid": "127839",
"AQLid": "47",
"QDes": "/薯条",
"EMCode": "400154"
},
{
"QSid": "🍺",
"QCid": "127866",
"AQLid": "48",
"QDes": "/啤酒",
"EMCode": "400181"
},
{
"QSid": "🍻",
"QCid": "127867",
"AQLid": "49",
"QDes": "/干杯",
"EMCode": "400182"
},
{
"QSid": "🍸",
"QCid": "127864",
"AQLid": "50",
"QDes": "/高脚杯",
"EMCode": "400179"
},
{
"QSid": "☕",
"QCid": "9749",
"AQLid": "51",
"QDes": "/咖啡",
"EMCode": "401262"
},
{
"QSid": "🍎",
"QCid": "127822",
"AQLid": "52",
"QDes": "/苹果",
"EMCode": "400137"
},
{
"QSid": "🍊",
"QCid": "127818",
"AQLid": "53",
"QDes": "/橙子",
"EMCode": "400133"
},
{
"QSid": "🍓",
"QCid": "127827",
"AQLid": "54",
"QDes": "/草莓",
"EMCode": "400142"
},
{
"QSid": "🍉",
"QCid": "127817",
"AQLid": "55",
"QDes": "/西瓜",
"EMCode": "400132"
},
{
"QSid": "💊",
"QCid": "128138",
"AQLid": "56",
"QDes": "/药丸",
"EMCode": "400612"
},
{
"QSid": "🚬",
"QCid": "128684",
"AQLid": "57",
"QDes": "/吸烟",
"EMCode": "400987"
},
{
"QSid": "🎄",
"QCid": "127876",
"AQLid": "58",
"QDes": "/圣诞树",
"EMCode": "400188"
},
{
"QSid": "🌹",
"QCid": "127801",
"AQLid": "59",
"QDes": "/玫瑰",
"EMCode": "400116"
},
{
"QSid": "🎉",
"QCid": "127881",
"AQLid": "60",
"QDes": "/庆祝",
"EMCode": "400198"
},
{
"QSid": "🌴",
"QCid": "127796",
"AQLid": "61",
"QDes": "/椰子树",
"EMCode": "400112"
},
{
"QSid": "💝",
"QCid": "128157",
"AQLid": "62",
"QDes": "/礼物",
"EMCode": "400631"
},
{
"QSid": "🎀",
"QCid": "127872",
"AQLid": "63",
"QDes": "/蝴蝶结",
"EMCode": "400184"
},
{
"QSid": "🎈",
"QCid": "127880",
"AQLid": "64",
"QDes": "/气球",
"EMCode": "400197"
},
{
"QSid": "🐚",
"QCid": "128026",
"AQLid": "65",
"QDes": "/海螺",
"EMCode": "400314"
},
{
"QSid": "💍",
"QCid": "128141",
"AQLid": "66",
"QDes": "/戒指",
"EMCode": "400615"
},
{
"QSid": "💣",
"QCid": "128163",
"AQLid": "67",
"QDes": "/炸弹",
"EMCode": "400637"
},
{
"QSid": "👑",
"QCid": "128081",
"AQLid": "68",
"QDes": "/皇冠",
"EMCode": "400432"
},
{
"QSid": "🔔",
"QCid": "128276",
"AQLid": "69",
"QDes": "/铃铛",
"EMCode": "400751"
},
{
"QSid": "⭐",
"QCid": "11088",
"AQLid": "70",
"QDes": "/星星",
"EMCode": "401686"
},
{
"QSid": "✨",
"QCid": "10024",
"AQLid": "71",
"QDes": "/闪光",
"EMCode": "401137"
},
{
"QSid": "💨",
"QCid": "128168",
"AQLid": "72",
"QDes": "/吹气",
"EMCode": "400642"
},
{
"QSid": "💦",
"QCid": "128166",
"AQLid": "73",
"QDes": "/水",
"EMCode": "400640"
},
{
"QSid": "🔥",
"QCid": "128293",
"AQLid": "74",
"QDes": "/火",
"EMCode": "400768"
},
{
"QSid": "🏆",
"QCid": "127942",
"AQLid": "75",
"QDes": "/奖杯",
"EMCode": "400256"
},
{
"QSid": "💰",
"QCid": "128176",
"AQLid": "76",
"QDes": "/钱",
"EMCode": "400655"
},
{
"QSid": "💤",
"QCid": "128164",
"AQLid": "77",
"QDes": "/睡觉",
"EMCode": "400638"
},
{
"QSid": "⚡",
"QCid": "9889",
"AQLid": "78",
"QDes": "/闪电",
"EMCode": "401685"
},
{
"QSid": "👣",
"QCid": "128099",
"AQLid": "79",
"QDes": "/脚印",
"EMCode": "400450"
},
{
"QSid": "💩",
"QCid": "128169",
"AQLid": "80",
"QDes": "/便便",
"EMCode": "400643"
},
{
"QSid": "💉",
"QCid": "128137",
"AQLid": "81",
"QDes": "/打针",
"EMCode": "400611"
},
{
"QSid": "♨",
"QCid": "9832",
"AQLid": "82",
"QDes": "/热",
"EMCode": "401287"
},
{
"QSid": "📫",
"QCid": "128235",
"AQLid": "83",
"QDes": "/邮箱",
"EMCode": "400714"
},
{
"QSid": "🔑",
"QCid": "128273",
"AQLid": "84",
"QDes": "/钥匙",
"EMCode": "400748"
},
{
"QSid": "🔒",
"QCid": "128274",
"AQLid": "85",
"QDes": "/锁",
"EMCode": "400749"
},
{
"QSid": "✈",
"QCid": "9992",
"AQLid": "86",
"QDes": "/飞机",
"EMCode": "401298"
},
{
"QSid": "🚄",
"QCid": "128644",
"AQLid": "87",
"QDes": "/列车",
"EMCode": "400942"
},
{
"QSid": "🚗",
"QCid": "128663",
"AQLid": "88",
"QDes": "/汽车",
"EMCode": "400961"
},
{
"QSid": "🚤",
"QCid": "128676",
"AQLid": "89",
"QDes": "/快艇",
"EMCode": "400979"
},
{
"QSid": "🚲",
"QCid": "128690",
"AQLid": "90",
"QDes": "/自行车",
"EMCode": "400993"
},
{
"QSid": "🐎",
"QCid": "128014",
"AQLid": "91",
"QDes": "/骑马",
"EMCode": "400302"
},
{
"QSid": "🚀",
"QCid": "128640",
"AQLid": "92",
"QDes": "/火箭",
"EMCode": "400938"
},
{
"QSid": "🚌",
"QCid": "128652",
"AQLid": "93",
"QDes": "/公交",
"EMCode": "400950"
},
{
"QSid": "⛵",
"QCid": "9973",
"AQLid": "94",
"QDes": "/船",
"EMCode": "401294"
},
{
"QSid": "👩",
"QCid": "128105",
"AQLid": "95",
"QDes": "/妈妈",
"EMCode": "400482"
},
{
"QSid": "👨",
"QCid": "128104",
"AQLid": "96",
"QDes": "/爸爸",
"EMCode": "400465"
},
{
"QSid": "👧",
"QCid": "128103",
"AQLid": "97",
"QDes": "/女孩",
"EMCode": "400459"
},
{
"QSid": "👦",
"QCid": "128102",
"AQLid": "98",
"QDes": "/男孩",
"EMCode": "400453"
},
{
"QSid": "🐵",
"QCid": "128053",
"AQLid": "99",
"QDes": "/猴",
"EMCode": "400341"
},
{
"QSid": "🐙",
"QCid": "128025",
"AQLid": "100",
"QDes": "/章鱼",
"EMCode": "400313"
},
{
"QSid": "🐷",
"QCid": "128055",
"AQLid": "101",
"QDes": "/猪",
"EMCode": "400343"
},
{
"QSid": "💀",
"QCid": "128128",
"AQLid": "102",
"QDes": "/骷髅",
"EMCode": "400572"
},
{
"QSid": "🐤",
"QCid": "128036",
"AQLid": "103",
"QDes": "/小鸡",
"EMCode": "400324"
},
{
"QSid": "🐨",
"QCid": "128040",
"AQLid": "104",
"QDes": "/树懒",
"EMCode": "400328"
},
{
"QSid": "🐮",
"QCid": "128046",
"AQLid": "105",
"QDes": "/牛",
"EMCode": "400334"
},
{
"QSid": "🐔",
"QCid": "128020",
"AQLid": "106",
"QDes": "/公鸡",
"EMCode": "400308"
},
{
"QSid": "🐸",
"QCid": "128056",
"AQLid": "107",
"QDes": "/青蛙",
"EMCode": "400344"
},
{
"QSid": "👻",
"QCid": "128123",
"AQLid": "108",
"QDes": "/幽灵",
"EMCode": "400562"
},
{
"QSid": "🐛",
"QCid": "128027",
"AQLid": "109",
"QDes": "/虫",
"EMCode": "400315"
},
{
"QSid": "🐠",
"QCid": "128032",
"AQLid": "110",
"QDes": "/鱼",
"EMCode": "400320"
},
{
"QSid": "🐶",
"QCid": "128054",
"AQLid": "111",
"QDes": "/狗",
"EMCode": "400342"
},
{
"QSid": "🐯",
"QCid": "128047",
"AQLid": "112",
"QDes": "/老虎",
"EMCode": "400335"
},
{
"QSid": "👼",
"QCid": "128124",
"AQLid": "113",
"QDes": "/天使",
"EMCode": "400563"
},
{
"QSid": "🐧",
"QCid": "128039",
"AQLid": "114",
"QDes": "/企鹅",
"EMCode": "400327"
},
{
"QSid": "🐳",
"QCid": "128051",
"AQLid": "115",
"QDes": "/鲸鱼",
"EMCode": "400339"
},
{
"QSid": "🐭",
"QCid": "128045",
"AQLid": "116",
"QDes": "/老鼠",
"EMCode": "400333"
},
{
"QSid": "👒",
"QCid": "128082",
"AQLid": "117",
"QDes": "/帽子",
"EMCode": "400433"
},
{
"QSid": "👗",
"QCid": "128087",
"AQLid": "118",
"QDes": "/连衣裙",
"EMCode": "400438"
},
{
"QSid": "💄",
"QCid": "128132",
"AQLid": "119",
"QDes": "/口红",
"EMCode": "400591"
},
{
"QSid": "👠",
"QCid": "128096",
"AQLid": "120",
"QDes": "/高跟鞋",
"EMCode": "400447"
},
{
"QSid": "👢",
"QCid": "128098",
"AQLid": "121",
"QDes": "/靴子",
"EMCode": "400449"
},
{
"QSid": "🌂",
"QCid": "127746",
"AQLid": "122",
"QDes": "/雨伞",
"EMCode": "400077"
},
{
"QSid": "👜",
"QCid": "128092",
"AQLid": "123",
"QDes": "/包",
"EMCode": "400443"
},
{
"QSid": "👙",
"QCid": "128089",
"AQLid": "124",
"QDes": "/内衣",
"EMCode": "400440"
},
{
"QSid": "👕",
"QCid": "128085",
"AQLid": "125",
"QDes": "/衣服",
"EMCode": "400436"
},
{
"QSid": "👟",
"QCid": "128095",
"AQLid": "126",
"QDes": "/鞋子",
"EMCode": "400446"
},
{
"QSid": "☁",
"QCid": "9729",
"AQLid": "127",
"QDes": "/云朵",
"EMCode": "401329"
},
{
"QSid": "☀",
"QCid": "9728",
"AQLid": "128",
"QDes": "/晴天",
"EMCode": "401328"
},
{
"QSid": "☔",
"QCid": "9748",
"AQLid": "129",
"QDes": "/雨天",
"EMCode": "401342"
},
{
"QSid": "🌙",
"QCid": "127769",
"AQLid": "130",
"QDes": "/月亮",
"EMCode": "400100"
},
{
"QSid": "⛄",
"QCid": "9924",
"AQLid": "131",
"QDes": "/雪人",
"EMCode": "401346"
},
{
"QSid": "⭕",
"QCid": "11093",
"AQLid": "132",
"QDes": "/正确",
"EMCode": "401687"
},
{
"QSid": "❌",
"QCid": "10060",
"AQLid": "133",
"QDes": "/错误",
"EMCode": "401142"
},
{
"QSid": "❔",
"QCid": "10068",
"AQLid": "134",
"QDes": "/问号",
"EMCode": "401145"
},
{
"QSid": "❕",
"QCid": "10069",
"AQLid": "135",
"QDes": "/叹号",
"EMCode": "401146"
},
{
"QSid": "☎",
"QCid": "9742",
"AQLid": "136",
"QDes": "/电话",
"EMCode": "401398"
},
{
"QSid": "📷",
"QCid": "128247",
"AQLid": "137",
"QDes": "/相机",
"EMCode": "400726"
},
{
"QSid": "📱",
"QCid": "128241",
"AQLid": "138",
"QDes": "/手机",
"EMCode": "400720"
},
{
"QSid": "📠",
"QCid": "128224",
"AQLid": "139",
"QDes": "/传真",
"EMCode": "400703"
},
{
"QSid": "💻",
"QCid": "128187",
"AQLid": "140",
"QDes": "/电脑",
"EMCode": "400666"
},
{
"QSid": "🎥",
"QCid": "127909",
"AQLid": "141",
"QDes": "/摄影机",
"EMCode": "400214"
},
{
"QSid": "🎤",
"QCid": "127908",
"AQLid": "142",
"QDes": "/话筒",
"EMCode": "400213"
},
{
"QSid": "🔫",
"QCid": "128299",
"AQLid": "143",
"QDes": "/手枪",
"EMCode": "400774"
},
{
"QSid": "💿",
"QCid": "128191",
"AQLid": "144",
"QDes": "/光碟",
"EMCode": "400670"
},
{
"QSid": "💓",
"QCid": "128147",
"AQLid": "145",
"QDes": "/爱心",
"EMCode": "400621"
},
{
"QSid": "♣",
"QCid": "9827",
"AQLid": "146",
"QDes": "/扑克",
"EMCode": "401385"
},
{
"QSid": "🀄",
"QCid": "126980",
"AQLid": "147",
"QDes": "/麻将",
"EMCode": "401386"
},
{
"QSid": "〽",
"QCid": "12349",
"AQLid": "148",
"QDes": "/股票",
"EMCode": "401691"
},
{
"QSid": "🎰",
"QCid": "127920",
"AQLid": "149",
"QDes": "/老虎机",
"EMCode": "400225"
},
{
"QSid": "🚥",
"QCid": "128677",
"AQLid": "150",
"QDes": "/信号灯",
"EMCode": "400980"
},
{
"QSid": "🚧",
"QCid": "128679",
"AQLid": "151",
"QDes": "/路障",
"EMCode": "400982"
},
{
"QSid": "🎸",
"QCid": "127928",
"AQLid": "152",
"QDes": "/吉他",
"EMCode": "400233"
},
{
"QSid": "💈",
"QCid": "128136",
"AQLid": "153",
"QDes": "/理发厅",
"EMCode": "400610"
},
{
"QSid": "🛀",
"QCid": "128704",
"AQLid": "154",
"QDes": "/浴缸",
"EMCode": "401022"
},
{
"QSid": "🚽",
"QCid": "128701",
"AQLid": "155",
"QDes": "/马桶",
"EMCode": "401019"
},
{
"QSid": "🏠",
"QCid": "127968",
"AQLid": "156",
"QDes": "/家",
"EMCode": "400271"
},
{
"QSid": "⛪",
"QCid": "9962",
"AQLid": "157",
"QDes": "/教堂",
"EMCode": "401281"
},
{
"QSid": "🏦",
"QCid": "127974",
"AQLid": "158",
"QDes": "/银行",
"EMCode": "400277"
},
{
"QSid": "🏥",
"QCid": "127973",
"AQLid": "159",
"QDes": "/医院",
"EMCode": "400276"
},
{
"QSid": "🏨",
"QCid": "127976",
"AQLid": "160",
"QDes": "/酒店",
"EMCode": "400279"
},
{
"QSid": "🏧",
"QCid": "127975",
"AQLid": "161",
"QDes": "/取款机",
"EMCode": "400278"
},
{
"QSid": "🏪",
"QCid": "127978",
"AQLid": "162",
"QDes": "/便利店",
"EMCode": "400281"
},
{
"QSid": "🚹",
"QCid": "128697",
"AQLid": "163",
"QDes": "/男性",
"EMCode": "401015"
},
{
"QSid": "🚺",
"QCid": "128698",
"AQLid": "164",
"QDes": "/女性",
"EMCode": "401016"
}
]
}
================================================
FILE: icon.py
================================================
qq_icon_png = b'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'
github_mark = b'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'
================================================
FILE: install.ps1
================================================
pyinstaller -i icon.ico -w -F ./GUI.py
sleep 5
================================================
FILE: proto/RichMsg.proto
================================================
syntax = "proto3";
message ForwardExtra {
int32 forward_orgId = 1;
string forward_orgUin = 2;
int32 forward_orgUinType = 3;
string forward_orgUrl = 4;
string forward_thumbPath = 5;
int32 forward_orgFileSizeType = 6;
}
message PicRec {
string localPath = 1;
int32 size = 2;
int32 type = 3;
bool isRead = 4;
string uuid = 5;
string md5 = 6;
string serverStorageSource = 7;
string thumbMsgUrl = 8;
string bigMsgUrl = 9;
string rawMsgUrl = 10;
int32 fileSizeFlag = 11;
int32 uiOperatorFlag = 12;
ForwardExtra forwardInfo = 13;
int32 version = 14;
int32 isReport = 15;
uint64 groupFileID = 16;
string localUUID = 17;
int32 preDownState = 18;
int32 preDownNetwork = 19;
int32 previewed = 20;
uint32 uint32_thumb_width = 21;
uint32 uint32_thumb_height = 22;
uint32 uint32_width = 23;
uint32 uint32_height = 24;
uint32 uint32_image_type = 25;
uint32 uint32_show_len = 26;
uint32 uint32_download_len = 27;
uint32 uint32_current_len = 28;
uint32 notPreDownloadReason = 29;
bool enableEnc = 30;
string bigThumbMsgUrl = 31;
bytes bytes_pb_reserved = 32;
bool bool_story_pic_send_to_recent = 33;
}
message MarketFaceRec {
}
message Msg {
repeated Elem elems = 1;
}
message Elem {
bytes textMsg = 1;
bytes picMsg = 2;
MarketFaceRec markfaceMsg = 3;
string sourceMsgInfo = 4;
}
message SafeMoreInfo {
string strMsgTxt = 1;
string strFromMobile = 2;
string strFromName = 3;
}
message Test {
string str = 16;
}
message PttRec {
string localPath = 1;
uint64 size = 2;
uint32 type = 3;
bool isRead = 4;
string uuid = 5;
string md5 = 6;
string serverStorageSource = 7;
int32 version = 8;
int32 isReport = 9;
int32 pttFlag = 10;
uint64 groupFileID = 11;
string sttText = 12;
int32 longPttVipFlag = 13;
bool expandStt = 14;
string group_file_key = 15;
uint64 msgRecTime = 16;
uint64 msgTime = 17;
uint32 voiceType = 18;
uint32 voiceLength = 19;
uint32 voiceChangeFlag = 20;
string directUrl = 21;
uint32 busiType = 22;
string fullLocalPath = 23;
uint64 extFlag = 24;
uint32 redpack_type = 25;
uint32 autototext_voice = 26;
}
================================================
FILE: proto/RichMsg_pb2.py
================================================
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: RichMsg.proto
"""Generated protocol buffer code."""
from google.protobuf.internal import builder as _builder
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
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\rRichMsg.proto\"\xad\x01\n\x0c\x46orwardExtra\x12\x15\n\rforward_orgId\x18\x01 \x01(\x05\x12\x16\n\x0e\x66orward_orgUin\x18\x02 \x01(\t\x12\x1a\n\x12\x66orward_orgUinType\x18\x03 \x01(\x05\x12\x16\n\x0e\x66orward_orgUrl\x18\x04 \x01(\t\x12\x19\n\x11\x66orward_thumbPath\x18\x05 \x01(\t\x12\x1f\n\x17\x66orward_orgFileSizeType\x18\x06 \x01(\x05\"\xf6\x05\n\x06PicRec\x12\x11\n\tlocalPath\x18\x01 \x01(\t\x12\x0c\n\x04size\x18\x02 \x01(\x05\x12\x0c\n\x04type\x18\x03 \x01(\x05\x12\x0e\n\x06isRead\x18\x04 \x01(\x08\x12\x0c\n\x04uuid\x18\x05 \x01(\t\x12\x0b\n\x03md5\x18\x06 \x01(\t\x12\x1b\n\x13serverStorageSource\x18\x07 \x01(\t\x12\x13\n\x0bthumbMsgUrl\x18\x08 \x01(\t\x12\x11\n\tbigMsgUrl\x18\t \x01(\t\x12\x11\n\trawMsgUrl\x18\n \x01(\t\x12\x14\n\x0c\x66ileSizeFlag\x18\x0b \x01(\x05\x12\x16\n\x0euiOperatorFlag\x18\x0c \x01(\x05\x12\"\n\x0b\x66orwardInfo\x18\r \x01(\x0b\x32\r.ForwardExtra\x12\x0f\n\x07version\x18\x0e \x01(\x05\x12\x10\n\x08isReport\x18\x0f \x01(\x05\x12\x13\n\x0bgroupFileID\x18\x10 \x01(\x04\x12\x11\n\tlocalUUID\x18\x11 \x01(\t\x12\x14\n\x0cpreDownState\x18\x12 \x01(\x05\x12\x16\n\x0epreDownNetwork\x18\x13 \x01(\x05\x12\x11\n\tpreviewed\x18\x14 \x01(\x05\x12\x1a\n\x12uint32_thumb_width\x18\x15 \x01(\r\x12\x1b\n\x13uint32_thumb_height\x18\x16 \x01(\r\x12\x14\n\x0cuint32_width\x18\x17 \x01(\r\x12\x15\n\ruint32_height\x18\x18 \x01(\r\x12\x19\n\x11uint32_image_type\x18\x19 \x01(\r\x12\x17\n\x0fuint32_show_len\x18\x1a \x01(\r\x12\x1b\n\x13uint32_download_len\x18\x1b \x01(\r\x12\x1a\n\x12uint32_current_len\x18\x1c \x01(\r\x12\x1c\n\x14notPreDownloadReason\x18\x1d \x01(\r\x12\x11\n\tenableEnc\x18\x1e \x01(\x08\x12\x16\n\x0e\x62igThumbMsgUrl\x18\x1f \x01(\t\x12\x19\n\x11\x62ytes_pb_reserved\x18 \x01(\x0c\x12%\n\x1d\x62ool_story_pic_send_to_recent\x18! \x01(\x08\"\x0f\n\rMarketFaceRec\"\x1b\n\x03Msg\x12\x14\n\x05\x65lems\x18\x01 \x03(\x0b\x32\x05.Elem\"c\n\x04\x45lem\x12\x0f\n\x07textMsg\x18\x01 \x01(\x0c\x12\x0e\n\x06picMsg\x18\x02 \x01(\x0c\x12#\n\x0bmarkfaceMsg\x18\x03 \x01(\x0b\x32\x0e.MarketFaceRec\x12\x15\n\rsourceMsgInfo\x18\x04 \x01(\t\"M\n\x0cSafeMoreInfo\x12\x11\n\tstrMsgTxt\x18\x01 \x01(\t\x12\x15\n\rstrFromMobile\x18\x02 \x01(\t\x12\x13\n\x0bstrFromName\x18\x03 \x01(\t\"\x13\n\x04Test\x12\x0b\n\x03str\x18\x10 \x01(\t\"\xff\x03\n\x06PttRec\x12\x11\n\tlocalPath\x18\x01 \x01(\t\x12\x0c\n\x04size\x18\x02 \x01(\x04\x12\x0c\n\x04type\x18\x03 \x01(\r\x12\x0e\n\x06isRead\x18\x04 \x01(\x08\x12\x0c\n\x04uuid\x18\x05 \x01(\t\x12\x0b\n\x03md5\x18\x06 \x01(\t\x12\x1b\n\x13serverStorageSource\x18\x07 \x01(\t\x12\x0f\n\x07version\x18\x08 \x01(\x05\x12\x10\n\x08isReport\x18\t \x01(\x05\x12\x0f\n\x07pttFlag\x18\n \x01(\x05\x12\x13\n\x0bgroupFileID\x18\x0b \x01(\x04\x12\x0f\n\x07sttText\x18\x0c \x01(\t\x12\x16\n\x0elongPttVipFlag\x18\r \x01(\x05\x12\x11\n\texpandStt\x18\x0e \x01(\x08\x12\x16\n\x0egroup_file_key\x18\x0f \x01(\t\x12\x12\n\nmsgRecTime\x18\x10 \x01(\x04\x12\x0f\n\x07msgTime\x18\x11 \x01(\x04\x12\x11\n\tvoiceType\x18\x12 \x01(\r\x12\x13\n\x0bvoiceLength\x18\x13 \x01(\r\x12\x17\n\x0fvoiceChangeFlag\x18\x14 \x01(\r\x12\x11\n\tdirectUrl\x18\x15 \x01(\t\x12\x10\n\x08\x62usiType\x18\x16 \x01(\r\x12\x15\n\rfullLocalPath\x18\x17 \x01(\t\x12\x0f\n\x07\x65xtFlag\x18\x18 \x01(\x04\x12\x14\n\x0credpack_type\x18\x19 \x01(\r\x12\x18\n\x10\x61utototext_voice\x18\x1a \x01(\rb\x06proto3')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'RichMsg_pb2', globals())
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
_FORWARDEXTRA._serialized_start=18
_FORWARDEXTRA._serialized_end=191
_PICREC._serialized_start=194
_PICREC._serialized_end=952
_MARKETFACEREC._serialized_start=954
_MARKETFACEREC._serialized_end=969
_MSG._serialized_start=971
_MSG._serialized_end=998
_ELEM._serialized_start=1000
_ELEM._serialized_end=1099
_SAFEMOREINFO._serialized_start=1101
_SAFEMOREINFO._serialized_end=1178
_TEST._serialized_start=1180
_TEST._serialized_end=1199
_PTTREC._serialized_start=1202
_PTTREC._serialized_end=1713
# @@protoc_insertion_point(module_scope)
================================================
FILE: proto/__init__.py
================================================
# coding=utf-8
================================================
FILE: proto/compile
================================================
protoc RichMsg.proto --python_out=.
================================================
FILE: requirements.txt
================================================
tk
protobuf
av
pilk
gitextract_56qtarj0/ ├── .gitignore ├── GUI.py ├── GUI.spec ├── LICENSE ├── QQ_History.py ├── README.md ├── emoticon/ │ └── face_config.json ├── icon.py ├── install.ps1 ├── proto/ │ ├── RichMsg.proto │ ├── RichMsg_pb2.py │ ├── __init__.py │ └── compile └── requirements.txt
SYMBOL INDEX (35 symbols across 2 files)
FILE: GUI.py
class GUI_CONST (line 13) | class GUI_CONST:
function Enter (line 17) | def Enter():
function SelectDBPath (line 46) | def SelectDBPath():
function SelectImgPath (line 51) | def SelectImgPath():
function url (line 56) | def url():
FILE: QQ_History.py
function crc64 (line 20) | def crc64(s):
function tempFilename (line 38) | def tempFilename() -> str:
function isEmpty (line 44) | def isEmpty(s):
class QQoutput (line 54) | class QQoutput():
method __init__ (line 55) | def __init__(self, base_path: str, qq_self: str, emoji: int = 1, with_...
method getDisplayName (line 91) | def getDisplayName(friend: list) -> str:
method getSafePath (line 99) | def getSafePath(ans: str) -> str:
method detect_TIM (line 113) | def detect_TIM(self):
method mydecrypt (line 123) | def mydecrypt(self, data):
method fix (line 130) | def fix(self, data, mode):
method decrypt (line 167) | def decrypt(self, data, msg_type=-1000):
method add_emoji (line 207) | def add_emoji(self, msg):
method message (line 236) | def message(self, qq: str, mode: int):
method get_friends (line 269) | def get_friends(self):
method get_troop_members (line 272) | def get_troop_members(self, qq: str):
method _fill_cursors (line 304) | def _fill_cursors(self, cmd):
method fill_cursor (line 317) | def fill_cursor(self, cmd):
method output (line 325) | def output(self, qq: str, mode: int, output_path: str = "."):
method init_key (line 383) | def init_key(self):
method init_paths (line 388) | def init_paths(self):
method init_friend_list (line 412) | def init_friend_list(self):
method init_troop_list (line 426) | def init_troop_list(self):
method map_new_emoji (line 445) | def map_new_emoji(self):
method get_base64_from_pic (line 459) | def get_base64_from_pic(self, path):
method decode_pic (line 463) | def decode_pic(self, data):
method decode_mix_msg (line 488) | def decode_mix_msg(self, data):
method decode_silk (line 503) | def decode_silk(self, data):
method decode_share_url (line 562) | def decode_share_url(self, msg):
function main (line 567) | def main(base_path, qq_self, qq, mode, emoji, with_img, combine_img, dum...
function run_directly (line 620) | def run_directly():
Condensed preview — 14 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (157K chars).
[
{
"path": ".gitignore",
"chars": 172,
"preview": "*.txt\n!requirements.txt\n*.db\n*.html\n*.db-shm\n*.db-wal\n*.zip\n*.exe\n*.spec\n!GUI.spec\nbuild/\ndist/\n__pycache__/\nqq/\nQQ*/\nco"
},
{
"path": "GUI.py",
"chars": 3895,
"preview": "import tkinter as tk\nfrom tkinter import filedialog\nimport tkinter.ttk as ttk\nfrom icon import qq_icon_png, github_mark\n"
},
{
"path": "GUI.spec",
"chars": 830,
"preview": "# -*- mode: python ; coding: utf-8 -*-\n\n\nblock_cipher = None\n\n\na = Analysis(\n ['GUI.py'],\n pathex=[],\n binaries"
},
{
"path": "LICENSE",
"chars": 1067,
"preview": "MIT License\n\nCopyright (c) 2023 Young-Lord\n\nPermission is hereby granted, free of charge, to any person obtaining a copy"
},
{
"path": "QQ_History.py",
"chars": 23557,
"preview": "import hashlib\nimport sqlite3\nimport time\nimport os\nimport traceback\nimport json\nimport base64\nfrom proto.RichMsg_pb2 im"
},
{
"path": "README.md",
"chars": 4788,
"preview": "# QQ聊天记录导出\n\n本项目用于将 **非 QQNT** 的 Android 端 QQ/TIM 的聊天记录数据库转换为 HTML 文件,并转换图片、语音等部分特殊消息。 \n\n## 关于其他平台(Windows, MacOS, iOS…)\n"
},
{
"path": "emoticon/face_config.json",
"chars": 48058,
"preview": "{\n \"sysface\": [\n {\n \"QSid\": \"14\",\n \"QDes\": \"/微笑\",\n \"IQLid\": \"23\",\n \"AQLid\": \"23\",\n \"EMCode\""
},
{
"path": "icon.py",
"chars": 47372,
"preview": "qq_icon_png = b'iVBORw0KGgoAAAANSUhEUgAAAPIAAAEgEAYAAADeefJ3AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAA"
},
{
"path": "install.ps1",
"chars": 46,
"preview": "pyinstaller -i icon.ico -w -F ./GUI.py\nsleep 5"
},
{
"path": "proto/RichMsg.proto",
"chars": 2159,
"preview": "syntax = \"proto3\";\n\nmessage ForwardExtra {\n int32 forward_orgId = 1;\n string forward_orgUin = 2;\n int32 forward_orgUi"
},
{
"path": "proto/RichMsg_pb2.py",
"chars": 4650,
"preview": "# -*- coding: utf-8 -*-\n# Generated by the protocol buffer compiler. DO NOT EDIT!\n# source: RichMsg.proto\n\"\"\"Generated "
},
{
"path": "proto/__init__.py",
"chars": 15,
"preview": "# coding=utf-8\n"
},
{
"path": "proto/compile",
"chars": 35,
"preview": "protoc RichMsg.proto --python_out=."
},
{
"path": "requirements.txt",
"chars": 19,
"preview": "tk\nprotobuf\nav\npilk"
}
]
About this extraction
This page contains the full source code of the QQBackup/QQ-History-Backup GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 14 files (133.5 KB), approximately 64.6k tokens, and a symbol index with 35 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.