Skip to content
This repository has been archived by the owner on Nov 2, 2023. It is now read-only.

Commit

Permalink
Merge pull request #27 from takayama-lily/dev
Browse files Browse the repository at this point in the history
-
  • Loading branch information
takayama-lily authored Sep 9, 2020
2 parents d0db522 + e8e4e51 commit 6d813aa
Show file tree
Hide file tree
Showing 6 changed files with 282 additions and 194 deletions.
6 changes: 4 additions & 2 deletions client.js
Original file line number Diff line number Diff line change
Expand Up @@ -661,8 +661,9 @@ class AndroidClient extends Client {
return buildApiRet(100);
try {
try {
var packet = await outgoing.buildPrivateMessageRequestPacket(user_id, message, auto_escape, this);
var packet = await outgoing.commonMessage(user_id, message, auto_escape, false, false, this);
} catch (e) {
this.logger.debug(e);
return buildApiRet(100);
}
let message_id = this.curr_msg_id;
Expand Down Expand Up @@ -695,8 +696,9 @@ class AndroidClient extends Client {
return buildApiRet(100);
try {
try {
var packet = await outgoing.buildSendGroupMessageRequestPacket(group_id, message, auto_escape, as_long, this);
var packet = await outgoing.commonMessage(group_id, message, auto_escape, true, as_long, this);
} catch (e) {
this.logger.debug(e);
return buildApiRet(100);
}

Expand Down
26 changes: 6 additions & 20 deletions docs/project.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@

----

|[消息]|文字和表情|长消息|图片|语音|合并转发|其他富文本|
|[消息]|文字和表情|长消息|图片|语音|合并转发|xml/json|
|-|-|-|-|-|-|-|
|好友|||||||
|群聊|||||||
|临时会话|||||||
|好友|||||||
|群聊|||||||
|临时会话|||||||

----

Expand Down Expand Up @@ -59,21 +59,7 @@
|file|||群文件,[CQ:file,url=xxxxxx,size=123456,md5=xxxxxx,duration=0,name=xxxxxx]|
|music|||
|video|||
|location|||
|location|||[CQ:location,address=江西省九江市修水县,lat=29.063940,lng=114.339610]|
|reply|||
|share|||

----

## 不会支持的功能

* 点赞
* 抢红包等金钱相关
* 搜索添加群、搜索添加好友
* 自定义(伪造)消息转发
* 自定义卡片消息

## 考虑支持的功能

* 添加群员为好友
* 邀请好友入群
|node|||[CQ:node,uin=123456789,name=昵称,content=消息内容,time=时间戳]<br>time可省略,暂时只支持纯文本|
142 changes: 114 additions & 28 deletions lib/message.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ function s__s(s) {
function parseMessage(elems) {
const chain = [];
let raw_message = "";
let bface_tmp = null;
let bface_tmp = null, light_app = false;
for (let v of elems) {
const type = Object.keys(v)[0];
const msg = {type:"",data:{}};
Expand All @@ -62,12 +62,20 @@ function parseMessage(elems) {
// console.log(a.toString());
break;
case "lightApp":
const data = JSON.parse(zlib.unzipSync(o.data.slice(1)).toString());
if (data.app === "com.tencent.map") {
msg.type = "location";
msg.data = data.meta["Location.Search"];
delete msg.data.from;
light_app = true;
}
break;
case "transElemInfo":
msg.type = "file";
msg.data = pb.decode("ObjMsg", o.elemValue.slice(3)).msgContentInfo[0].msgFile;
break;
case "text":
if (light_app) break;
if (bface_tmp && o.str && o.str.startsWith("[")) {
msg.data.file = bface_tmp, msg.type = "bface";
msg.data.text = o.str.replace("[","").replace("]","").trim();
Expand Down Expand Up @@ -139,7 +147,7 @@ function parseImage(o) {
if (o.origUrl)
data.url = "http://c2cpicdw.qpic.cn" + o.origUrl;
} else {
data.file = o.md5.toString("hex") + o.size;
data.file = o.md5.toString("hex");
if (o.size)
data.file += o.size;
if (o.origUrl)
Expand All @@ -151,6 +159,7 @@ function parseImage(o) {
//----------------------------------------------------------------------------------------------------

const AT_BUF = Buffer.from([0,1,0,0,0]);
const BUF1 = Buffer.from([1]);
const BUF2 = Buffer.alloc(2);
const BUF4 = Buffer.alloc(4);
const FACE_OLD_BUF = Buffer.from([0x00, 0x01, 0x00, 0x04, 0x52, 0xCC, 0xF5, 0xD0]);
Expand Down Expand Up @@ -303,10 +312,9 @@ async function buildImageMessage(chain, cq, is_group, is_flash = false) {
return false;
}
}
chain[0] = [], chain[0].push({
buf, md5, size, index: 0, type: "flash"
});
return true;
return {
buf, md5, size
};
}

let elem, index = chain.length - 1;
Expand Down Expand Up @@ -449,12 +457,53 @@ async function buildRecordMessage(chain, data, is_group) {
return false;
}
md5 = common.md5(buf), size = buf.length;
chain[0].unshift({
buf, md5, size, ext, type: "ptt"
return {
buf, md5, size, ext
};
}

function buildForwardNode(chain, data) {
let {name, uin, content, time} = data;
uin = parseInt(uin);
if (!common.checkUin(uin) || !content) return false;
content = content.toString();
time = time ? parseInt(time) : common.timestamp();
name = name ? name : "无名氏";
chain.push({
uin, content, time, name
});
return true;
}

function buildLocationNode(chain, data) {
let {address, lat, lng, name, id} = data;
if (!address || !lat || !lng) return;
name = name ? name : "位置分享";
let build = {
config: { forward: true, type: 'card', autosize: true },
prompt: '[应用]地图',
from: 1,
app: 'com.tencent.map',
ver: '1.0.3.5',
view: 'LocationShare',
meta: {
'Location.Search': {
from: 'plusPanel',
id: id?id:"",
lat, lng, name, address
}
},
desc: '地图'
};
build = Buffer.concat([BUF1, zlib.deflateSync(JSON.stringify(build))]);
chain.push({
lightApp: {data: build}
});
chain.push({
text: {str: "收到[[应用]地图]消息,请升级QQ版本查看"}
});
}

/**
* @async
* @param {Array} chain
Expand All @@ -469,6 +518,7 @@ async function buildRecordMessage(chain, data, is_group) {
* @param {Promise[]} tasks
*/
async function buildMessageFromString(chain, message, escape, is_group, stat, tasks) {
let elem;
if (escape) {
stat.length += buildTextMessage(chain, message);
return;
Expand All @@ -478,23 +528,25 @@ async function buildMessageFromString(chain, message, escape, is_group, stat, ta
for (let v of res) {
const text = message.slice(prev_index, v.index).replace(/&#91;|&#93;|&amp;/g, _ss_);
if (text)
stat.length += buildTextMessage(chain, text);
await buildElement(chain, "text", {text}, is_group, stat, tasks)

const elem = v[0];
let cq = elem.replace("[CQ:", "cqtype=");
const element = v[0];
let cq = element.replace("[CQ:", "cqtype=");
cq = cq.substr(0, cq.length - 1);
cq = querystring.parse(cq, ",");
for (let k of Object.keys(cq))
cq[k] = cq[k].replace(/&#44;|&#91;|&#93;|&amp;/g, s__s);

await buildElement(chain, cq.cqtype.trim(), cq, is_group, stat, tasks)
if (stat.has_ptt || stat.has_flash)
break;
elem = await buildElement(chain, cq.cqtype.trim(), cq, is_group, stat, tasks)
if (stat.is_ptt || stat.is_flash)
return elem;

prev_index = v.index + elem.length;
prev_index = v.index + element.length;
}
if (prev_index < message.length) {
const text = message.slice(prev_index).replace(/&#91;|&#93;|&amp;/g, _ss_);
await buildElement(chain, "text", {text}, is_group, stat, tasks)
}
if (prev_index < message.length)
stat.length += buildTextMessage(chain, message.slice(prev_index).replace(/&#91;|&#93;|&amp;/g, _ss_));
}

/**
Expand All @@ -507,21 +559,38 @@ async function buildMessageFromString(chain, message, escape, is_group, stat, ta
async function buildMessage(message, escape, is_group) {
const chain = [[]], tasks = [];
const stat = {
length: 0, at_cnt: 0, face_cnt: 0, bface_cnt: 0, img_cnt: 0, has_ptt: false, has_flash: false
length: 0, at_cnt: 0, face_cnt: 0, bface_cnt: 0, img_cnt: 0,
is_ptt: false, is_flash: false, is_forward: false
};
let elem;
if (typeof message === "string")
await buildMessageFromString(chain, message, escape, is_group, stat, tasks);
elem = await buildMessageFromString(chain, message, escape, is_group, stat, tasks);
else {
for (let v of message) {
if (!v.data) continue;
await buildElement(chain, v.type, v.data, is_group, stat, tasks);
if (stat.has_ptt || stat.has_flash)
elem = await buildElement(chain, v.type, v.data, is_group, stat, tasks);
if (stat.is_ptt || stat.is_flash)
break;
}
}

if (stat.has_ptt) {
return [chain[0][0]];
if (stat.is_ptt) {
return {
type: "ptt", elem
}
}

if (stat.is_flash) {
return {
type: "flash", elem
}
}

if (stat.is_forward) {
chain.shift();
return {
type: "forward", elem: chain
}
}

if (tasks.length)
Expand Down Expand Up @@ -562,6 +631,10 @@ async function buildMessage(message, escape, is_group) {
* @param {Promise[]} tasks 异步任务列表
*/
async function buildElement(chain, type, data, is_group, stat, tasks) {
if (stat.is_forward && type !== "node")
return;
if (chain.length > 1 && !stat.is_forward && type === "node")
return;
switch (type) {
// case "reply":
// buildReplyMessage(chain, data);
Expand Down Expand Up @@ -590,13 +663,26 @@ async function buildElement(chain, type, data, is_group, stat, tasks) {
tasks.push(task);
break;
case "flash":
var task = await buildImageMessage(chain, data, is_group, true);
if (task instanceof Promise)
stat.has_flash = true;
tasks.push(task);
const flash = await buildImageMessage(chain, data, is_group, true);
if (flash) {
stat.is_flash = true;
return flash;
}
break;
case "record":
stat.has_ptt = await buildRecordMessage(chain, data, is_group);
const ptt = await buildRecordMessage(chain, data, is_group);
if (ptt) {
stat.is_ptt = true;
return ptt;
}
break;
case "node":
if (buildForwardNode(chain, data))
stat.is_forward = true;
break;
case "location":
buildLocationNode(chain, data);
break;
default:
break;
}
Expand Down
Loading

0 comments on commit 6d813aa

Please sign in to comment.