chat.js
// app/controller/chat.js const Controller = require('egg').Controller; class ChatController extends Controller { // 连接socket async connect() { const { ctx, app, service } = this; if (!ctx.websocket) { ctx.throw(400, '非法访问'); } // console.log(`clients: ${app.ws.clients.size}`); // 监听接收消息和关闭socket ctx.websocket .on('message', msg => { // console.log('接收消息', msg); }) .on('close', (code, reason) => { // 用户下线 console.log('用户下线', code, reason); let user_id = ctx.websocket.user_id; // 移除redis中的用户上线记录 service.cache.remove('online_' + user_id); if (app.ws.user && app.ws.user[user_id]) { delete app.ws.user[user_id]; } }); } // 发送消息 async send() { const { ctx, app, service } = this; // 拿到当前用户id let current_user_id = ctx.authUser.id; // 验证参数 ctx.validate({ to_id: { type: 'int', required: true, desc: '接收人/群id' }, chat_type: { type: 'string', required: true, range: { in: ['user', 'group'] }, desc: '接收类型' }, type: { type: 'string', required: true, range: { in: ['text', 'image', 'video', 'audio', 'emoticon', 'card'] }, desc: '消息类型' }, data: { type: 'string', required: true, desc: '消息内容' }, options: { type: 'string', required: true } }); // 获取参数 let { to_id, chat_type, type, data, options } = ctx.request.body; // 单聊 if (chat_type === 'user') { // 验证好友是否存在,并且对方没有把你拉黑 let Friend = await app.model.Friend.findOne({ where: { user_id: to_id, friend_id: current_user_id, isblack: 0 }, include: [{ model: app.model.User, as: "userInfo" }, { model: app.model.User, as: "friendInfo" }] }); if (!Friend) { return ctx.apiFail('对方不存在或者已经把你拉黑'); } // 验证好友是否被禁用 if (!Friend.userInfo.status) { return ctx.apiFail('对方已被禁用'); } // 构建消息格式 let from_name = Friend.friendInfo.nickname ? Friend.friendInfo.nickname : Friend.friendInfo.username; if (Friend.nickname) { from_name = Friend.nickname; } let message = { id: (new Date()).getTime(), // 唯一id,后端生成唯一id from_avatar: Friend.friendInfo.avatar,// 发送者头像 from_name, // 发送者昵称 from_id: current_user_id, // 发送者id to_id, // 接收人/群 id to_name: Friend.userInfo.nickname ? Friend.userInfo.nickname : Friend.userInfo.username, // 接收人/群 名称 to_avatar: Friend.userInfo.avatar, // 接收人/群 头像 chat_type: 'user', // 接收类型 type,// 消息类型 data, // 消息内容 options: {}, // 其他参数 create_time: (new Date()).getTime(), // 创建时间 isremove: 0, // 是否撤回 } // 视频,截取封面 if (message.type === 'video') { message.options.poster = message.data + '?x-oss-process=video/snapshot,t_10,m_fast,w_300,f_png'; } // 音频,带上音频时长 if (message.type === 'audio') { options = JSON.parse(options); message.options.time = options.time || 1; } // 名片 if (message.type === 'card') { // 验证名片用户是否存在 message.options = JSON.parse(options) } ctx.sendAndSaveMessage(to_id, message); // 存储到自己的聊天记录中 chatlog_当前用户id_user_对方用户id service.cache.setList(`chatlog_${current_user_id}_${message.chat_type}_${to_id}`, message); // 返回成功 return ctx.apiSuccess(message); } // 群聊 // 验证群聊是否存在,且你是否在该群中 let group = await app.model.Group.findOne({ where: { status: 1, id: to_id }, include: [{ model: app.model.GroupUser, attributes: ['user_id', 'nickname'] }] }); if (!group) { return ctx.apiFail('该群聊不存在或者已被封禁'); } let index = group.group_users.findIndex(item => item.user_id === current_user_id); if (index === -1) { return ctx.apiFail('你不是该群的成员'); } // 组织数据格式 let from_name = group.group_users[index].nickname; let message = { id: (new Date()).getTime(), // 唯一id,后端生成唯一id from_avatar: ctx.authUser.avatar,// 发送者头像 from_name: from_name || ctx.authUser.nickname || ctx.authUser.username, // 发送者昵称 from_id: current_user_id, // 发送者id to_id, // 接收人/群 id to_name: group.name, // 接收人/群 名称 to_avatar: group.avatar, // 接收人/群 头像 chat_type: 'group', // 接收类型 type,// 消息类型 data, // 消息内容 options: {}, // 其他参数 create_time: (new Date()).getTime(), // 创建时间 isremove: 0, // 是否撤回 group: group } // 视频,截取封面 if (message.type === 'video') { message.options.poster = message.data + '?x-oss-process=video/snapshot,t_10,m_fast,w_300,f_png'; } // 音频,带上音频时长 if (message.type === 'audio') { options = JSON.parse(options); message.options.time = options.time || 1; } // 名片 if (message.type === 'card') { // 验证名片用户是否存在 message.options = JSON.parse(options) } // 推送消息 group.group_users.forEach(item => { if (item.user_id !== current_user_id) { ctx.sendAndSaveMessage(item.user_id, message); } }); ctx.apiSuccess(message); } // 获取离线消息 async getmessage() { const { ctx, app, service } = this; let current_user_id = ctx.authUser.id; let key = 'getmessage_' + current_user_id; let list = await service.cache.getList(key); // 清除离线消息 await service.cache.remove(key); // 批量推送 list.forEach(async (message) => { let d = JSON.parse(message); ctx.sendAndSaveMessage(current_user_id, d.message, d.msg); }); } // 撤回 async recall(){ const { ctx,app } = this; let current_user_id = ctx.authUser.id; ctx.validate({ to_id:{ type:'int', required:true, desc:'接收人/群id' }, chat_type:{ type:'string', required:true, range:{ in:['user','group'] }, desc:'接收类型' }, id:{ type:'int', required:true, desc:'消息id' } }); let {to_id,chat_type,id} = ctx.request.body; let message = { from_id:current_user_id, to_id, chat_type, id } // 单聊 if(chat_type === 'user'){ ctx.sendAndSaveMessage(to_id,message,'recall'); return ctx.apiSuccess(message); } // 群聊 let group = await app.model.Group.findOne({ where:{ id:to_id, status:1 }, include:[{ model:app.model.GroupUser, attributes:['user_id'] }] }); if(group){ group.group_users.forEach(item=>{ if(item.user_id !== current_user_id){ ctx.sendAndSaveMessage(item.user_id,message,'recall'); } }); } return ctx.apiSuccess(message); } } module.exports = ChatController;
router.js
// 撤回消息 router.post('/chat/recall',controller.chat.recall);
感谢大家观看,我们下次见