softchatjs-core
Version:
Javascript client for JS based frameworks
1 lines • 14.6 kB
Source Map (JSON)
{"version":3,"sources":["../src/utils.ts","../src/Broadcast.ts"],"sourcesContent":["import moment from 'moment';\r\n\r\nimport { Conversation, StringOrNumber, Participant, ParticipantListInfo, Message, MessageStates, UserMeta } from \"./types\";\r\n\r\nfunction murmurHash3_x64_64(str: string, seed = 0) {\r\n let h1 = BigInt(seed);\r\n let h2 = BigInt(seed);\r\n const c1 = BigInt(\"0x87c37b91114253d5\");\r\n const c2 = BigInt(\"0x4cf5ad432745937f\");\r\n\r\n let length = str.length;\r\n const remainder = length & 15; // length % 16\r\n const bytes = length - remainder;\r\n\r\n for (let i = 0; i < bytes; i += 16) {\r\n let k1 =\r\n BigInt(str.charCodeAt(i)) |\r\n (BigInt(str.charCodeAt(i + 1)) << BigInt(8)) |\r\n (BigInt(str.charCodeAt(i + 2)) << BigInt(16)) |\r\n (BigInt(str.charCodeAt(i + 3)) << BigInt(24)) |\r\n (BigInt(str.charCodeAt(i + 4)) << BigInt(32)) |\r\n (BigInt(str.charCodeAt(i + 5)) << BigInt(40)) |\r\n (BigInt(str.charCodeAt(i + 6)) << BigInt(48)) |\r\n (BigInt(str.charCodeAt(i + 7)) << BigInt(56));\r\n\r\n let k2 =\r\n BigInt(str.charCodeAt(i + 8)) |\r\n (BigInt(str.charCodeAt(i + 9)) << BigInt(8)) |\r\n (BigInt(str.charCodeAt(i + 10)) << BigInt(16)) |\r\n (BigInt(str.charCodeAt(i + 11)) << BigInt(24)) |\r\n (BigInt(str.charCodeAt(i + 12)) << BigInt(32)) |\r\n (BigInt(str.charCodeAt(i + 13)) << BigInt(40)) |\r\n (BigInt(str.charCodeAt(i + 14)) << BigInt(48)) |\r\n (BigInt(str.charCodeAt(i + 15)) << BigInt(56));\r\n\r\n k1 = k1 * c1;\r\n k1 = (k1 << BigInt(31)) | (k1 >> BigInt(33));\r\n k1 = k1 * c2;\r\n h1 ^= k1;\r\n\r\n h1 = (h1 << BigInt(27)) | (h1 >> BigInt(37));\r\n h1 = h1 + h2;\r\n h1 = h1 * BigInt(5) + BigInt(\"0x52dce729\");\r\n\r\n k2 = k2 * c2;\r\n k2 = (k2 << BigInt(33)) | (k2 >> BigInt(31));\r\n k2 = k2 * c1;\r\n h2 ^= k2;\r\n\r\n h2 = (h2 << BigInt(31)) | (h2 >> BigInt(33));\r\n h2 = h1 + h2;\r\n h2 = h2 * BigInt(5) + BigInt(\"0x38495ab5\");\r\n }\r\n\r\n let k1 = BigInt(0);\r\n let k2 = BigInt(0);\r\n\r\n switch (remainder) {\r\n case 15:\r\n k2 ^= BigInt(str.charCodeAt(bytes + 14)) << BigInt(48);\r\n case 14:\r\n k2 ^= BigInt(str.charCodeAt(bytes + 13)) << BigInt(40);\r\n case 13:\r\n k2 ^= BigInt(str.charCodeAt(bytes + 12)) << BigInt(32);\r\n case 12:\r\n k2 ^= BigInt(str.charCodeAt(bytes + 11)) << BigInt(24);\r\n case 11:\r\n k2 ^= BigInt(str.charCodeAt(bytes + 10)) << BigInt(16);\r\n case 10:\r\n k2 ^= BigInt(str.charCodeAt(bytes + 9)) << BigInt(8);\r\n case 9:\r\n k2 ^= BigInt(str.charCodeAt(bytes + 8));\r\n k2 = k2 * c2;\r\n k2 = (k2 << BigInt(33)) | (k2 >> BigInt(31));\r\n k2 = k2 * c1;\r\n h2 ^= k2;\r\n case 8:\r\n k1 ^= BigInt(str.charCodeAt(bytes + 7)) << BigInt(56);\r\n case 7:\r\n k1 ^= BigInt(str.charCodeAt(bytes + 6)) << BigInt(48);\r\n case 6:\r\n k1 ^= BigInt(str.charCodeAt(bytes + 5)) << BigInt(40);\r\n case 5:\r\n k1 ^= BigInt(str.charCodeAt(bytes + 4)) << BigInt(32);\r\n case 4:\r\n k1 ^= BigInt(str.charCodeAt(bytes + 3)) << BigInt(24);\r\n case 3:\r\n k1 ^= BigInt(str.charCodeAt(bytes + 2)) << BigInt(16);\r\n case 2:\r\n k1 ^= BigInt(str.charCodeAt(bytes + 1)) << BigInt(8);\r\n case 1:\r\n k1 ^= BigInt(str.charCodeAt(bytes));\r\n k1 = k1 * c1;\r\n k1 = (k1 << BigInt(31)) | (k1 >> BigInt(33));\r\n k1 = k1 * c2;\r\n h1 ^= k1;\r\n }\r\n\r\n h1 ^= BigInt(length);\r\n h2 ^= BigInt(length);\r\n\r\n h1 += h2;\r\n h2 += h1;\r\n\r\n h1 ^= h1 >> BigInt(33);\r\n h1 = h1 * BigInt(\"0xff51afd7ed558ccd\");\r\n h1 ^= h1 >> BigInt(33);\r\n h1 = h1 * BigInt(\"0xc4ceb9fe1a85ec53\");\r\n h1 ^= h1 >> BigInt(33);\r\n\r\n h2 ^= h2 >> BigInt(33);\r\n h2 = h2 * BigInt(\"0xff51afd7ed558ccd\");\r\n h2 ^= h2 >> BigInt(33);\r\n h2 = h2 * BigInt(\"0xc4ceb9fe1a85ec53\");\r\n h2 ^= h2 >> BigInt(33);\r\n\r\n h1 += h2;\r\n h2 += h1;\r\n\r\n // Combine h1 and h2 to return a 64-bit hash\r\n return (h1 & BigInt(\"0xFFFFFFFFFFFFFFFF\")).toString(16);\r\n}\r\n\r\n// Updated generateConversationId using MurmurHash3 x64 (64-bit)\r\nexport function generateConversationId(str1: string, str2: string, projectId: string) {\r\n // Sort the strings alphabetically to ensure consistency\r\n const sortedStrings = [str1, str2].sort();\r\n // Concatenate the sorted strings with a delimiter\r\n const combinedString = sortedStrings.join(\"_\");\r\n // Generate a 64-bit hash of the combined string using MurmurHash3 x64\r\n const hash = murmurHash3_x64_64(`${projectId}:${combinedString}`);\r\n // Return the hash as the unique ID\r\n return hash;\r\n}\r\n\r\nexport const generateId = () => {\r\n let uuid = '';\r\n const characters = 'abcdef0123456789';\r\n for (let i = 0; i < 32; i++) {\r\n const randomNumber = Math.floor(Math.random() * characters.length);\r\n const character = characters.charAt(randomNumber);\r\n if (i === 8 || i === 12 || i === 16 || i === 20) {\r\n uuid += '-';\r\n }\r\n uuid += character;\r\n }\r\n return uuid;\r\n}\r\n\r\n\r\nexport const getUserInfoWithId = (userId: string, participantList: ParticipantListInfo[]): {\r\n presentUser: UserMeta | undefined,\r\n receivingUser: UserMeta | undefined,\r\n} => {\r\n let presentUser = participantList.find(participant => participant.participantId === userId);\r\n let otherParticipants = participantList.filter(participant => participant.participantId !== userId)\r\n return { presentUser: presentUser?.participantDetails, receivingUser: otherParticipants[0]?.participantDetails };\r\n};\r\n\r\nexport const truncate = (str: string, len: number) => {\r\n return str.length > len ? str.substring(0, len)+'...' : str;\r\n}\r\n\r\nexport const getConversationTitle = (userId: string, converstaion: Conversation) => {\r\n if(converstaion.conversationType === 'private-chat'){\r\n const userInfos = getUserInfoWithId(userId, converstaion.participantList);\r\n\r\n const firstname = userInfos.receivingUser?.firstname\r\n const username = userInfos.receivingUser?.username\r\n return firstname? firstname : username\r\n }\r\n if(converstaion.conversationType === 'group-chat') {\r\n return converstaion.groupMeta?.groupName || 'no-groupname'\r\n }\r\n}\r\n\r\nexport const getUsernameInitials = (username: string) =>{\r\n return username.substring(0, 1)\r\n}\r\n\r\nexport function formatMessageTime(time: Date | string) {\r\n return moment(new Date(time)).format(\"hh:mm a\");\r\n}\r\n\r\nexport function formatConversationTime(time: Date | string) {\r\n const now = moment();\r\n const then = moment(time);\r\n const duration = moment.duration(now.diff(then));\r\n\r\n // Get the largest unit\r\n const years = Math.floor(duration.asYears());\r\n if (years > 0) return years + 'yr';\r\n\r\n const months = Math.floor(duration.asMonths());\r\n if (months > 0) return months + 'mo';\r\n\r\n const weeks = Math.floor(duration.asWeeks());\r\n if (weeks > 0) return weeks + 'w';\r\n\r\n const days = Math.floor(duration.asDays());\r\n if (days > 0) return days + 'd';\r\n\r\n const hours = Math.floor(duration.asHours());\r\n if (hours > 0) return hours + 'h';\r\n\r\n const minutes = Math.floor(duration.asMinutes());\r\n if (minutes > 0) return minutes + 'm';\r\n\r\n // If duration is less than 1 minute\r\n return 'Just now';\r\n}\r\n\r\nexport const generateFillerTimestamps = () => {\r\n return {\r\n createdAt: new Date(),\r\n updatedAt: new Date(),\r\n }\r\n}\r\n\r\nexport const getUnreadMessageIds = (conversation: Conversation, userId: string) => {\r\n var ids: string[] = []\r\n conversation.messages.map(m => {\r\n if (m.messageState === MessageStates.SENT && m.from !== userId) {\r\n ids.push(m.messageId)\r\n }\r\n })\r\n return ids\r\n}\r\n\r\nexport const getQuotedMessage = (messageId: string, messages: Message[]) => {\r\n const message = messages.find(msg => msg.messageId === messageId)\r\n return message\r\n}\r\n","import Connection from \"./Connection\";\r\nimport { Errors } from \"./error\";\r\nimport { Events } from \"./events\";\r\nimport {\r\n AttachmentTypes,\r\n BroadcastListMeta,\r\n Conversation,\r\n ConversationListItem,\r\n ConversationType,\r\n GroupChatMeta,\r\n Message,\r\n MessageStates,\r\n Participant,\r\n Prettify,\r\n SendGroupMessageGenerics,\r\n SendMessageGenerics,\r\n ServerActions,\r\n UserMeta,\r\n} from \"./types\";\r\nimport {\r\n generateConversationId,\r\n generateFillerTimestamps,\r\n generateId,\r\n} from \"./utils\";\r\n\r\nlet userMetaSample = {\r\n id: \"\",\r\n username: \"\",\r\n email: \"\",\r\n firstname: \"\",\r\n lastname: \"\",\r\n profileImgUrl: \"\",\r\n phone: \"\",\r\n profileBannerUrl: \"\",\r\n custom: {},\r\n};\r\nexport default class BroadcastList {\r\n private static conversation: BroadcastList | null = null;\r\n private connection: Connection;\r\n private participants: UserMeta[];\r\n\r\n constructor(connection: Connection, participants: UserMeta[]) {\r\n this.connection = connection;\r\n this.participants = participants;\r\n }\r\n\r\n static getInstance(\r\n connection: Connection,\r\n participants: UserMeta[]\r\n ): BroadcastList {\r\n if (BroadcastList.conversation) {\r\n return BroadcastList.conversation;\r\n }\r\n BroadcastList.conversation = new BroadcastList(connection, participants);\r\n return BroadcastList.conversation;\r\n }\r\n\r\n private generateConversation(\r\n name: string,\r\n conversationId: string\r\n ): Conversation & { name: string } {\r\n const timeStamps = generateFillerTimestamps();\r\n const participantIds = this.participants.map((p) => p.uid);\r\n const senderObject = {\r\n id: generateId(),\r\n uid: this.connection.userMeta.uid,\r\n participantId: this.connection.userMeta.uid,\r\n participantDetails: {\r\n ...this.connection.userMeta,\r\n ...timeStamps,\r\n },\r\n ...timeStamps,\r\n };\r\n\r\n const updatedParticipantList = this.participants.map((participant) => ({\r\n id: generateId(),\r\n uid: participant.uid,\r\n participantId: participant.uid,\r\n participantDetails: {\r\n ...participant,\r\n ...timeStamps,\r\n },\r\n ...timeStamps,\r\n }));\r\n\r\n const participantList = [senderObject, ...updatedParticipantList];\r\n\r\n return {\r\n name,\r\n participants: [this.connection.userMeta.uid, ...participantIds],\r\n admins: [this.connection.userMeta.uid],\r\n conversationId,\r\n messages: [],\r\n conversationType: \"broadcast-chat\",\r\n participantList,\r\n meta: null,\r\n groupMeta: null,\r\n ...timeStamps,\r\n };\r\n }\r\n\r\n create(name: string = `${this.participants.length} Recipients`) {\r\n try {\r\n if (!this.connection) {\r\n throw new Error(\"Inialize uesr before calling method\");\r\n }\r\n const conversationId = generateId();\r\n const newConveration = this.generateConversation(name, conversationId);\r\n const socketMessage = {\r\n action: ServerActions.CREATE_BROADCAST_LIST,\r\n message: {\r\n conversationId,\r\n name: name,\r\n participants: this.participants,\r\n token: this.connection.wsAccessConfig.token,\r\n user: this.connection.userMeta,\r\n },\r\n };\r\n this.connection.socket.send(JSON.stringify(socketMessage));\r\n this.connection.broadcastListMeta[conversationId] = {\r\n conversation: newConveration,\r\n lastMessage: null,\r\n unread: [],\r\n };\r\n this.reset();\r\n this.connection.emit(Events.BROADCAST_LIST_META_CHANGED, {\r\n broadcastListMeta: this.connection.broadcastListMeta,\r\n });\r\n return {\r\n [conversationId]: {\r\n conversation: newConveration,\r\n lastMessage: null,\r\n unread: [],\r\n },\r\n };\r\n } catch (error) {\r\n if(error instanceof Error){\r\n console.error(error.message);\r\n }\r\n }\r\n }\r\n\r\n reset() {\r\n BroadcastList.conversation = null;\r\n }\r\n}\r\n"],"mappings":"AAAA,OAAOA,MAAY,SAuIZ,IAAMC,EAAa,IAAM,CAC5B,IAAIC,EAAO,GACLC,EAAa,mBACnB,QAASC,EAAI,EAAGA,EAAI,GAAIA,IAAK,CAC3B,IAAMC,EAAe,KAAK,MAAM,KAAK,OAAO,EAAIF,EAAW,MAAM,EAC3DG,EAAYH,EAAW,OAAOE,CAAY,GAC5CD,IAAM,GAAKA,IAAM,IAAMA,IAAM,IAAMA,IAAM,MAC3CF,GAAQ,KAEVA,GAAQI,CACV,CACA,OAAOJ,CACX,EAiEO,IAAMK,EAA2B,KAC/B,CACL,UAAW,IAAI,KACf,UAAW,IAAI,IACjB,GCpLF,IAAqBC,EAArB,MAAqBA,CAAc,CAKjC,YAAYC,EAAwBC,EAA0B,CAC5D,KAAK,WAAaD,EAClB,KAAK,aAAeC,CACtB,CAEA,OAAO,YACLD,EACAC,EACe,CACf,OAAIF,EAAc,eAGlBA,EAAc,aAAe,IAAIA,EAAcC,EAAYC,CAAY,GAChEF,EAAc,YACvB,CAEQ,qBACNG,EACAC,EACiC,CACjC,IAAMC,EAAaC,EAAyB,EACtCC,EAAiB,KAAK,aAAa,IAAKC,GAAMA,EAAE,GAAG,EACnDC,EAAe,CACnB,GAAIC,EAAW,EACf,IAAK,KAAK,WAAW,SAAS,IAC9B,cAAe,KAAK,WAAW,SAAS,IACxC,mBAAoB,CAClB,GAAG,KAAK,WAAW,SACnB,GAAGL,CACL,EACA,GAAGA,CACL,EAEMM,EAAyB,KAAK,aAAa,IAAKC,IAAiB,CACrE,GAAIF,EAAW,EACf,IAAKE,EAAY,IACjB,cAAeA,EAAY,IAC3B,mBAAoB,CAClB,GAAGA,EACH,GAAGP,CACL,EACA,GAAGA,CACL,EAAE,EAEIQ,EAAkB,CAACJ,EAAc,GAAGE,CAAsB,EAEhE,MAAO,CACL,KAAAR,EACA,aAAc,CAAC,KAAK,WAAW,SAAS,IAAK,GAAGI,CAAc,EAC9D,OAAQ,CAAC,KAAK,WAAW,SAAS,GAAG,EACrC,eAAAH,EACA,SAAU,CAAC,EACX,iBAAkB,iBAClB,gBAAAS,EACA,KAAM,KACN,UAAW,KACX,GAAGR,CACL,CACF,CAEA,OAAOF,EAAe,GAAG,KAAK,aAAa,MAAM,cAAe,CAC9D,GAAI,CACF,GAAI,CAAC,KAAK,WACR,MAAM,IAAI,MAAM,qCAAqC,EAEvD,IAAMC,EAAiBM,EAAW,EAC5BI,EAAiB,KAAK,qBAAqBX,EAAMC,CAAc,EAC/DW,EAAgB,CACpB,6BACA,QAAS,CACP,eAAAX,EACA,KAAMD,EACN,aAAc,KAAK,aACnB,MAAO,KAAK,WAAW,eAAe,MACtC,KAAM,KAAK,WAAW,QACxB,CACF,EACA,YAAK,WAAW,OAAO,KAAK,KAAK,UAAUY,CAAa,CAAC,EACzD,KAAK,WAAW,kBAAkBX,CAAc,EAAI,CAClD,aAAcU,EACd,YAAa,KACb,OAAQ,CAAC,CACX,EACA,KAAK,MAAM,EACX,KAAK,WAAW,mCAAyC,CACvD,kBAAmB,KAAK,WAAW,iBACrC,CAAC,EACM,CACL,CAACV,CAAc,EAAG,CAChB,aAAcU,EACd,YAAa,KACb,OAAQ,CAAC,CACX,CACF,CACF,OAASE,EAAO,CACXA,aAAiB,OAClB,QAAQ,MAAMA,EAAM,OAAO,CAE/B,CACF,CAEA,OAAQ,CACNhB,EAAc,aAAe,IAC/B,CACF,EA7GqBA,EACJ,aAAqC,KADtD,IAAqBiB,EAArBjB","names":["moment","generateId","uuid","characters","i","randomNumber","character","generateFillerTimestamps","_BroadcastList","connection","participants","name","conversationId","timeStamps","generateFillerTimestamps","participantIds","p","senderObject","generateId","updatedParticipantList","participant","participantList","newConveration","socketMessage","error","BroadcastList"]}