Full Code of QQBackup/QQ-History-Backup for AI

master edc6653a7043 cached
14 files
133.5 KB
64.6k tokens
35 symbols
1 requests
Download .txt
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使用方法

![GUI_image](./img/GUI.png)

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

## 输出截图

![screenshot](./img/layout.png)
![screenshot](./img/images.png)

如果没有启用合并图片,拷贝生成的聊天记录时需要一起拷贝 `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
Download .txt
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
Download .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.

Copied to clipboard!