Files
doneit-web/src/app/services/chat/message.service.ts
T
Peter Maquiran 8459f61150 fix issue
2023-02-08 16:06:14 +01:00

584 lines
15 KiB
TypeScript

import { Injectable } from '@angular/core';
import { Message } from 'src/app/models/chatMethod';
import { SessionStore } from 'src/app/store/session.service';
import { capitalizeTxt } from 'src/plugin/text';
import { NfService } from 'src/app/services/chat/nf.service';
import { RochetChatConnectorService } from 'src/app/services/chat/rochet-chat-connector.service';
import { showDateDuration } from 'src/plugin/showDateDuration';
import { ChatMethodsService } from './chat-methods.service';
import { MessageModel } from '../../models/beast-orm';
import { AESEncrypt } from '../aesencrypt.service';
import { HttpEventType } from '@angular/common/http';
import { AttachmentsService } from 'src/app/services/attachments.service';
import { NetworkServiceService , ConnectionStatus} from 'src/app/services/network-service.service';
import { ChatSystemService } from './chat-system.service';
import { v4 as uuidv4 } from 'uuid'
import { NotificationsService } from 'src/app/services/notifications.service';
@Injectable({
providedIn: 'root'
})
export class MessageService {
customFields
channels = []
mentions = []
msg = ''
rid = ''
ts = {}
u = {
name: '',
username: '',
_id: ""
}
t = ''
_id = ''
id = '' // table id
_updatedAt
file
attachments
displayType = ''
temporaryData: any = {}
hasFile = false
hasSendAttachment = false
sendAttempt = 0
uploadingFile = false
errorUploadingAttachment = false
loadHistory = false
from: 'Offline'|'History'|'stream'| 'send'
duration = ''
localReference = null
viewed: string[] = []
received: string[]= []
addToDb = false
messageSend = false
delate = false
delateRequest = false
downloadLoader: boolean = false
downloadAttachments = false;
downloadAttachmentsTemp = 0;
UploadAttachmentsTemp = 0;
manualRetry = false
origin: 'history' | 'stream' | 'local'
rowInstance: MessageModel
constructor(
private NfService: NfService,
private RochetChatConnectorService: RochetChatConnectorService,
private ChatMethodsService: ChatMethodsService,
private AESEncrypt: AESEncrypt,
private AttachmentsService: AttachmentsService,
private NetworkServiceService: NetworkServiceService,
private ChatSystemService: ChatSystemService,
private notificationService: NotificationsService) {
}
setData({customFields = {}, channels, mentions, msg ,rid ,ts, u, t, _id, id, _updatedAt, file, attachments, temporaryData, localReference = 'out-'+uuidv4() , viewed = [], received = [], delate = false, delateRequest =false, from, sendAttempt = 0, origin }:Message) {
this.channels = channels || []
this.mentions = mentions || []
this.msg = msg || ""
this.rid = rid
this.ts = ts
this.u = u || { name: this.usernameToDisplayName(SessionStore.user.UserName), username: SessionStore.user.UserName, _id: ""}
this.t = t
this._id = _id || ""
this._updatedAt = _updatedAt || new Date().getTime()
this.file = file
this.temporaryData = temporaryData
this.localReference = localReference || null
this.id = id
this.delate = delate
this.delateRequest = delateRequest
this.sendAttempt = 0
this.origin = origin
if(this.attachments?.length >= 1 && attachments?.length >= 1) {
this.attachments[0] = Object.assign(this.attachments[0], attachments[0])
} else {
this.attachments = attachments
}
this.viewed = [...new Set([...viewed,...this.viewed])];
this.received = [...new Set([...received,...this.received])];
if(!this.ts) {
this.messageSend = false
} else {
this.messageSend = true
}
if (this.file) {
if(this.file.type) {
if(typeof(this.file.type) == 'string') {
this.hasFile = true
}
}
}
if(this.hasFile) {
if(this.file.type != 'application/webtrix') {
this.displayType = this.file.type.replace('application/','').toUpperCase()
}
}
if(!this.u.name && this.u.username) {
const user = this.ChatSystemService.users.find((u)=> u.username == this.u.username)
if(user) {
this.u.name = user.name
} else if( this.u.username == SessionStore.user.UserName) {
this.u.name = SessionStore.user.FullName
} else {
// console.log(user.username, SessionStore.user.UserName)
}
}
this.calDateDuration()
}
get offline () {
if(!this._id) {
return true
}
if(!this.ts) {
return true
}
return false
}
/**
* Message is on the server
*/
get online() {
return !this.offline
}
/**
* if Message is already saved on database
*/
get save() {
return this.id != ''
}
private usernameToDisplayName(username) {
try {
const firstName = capitalizeTxt(username.split('.')[0])
const lastName = capitalizeTxt(username.split('.')[1])
return firstName + ' ' + lastName
} catch (error) {
return username
}
}
async send(): Promise<any> {
if(this.messageSend) {
return new Promise((resolve, reject) => {
resolve('solve')
})
}
this.sendAttempt++;
this.manualRetry = false
if(!this.hasFile) {
const params = {
roomId:this.rid,
msg:this.msg,
localReference: this.localReference
}
await this.sendRequest(params)
} else {
let uploadSuccessfully = await this.sendRequestAttachment()
if(uploadSuccessfully) {
const params = {roomId:this.rid, msg: this.msg, attachments: this.attachments, file: this.file, localReference: this.localReference}
await this.sendRequest(params)
} else if(this.RochetChatConnectorService.isLogin == false) {
this.RochetChatConnectorService.registerCallback({
type: 'reConnect',
funx: async () => {
this.send().catch((error) =>{
console.error(error)
})
return true
}
})
} else if(this.NetworkServiceService.getCurrentNetworkStatus() == ConnectionStatus.Offline) {
this.RochetChatConnectorService.registerCallback({
type: 'reConnect',
funx: async ()=> {
await this.send().catch((error) => {
console.error(error)
})
return true
}
})
} else if (this.UploadAttachmentsTemp <= 3) {
setTimeout(async () => {
return await this.send()
}, 3000)
} else if (this.NetworkServiceService.getCurrentNetworkStatus() == ConnectionStatus.Online) {
this.manualRetry = true
}
}
}
functionTimer = null;
async sendRequestAttachment() {
this.uploadingFile = true
let uploadSuccessfully = false
if(this.hasSendAttachment == false) {
try {
uploadSuccessfully = await this.NfService.beforeSendAttachment(this)
this.UploadAttachmentsTemp++
this.uploadingFile = false
this.manualRetry = false
this.errorUploadingAttachment = false
this.hasSendAttachment = true
this.temporaryData = {}
} catch (error) {
this.uploadingFile = false
this.errorUploadingAttachment = true
this.UploadAttachmentsTemp++
console.error('beforeSendAttachment error:', error)
}
}
return uploadSuccessfully
}
async sendRequest(params) {
if(params?.attachments) {
if(params?.attachments[0]?.image_url) {
delete params?.attachments[0]?.image_url
}
}
if(this.NetworkServiceService.getCurrentNetworkStatus() == ConnectionStatus.Online) {
if(this.msg == '<script></script>') {
if(this.sendAttempt >= 4) {
this.RochetChatConnectorService.send(params).then(
(ChatMessage: any) => {
ChatMessage = ChatMessage.message.result
clearTimeout(this.functionTimer);
this.redefinedMessage(ChatMessage)
console.log()
}
).catch((error) => {
clearTimeout(this.functionTimer);
console.error(error)
})
}
} else {
this.RochetChatConnectorService.send(params).then(
(ChatMessage: any) => {
ChatMessage = ChatMessage.message.result
clearTimeout(this.functionTimer);
this.redefinedMessage(ChatMessage)
}
).catch((error) => {
clearTimeout(this.functionTimer);
console.error(error)
})
}
this.functionTimer = setTimeout(() => {
this.RochetChatConnectorService.registerCallback({
type:'Onmessage',
key:'ping-pong-message',
funx:(message: any) => {
if(message.msg == "ping") {
if(this.sendAttempt >= 3) {
this.manualRetry = true
} else {
this.send()
}
return true
}
this.saveChanges()
}
})
this.RochetChatConnectorService.wsSend({message:{msg:"pong"}, loginRequired: false})
}, 3000)
} else {
this.RochetChatConnectorService.registerCallback({
type: 'reConnect',
funx: async ()=> {
this.send().catch((error) =>{
console.error(error)
})
return true
}
})
}
}
async redefinedMessage(ChatMessage , update = true) {
ChatMessage = this.NfService.fix_updatedAt(ChatMessage)
const message = this.getChatObj()
this.manualRetry = false
this.messageSend = true
ChatMessage = Object.assign(message, ChatMessage)
this.setData(ChatMessage)
const roomObject = this.ChatSystemService.getRoomById(this.rid)
const users = roomObject.getUsersByStatus('online')
for(const user of users) {
this.addReceived(user._id)
}
if(!roomObject.isGroup) {
var memeberTosend = this.ChatSystemService.getRoomById(this.rid).membersExcludeMe
console.log(ChatMessage)
this.notificationService.ChatSendMessageNotification(memeberTosend[0].username,ChatMessage.u.name,ChatMessage.msg,this.rid)
} else {
var memeberTosend = this.ChatSystemService.getRoomById(this.rid).membersExcludeMe
var usersNames = [];
for(let i = 0; i < memeberTosend.length; i++) {
usersNames.push(memeberTosend[i].username)
}
this.notificationService.ChatSendMessageNotificationGrup(usersNames,ChatMessage.u.name,ChatMessage.msg,this.rid)
}
await this.saveChanges()
}
sendNotificaton
downloadFileMsg() {
this.downloadLoader = true;
let downloadFile = "";
this.AttachmentsService.downloadFile(this.file.guid).subscribe(async (event) => {
if (event.type === HttpEventType.DownloadProgress) {
} else if (event.type === HttpEventType.Response) {
if (this.file.type == "application/img") {
downloadFile = 'data:image/jpeg;base64,' + btoa(new Uint8Array(event.body).reduce((data, byte) => data + String.fromCharCode(byte), ''));
} else if (this.file.type != "application/img") {
downloadFile = new Uint8Array(event.body).reduce((data, byte) => data + String.fromCharCode(byte), '');
}
this.attachments[0] = {
image_url: downloadFile,
name: this.attachments[0].name,
title: this.attachments[0].title,
title_link: downloadFile,
title_link_download: this.attachments[0].title_link_download,
ts: this.attachments[0].ts
}
// save the changes to the storage
this.saveChanges()
this.downloadLoader = false;
this.downloadAttachments = true
this.downloadAttachmentsTemp++;
}
}, ()=>{
// error
this.downloadLoader = false;
this.downloadAttachments = false
this.downloadAttachmentsTemp++;
});
}
private calDateDuration(date = null) {
this.duration = showDateDuration(date || this._updatedAt);
}
async delateStatusFalse() {
this.delate = true
this.saveChanges()
}
addViewed(id: string) {
if(this.messageOwner()) {
let found = this.viewed.find((UserId) => UserId == id)
if(!found) {
this.viewed.push(id)
return true
}
}
return false
}
addReceived(id: string) {
if(this.messageOwner()) {
let found = this.received.find((UserId) => UserId == id)
if(!found) {
this.received.push(id)
return true
}
}
return false
}
async delateDB() {
if(!this.rowInstance) {
this.rowInstance = await this.getRowInstance()
}
await this.rowInstance.delete()
}
isSenderIsNotMe(ChatMessage) {
return SessionStore.user.ChatData.data.userId != ChatMessage.u._id
}
messageOwner() {
return SessionStore.user.ChatData.data.userId == this.u._id
}
getChatObj() {
return {
channels: this.channels,
mentions: this.mentions,
// msg: this.AESEncrypt.encrypt(this.msg, SessionStore.user.UserName),
sendAttempt: this.sendAttempt,
msg:this.msg,
rid: this.rid,
ts: this.ts,
u: this.u,
_id: this._id,
id: this.id,
origin: this.origin,
_updatedAt: this._updatedAt,
messageSend: this.messageSend,
offline: this.offline,
viewed: this.viewed,
received: this.received,
localReference: this.localReference,
attachments: this.attachments,
file: this.file,
delate: this.delate
}
}
earlySave = false
async addMessageDB() {
if(!this.addToDb && this.save) {
this.addToDb = true
const message = this.getChatObj()
delete message.id
const createdMessage = await MessageModel.create(message)
this.rowInstance = createdMessage
this.id = createdMessage.id
if(this.earlySave) {
this.saveChanges();
}
}
}
async getRowInstance () {
if(this.save) {
const message = this.getChatObj()
let a
if(!message.id) {
delete message.id
}
if (this.localReference) {
a = await MessageModel.get({localReference: this.localReference})
} else if (this._id) {
a = await MessageModel.get({_id: this._id})
} else if(this.id) {
a = await MessageModel.get({id: this.id})
}
return a
}
}
async saveChanges() {
if(!this.rowInstance) {
this.rowInstance = await this.getRowInstance()
}
if(this.save && this.rowInstance) {
const message = this.getChatObj()
if(!message.id) {
delete message.id
}
for( const [name, value] of Object.entries(message)) {
this.rowInstance[name] = value
}
await this.rowInstance.save()
} else {
this.earlySave = true
console.log('save change to early')
}
}
decryptMessage() {
try {
// this.msg = this.AESEncrypt.decrypt(this.msg, SessionStore.user.UserName)
} catch (error) {}
}
}