diff --git a/dist/whatsapp-bridge.user.js b/dist/whatsapp-bridge.user.js index 68ded0a..f6c6dfb 100644 --- a/dist/whatsapp-bridge.user.js +++ b/dist/whatsapp-bridge.user.js @@ -2,7 +2,7 @@ // ==UserScript== // @name WhatsApp Web Bridge // @namespace https://rul.sh/ -// @version 0.0.8 +// @version 0.0.9 // @description WhatsApp Web WebSocket bridge // @match https://web.whatsapp.com/* // @updateURL https://git.rul.sh/khairul169/whatsapp-bridge/raw/branch/main/dist/whatsapp-bridge.user.js @@ -342,6 +342,7 @@ type: "event", event: "ready", data: { + version: "0.0.9", authenticated: WPP.conn.isAuthenticated(), deviceId: consts.DEVICE_ID, deviceName: consts.DEVICE_NAME diff --git a/dist/whatsapp-bridge.user.js.map b/dist/whatsapp-bridge.user.js.map index 10881cf..2f7d0a1 100644 --- a/dist/whatsapp-bridge.user.js.map +++ b/dist/whatsapp-bridge.user.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../src/userscript/serializer.ts", "../src/userscript/index.ts"], - "sourcesContent": ["import type {\r\n ChatDTO,\r\n ContactDTO,\r\n GroupMetadataDTO,\r\n GroupParticipantDTO,\r\n LocationDTO,\r\n MessageDTO,\r\n MessageIdDTO,\r\n SerializedId,\r\n} from \"../shared/dto\";\r\n\r\n/**\r\n * WA models contain a lot of internal properties and sometimes\r\n * circular references. Never JSON.stringify them directly.\r\n */\r\nexport function serialize(value: any): any {\r\n if (value == null) {\r\n return value;\r\n }\r\n\r\n if (Array.isArray(value)) {\r\n return value.map(serialize);\r\n }\r\n\r\n if (typeof value !== \"object\") {\r\n return value;\r\n }\r\n\r\n const result: Record = {};\r\n\r\n for (const key of Object.keys(value)) {\r\n const v = value[key];\r\n\r\n if (\r\n typeof v === \"string\" ||\r\n typeof v === \"number\" ||\r\n typeof v === \"boolean\" ||\r\n v === null\r\n ) {\r\n result[key] = v;\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\nfunction safeProperty(object: unknown, key: string): T | undefined {\r\n try {\r\n if (object && typeof object === \"object\") {\r\n return (object as any)[key];\r\n }\r\n } catch {\r\n return undefined;\r\n }\r\n\r\n return undefined;\r\n}\r\n\r\nexport function safeGet(\r\n object: unknown,\r\n key: string,\r\n): T | undefined {\r\n if (object == null || typeof object !== \"object\") {\r\n return undefined;\r\n }\r\n\r\n try {\r\n return (object as any)[key];\r\n } catch {\r\n return undefined;\r\n }\r\n}\r\n\r\nexport function pick(\r\n source: any,\r\n keys: readonly string[],\r\n): Partial {\r\n const result: Record = {};\r\n\r\n for (const key of keys) {\r\n const value = safeGet(source, key);\r\n\r\n if (value !== undefined) {\r\n result[key] = serialize(value);\r\n }\r\n }\r\n\r\n return result as Partial;\r\n}\r\n\r\nexport function serializeId(id: any): SerializedId | string | null {\r\n if (id == null) {\r\n return null;\r\n }\r\n\r\n if (typeof id === \"string\") {\r\n return id;\r\n }\r\n\r\n if (typeof id !== \"object\") {\r\n return String(id);\r\n }\r\n\r\n const result: SerializedId = {};\r\n\r\n for (const key of [\r\n \"_serialized\",\r\n \"user\",\r\n \"server\",\r\n \"domain\",\r\n \"device\",\r\n \"agent\",\r\n \"fromMe\",\r\n \"remote\",\r\n \"participant\",\r\n ]) {\r\n const value = safeGet(id, key);\r\n\r\n if (value !== undefined) {\r\n result[key] = serialize(value) as any;\r\n }\r\n }\r\n\r\n // Some WA objects expose useful fields that aren't\r\n // enumerable.\r\n if (!result._serialized && typeof safeGet(id, \"toString\") === \"function\") {\r\n try {\r\n const serialized = id.toString();\r\n\r\n if (serialized && serialized !== \"[object Object]\") {\r\n result._serialized = serialized;\r\n }\r\n } catch {}\r\n }\r\n\r\n return Object.keys(result).length ? result : String(id);\r\n}\r\n\r\nexport function serializeChat(chat: any): ChatDTO {\r\n const rawPreviewMessage = safeProperty(chat, \"previewMessage\");\r\n\r\n return {\r\n id: serializeId(chat.id),\r\n accountLid: chat.accountLid,\r\n name: chat.name,\r\n formattedTitle: chat.formattedTitle,\r\n\r\n isGroup: chat.isGroup,\r\n isUser: chat.isUser,\r\n isReadOnly: chat.isReadOnly,\r\n archived: chat.archived,\r\n unreadCount: chat.unreadCount,\r\n previewMessage: rawPreviewMessage\r\n ? serializeMessage(rawPreviewMessage)\r\n : null,\r\n\r\n timestamp: chat.t,\r\n lastMessage: chat.lastMessage ? serialize(chat.lastMessage) : null,\r\n };\r\n}\r\n\r\nexport function serializeContact(contact: any): ContactDTO {\r\n return {\r\n id: serializeId(contact.id),\r\n\r\n accountLid: contact.accountLid ?? null,\r\n name: contact.name ?? null,\r\n pushname: contact.pushname ?? null,\r\n shortName: contact.shortName ?? null,\r\n formattedName: contact.formattedName ?? null,\r\n notifyName: contact.notifyName ?? null,\r\n number: contact.number ?? null,\r\n\r\n isMe: contact.isMe ?? false,\r\n isUser: contact.isUser ?? false,\r\n isBusiness: contact.isBusiness ?? false,\r\n isEnterprise: contact.isEnterprise ?? false,\r\n isGroup: contact.isGroup ?? false,\r\n isMyContact: contact.isMyContact ?? false,\r\n isBlocked: contact.isBlocked ?? false,\r\n\r\n profilePicThumbObj: contact.profilePicThumbObj\r\n ? serialize(contact.profilePicThumbObj)\r\n : undefined,\r\n };\r\n}\r\n\r\nexport function serializeGroupParticipant(\r\n participant: any,\r\n): GroupParticipantDTO {\r\n return {\r\n id: serializeId(participant.id),\r\n\r\n isAdmin: participant.isAdmin ?? false,\r\n isSuperAdmin: participant.isSuperAdmin ?? false,\r\n isSuperParticipant: participant.isSuperParticipant ?? false,\r\n isBusiness: participant.isBusiness ?? false,\r\n };\r\n}\r\n\r\nexport function serializeGroupMetadata(metadata: any): GroupMetadataDTO {\r\n return {\r\n id: serializeId(metadata.id),\r\n\r\n subject: metadata.subject ?? null,\r\n subjectOwner: serializeId(metadata.subjectOwner),\r\n subjectTime: metadata.subjectTime ?? null,\r\n creation: metadata.creation ?? null,\r\n owner: serializeId(metadata.owner),\r\n\r\n participants: Array.isArray(metadata.participants)\r\n ? (metadata.participants\r\n .map(serializeGroupParticipant)\r\n .filter(Boolean) as GroupParticipantDTO[])\r\n : [],\r\n\r\n size: metadata.size ?? metadata.participants?.length ?? 0,\r\n restrict: metadata.restrict ?? false,\r\n announce: metadata.announce ?? false,\r\n isCommunity: metadata.isCommunity ?? false,\r\n isCommunityAnnounce: metadata.isCommunityAnnounce ?? false,\r\n };\r\n}\r\nexport function serializeMessageId(id: any): MessageIdDTO | null {\r\n if (!id) {\r\n return null;\r\n }\r\n\r\n return {\r\n id: id.id ?? null,\r\n _serialized: id._serialized ?? null,\r\n fromMe: id.fromMe ?? false,\r\n remote: serializeId(id.remote),\r\n participant: serializeId(id.participant),\r\n };\r\n}\r\nexport function serializeLocation(location: any): LocationDTO | null {\r\n if (!location) {\r\n return null;\r\n }\r\n\r\n return {\r\n latitude: location.latitude ?? null,\r\n longitude: location.longitude ?? null,\r\n description: location.description ?? null,\r\n address: location.address ?? null,\r\n url: location.url ?? null,\r\n name: location.name ?? null,\r\n };\r\n}\r\nexport function serializeMessageLink(link: any): any {\r\n return {\r\n link: link?.link ?? null,\r\n isSuspicious: link?.isSuspicious ?? false,\r\n };\r\n}\r\nexport function serializeMessage(message: any): MessageDTO {\r\n const quotedMsgId = safeProperty(message, \"quotedMsgId\");\r\n const hasQuoted = !!quotedMsgId;\r\n let quotedMsg = null;\r\n\r\n if (hasQuoted) {\r\n const rawQuoted = safeProperty(message, \"quotedMsg\");\r\n if (rawQuoted) {\r\n quotedMsg = serializeMessage(rawQuoted);\r\n }\r\n }\r\n\r\n return {\r\n id: serializeMessageId(message.id)!,\r\n chatId: message.chatId ?? message.id?.remote?._serialized ?? null,\r\n from: serializeId(message.from),\r\n to: serializeId(message.to),\r\n author: serializeId(message.author),\r\n fromMe: message.id?.fromMe || message.fromMe || false,\r\n body: message.body ?? null,\r\n caption: message.caption ?? null,\r\n type: message.type ?? null,\r\n subtype: message.subtype ?? null,\r\n timestamp: message.t ?? message.timestamp ?? null,\r\n ack: message.ack ?? null,\r\n hasMedia: message.hasMedia ?? false,\r\n mediaKey: message.mediaKey ?? null,\r\n isForwarded: message.isForwarded ?? false,\r\n forwardingScore: message.forwardingScore ?? 0,\r\n isStarred: message.isStarred ?? false,\r\n broadcast: message.broadcast ?? false,\r\n notifyName: message.notifyName ?? null,\r\n mentionedIds: Array.isArray(message.mentionedIds)\r\n ? message.mentionedIds.map(serializeId)\r\n : [],\r\n quotedMsgId: serializeMessageId(quotedMsgId),\r\n quotedMsg,\r\n links: Array.isArray(message.links)\r\n ? message.links.map(serializeMessageLink)\r\n : [],\r\n location: serializeLocation(message.location),\r\n vCard: message.vCard ?? null,\r\n vCards: Array.isArray(message.vCards) ? message.vCards : [],\r\n filename: message.filename ?? null,\r\n mimetype: message.mimetype ?? null,\r\n size: message.size ?? null,\r\n duration: message.duration ?? null,\r\n };\r\n}\r\n", "import type { BridgeRequest } from \"../shared/protocol\";\r\nimport {\r\n serialize,\r\n serializeChat,\r\n serializeContact,\r\n serializeGroupMetadata,\r\n serializeMessage,\r\n} from \"./serializer\";\r\n\r\nlet socket: WebSocket | undefined;\r\nlet consts: Record = {\r\n DEVICE_ID: String(Date.now()),\r\n DEVICE_NAME: \"\",\r\n};\r\n\r\nfunction init() {\r\n try {\r\n const _consts = localStorage.getItem(\"wa-bridge-consts\");\r\n if (!_consts) {\r\n localStorage.setItem(\"wa-bridge-consts\", JSON.stringify(consts));\r\n } else {\r\n consts = JSON.parse(_consts);\r\n }\r\n } catch (_) {}\r\n}\r\n\r\nfunction send(message: unknown) {\r\n if (socket?.readyState !== WebSocket.OPEN) {\r\n throw new Error(\"WebSocket is not connected\");\r\n }\r\n\r\n socket.send(JSON.stringify(message));\r\n}\r\n\r\nfunction reply(id: string, result: unknown) {\r\n send({\r\n type: \"response\",\r\n id,\r\n ok: true,\r\n result: serialize(result),\r\n });\r\n}\r\n\r\nfunction error(id: string, err: unknown) {\r\n send({\r\n type: \"response\",\r\n id,\r\n ok: false,\r\n error: {\r\n code: \"ERROR\",\r\n message:\r\n typeof err === \"object\" && \"message\" in err!\r\n ? err.message\r\n : String(err),\r\n },\r\n });\r\n}\r\n\r\nasync function handleRequest(request: BridgeRequest) {\r\n switch (request.method) {\r\n case \"status\":\r\n return {\r\n authenticated: WPP.conn.isAuthenticated(),\r\n ready: WPP.isReady,\r\n deviceId: consts.DEVICE_ID,\r\n deviceName: consts.DEVICE_NAME,\r\n };\r\n\r\n case \"listChats\": {\r\n const chats = await WPP.chat.list({\r\n ...(request.params?.limit != null\r\n ? { count: request.params.limit }\r\n : {}),\r\n ...(request.params?.groupsOnly ? { onlyGroups: true } : {}),\r\n ...(request.params?.usersOnly ? { onlyUsers: true } : {}),\r\n });\r\n\r\n return chats.filter(Boolean).map(serializeChat);\r\n }\r\n\r\n case \"listContacts\": {\r\n const contacts = await WPP.contact.list();\r\n\r\n const result = request.params?.limit\r\n ? contacts.slice(0, request.params.limit)\r\n : contacts;\r\n\r\n return result.filter(Boolean).map(serializeContact);\r\n }\r\n\r\n case \"listGroups\": {\r\n const groups = await WPP.group.getAllGroups();\r\n\r\n return groups\r\n .filter((i) => i.groupMetadata != null)\r\n .map((i) => serializeGroupMetadata(i.groupMetadata));\r\n }\r\n\r\n case \"getMessages\": {\r\n const messages = await WPP.chat.getMessages(request.params.chatId, {\r\n count: request.params.count ?? 50,\r\n direction: request.params.direction,\r\n id: request.params.id,\r\n });\r\n\r\n return messages.filter(Boolean).map(serializeMessage);\r\n }\r\n\r\n case \"sendText\": {\r\n const result = await WPP.chat.sendTextMessage(\r\n request.params.chatId,\r\n request.params.text,\r\n request.params.options,\r\n );\r\n\r\n return serialize(result);\r\n }\r\n\r\n case \"sendFile\": {\r\n const result = await WPP.chat.sendFileMessage(\r\n request.params.chatId,\r\n request.params.data,\r\n request.params.options,\r\n );\r\n\r\n return serialize(result);\r\n }\r\n\r\n case \"getMedia\":\r\n const media = await WPP.chat\r\n .downloadMedia(request.params)\r\n .then(WPP.util.blobToBase64);\r\n return media;\r\n\r\n case \"exec\":\r\n const fn = new Function(request.params);\r\n return fn();\r\n\r\n default:\r\n throw new Error(`Unknown method: ${(request as any).method}`);\r\n }\r\n}\r\n\r\nfunction connect() {\r\n if (\r\n socket &&\r\n (socket.readyState === WebSocket.OPEN ||\r\n socket.readyState === WebSocket.CONNECTING)\r\n ) {\r\n return;\r\n }\r\n\r\n socket = new WebSocket(__WS_URL__);\r\n\r\n socket.onopen = () => {\r\n console.log(\"[WA Bridge] connected\", __WS_URL__);\r\n\r\n send({\r\n type: \"event\",\r\n event: \"ready\",\r\n data: {\r\n authenticated: WPP.conn.isAuthenticated(),\r\n deviceId: consts.DEVICE_ID,\r\n deviceName: consts.DEVICE_NAME,\r\n },\r\n });\r\n };\r\n\r\n socket.onmessage = async (event) => {\r\n try {\r\n const request = JSON.parse(event.data) as BridgeRequest;\r\n\r\n if (request.type === \"ping\") {\r\n send({ type: \"pong\" });\r\n }\r\n\r\n if (request.type !== \"request\") {\r\n return;\r\n }\r\n\r\n try {\r\n const result = await handleRequest(request);\r\n\r\n reply(request.id, JSON.stringify(result));\r\n } catch (err) {\r\n error(request.id, err);\r\n }\r\n } catch (err) {\r\n console.error(\"[WA Bridge] invalid message\", err);\r\n }\r\n };\r\n\r\n socket.onclose = (event) => {\r\n console.log(\"[WA Bridge] disconnected\", {\r\n code: event.code,\r\n reason: event.reason,\r\n wasClean: event.wasClean,\r\n });\r\n\r\n socket = undefined;\r\n setTimeout(connect, 3000);\r\n };\r\n\r\n socket.onerror = (event) => {\r\n console.error(\"[WA Bridge] websocket error\", event);\r\n };\r\n}\r\n\r\nfunction start() {\r\n WPP.loader.onReady(() => {\r\n console.log(\"[WA Bridge] WA-JS ready\");\r\n\r\n connect();\r\n\r\n /*\r\n * Forward new-message events to Node.\r\n */\r\n WPP.on(\"chat.new_message\", (message: unknown) => {\r\n if (socket?.readyState !== WebSocket.OPEN) {\r\n return;\r\n }\r\n\r\n send({\r\n type: \"event\",\r\n event: \"message\",\r\n data: serializeMessage(message),\r\n });\r\n });\r\n });\r\n}\r\n\r\ninit();\r\nstart();\r\n"], - "mappings": "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", + "sourcesContent": ["import type {\r\n ChatDTO,\r\n ContactDTO,\r\n GroupMetadataDTO,\r\n GroupParticipantDTO,\r\n LocationDTO,\r\n MessageDTO,\r\n MessageIdDTO,\r\n SerializedId,\r\n} from \"../shared/dto\";\r\n\r\n/**\r\n * WA models contain a lot of internal properties and sometimes\r\n * circular references. Never JSON.stringify them directly.\r\n */\r\nexport function serialize(value: any): any {\r\n if (value == null) {\r\n return value;\r\n }\r\n\r\n if (Array.isArray(value)) {\r\n return value.map(serialize);\r\n }\r\n\r\n if (typeof value !== \"object\") {\r\n return value;\r\n }\r\n\r\n const result: Record = {};\r\n\r\n for (const key of Object.keys(value)) {\r\n const v = value[key];\r\n\r\n if (\r\n typeof v === \"string\" ||\r\n typeof v === \"number\" ||\r\n typeof v === \"boolean\" ||\r\n v === null\r\n ) {\r\n result[key] = v;\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\nfunction safeProperty(object: unknown, key: string): T | undefined {\r\n try {\r\n if (object && typeof object === \"object\") {\r\n return (object as any)[key];\r\n }\r\n } catch {\r\n return undefined;\r\n }\r\n\r\n return undefined;\r\n}\r\n\r\nexport function safeGet(\r\n object: unknown,\r\n key: string,\r\n): T | undefined {\r\n if (object == null || typeof object !== \"object\") {\r\n return undefined;\r\n }\r\n\r\n try {\r\n return (object as any)[key];\r\n } catch {\r\n return undefined;\r\n }\r\n}\r\n\r\nexport function pick(\r\n source: any,\r\n keys: readonly string[],\r\n): Partial {\r\n const result: Record = {};\r\n\r\n for (const key of keys) {\r\n const value = safeGet(source, key);\r\n\r\n if (value !== undefined) {\r\n result[key] = serialize(value);\r\n }\r\n }\r\n\r\n return result as Partial;\r\n}\r\n\r\nexport function serializeId(id: any): SerializedId | string | null {\r\n if (id == null) {\r\n return null;\r\n }\r\n\r\n if (typeof id === \"string\") {\r\n return id;\r\n }\r\n\r\n if (typeof id !== \"object\") {\r\n return String(id);\r\n }\r\n\r\n const result: SerializedId = {};\r\n\r\n for (const key of [\r\n \"_serialized\",\r\n \"user\",\r\n \"server\",\r\n \"domain\",\r\n \"device\",\r\n \"agent\",\r\n \"fromMe\",\r\n \"remote\",\r\n \"participant\",\r\n ]) {\r\n const value = safeGet(id, key);\r\n\r\n if (value !== undefined) {\r\n result[key] = serialize(value) as any;\r\n }\r\n }\r\n\r\n // Some WA objects expose useful fields that aren't\r\n // enumerable.\r\n if (!result._serialized && typeof safeGet(id, \"toString\") === \"function\") {\r\n try {\r\n const serialized = id.toString();\r\n\r\n if (serialized && serialized !== \"[object Object]\") {\r\n result._serialized = serialized;\r\n }\r\n } catch {}\r\n }\r\n\r\n return Object.keys(result).length ? result : String(id);\r\n}\r\n\r\nexport function serializeChat(chat: any): ChatDTO {\r\n const rawPreviewMessage = safeProperty(chat, \"previewMessage\");\r\n\r\n return {\r\n id: serializeId(chat.id),\r\n accountLid: chat.accountLid,\r\n name: chat.name,\r\n formattedTitle: chat.formattedTitle,\r\n\r\n isGroup: chat.isGroup,\r\n isUser: chat.isUser,\r\n isReadOnly: chat.isReadOnly,\r\n archived: chat.archived,\r\n unreadCount: chat.unreadCount,\r\n previewMessage: rawPreviewMessage\r\n ? serializeMessage(rawPreviewMessage)\r\n : null,\r\n\r\n timestamp: chat.t,\r\n lastMessage: chat.lastMessage ? serialize(chat.lastMessage) : null,\r\n };\r\n}\r\n\r\nexport function serializeContact(contact: any): ContactDTO {\r\n return {\r\n id: serializeId(contact.id),\r\n\r\n accountLid: contact.accountLid ?? null,\r\n name: contact.name ?? null,\r\n pushname: contact.pushname ?? null,\r\n shortName: contact.shortName ?? null,\r\n formattedName: contact.formattedName ?? null,\r\n notifyName: contact.notifyName ?? null,\r\n number: contact.number ?? null,\r\n\r\n isMe: contact.isMe ?? false,\r\n isUser: contact.isUser ?? false,\r\n isBusiness: contact.isBusiness ?? false,\r\n isEnterprise: contact.isEnterprise ?? false,\r\n isGroup: contact.isGroup ?? false,\r\n isMyContact: contact.isMyContact ?? false,\r\n isBlocked: contact.isBlocked ?? false,\r\n\r\n profilePicThumbObj: contact.profilePicThumbObj\r\n ? serialize(contact.profilePicThumbObj)\r\n : undefined,\r\n };\r\n}\r\n\r\nexport function serializeGroupParticipant(\r\n participant: any,\r\n): GroupParticipantDTO {\r\n return {\r\n id: serializeId(participant.id),\r\n\r\n isAdmin: participant.isAdmin ?? false,\r\n isSuperAdmin: participant.isSuperAdmin ?? false,\r\n isSuperParticipant: participant.isSuperParticipant ?? false,\r\n isBusiness: participant.isBusiness ?? false,\r\n };\r\n}\r\n\r\nexport function serializeGroupMetadata(metadata: any): GroupMetadataDTO {\r\n return {\r\n id: serializeId(metadata.id),\r\n\r\n subject: metadata.subject ?? null,\r\n subjectOwner: serializeId(metadata.subjectOwner),\r\n subjectTime: metadata.subjectTime ?? null,\r\n creation: metadata.creation ?? null,\r\n owner: serializeId(metadata.owner),\r\n\r\n participants: Array.isArray(metadata.participants)\r\n ? (metadata.participants\r\n .map(serializeGroupParticipant)\r\n .filter(Boolean) as GroupParticipantDTO[])\r\n : [],\r\n\r\n size: metadata.size ?? metadata.participants?.length ?? 0,\r\n restrict: metadata.restrict ?? false,\r\n announce: metadata.announce ?? false,\r\n isCommunity: metadata.isCommunity ?? false,\r\n isCommunityAnnounce: metadata.isCommunityAnnounce ?? false,\r\n };\r\n}\r\nexport function serializeMessageId(id: any): MessageIdDTO | null {\r\n if (!id) {\r\n return null;\r\n }\r\n\r\n return {\r\n id: id.id ?? null,\r\n _serialized: id._serialized ?? null,\r\n fromMe: id.fromMe ?? false,\r\n remote: serializeId(id.remote),\r\n participant: serializeId(id.participant),\r\n };\r\n}\r\nexport function serializeLocation(location: any): LocationDTO | null {\r\n if (!location) {\r\n return null;\r\n }\r\n\r\n return {\r\n latitude: location.latitude ?? null,\r\n longitude: location.longitude ?? null,\r\n description: location.description ?? null,\r\n address: location.address ?? null,\r\n url: location.url ?? null,\r\n name: location.name ?? null,\r\n };\r\n}\r\nexport function serializeMessageLink(link: any): any {\r\n return {\r\n link: link?.link ?? null,\r\n isSuspicious: link?.isSuspicious ?? false,\r\n };\r\n}\r\nexport function serializeMessage(message: any): MessageDTO {\r\n const quotedMsgId = safeProperty(message, \"quotedMsgId\");\r\n const hasQuoted = !!quotedMsgId;\r\n let quotedMsg = null;\r\n\r\n if (hasQuoted) {\r\n const rawQuoted = safeProperty(message, \"quotedMsg\");\r\n if (rawQuoted) {\r\n quotedMsg = serializeMessage(rawQuoted);\r\n }\r\n }\r\n\r\n return {\r\n id: serializeMessageId(message.id)!,\r\n chatId: message.chatId ?? message.id?.remote?._serialized ?? null,\r\n from: serializeId(message.from),\r\n to: serializeId(message.to),\r\n author: serializeId(message.author),\r\n fromMe: message.id?.fromMe || message.fromMe || false,\r\n body: message.body ?? null,\r\n caption: message.caption ?? null,\r\n type: message.type ?? null,\r\n subtype: message.subtype ?? null,\r\n timestamp: message.t ?? message.timestamp ?? null,\r\n ack: message.ack ?? null,\r\n hasMedia: message.hasMedia ?? false,\r\n mediaKey: message.mediaKey ?? null,\r\n isForwarded: message.isForwarded ?? false,\r\n forwardingScore: message.forwardingScore ?? 0,\r\n isStarred: message.isStarred ?? false,\r\n broadcast: message.broadcast ?? false,\r\n notifyName: message.notifyName ?? null,\r\n mentionedIds: Array.isArray(message.mentionedIds)\r\n ? message.mentionedIds.map(serializeId)\r\n : [],\r\n quotedMsgId: serializeMessageId(quotedMsgId),\r\n quotedMsg,\r\n links: Array.isArray(message.links)\r\n ? message.links.map(serializeMessageLink)\r\n : [],\r\n location: serializeLocation(message.location),\r\n vCard: message.vCard ?? null,\r\n vCards: Array.isArray(message.vCards) ? message.vCards : [],\r\n filename: message.filename ?? null,\r\n mimetype: message.mimetype ?? null,\r\n size: message.size ?? null,\r\n duration: message.duration ?? null,\r\n };\r\n}\r\n", "import type { BridgeRequest } from \"../shared/protocol\";\r\nimport {\r\n serialize,\r\n serializeChat,\r\n serializeContact,\r\n serializeGroupMetadata,\r\n serializeMessage,\r\n} from \"./serializer\";\r\n\r\nlet socket: WebSocket | undefined;\r\nlet consts: Record = {\r\n DEVICE_ID: String(Date.now()),\r\n DEVICE_NAME: \"\",\r\n};\r\n\r\nfunction init() {\r\n try {\r\n const _consts = localStorage.getItem(\"wa-bridge-consts\");\r\n if (!_consts) {\r\n localStorage.setItem(\"wa-bridge-consts\", JSON.stringify(consts));\r\n } else {\r\n consts = JSON.parse(_consts);\r\n }\r\n } catch (_) {}\r\n}\r\n\r\nfunction send(message: unknown) {\r\n if (socket?.readyState !== WebSocket.OPEN) {\r\n throw new Error(\"WebSocket is not connected\");\r\n }\r\n\r\n socket.send(JSON.stringify(message));\r\n}\r\n\r\nfunction reply(id: string, result: unknown) {\r\n send({\r\n type: \"response\",\r\n id,\r\n ok: true,\r\n result: serialize(result),\r\n });\r\n}\r\n\r\nfunction error(id: string, err: unknown) {\r\n send({\r\n type: \"response\",\r\n id,\r\n ok: false,\r\n error: {\r\n code: \"ERROR\",\r\n message:\r\n typeof err === \"object\" && \"message\" in err!\r\n ? err.message\r\n : String(err),\r\n },\r\n });\r\n}\r\n\r\nasync function handleRequest(request: BridgeRequest) {\r\n switch (request.method) {\r\n case \"status\":\r\n return {\r\n authenticated: WPP.conn.isAuthenticated(),\r\n ready: WPP.isReady,\r\n deviceId: consts.DEVICE_ID,\r\n deviceName: consts.DEVICE_NAME,\r\n };\r\n\r\n case \"listChats\": {\r\n const chats = await WPP.chat.list({\r\n ...(request.params?.limit != null\r\n ? { count: request.params.limit }\r\n : {}),\r\n ...(request.params?.groupsOnly ? { onlyGroups: true } : {}),\r\n ...(request.params?.usersOnly ? { onlyUsers: true } : {}),\r\n });\r\n\r\n return chats.filter(Boolean).map(serializeChat);\r\n }\r\n\r\n case \"listContacts\": {\r\n const contacts = await WPP.contact.list();\r\n\r\n const result = request.params?.limit\r\n ? contacts.slice(0, request.params.limit)\r\n : contacts;\r\n\r\n return result.filter(Boolean).map(serializeContact);\r\n }\r\n\r\n case \"listGroups\": {\r\n const groups = await WPP.group.getAllGroups();\r\n\r\n return groups\r\n .filter((i) => i.groupMetadata != null)\r\n .map((i) => serializeGroupMetadata(i.groupMetadata));\r\n }\r\n\r\n case \"getMessages\": {\r\n const messages = await WPP.chat.getMessages(request.params.chatId, {\r\n count: request.params.count ?? 50,\r\n direction: request.params.direction,\r\n id: request.params.id,\r\n });\r\n\r\n return messages.filter(Boolean).map(serializeMessage);\r\n }\r\n\r\n case \"sendText\": {\r\n const result = await WPP.chat.sendTextMessage(\r\n request.params.chatId,\r\n request.params.text,\r\n request.params.options,\r\n );\r\n\r\n return serialize(result);\r\n }\r\n\r\n case \"sendFile\": {\r\n const result = await WPP.chat.sendFileMessage(\r\n request.params.chatId,\r\n request.params.data,\r\n request.params.options,\r\n );\r\n\r\n return serialize(result);\r\n }\r\n\r\n case \"getMedia\":\r\n const media = await WPP.chat\r\n .downloadMedia(request.params)\r\n .then(WPP.util.blobToBase64);\r\n return media;\r\n\r\n case \"exec\":\r\n const fn = new Function(request.params);\r\n return fn();\r\n\r\n default:\r\n throw new Error(`Unknown method: ${(request as any).method}`);\r\n }\r\n}\r\n\r\nfunction connect() {\r\n if (\r\n socket &&\r\n (socket.readyState === WebSocket.OPEN ||\r\n socket.readyState === WebSocket.CONNECTING)\r\n ) {\r\n return;\r\n }\r\n\r\n socket = new WebSocket(__WS_URL__);\r\n\r\n socket.onopen = () => {\r\n console.log(\"[WA Bridge] connected\", __WS_URL__);\r\n\r\n send({\r\n type: \"event\",\r\n event: \"ready\",\r\n data: {\r\n version: __VERSION__,\r\n authenticated: WPP.conn.isAuthenticated(),\r\n deviceId: consts.DEVICE_ID,\r\n deviceName: consts.DEVICE_NAME,\r\n },\r\n });\r\n };\r\n\r\n socket.onmessage = async (event) => {\r\n try {\r\n const request = JSON.parse(event.data) as BridgeRequest;\r\n\r\n if (request.type === \"ping\") {\r\n send({ type: \"pong\" });\r\n }\r\n\r\n if (request.type !== \"request\") {\r\n return;\r\n }\r\n\r\n try {\r\n const result = await handleRequest(request);\r\n\r\n reply(request.id, JSON.stringify(result));\r\n } catch (err) {\r\n error(request.id, err);\r\n }\r\n } catch (err) {\r\n console.error(\"[WA Bridge] invalid message\", err);\r\n }\r\n };\r\n\r\n socket.onclose = (event) => {\r\n console.log(\"[WA Bridge] disconnected\", {\r\n code: event.code,\r\n reason: event.reason,\r\n wasClean: event.wasClean,\r\n });\r\n\r\n socket = undefined;\r\n setTimeout(connect, 3000);\r\n };\r\n\r\n socket.onerror = (event) => {\r\n console.error(\"[WA Bridge] websocket error\", event);\r\n };\r\n}\r\n\r\nfunction start() {\r\n WPP.loader.onReady(() => {\r\n console.log(\"[WA Bridge] WA-JS ready\");\r\n\r\n connect();\r\n\r\n /*\r\n * Forward new-message events to Node.\r\n */\r\n WPP.on(\"chat.new_message\", (message: unknown) => {\r\n if (socket?.readyState !== WebSocket.OPEN) {\r\n return;\r\n }\r\n\r\n send({\r\n type: \"event\",\r\n event: \"message\",\r\n data: serializeMessage(message),\r\n });\r\n });\r\n });\r\n}\r\n\r\ninit();\r\nstart();\r\n"], + "mappings": "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", "names": [] } diff --git a/esbuild.mjs b/esbuild.mjs index 3e422e7..b252d20 100644 --- a/esbuild.mjs +++ b/esbuild.mjs @@ -22,6 +22,7 @@ await esbuild.build({ target: "es2020", define: { + __VERSION__: JSON.stringify(VERSION), __WS_URL__: JSON.stringify(WS_URL), }, diff --git a/package.json b/package.json index a0d389a..0d73e87 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "whatsapp-bridge", "module": "index.ts", "type": "module", - "version": "0.0.8", + "version": "0.0.9", "private": true, "scripts": { "build": "bun run esbuild.mjs", diff --git a/src/userscript/index.ts b/src/userscript/index.ts index dc6576f..dd11c6f 100644 --- a/src/userscript/index.ts +++ b/src/userscript/index.ts @@ -159,6 +159,7 @@ function connect() { type: "event", event: "ready", data: { + version: __VERSION__, authenticated: WPP.conn.isAuthenticated(), deviceId: consts.DEVICE_ID, deviceName: consts.DEVICE_NAME, diff --git a/src/userscript/types.d.ts b/src/userscript/types.d.ts index 8260b69..2533d56 100644 --- a/src/userscript/types.d.ts +++ b/src/userscript/types.d.ts @@ -1,3 +1,4 @@ +declare const __VERSION__: string; declare const __WS_URL__: string; type SendMessageOptions = {