yekonga-server
Version:
Yekonga Server
361 lines (290 loc) • 12.3 kB
JavaScript
// @ts-nocheck
const H = Yekonga.Helper;
const path = global.serverLibrary.path;
const Middleware = require(path.join(__dirname, 'middleware'));
module.exports = (socketServer, options) => {
var localOptions = {
debug: true
}
new ChatConnection(socketServer, options);
}
class ChatConnection {
static channel = '/chat';
constructor(socket, options) {
options = options || {};
this._roomRooms = {}
this._socket = socket.of(ChatConnection.channel);
this.initializeSocket();
}
initializeSocket() {
this._socket
.use(async function(socket, next) {
if(typeof next == 'function') {
next();
}
})
.on('connection', (socket) => {
// console.log(socket);
console.warn(`connected: /chat`);
socket.on('open', async (data) => {
var {
chatGroupId,
reference,
type,
localProfile,
remoteProfile,
} = data || {};
type = (H.isNotEmpty(type))? type: 'private';
var group = null;
var localMemberId = null;
var remoteMemberId = null;
var localMember = await this.getGroupMember({ reference, ...localProfile });
var remoteMember = null;
var where = {
reference: reference,
type: type,
};
localMemberId = `${localMember.chatGroupMemberId}`;
if(H.isNotEmpty(chatGroupId)) {
where.chatGroupId = chatGroupId;
}
if(type == 'private') {
if(remoteProfile && remoteProfile.userId) {
remoteMember = await this.getGroupMember({ reference, ...remoteProfile });
}
if(remoteMember) {
remoteMemberId = `${remoteMember.chatGroupMemberId}`;
}
where.members = { all: [localMemberId, remoteMemberId] }
}
// console.log("remoteProfile", remoteProfile);
// console.log("localProfile", localProfile);
// console.log(where);
group = await Yekonga.Model.ChatGroup.findOne(where, true);
if(!group) {
var body = {
reference: reference,
type: type,
members: [],
}
if(localMemberId) body.members.push(localMemberId);
if(remoteMemberId) body.members.push(remoteMemberId);
group = H.getFirst(await Yekonga.Model.ChatGroup.create(body, true));
}
if(group) {
if(Array.isArray(group.members)) {
group.members = group.members.map((e)=>`${e}`);
}
if(localMemberId && !group.members.includes(localMemberId)) {
group.members.push(localMemberId);
}
if(remoteMemberId && !group.members.includes(remoteMemberId)) {
group.members.push(remoteMemberId);
}
await Yekonga.Model.ChatGroup.update({
members: group.members
}, {
chatGroupId: group.chatGroupId
}, true);
}
var messages = await this.getMessages(socket, group.chatGroupId);
socket.emit('back-open', {
...group,
roomId: group.chatGroupId,
localProfile: localMember,
messages,
});
});
socket.on('join', async ({ roomId, chatGroupMemberId }) => {
socket.roomId = roomId;
socket.chatGroupMemberId = chatGroupMemberId;
socket.join(roomId, chatGroupMemberId);
socket.broadcast.to(roomId).emit('receive-join', { roomId, chatGroupMemberId });
});
socket.on('typing', ({ roomId, chatGroupMemberId, name, profileUrl }) => {
socket.broadcast.to(roomId).emit("receive-typing", { roomId, chatGroupMemberId, name, profileUrl });
});
socket.on('message-media', async ({roomId, chatMessageId, media, type }) => {
var mediaData = null;
if(Array.isArray(media) && media.length) {
mediaData = [];
for (let i = 0; i < media.length; i++) {
var data = {};
var m = media[i];
data.fileName = m.fileName;
data.fileType = m.fileType;
data.fileSize = m.fileSize;
data.url = m.base64;
mediaData[i] = data;
}
} else if(media) {
mediaData = [{
fileName: media.fileName,
fileType: media.fileType,
fileSize: media.fileSize,
url: media.base64,
}];
}
if(mediaData) {
var _message = H.getFirst(await Yekonga.Model.ChatMessage.update({
type: type? type: 'media',
media: mediaData,
}, { chatMessageId }, true));
if(_message) {
var chatMessageId = _message.chatMessageId;
var message = await this.getSingleMessage(socket, chatMessageId);
socket.emit('back-message', { roomId, ...message, update: true });
socket.broadcast.to(roomId).emit("receive-message", { roomId, ...message, update: true });
}
}
});
socket.on('message', async ({ roomId, chatGroupMemberId, content, type, media }) => {
// console.log(media);
// console.log("================================");
if(Array.isArray(media) && media.length) {
for (let i = 0; i < media.length; i++) {
var data = {};
var m = media[i];
data.fileName = m.fileName;
data.fileType = m.fileType;
data.fileSize = m.fileSize;
data.url = m.base64;
media[i] = data;
}
} else {
media = null;
}
var _message = H.getFirst(await Yekonga.Model.ChatMessage.create({
chatGroupId: roomId,
chatGroupMemberId: chatGroupMemberId,
content: content,
type: type? type: 'text',
media: media,
}, true));
if(_message) {
var chatMessageId = _message.chatMessageId;
var members = await Yekonga.Model.ChatGroupMember.find({ chatGroupId: roomId }, true);
for (let i = 0; i < members.length; i++) {
const e = members[i];
await Yekonga.Model.ChatMessageStatus.create({
chatMessageId: chatMessageId,
chatGroupMemberId: e.chatGroupMemberId,
});
}
var message = await this.getSingleMessage(socket, chatMessageId);
socket.emit('back-message', {roomId, ...message });
socket.broadcast.to(roomId).emit("receive-message", {roomId, ...message});
}
});
socket.on('received', ({ roomId, chatGroupMemberId, chatMessageId }) => {
socket.broadcast.to(roomId).emit("receive-delivered", {roomId, chatGroupMemberId, chatMessageId})
});
socket.on('opened', ({ roomId, chatGroupMemberId, chatMessageId }) => {
socket.broadcast.to(roomId).emit("receive-opened", {roomId, chatGroupMemberId, chatMessageId})
});
socket.on('leave', (data) => {
console.log('leave',data);
var { roomId, chatGroupMemberId, userReferenceId } = data || {}
if(roomId) {
socket.leave(roomId);
socket.broadcast.to(roomId).emit('leave', {chatGroupMemberId, userReferenceId})
}
});
socket.on('disconnect', () => {
const roomId = socket.roomId? socket.roomId: null;
const chatGroupMemberId = socket.chatGroupMemberId? socket.chatGroupMemberId: null;
if(roomId) {
socket.leave(roomId);
socket.broadcast.to(roomId).emit('leave', {roomId, chatGroupMemberId});
}
})
socket.on('error', function (e) {
console.log('socket.io error:' + e);
});
});
setInterval(() => {
this._socket.emit('active', true);
}, 5000);
}
queryFields = `
chatMessageId,
chatGroupId,
roomId: chatGroupId,
chatGroupMemberId,
content,
media,
mediaReference,
type,
timestamp,
user: chatGroupMember(accessRole:"${Yekonga.Config.masterKey}") {
chatGroupMemberId,
userId,
userReferenceId,
name,
profileUrl,
isAdmin,
isOwner,
},
chatMessageStatuses {
chatGroupMemberId,
sent,
received,
opened,
},
`;
async getGroupMemberId({reference, userId, userReferenceId, name, profileUrl}) {
var id = null;
var member = await this.getGroupMember({reference, userId, userReferenceId, name, profileUrl});
if(member) {
id = member.chatGroupMemberId;
}
return id;
}
async getGroupMember({reference, userId, userReferenceId, name, profileUrl}) {
var member = await Yekonga.Model.ChatGroupMember.findOne({
reference, userId, userReferenceId
}, true);
if(!member) {
member = H.getFirst(await Yekonga.Model.ChatGroupMember.create({
reference,
userId,
userReferenceId,
name,
profileUrl,
}, true));
}
return member;
}
async getMessages(req, id) {
var headers = {}
if(req.Yekonga && req.Yekonga.Client && req.Yekonga.Client.headers) {
headers = req.Yekonga.Client.headers;
}
var queryBody = `query{list:chatMessages(where:{chatGroupId:{equalTo: "${id}"}},orderBy:{key:timestamp, value:ASC}) { ${this.queryFields} }}`;
// console.log(queryBody);
var data = await Yekonga.Helper.getGraphql({query:queryBody}, headers, null, {});
if(data && data.list) {
return data.list
}
return [];
}
async getSingleMessage(req, id) {
var headers = {}
if(req.Yekonga && req.Yekonga.Client && req.Yekonga.Client.headers) {
headers = req.Yekonga.Client.headers;
}
var queryBody = `query{single:chatMessage(where:{chatMessageId:{equalTo: "${id}"}}) { ${this.queryFields} }}`;
var data = await Yekonga.Helper.getGraphql({query:queryBody}, headers, 'single', {});
if(data && data.single) {
return data.single
}
return null;
}
}
async function createChatMessage() {
}
async function sendChatMessageStatus() {
}
// cancel pending order
Yekonga.registerCronjob('processChatMessageStatus', 1000, async function(){
});