219 lines
6.3 KiB
JavaScript
219 lines
6.3 KiB
JavaScript
const path = require("path");
|
|
const fs = require("fs");
|
|
const socket = require("./socket.js");
|
|
const db = require("./db.js");
|
|
const {
|
|
bot,
|
|
getDisplayName,
|
|
getGroupMsgSpeaker,
|
|
getGroupMsgContent,
|
|
getNickName,
|
|
} = require("./bot.js");
|
|
const {
|
|
composeMessageID,
|
|
composeMediaFilePath,
|
|
composeFilename,
|
|
composeCacheFilePath,
|
|
fileMD5,
|
|
ensureMediaDir,
|
|
} = require("./util");
|
|
|
|
async function processMessage(msg) {
|
|
if ([50, 51, 52, 53, 9999].includes(msg.MsgType)) {
|
|
return;
|
|
}
|
|
const peerContact = bot.contacts[msg.getPeerUserName()];
|
|
const fromContact = bot.contacts[msg["FromUserName"]];
|
|
const toContact = bot.contacts[msg["ToUserName"]];
|
|
if (!peerContact || !fromContact || !toContact) {
|
|
// TODO: notify self
|
|
return;
|
|
}
|
|
if (
|
|
bot.Contact.isPublicContact(peerContact) ||
|
|
(bot.Contact.isSpContact(peerContact) &&
|
|
peerContact.UserName !== "filehelper")
|
|
) {
|
|
return;
|
|
}
|
|
|
|
ensureMediaDir(msg);
|
|
|
|
const msgID = msg["MsgId"];
|
|
const msgType = msg["MsgType"];
|
|
|
|
const m = {
|
|
messageID: msgID,
|
|
composedID: composeMessageID(msg),
|
|
createTimestamp: msg["CreateTime"],
|
|
messageType: msgType,
|
|
fromID: msg["FromUserName"],
|
|
toID: msg["ToUserName"],
|
|
fromName: getDisplayName(fromContact),
|
|
fromNickName: getNickName(fromContact),
|
|
toName: getDisplayName(toContact),
|
|
toNickName: getNickName(toContact),
|
|
type: "unknown",
|
|
content: null,
|
|
group: bot.Contact.isRoomContact(peerContact) ? peerContact : null,
|
|
speakingGroupMember: null,
|
|
filename: null,
|
|
displayFilename: msg["FileName"] || "",
|
|
fileSize: msg.FileSize | 0,
|
|
isGroupMessage: bot.Contact.isRoomContact(peerContact),
|
|
isSentBySelf: msg.isSendBySelf,
|
|
};
|
|
|
|
if (m.isGroupMessage) {
|
|
if (!msg.isSendBySelf) {
|
|
m.speakingGroupMember = getGroupMsgSpeaker(msg);
|
|
}
|
|
}
|
|
|
|
switch (msgType) {
|
|
case bot.CONF.MSGTYPE_TEXT:
|
|
// 文本消息
|
|
m.type = "text";
|
|
m.content = m.isGroupMessage ? getGroupMsgContent(msg) : msg["Content"];
|
|
break;
|
|
case bot.CONF.MSGTYPE_EMOTICON:
|
|
case bot.CONF.MSGTYPE_IMAGE: {
|
|
const suffix = msgType === bot.CONF.MSGTYPE_IMAGE ? ".jpg" : ".gif";
|
|
m.type = "img";
|
|
m.content =
|
|
`[${msgType === bot.CONF.MSGTYPE_IMAGE ? "图片" : "表情"}]` +
|
|
(msg["FileName"] || "");
|
|
if (msg["HasProductId"]) {
|
|
m.type = "unknown";
|
|
m.content = "[表情贴图]请在手机上查看";
|
|
break;
|
|
}
|
|
const cachePath = composeCacheFilePath(msg, suffix);
|
|
// ENHANCE: 提前判断表情是否存在,节约带宽
|
|
const res = await bot.getMsgImg(msg.MsgId);
|
|
fs.writeFileSync(cachePath, res.data);
|
|
const md5 = await fileMD5(cachePath);
|
|
m.filename = md5 + suffix;
|
|
const filename = composeMediaFilePath(msg, m.filename);
|
|
if (fs.existsSync(filename)) {
|
|
fs.rmSync(cachePath);
|
|
} else {
|
|
fs.renameSync(cachePath, filename);
|
|
}
|
|
break;
|
|
}
|
|
case bot.CONF.MSGTYPE_VOICE: {
|
|
m.type = "voice";
|
|
m.content = "[语音消息]";
|
|
m.filename = composeFilename(msg, ".mp3");
|
|
const { data } = await bot.getVoice(msg.MsgId);
|
|
fs.writeFileSync(composeMediaFilePath(msg, m.filename), data);
|
|
break;
|
|
}
|
|
case bot.CONF.MSGTYPE_VIDEO:
|
|
case bot.CONF.MSGTYPE_MICROVIDEO: {
|
|
m.type = "video";
|
|
m.content = "[视频]";
|
|
const suffix = ".mp4";
|
|
const cachePath = composeCacheFilePath(msg, suffix);
|
|
const res = await bot.getVideo(msg.MsgId);
|
|
fs.writeFileSync(cachePath, res.data);
|
|
const md5 = await fileMD5(cachePath);
|
|
m.filename = md5 + suffix;
|
|
const filename = composeMediaFilePath(msg, m.filename);
|
|
if (fs.existsSync(filename)) {
|
|
fs.rmSync(cachePath);
|
|
} else {
|
|
fs.renameSync(cachePath, filename);
|
|
}
|
|
break;
|
|
}
|
|
case bot.CONF.MSGTYPE_APP:
|
|
if (msg.AppMsgType === 5) {
|
|
m.type = "text";
|
|
m.content = "[链接]" + msg["FileName"] + ": " + msg["Url"];
|
|
break;
|
|
} else if (msg.AppMsgType == 6) {
|
|
m.type = "file";
|
|
m.content = "[文件]" + m.displayFilename;
|
|
if (!(msg.FileSize < 10 * 1024 * 1024)) {
|
|
// 忽略10M以上的大文件
|
|
m.type = "unknown";
|
|
m.filename = null;
|
|
break;
|
|
}
|
|
const suffix = path.extname(m.displayFilename);
|
|
const cachePath = composeCacheFilePath(msg, suffix);
|
|
const res = await bot.getDoc(
|
|
msg.FromUserName,
|
|
msg.MediaId,
|
|
msg.FileName
|
|
);
|
|
fs.writeFileSync(cachePath, res.data);
|
|
const md5 = await fileMD5(cachePath);
|
|
m.filename = md5 + suffix;
|
|
const filename = composeMediaFilePath(msg, m.filename);
|
|
if (fs.existsSync(filename)) {
|
|
fs.rmSync(cachePath);
|
|
} else {
|
|
fs.renameSync(cachePath, filename);
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (m.type === "unknown") {
|
|
m.content ||= "未知类型的消息,请在手机上查看";
|
|
}
|
|
|
|
const dbMsg = {
|
|
messageID: m.composedID,
|
|
createTimestamp: m.createTimestamp,
|
|
type: m.type,
|
|
messageType: m.messageType,
|
|
fromName: m.fromName,
|
|
fromNickName: m.fromNickName,
|
|
toName: m.toName,
|
|
toNickName: m.toNickName,
|
|
isGroupMessage: m.isGroupMessage,
|
|
speakingGroupMemberName:
|
|
(m.speakingGroupMember && getDisplayName(m.speakingGroupMember)) || null,
|
|
content: m.content,
|
|
filename: m.filename,
|
|
fileSize: m.fileSize,
|
|
displayFilename: m.displayFilename,
|
|
isSentBySelf: m.isSentBySelf,
|
|
};
|
|
const clientMsg = {
|
|
messageID: m.composedID,
|
|
createTimestamp: m.createTimestamp,
|
|
type: m.type,
|
|
fromID: m.fromID,
|
|
fromName: m.fromName,
|
|
fromNickName: m.fromNickName,
|
|
toID: m.toID,
|
|
toName: m.toName,
|
|
toNickName: m.toNickName,
|
|
isGroupMessage: m.isGroupMessage,
|
|
isSentBySelf: m.isSentBySelf,
|
|
speakingGroupMemberID:
|
|
m.speakingGroupMember && m.speakingGroupMember.UserName,
|
|
speakingGroupMemberName:
|
|
(m.speakingGroupMember && getDisplayName(m.speakingGroupMember)) || null,
|
|
content: m.content,
|
|
filename: m.filename,
|
|
fileSize: m.fileSize,
|
|
displayFilename: m.displayFilename,
|
|
};
|
|
if (!bot.Contact.isSpContact(peerContact)) {
|
|
await db.pushMessage(dbMsg);
|
|
}
|
|
socket.pushMessage(clientMsg);
|
|
}
|
|
|
|
module.exports = {
|
|
processMessage,
|
|
};
|