-- use database fortern
create schema qqnt;
comment on schema qqnt is 'Fortern的QQNT聊天记录';

-- QQNT 原始的 group_msg_table 表结构
-- 为了快速导入数据而创建的临时表，无需索引
create table qqnt.group_msg_tmp
(
    "40001" bigint primary key,
    "40002" bigint,
    "40003" integer,
    "40010" integer,
    "40011" integer,
    "40012" integer,
    "40013" integer,
    "40020" text,
    "40026" integer,
    "40021" text,
    "40027" bigint,
    "40040" integer,
    "40041" integer,
    "40050" integer,
    "40052" integer,
    "40090" text,
    "40093" text,
    "40800" BYTEA,
    "40900" BYTEA,
    "40105" integer,
    "40005" integer,
    "40058" integer,
    "40006" bigint,
    "40100" integer,
    "40600" BYTEA,
    "40060" integer,
    "40850" bigint,
    "40851" integer,
    "40601" BYTEA,
    "40801" BYTEA,
    "40605" BYTEA,
    "40030" bigint,
    "40033" bigint,
    "40062" BYTEA,
    "40083" integer,
    "40084" integer
);


-- 处理后可读的 group_msg_table 表
-- https://docs.aaqwq.top/view/db_file_analysis/nt_msg.db.html
create table qqnt.group_msg_table
(
    -- 40001 消息ID，具有唯一性
    id                 bigint       not null
        primary key,
    -- 40002 消息随机值，用于对消息去重
    msg_random         bigint       not null,
    -- 40003 群聊消息ID，在每个聊天中依次递增
    msg_seq            integer      not null,
    -- 40010 聊天类型，私聊为1，群聊为2，频道为4，公众号为103，企业客服为102，临时会话为100
    chat_type          integer      not null,
    -- 40011 消息类型，详见下表
    msg_type           integer      not null,
    -- 40012 pb消息类型，详见下表
    sub_msg_type       integer      not null,
    -- 40013 发送标志，本机发送的消息为1，其他客户端发送的为2，别人发的消息为0 ，转发消息为5，在已退出或被封禁的消息中为当日整点时间戳
    send_type          integer      not null,
    -- 40020 nt_uid, 对应 nt_uid_mapping_table
    sender_uid         varchar(200) not null,
    -- 40026 未知
    q40026             integer,
    -- 40021 会话ID
    peer_uid           varchar(200) not null,
    -- 40027 会话ID，通常是群号
    peer_uin           bigint       not null,
    -- 40040 未知
    q40040             integer,
    -- 40041 发送状态，2为成功，0为发送被阻止（如不是对方好友），1为尚未发送成功（比如网络问题），3为消息被和谐
    send_status        integer      not null,
    -- 40050 发送消息时的时间戳(精确到秒)
    msg_time           integer      not null,
    -- 40052 未知
    q40052             integer,
    -- 40090 发送者群名片，旧版 QQ 迁移数据中格式为 name(12345) 或 name<i@example.com>， QQNT 中为群名片
    send_member_name   varchar(200),
    -- 40093 发送者昵称，旧版 QQ 此字段为空，QQNT 中未设置群名片时才有此字段
    send_nick_name     varchar(200) not null,
    -- 40800 聊天消息，最为复杂
    msg_content        bytea,
    -- 40900 不同情况下存在不一样的数据（以列40011为区分）。 值为8时，列40900存贮转发聊天的缓存；值为9时，列40900存贮引用的消息
    msg_quote          bytea,
    -- 40105 未知
    q40105             integer,
    -- 40005 只知道自己发的消息一定概率存在数值，正常情况为0
    q40005             integer,
    -- 40058 当日 0 时整的时间戳格式，精确到秒，时区为 UTC+08:00
    midnight_timestamp integer      not null,
    -- 40006 未知
    elem_id            bigint       not null,
    -- 40100 @状态
    at_status          integer,
    -- 40600 十六进制。值为 14 00 时，为回复消息，为 6 代表有人回复自己，为2代表他人回复他人，值为c2e91304a8d114****时（不唯一），为撤回消息
    msg_status         bytea,
    -- 40060 已退出或已解散的群聊标志
    disband_flag       integer,
    -- 40850 该消息所回复的消息的序号，默认为 0
    reply_to           bigint,
    -- 40851 未知，默认为 0 或 NULL
    q40851             integer,
    -- 40601 未知，默认为 NULL
    q40601             bytea,
    -- 40801 未知，默认为 NULL
    q40801             bytea,
    -- 40605 未知，默认为 NULL
    q40605             bytea,
    -- 40030 群号
    group_no           bigint       not null,
    -- 40033 消息发送者QQ号
    qq_no              bigint       not null,
    -- 40062 存贮详细表态信息（包括表态表情和表态数量），其数字与 QQBOT 中表情编号对应（超级表情不在此列表中）
    emoji              bytea,
    -- 40083 表态表情数量总和？
    emoji_num          integer,
    -- 40084 表态表情数量总和？
    emoji_num_2        integer
);
-- 发送者QQ号索引
create index qq_no_index on qqnt.group_msg_table (qq_no);
-- 群号与QQ号联合索引
create index group_no_index on qqnt.group_msg_table (peer_uin, qq_no);
-- 时间索引
create index group_msg_time_index on qqnt.group_msg_table (msg_time);
-- 群号与时间的索引
create index group_no_msg_time_index on qqnt.group_msg_table (peer_uin, msg_time);
-- 消息类型联合索引
create index group_msg_type_index on qqnt.group_msg_table (peer_uin, msg_type, sub_msg_type);
-- 40011 msg_type 消息类型
-- 无消息（消息损坏？多见于已退出群聊且时间久远）：0
-- 消息空白（msgid存在，应该是没加载出来）：1
-- text文本消息：2
-- 群文件：3
-- 我的聊天记录里没有4~大佬带带＞︿＜
-- 系统（灰字）消息：5
-- 语音消息：6
-- 视频文件：7
-- 合并转发消息：8
-- 回复类型消息：9
-- 红包：10
-- 应用消息：11

-- 40012 sub_msg_type 区分pb消息类型
-- 非常规text消息：0
-- 普通文本消息：1
-- 群文件其他类型消息：1
-- 图片消息：2
-- 群文件图片消息：2
-- 群公告：3
-- 群文件视频消息：4
-- 撤回消息提醒：4
-- 群文件音频消息：8
-- 原创表情包：8
-- 射精消息：11
-- 拍一拍消息：12
-- 群文件docx消息：16
-- 平台文本消息：32
-- 群文件pptx消息：32
-- 回复类型消息：33
-- 群文件xlsx消息：64
-- 存在链接：161
-- 群文件zip消息：512
-- 群文件exe消息：2048
-- 表情消息：4096

-- msg_type(40011) 与 sub_msg_type(40012) 组合可判断消息类型
-- 由于优先级问题（特别是2类别的信息），部分消息不满足以下规则
-- 空消息：0，0
-- 已撤回消息：1，0
-- 普通文本类消息：2，1
-- 图片消息：2，2
-- 只带图片的纯文本消息：2，3
-- 纯表情消息：2，16
-- 带表情的纯文本消息：2，17
-- 带图片带表情的纯文本消息：2，19
-- 纯链接消息：2，129
-- 带表情链接消息：2，145
-- 机器人消息：2，577
-- 机器人Markdown消息：2，65
-- @消息：2，35
-- 回复引用消息（不带表情）：2，33
-- 回复引用消息（带表情）：2，49
-- 收藏表情：2，2
-- 收藏表情包：2，4096
-- 群文件其他类型消息：3，1
-- 群文件图片（png，jpg）消息：3，2
-- 群文件视频消息：3，4
-- 群文件音频（mp3，flac）消息：3，8
-- 群文件docx消息：3，16
-- 群文件pptx消息：3，32
-- 群文件xlsx消息：3，64
-- 群文件zip消息：3，512
-- 群文件exe消息：3，2048
-- 拍一拍消息：5，12
-- 撤回消息提醒：5，4
-- amr语音文件消息：6，0
-- 视频文件消息：7，0
-- 合并转发消息：8，0
-- 回复消息：9，33
-- 回复带图片消息（无@）：9，34
-- 回复带图片消息（有@）：9，35
-- 回复带图片带@：9，35
-- 回复卡片引用消息：9，49
-- 带表情回复：9，49
-- 带表情带图片带@：9，51
-- 回复存在链接的消息：9，161
-- 红包：10，0
-- 应用消息（如小程序）：11，0
-- 群公告：11，3
-- 表情包：17，8
-- 原创表情：17，8

-- QQNT 原始的 c2c_msg_table 表结构
-- 为了快速导入数据而创建的临时表，无需索引
create table qqnt.c2c_msg_tmp (
    "40001" bigint primary key,
    "40002" bigint,
    "40003" integer,
    "40010" integer,
    "40011" integer,
    "40012" integer,
    "40013" integer,
    "40020" text,
    "40026" integer,
    "40021" text,
    "40027" integer,
    "40040" integer,
    "40041" integer,
    "40050" integer,
    "40052" integer,
    "40090" text,
    "40093" text,
    "40800" bytea,
    "40900" bytea,
    "40105" integer,
    "40005" integer,
    "40058" integer,
    "40006" bigint,
    "40100" integer,
    "40600" bytea,
    "40060" integer,
    "40850" integer,
    "40851" integer,
    "40601" bytea,
    "40801" bytea,
    "40605" bytea,
    "40030" bigint,
    "40033" bigint,
    "40062" bytea,
    "40083" integer,
    "40084" integer
);

-- 私聊消息 c2c_msg_table
create table qqnt.c2c_msg_table
(
    -- 40001 消息ID，具有唯一性
    id                 bigint       not null
        primary key,
    -- 40002 消息随机值，用于对消息去重
    msg_random         bigint       not null,
    -- 40003 位置
    q40003             integer      not null,
    -- 40010 聊天类型，私聊为1，群聊为2，频道为4，公众号为103，企业客服为102，临时会话为100
    chat_type          integer      not null,
    -- 40011 消息类型，详见上表
    msg_type           integer      not null,
    -- 40012 pb消息类型，详见上表
    sub_msg_type       integer      not null,
    -- 40013 发送标志，可能？
    send_type          integer      not null,
    -- 40020 未知
    q40020             varchar(200) not null,
    -- 40026 未知
    q40026             integer      not null,
    -- 40021 未知
    q40021             varchar(200) not null,
    -- 40027 未知
    q40027             integer      not null,
    -- 40040 未知
    q40040             integer      not null,
    -- 40041 未知
    q40041             integer      not null,
    -- 40050 发送消息时的时间戳(精确到秒)
    msg_time           integer      not null,
    -- 40052 未知
    q40052             integer      not null,
    -- 40090 未知
    q40090             text,
    -- 40093 消息发送者的 QQ 昵称或是备注名
    q40093             varchar(200) not null,
    -- 40080 消息内容
    q40800             bytea,
    -- 40900 未知
    q40900             bytea,
    -- 40105 未知
    q40105             integer      not null,
    -- 40005 未知
    q40005             integer      not null,
    -- 40058 当日 0 时整的时间戳格式，精确到秒，时区为 UTC+08:00
    midnight_timestamp integer      not null,
    -- 40006 未知
    q40006             bigint       not null,
    -- 40010 未知
    q40100             integer      not null,
    -- 40600 未知
    q40600             bytea,
    -- 40060 未知
    q40060             integer      not null,
    -- 40850 未知
    q40850             integer      not null,
    -- 40851 未知
    q40851             integer      not null,
    -- 40601 未知
    q40601             bytea,
    -- 40801 未知
    q40801             bytea,
    -- 40605 未知
    q40605             bytea,
    -- 40030 对方 QQ 号（无论是对方还是自己发送的消息）
    peer_qq_no         bigint       not null,
    -- 40033 发送者的 QQ 号
    sender_qq_no       bigint       not null,
    -- 40062 未知
    q40062             bytea,
    -- 40083 未知
    q40083             integer      not null,
    -- 40084 未知
    q40084             integer      not null
);
-- 时间索引
create index c2c_msg_time_index on qqnt.c2c_msg_table (msg_time);
-- 私聊者 QQ 号与时间的索引
create index qq_no_msg_time_index on qqnt.c2c_msg_table (peer_qq_no, msg_time);

create table qqnt.group_msg_fts
(
    -- 主键id
    id         bigint primary key,
    -- 消息内容
    msg_text   text,
    -- 文件名
    file_name  varchar(250),
    -- 41703 未知
    q41703     varchar(50),
    -- 41704 未知
    q41704     varchar(50),
    -- 41705 未知
    q41705     varchar(50),
    -- 41706 未知
    q41706     varchar(50),
    -- 41707 未知
    q41707     varchar(50),
    -- 41701 group_msg_table的id的外键
    msg_id     bigint unique,
    -- 40050 发送消息时的时间戳(精确到秒)
    msg_time   integer      not null,
    -- 40003 群聊消息ID，在每个聊天中依次递增
    msg_seq    integer      not null,
    -- 40010 聊天类型，私聊为1，群聊为2，频道为4，公众号为103，企业客服为102，临时会话为100
    chat_type  integer      not null,
    -- 40021 会话ID
    peer_uid   varchar(200) not null,
    -- 40027 会话ID
    peer_uin   bigint       not null,
    -- 40020 nt_uid, 对应 nt_uid_mapping_table
    sender_uid varchar(200) not null
);
-- 时间索引
create index msg_time_index on qqnt.group_msg_fts (msg_time);
-- 群号与时间的索引
create index group_msg_time_index on qqnt.group_msg_fts (peer_uin, msg_time);
