server: 记录自己发送的消息
This commit is contained in:
@@ -14,6 +14,7 @@ let pushSQL =
|
|||||||
to_name,\
|
to_name,\
|
||||||
to_nickname,\
|
to_nickname,\
|
||||||
is_group_message,\
|
is_group_message,\
|
||||||
|
is_self_message,\
|
||||||
speaking_group_member_name,\
|
speaking_group_member_name,\
|
||||||
filename,\
|
filename,\
|
||||||
display_filename\
|
display_filename\
|
||||||
@@ -28,6 +29,7 @@ let pushSQL =
|
|||||||
$toName,\
|
$toName,\
|
||||||
$toNickName,\
|
$toNickName,\
|
||||||
$isGroupMessage,\
|
$isGroupMessage,\
|
||||||
|
$isSelfMessage,\
|
||||||
$speakingGroupMemberName,\
|
$speakingGroupMemberName,\
|
||||||
$filename,\
|
$filename,\
|
||||||
$displayFilename\
|
$displayFilename\
|
||||||
@@ -59,6 +61,7 @@ async function initDB(dbFile) {
|
|||||||
is_group_message INTEGER,
|
is_group_message INTEGER,
|
||||||
speaking_group_member_name TEXT,
|
speaking_group_member_name TEXT,
|
||||||
filename TEXT,
|
filename TEXT,
|
||||||
|
is_self_message, BOOLEAN,
|
||||||
display_filename TEXT)`
|
display_filename TEXT)`
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
@@ -86,6 +89,7 @@ async function pushMessage(message) {
|
|||||||
$toName: message.toName,
|
$toName: message.toName,
|
||||||
$toNickName: message.toNickName,
|
$toNickName: message.toNickName,
|
||||||
$isGroupMessage: message.isGroupMessage,
|
$isGroupMessage: message.isGroupMessage,
|
||||||
|
$isSelfMessage: message.isSentBySelf,
|
||||||
$speakingGroupMemberName: message.speakingGroupMemberName,
|
$speakingGroupMemberName: message.speakingGroupMemberName,
|
||||||
$content: message.content,
|
$content: message.content,
|
||||||
$filename: message.filename,
|
$filename: message.filename,
|
||||||
|
|||||||
@@ -184,6 +184,7 @@ async function processMessage(msg) {
|
|||||||
filename: m.filename,
|
filename: m.filename,
|
||||||
fileSize: m.fileSize,
|
fileSize: m.fileSize,
|
||||||
displayFilename: m.displayFilename,
|
displayFilename: m.displayFilename,
|
||||||
|
isSentBySelf: m.isSentBySelf,
|
||||||
};
|
};
|
||||||
const clientMsg = {
|
const clientMsg = {
|
||||||
messageID: m.composedID,
|
messageID: m.composedID,
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ const formidable = require("formidable");
|
|||||||
const dayjs = require("dayjs");
|
const dayjs = require("dayjs");
|
||||||
const { Server } = require("socket.io");
|
const { Server } = require("socket.io");
|
||||||
const { createServer } = require("http");
|
const { createServer } = require("http");
|
||||||
const { bot, getDisplayName, cacheAvatars } = require("./bot.js");
|
const db = require("./db.js");
|
||||||
|
const { bot, getDisplayName, cacheAvatars, getNickName } = require("./bot.js");
|
||||||
const { config } = require("./config.js");
|
const { config } = require("./config.js");
|
||||||
const {
|
const {
|
||||||
textSHA1,
|
textSHA1,
|
||||||
@@ -16,6 +17,8 @@ const {
|
|||||||
composeAvatarFileName,
|
composeAvatarFileName,
|
||||||
composeMediaFilePathFromID,
|
composeMediaFilePathFromID,
|
||||||
getOriginalMsgID,
|
getOriginalMsgID,
|
||||||
|
fileMD5,
|
||||||
|
composeMessageIDWithTimestamp,
|
||||||
} = require("./util.js");
|
} = require("./util.js");
|
||||||
|
|
||||||
const DEFAULT_ROOM = "default_room";
|
const DEFAULT_ROOM = "default_room";
|
||||||
@@ -57,20 +60,6 @@ io.use((socket, next) => {
|
|||||||
auth.platform
|
auth.platform
|
||||||
} connected at ${dayjs().format("YYYY-MM-DDTHH:MM:ss")}`;
|
} connected at ${dayjs().format("YYYY-MM-DDTHH:MM:ss")}`;
|
||||||
bot.sendText(text, "filehelper");
|
bot.sendText(text, "filehelper");
|
||||||
pushMessage({
|
|
||||||
messageID: "notice_" + (Date.now() + Math.random()),
|
|
||||||
createTimestamp: Math.trunc(Date.now() / 1000),
|
|
||||||
type: "text",
|
|
||||||
fromID: "filehelper",
|
|
||||||
fromName: "你自己",
|
|
||||||
fromNickName: "你自己",
|
|
||||||
toID: bot.user.UserName,
|
|
||||||
toName: "你自己",
|
|
||||||
toNickName: bot.user.NickName,
|
|
||||||
isGroupMessage: false,
|
|
||||||
isSentBySelf: false,
|
|
||||||
content: text,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function deactivateSession(socket) {
|
function deactivateSession(socket) {
|
||||||
@@ -132,16 +121,29 @@ async function sendMessage(_, { type, target, data, filename }) {
|
|||||||
return "联系人不存在";
|
return "联系人不存在";
|
||||||
}
|
}
|
||||||
let resp;
|
let resp;
|
||||||
|
let uploadedFilepath;
|
||||||
|
let content = "";
|
||||||
|
const isSentToGroup = bot.Contact.isRoomContact(targetContact);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "text":
|
case "text":
|
||||||
resp = await bot.sendText(data, target);
|
resp = await bot.sendText(data, target);
|
||||||
|
content = data;
|
||||||
break;
|
break;
|
||||||
case "emotion":
|
case "emotion":
|
||||||
resp = await bot.sendEmoticon(data, target);
|
resp = await bot.sendEmoticon(data, target);
|
||||||
|
// FIXME: 如果是收藏的图片表情,应解析
|
||||||
|
content = "[表情]";
|
||||||
break;
|
break;
|
||||||
case "img":
|
case "img":
|
||||||
case "video":
|
case "video":
|
||||||
case "file": {
|
case "file": {
|
||||||
|
if (type === "img") {
|
||||||
|
content = "[图片]";
|
||||||
|
} else if (type === "video") {
|
||||||
|
content = "[视频]";
|
||||||
|
} else {
|
||||||
|
content = "[文件]";
|
||||||
|
}
|
||||||
const defaultFilenameMap = {
|
const defaultFilenameMap = {
|
||||||
img: "pic.jpg",
|
img: "pic.jpg",
|
||||||
video: "video.mp4",
|
video: "video.mp4",
|
||||||
@@ -187,15 +189,42 @@ async function sendMessage(_, { type, target, data, filename }) {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
return e?.tips || e?.message || "消息发送失败";
|
return e?.tips || e?.message || "消息发送失败";
|
||||||
}
|
}
|
||||||
// 上传后删除
|
uploadedFilepath = newFilename;
|
||||||
fs.rm(newFilename, () => {});
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return "不支持的文件类型";
|
return "不支持的文件类型";
|
||||||
}
|
}
|
||||||
|
let mediaFilename;
|
||||||
|
if (uploadedFilepath) {
|
||||||
|
mediaFilename =
|
||||||
|
(await fileMD5(uploadedFilepath)) + path.extname(uploadedFilepath);
|
||||||
|
ensureMediaDirFromComposedID();
|
||||||
|
fs.renameSync();
|
||||||
|
}
|
||||||
|
const timestamp = dayjs().unix();
|
||||||
|
const composedID = composeMessageIDWithTimestamp(timestamp, resp.MsgID);
|
||||||
|
const dbMsg = {
|
||||||
|
messageID: composedID,
|
||||||
|
createTimestamp: timestamp,
|
||||||
|
type,
|
||||||
|
messageType: null,
|
||||||
|
fromName: bot.user.NickName,
|
||||||
|
fromNickName: bot.user.NickName,
|
||||||
|
toName: getDisplayName(targetContact),
|
||||||
|
toNickName: getNickName(targetContact),
|
||||||
|
isGroupMessage: isSentToGroup,
|
||||||
|
isSentBySelf: true,
|
||||||
|
speakingGroupMemberName: isSentToGroup && bot.user.NickName,
|
||||||
|
content: content,
|
||||||
|
filename: mediaFilename,
|
||||||
|
fileSize: uploadedFilepath && fs.statSync(uploadedFilepath).size,
|
||||||
|
displayFilename: filename || null,
|
||||||
|
};
|
||||||
|
db.pushMessage(dbMsg);
|
||||||
return {
|
return {
|
||||||
messageID: resp.MsgID,
|
messageID: resp.MsgID,
|
||||||
|
composedID,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
async function revokeMessage(_, { composedID, target }) {
|
async function revokeMessage(_, { composedID, target }) {
|
||||||
@@ -271,7 +300,7 @@ router.get("/session/:sessionID/media/:composedID/:filename", (ctx, next) => {
|
|||||||
|
|
||||||
/** 上传文件 */
|
/** 上传文件 */
|
||||||
router.post("/upload_file", async (ctx, next) => {
|
router.post("/upload_file", async (ctx, next) => {
|
||||||
if (!activeSessions.has(ctx.request.headers['sid'])) {
|
if (!activeSessions.has(ctx.request.headers["sid"])) {
|
||||||
ctx.throw(401);
|
ctx.throw(401);
|
||||||
}
|
}
|
||||||
const filename = dayjs().format("YYYYMMDD_") + String(Math.random()).slice(2);
|
const filename = dayjs().format("YYYYMMDD_") + String(Math.random()).slice(2);
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ const { config } = require("./config");
|
|||||||
function composeMessageID(msg) {
|
function composeMessageID(msg) {
|
||||||
return dayjs.unix(msg["CreateTime"]).format("YYYYMMDD") + msg["MsgId"];
|
return dayjs.unix(msg["CreateTime"]).format("YYYYMMDD") + msg["MsgId"];
|
||||||
}
|
}
|
||||||
|
function composeMessageIDWithTimestamp(timestamp, originalMsgID) {
|
||||||
|
return dayjs.unix(timestamp).format("YYYYMMDD") + originalMsgID;
|
||||||
|
}
|
||||||
function getOriginalMsgID(composedID) {
|
function getOriginalMsgID(composedID) {
|
||||||
return composedID.slice(8);
|
return composedID.slice(8);
|
||||||
}
|
}
|
||||||
@@ -38,6 +41,11 @@ function ensureMediaDir(msg) {
|
|||||||
fs.mkdirSync(dir, { recursive: true });
|
fs.mkdirSync(dir, { recursive: true });
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
|
function ensureMediaDirFromComposedID(composedID) {
|
||||||
|
const dir = composeMediaFilePathFromID(composedID, "");
|
||||||
|
fs.mkdirSync(dir, { recursive: true });
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
function ensureAvatarDir() {
|
function ensureAvatarDir() {
|
||||||
const dir = path.join(config.cacheDir, "avatar");
|
const dir = path.join(config.cacheDir, "avatar");
|
||||||
fs.mkdirSync(dir, { recursive: true });
|
fs.mkdirSync(dir, { recursive: true });
|
||||||
@@ -71,6 +79,7 @@ function textSHA1(text) {
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
composeMessageID,
|
composeMessageID,
|
||||||
|
composeMessageIDWithTimestamp,
|
||||||
getOriginalMsgID,
|
getOriginalMsgID,
|
||||||
composeFilename,
|
composeFilename,
|
||||||
composeMediaFilePath,
|
composeMediaFilePath,
|
||||||
@@ -78,6 +87,7 @@ module.exports = {
|
|||||||
composeCacheFilePath,
|
composeCacheFilePath,
|
||||||
composeAvatarFileName,
|
composeAvatarFileName,
|
||||||
ensureMediaDir,
|
ensureMediaDir,
|
||||||
|
ensureMediaDirFromComposedID,
|
||||||
ensureAvatarDir,
|
ensureAvatarDir,
|
||||||
ensureUploadDir,
|
ensureUploadDir,
|
||||||
fileMD5,
|
fileMD5,
|
||||||
|
|||||||
Reference in New Issue
Block a user