initial commit
This commit is contained in:
@@ -0,0 +1,298 @@
|
||||
import type {
|
||||
ChatDTO,
|
||||
ContactDTO,
|
||||
GroupMetadataDTO,
|
||||
GroupParticipantDTO,
|
||||
LocationDTO,
|
||||
MessageDTO,
|
||||
MessageIdDTO,
|
||||
SerializedId,
|
||||
} from "../shared/dto";
|
||||
|
||||
/**
|
||||
* WA models contain a lot of internal properties and sometimes
|
||||
* circular references. Never JSON.stringify them directly.
|
||||
*/
|
||||
export function serialize(value: any): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
return value.map(serialize);
|
||||
}
|
||||
|
||||
if (typeof value !== "object") {
|
||||
return value;
|
||||
}
|
||||
|
||||
const result: Record<string, unknown> = {};
|
||||
|
||||
for (const key of Object.keys(value)) {
|
||||
const v = value[key];
|
||||
|
||||
if (
|
||||
typeof v === "string" ||
|
||||
typeof v === "number" ||
|
||||
typeof v === "boolean" ||
|
||||
v === null
|
||||
) {
|
||||
result[key] = v;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function safeProperty<T>(object: unknown, key: string): T | undefined {
|
||||
try {
|
||||
if (object && typeof object === "object") {
|
||||
return (object as any)[key];
|
||||
}
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function safeGet<T = unknown>(
|
||||
object: unknown,
|
||||
key: string,
|
||||
): T | undefined {
|
||||
if (object == null || typeof object !== "object") {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
try {
|
||||
return (object as any)[key];
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export function pick<T extends object>(
|
||||
source: any,
|
||||
keys: readonly string[],
|
||||
): Partial<T> {
|
||||
const result: Record<string, unknown> = {};
|
||||
|
||||
for (const key of keys) {
|
||||
const value = safeGet(source, key);
|
||||
|
||||
if (value !== undefined) {
|
||||
result[key] = serialize(value);
|
||||
}
|
||||
}
|
||||
|
||||
return result as Partial<T>;
|
||||
}
|
||||
|
||||
export function serializeId(id: any): SerializedId | string | null {
|
||||
if (id == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (typeof id === "string") {
|
||||
return id;
|
||||
}
|
||||
|
||||
if (typeof id !== "object") {
|
||||
return String(id);
|
||||
}
|
||||
|
||||
const result: SerializedId = {};
|
||||
|
||||
for (const key of [
|
||||
"_serialized",
|
||||
"user",
|
||||
"server",
|
||||
"domain",
|
||||
"device",
|
||||
"agent",
|
||||
"fromMe",
|
||||
"remote",
|
||||
"participant",
|
||||
]) {
|
||||
const value = safeGet(id, key);
|
||||
|
||||
if (value !== undefined) {
|
||||
result[key] = serialize(value) as any;
|
||||
}
|
||||
}
|
||||
|
||||
// Some WA objects expose useful fields that aren't
|
||||
// enumerable.
|
||||
if (!result._serialized && typeof safeGet(id, "toString") === "function") {
|
||||
try {
|
||||
const serialized = id.toString();
|
||||
|
||||
if (serialized && serialized !== "[object Object]") {
|
||||
result._serialized = serialized;
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
|
||||
return Object.keys(result).length ? result : String(id);
|
||||
}
|
||||
|
||||
export function serializeChat(chat: any): ChatDTO {
|
||||
return {
|
||||
id: serializeId(chat.id),
|
||||
accountLid: chat.accountLid,
|
||||
name: chat.name,
|
||||
formattedTitle: chat.formattedTitle,
|
||||
|
||||
isGroup: chat.isGroup,
|
||||
isUser: chat.isUser,
|
||||
isReadOnly: chat.isReadOnly,
|
||||
archived: chat.archived,
|
||||
unreadCount: chat.unreadCount,
|
||||
|
||||
timestamp: chat.t,
|
||||
lastMessage: chat.lastMessage ? serialize(chat.lastMessage) : null,
|
||||
};
|
||||
}
|
||||
|
||||
export function serializeContact(contact: any): ContactDTO {
|
||||
return {
|
||||
id: serializeId(contact.id),
|
||||
|
||||
accountLid: contact.accountLid ?? null,
|
||||
name: contact.name ?? null,
|
||||
pushname: contact.pushname ?? null,
|
||||
shortName: contact.shortName ?? null,
|
||||
formattedName: contact.formattedName ?? null,
|
||||
number: contact.number ?? null,
|
||||
|
||||
isMe: contact.isMe ?? false,
|
||||
isUser: contact.isUser ?? false,
|
||||
isBusiness: contact.isBusiness ?? false,
|
||||
isEnterprise: contact.isEnterprise ?? false,
|
||||
isGroup: contact.isGroup ?? false,
|
||||
isMyContact: contact.isMyContact ?? false,
|
||||
isBlocked: contact.isBlocked ?? false,
|
||||
|
||||
profilePicThumbObj: contact.profilePicThumbObj
|
||||
? serialize(contact.profilePicThumbObj)
|
||||
: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
export function serializeGroupParticipant(
|
||||
participant: any,
|
||||
): GroupParticipantDTO {
|
||||
return {
|
||||
id: serializeId(participant.id),
|
||||
|
||||
isAdmin: participant.isAdmin ?? false,
|
||||
isSuperAdmin: participant.isSuperAdmin ?? false,
|
||||
isSuperParticipant: participant.isSuperParticipant ?? false,
|
||||
isBusiness: participant.isBusiness ?? false,
|
||||
};
|
||||
}
|
||||
|
||||
export function serializeGroupMetadata(metadata: any): GroupMetadataDTO {
|
||||
return {
|
||||
id: serializeId(metadata.id),
|
||||
|
||||
subject: metadata.subject ?? null,
|
||||
subjectOwner: serializeId(metadata.subjectOwner),
|
||||
subjectTime: metadata.subjectTime ?? null,
|
||||
creation: metadata.creation ?? null,
|
||||
owner: serializeId(metadata.owner),
|
||||
|
||||
participants: Array.isArray(metadata.participants)
|
||||
? (metadata.participants
|
||||
.map(serializeGroupParticipant)
|
||||
.filter(Boolean) as GroupParticipantDTO[])
|
||||
: [],
|
||||
|
||||
size: metadata.size ?? metadata.participants?.length ?? 0,
|
||||
restrict: metadata.restrict ?? false,
|
||||
announce: metadata.announce ?? false,
|
||||
isCommunity: metadata.isCommunity ?? false,
|
||||
isCommunityAnnounce: metadata.isCommunityAnnounce ?? false,
|
||||
};
|
||||
}
|
||||
export function serializeMessageId(id: any): MessageIdDTO | null {
|
||||
if (!id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
id: id.id ?? null,
|
||||
_serialized: id._serialized ?? null,
|
||||
fromMe: id.fromMe ?? false,
|
||||
remote: serializeId(id.remote),
|
||||
participant: serializeId(id.participant),
|
||||
};
|
||||
}
|
||||
export function serializeLocation(location: any): LocationDTO | null {
|
||||
if (!location) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
latitude: location.latitude ?? null,
|
||||
longitude: location.longitude ?? null,
|
||||
description: location.description ?? null,
|
||||
address: location.address ?? null,
|
||||
url: location.url ?? null,
|
||||
name: location.name ?? null,
|
||||
};
|
||||
}
|
||||
export function serializeMessageLink(link: any): any {
|
||||
return {
|
||||
link: link?.link ?? null,
|
||||
isSuspicious: link?.isSuspicious ?? false,
|
||||
};
|
||||
}
|
||||
export function serializeMessage(message: any): MessageDTO {
|
||||
const quotedMsgId = safeProperty<any>(message, "quotedMsgId");
|
||||
const hasQuoted = !!quotedMsgId;
|
||||
let quotedMsg = null;
|
||||
|
||||
if (hasQuoted) {
|
||||
const rawQuoted = safeProperty<any>(message, "quotedMsg");
|
||||
if (rawQuoted) {
|
||||
quotedMsg = serializeMessage(rawQuoted);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
id: serializeMessageId(message.id)!,
|
||||
chatId: message.chatId ?? message.id?.remote?._serialized ?? null,
|
||||
from: serializeId(message.from),
|
||||
to: serializeId(message.to),
|
||||
author: serializeId(message.author),
|
||||
fromMe: message.fromMe ?? false,
|
||||
body: message.body ?? null,
|
||||
caption: message.caption ?? null,
|
||||
type: message.type ?? null,
|
||||
subtype: message.subtype ?? null,
|
||||
timestamp: message.timestamp ?? null,
|
||||
ack: message.ack ?? null,
|
||||
hasMedia: message.hasMedia ?? false,
|
||||
mediaKey: message.mediaKey ?? null,
|
||||
isForwarded: message.isForwarded ?? false,
|
||||
forwardingScore: message.forwardingScore ?? 0,
|
||||
isStarred: message.isStarred ?? false,
|
||||
broadcast: message.broadcast ?? false,
|
||||
mentionedIds: Array.isArray(message.mentionedIds)
|
||||
? message.mentionedIds.map(serializeId)
|
||||
: [],
|
||||
quotedMsgId: serializeMessageId(quotedMsgId),
|
||||
quotedMsg,
|
||||
links: Array.isArray(message.links)
|
||||
? message.links.map(serializeMessageLink)
|
||||
: [],
|
||||
location: serializeLocation(message.location),
|
||||
vCard: message.vCard ?? null,
|
||||
vCards: Array.isArray(message.vCards) ? message.vCards : [],
|
||||
filename: message.filename ?? null,
|
||||
mimetype: message.mimetype ?? null,
|
||||
size: message.size ?? null,
|
||||
duration: message.duration ?? null,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user