mirror of
https://github.com/FranP-code/Baileys.git
synced 2025-10-13 00:32:22 +00:00
457 lines
14 KiB
TypeScript
457 lines
14 KiB
TypeScript
import { WA } from '../Binary/Constants'
|
|
import { proto } from '../../WAMessage/WAMessage'
|
|
import { Agent } from 'https'
|
|
import KeyedDB from '@adiwajshing/keyed-db'
|
|
|
|
export const WS_URL = 'wss://web.whatsapp.com/ws'
|
|
export const DEFAULT_ORIGIN = 'https://web.whatsapp.com'
|
|
|
|
export const KEEP_ALIVE_INTERVAL_MS = 20*1000
|
|
|
|
// export the WAMessage Prototypes
|
|
export { proto as WAMessageProto }
|
|
export type WANode = WA.Node
|
|
export type WAMessage = proto.WebMessageInfo
|
|
export type WAMessageContent = proto.IMessage
|
|
export type WAContactMessage = proto.ContactMessage
|
|
export type WAMessageKey = proto.IMessageKey
|
|
export type WATextMessage = proto.ExtendedTextMessage
|
|
export type WAContextInfo = proto.IContextInfo
|
|
export type WAGenericMediaMessage = proto.IVideoMessage | proto.IImageMessage | proto.IAudioMessage | proto.IDocumentMessage | proto.IStickerMessage
|
|
export import WA_MESSAGE_STUB_TYPE = proto.WebMessageInfo.WebMessageInfoStubType
|
|
export import WA_MESSAGE_STATUS_TYPE = proto.WebMessageInfo.WebMessageInfoStatus
|
|
|
|
export type WAInitResponse = {
|
|
ref: string
|
|
ttl: number
|
|
status: 200
|
|
}
|
|
|
|
export interface WALocationMessage {
|
|
degreesLatitude: number
|
|
degreesLongitude: number
|
|
address?: string
|
|
}
|
|
/** Reverse stub type dictionary */
|
|
export const WA_MESSAGE_STUB_TYPES = function () {
|
|
const types = WA_MESSAGE_STUB_TYPE
|
|
const dict: Record<number, string> = {}
|
|
Object.keys(types).forEach(element => dict[ types[element] ] = element)
|
|
return dict
|
|
}()
|
|
|
|
export class BaileysError extends Error {
|
|
status?: number
|
|
context: any
|
|
|
|
constructor (message: string, context: any) {
|
|
super (message)
|
|
this.name = 'BaileysError'
|
|
this.status = context.status
|
|
this.context = context
|
|
}
|
|
}
|
|
export const TimedOutError = () => new BaileysError ('timed out', { status: 408 })
|
|
export const CancelledError = () => new BaileysError ('cancelled', { status: 500 })
|
|
|
|
export interface WAQuery {
|
|
json: any[] | WANode
|
|
binaryTags?: WATag
|
|
timeoutMs?: number
|
|
tag?: string
|
|
expect200?: boolean
|
|
waitForOpen?: boolean
|
|
longTag?: boolean
|
|
requiresPhoneConnection?: boolean
|
|
startDebouncedTimeout?: boolean
|
|
}
|
|
export enum ReconnectMode {
|
|
/** does not reconnect */
|
|
off = 0,
|
|
/** reconnects only when the connection is 'lost' or 'close' */
|
|
onConnectionLost = 1,
|
|
/** reconnects on all disconnects, including take overs */
|
|
onAllErrors = 2
|
|
}
|
|
export type WALoadChatOptions = {
|
|
searchString?: string
|
|
custom?: (c: WAChat) => boolean
|
|
loadProfilePicture?: boolean
|
|
}
|
|
export type WAConnectOptions = {
|
|
/**
|
|
* New QR generation interval, set to null if you don't want to regenerate
|
|
* @deprecated no need to set this as we use WA ttl
|
|
* */
|
|
regenerateQRIntervalMs?: number
|
|
/** fails the connection if no data is received for X seconds */
|
|
maxIdleTimeMs?: number
|
|
/** maximum attempts to connect */
|
|
maxRetries?: number
|
|
/**
|
|
* @deprecated -- use the `chats-received` & `contacts-received` events
|
|
* should the chats be waited for
|
|
* */
|
|
waitForChats?: boolean
|
|
/**
|
|
* @deprecated -- use the `chats-received` & `contacts-received` events
|
|
* if set to true, the connect only waits for the last message of the chat
|
|
* */
|
|
waitOnlyForLastMessage?: boolean
|
|
/** max time for the phone to respond to a connectivity test */
|
|
phoneResponseTime?: number
|
|
connectCooldownMs?: number
|
|
/** agent used for WS connections */
|
|
agent?: Agent
|
|
/** agent used for fetch requests -- uploading/downloading media */
|
|
fetchAgent?: Agent
|
|
/** Always uses takeover for connections */
|
|
alwaysUseTakeover?: boolean
|
|
}
|
|
/** from: https://stackoverflow.com/questions/3809401/what-is-a-good-regular-expression-to-match-a-url */
|
|
export const URL_REGEX = /[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)?/gi
|
|
|
|
export type WAConnectionState = 'open' | 'connecting' | 'close'
|
|
|
|
export const UNAUTHORIZED_CODES = [401, 419]
|
|
/** Types of Disconnect Reasons */
|
|
export enum DisconnectReason {
|
|
/** The connection was closed intentionally */
|
|
intentional = 'intentional',
|
|
/** The connection was terminated either by the client or server */
|
|
close = 'close',
|
|
/** The connection was lost, called when the server stops responding to requests */
|
|
lost = 'lost',
|
|
/** When WA Web is opened elsewhere & this session is disconnected */
|
|
replaced = 'replaced',
|
|
/** The credentials for the session have been invalidated, i.e. logged out either from the phone or WA Web */
|
|
invalidSession = 'invalid_session',
|
|
/** Received a 500 result in a query -- something has gone very wrong */
|
|
badSession = 'bad_session',
|
|
/** No idea, can be a sign of log out too */
|
|
unknown = 'unknown',
|
|
/** Well, the connection timed out */
|
|
timedOut = 'timed out'
|
|
}
|
|
export interface MediaConnInfo {
|
|
auth: string
|
|
ttl: number
|
|
hosts: {
|
|
hostname: string
|
|
}[]
|
|
fetchDate: Date
|
|
}
|
|
export interface AuthenticationCredentials {
|
|
clientID: string
|
|
serverToken: string
|
|
clientToken: string
|
|
encKey: Buffer
|
|
macKey: Buffer
|
|
}
|
|
export interface AuthenticationCredentialsBase64 {
|
|
clientID: string
|
|
serverToken: string
|
|
clientToken: string
|
|
encKey: string
|
|
macKey: string
|
|
}
|
|
export interface AuthenticationCredentialsBrowser {
|
|
WABrowserId: string
|
|
WASecretBundle: {encKey: string, macKey: string} | string
|
|
WAToken1: string
|
|
WAToken2: string
|
|
}
|
|
export type AnyAuthenticationCredentials = AuthenticationCredentialsBrowser | AuthenticationCredentialsBase64 | AuthenticationCredentials
|
|
|
|
export interface WAGroupCreateResponse {
|
|
status: number
|
|
gid?: string
|
|
participants?: [{ [key: string]: any }]
|
|
}
|
|
export interface WAGroupMetadata {
|
|
id: string
|
|
owner: string
|
|
subject: string
|
|
creation: number
|
|
desc?: string
|
|
descOwner?: string
|
|
descId?: string
|
|
/** is set when the group only allows admins to change group settings */
|
|
restrict?: 'true' | 'false'
|
|
/** is set when the group only allows admins to write messages */
|
|
announce?: 'true' | 'false'
|
|
participants: [{ id: string; isAdmin: boolean; isSuperAdmin: boolean }]
|
|
}
|
|
export interface WAGroupModification {
|
|
status: number
|
|
participants?: { [key: string]: any }
|
|
}
|
|
export interface WAPresenceData {
|
|
lastKnownPresence?: Presence
|
|
lastSeen?: number
|
|
name?: string
|
|
}
|
|
export interface WAContact extends WAPresenceData {
|
|
verify?: string
|
|
/** name of the contact, the contact has set on their own on WA */
|
|
notify?: string
|
|
jid: string
|
|
/** I have no idea */
|
|
vname?: string
|
|
/** name of the contact, you have saved on your WA */
|
|
name?: string
|
|
index?: string
|
|
/** short name for the contact */
|
|
short?: string
|
|
// Baileys Added
|
|
imgUrl?: string
|
|
}
|
|
export interface WAUser extends WAContact {
|
|
phone: any
|
|
}
|
|
export interface WAChat {
|
|
jid: string
|
|
|
|
t: number
|
|
/** number of unread messages, is < 0 if the chat is manually marked unread */
|
|
count: number
|
|
archive?: 'true' | 'false'
|
|
read_only?: 'true' | 'false'
|
|
mute?: string
|
|
pin?: string
|
|
spam: 'false' | 'true'
|
|
modify_tag: string
|
|
name?: string
|
|
|
|
// Baileys added properties
|
|
messages: KeyedDB<WAMessage, string>
|
|
imgUrl?: string
|
|
presences?: { [k: string]: WAPresenceData }
|
|
}
|
|
export type WAChatUpdate = Partial<WAChat> & { jid: string, hasNewMessage?: boolean }
|
|
export enum WAMetric {
|
|
debugLog = 1,
|
|
queryResume = 2,
|
|
liveLocation = 3,
|
|
queryMedia = 4,
|
|
queryChat = 5,
|
|
queryContact = 6,
|
|
queryMessages = 7,
|
|
presence = 8,
|
|
presenceSubscribe = 9,
|
|
group = 10,
|
|
read = 11,
|
|
chat = 12,
|
|
received = 13,
|
|
picture = 14,
|
|
status = 15,
|
|
message = 16,
|
|
queryActions = 17,
|
|
block = 18,
|
|
queryGroup = 19,
|
|
queryPreview = 20,
|
|
queryEmoji = 21,
|
|
queryVCard = 29,
|
|
queryStatus = 30,
|
|
queryStatusUpdate = 31,
|
|
queryLiveLocation = 33,
|
|
queryLabel = 36,
|
|
queryQuickReply = 39
|
|
}
|
|
|
|
export const STORIES_JID = 'status@broadcast'
|
|
|
|
export enum WAFlag {
|
|
available = 160,
|
|
ignore = 1 << 7,
|
|
acknowledge = 1 << 6,
|
|
unavailable = 1 << 4,
|
|
expires = 1 << 3,
|
|
composing = 1 << 2,
|
|
recording = 1 << 2,
|
|
paused = 1 << 2
|
|
}
|
|
/** Tag used with binary queries */
|
|
export type WATag = [WAMetric, WAFlag]
|
|
/** set of statuses visible to other people; see updatePresence() in WhatsAppWeb.Send */
|
|
export enum Presence {
|
|
unavailable = 'unavailable', // "offline"
|
|
available = 'available', // "online"
|
|
composing = 'composing', // "typing..."
|
|
recording = 'recording', // "recording..."
|
|
paused = 'paused', // stop typing
|
|
}
|
|
/** Set of message types that are supported by the library */
|
|
export enum MessageType {
|
|
text = 'conversation',
|
|
extendedText = 'extendedTextMessage',
|
|
contact = 'contactMessage',
|
|
location = 'locationMessage',
|
|
liveLocation = 'liveLocationMessage',
|
|
|
|
image = 'imageMessage',
|
|
video = 'videoMessage',
|
|
sticker = 'stickerMessage',
|
|
document = 'documentMessage',
|
|
audio = 'audioMessage',
|
|
product = 'productMessage'
|
|
}
|
|
|
|
export const MessageTypeProto = {
|
|
[MessageType.image]: proto.ImageMessage,
|
|
[MessageType.video]: proto.VideoMessage,
|
|
[MessageType.audio]: proto.AudioMessage,
|
|
[MessageType.sticker]: proto.StickerMessage,
|
|
[MessageType.document]: proto.DocumentMessage,
|
|
}
|
|
export enum ChatModification {
|
|
archive='archive',
|
|
unarchive='unarchive',
|
|
pin='pin',
|
|
unpin='unpin',
|
|
mute='mute',
|
|
unmute='unmute',
|
|
delete='delete'
|
|
}
|
|
export const HKDFInfoKeys = {
|
|
[MessageType.image]: 'WhatsApp Image Keys',
|
|
[MessageType.audio]: 'WhatsApp Audio Keys',
|
|
[MessageType.video]: 'WhatsApp Video Keys',
|
|
[MessageType.document]: 'WhatsApp Document Keys',
|
|
[MessageType.sticker]: 'WhatsApp Image Keys'
|
|
}
|
|
export enum Mimetype {
|
|
jpeg = 'image/jpeg',
|
|
png = 'image/png',
|
|
mp4 = 'video/mp4',
|
|
gif = 'video/gif',
|
|
pdf = 'application/pdf',
|
|
ogg = 'audio/ogg; codecs=opus',
|
|
mp4Audio = 'audio/mp4',
|
|
/** for stickers */
|
|
webp = 'image/webp',
|
|
}
|
|
export interface MessageOptions {
|
|
/** the message you want to quote */
|
|
quoted?: WAMessage
|
|
/** some random context info (can show a forwarded message with this too) */
|
|
contextInfo?: WAContextInfo
|
|
/** optional, if you want to manually set the timestamp of the message */
|
|
timestamp?: Date
|
|
/** (for media messages) the caption to send with the media (cannot be sent with stickers though) */
|
|
caption?: string
|
|
/**
|
|
* For location & media messages -- has to be a base 64 encoded JPEG if you want to send a custom thumb,
|
|
* or set to null if you don't want to send a thumbnail.
|
|
* Do not enter this field if you want to automatically generate a thumb
|
|
* */
|
|
thumbnail?: string
|
|
/** (for media messages) specify the type of media (optional for all media types except documents) */
|
|
mimetype?: Mimetype | string
|
|
/** (for media messages) file name for the media */
|
|
filename?: string
|
|
/** For audio messages, if set to true, will send as a `voice note` */
|
|
ptt?: boolean
|
|
/** Optional agent for media uploads */
|
|
uploadAgent?: Agent
|
|
/** If set to true (default), automatically detects if you're sending a link & attaches the preview*/
|
|
detectLinks?: boolean
|
|
/** Optionally specify the duration of the media (audio/video) in seconds */
|
|
duration?: number
|
|
/** Fetches new media options for every media file */
|
|
forceNewMediaOptions?: boolean
|
|
/** Wait for the message to be sent to the server (default true) */
|
|
waitForAck?: boolean
|
|
}
|
|
export interface WABroadcastListInfo {
|
|
status: number
|
|
name: string
|
|
recipients?: {id: string}[]
|
|
}
|
|
export interface WAUrlInfo {
|
|
'canonical-url': string
|
|
'matched-text': string
|
|
title: string
|
|
description: string
|
|
jpegThumbnail?: Buffer
|
|
}
|
|
export interface WAProfilePictureChange {
|
|
status: number
|
|
tag: string
|
|
eurl: string
|
|
}
|
|
export interface MessageInfo {
|
|
reads: {jid: string, t: string}[]
|
|
deliveries: {jid: string, t: string}[]
|
|
}
|
|
export interface WAMessageStatusUpdate {
|
|
from: string
|
|
to: string
|
|
/** Which participant caused the update (only for groups) */
|
|
participant?: string
|
|
timestamp: Date
|
|
/** Message IDs read/delivered */
|
|
ids: string[]
|
|
/** Status of the Message IDs */
|
|
type: WA_MESSAGE_STATUS_TYPE
|
|
}
|
|
|
|
export interface WAOpenResult {
|
|
/** Was this connection opened via a QR scan */
|
|
newConnection: boolean
|
|
user: WAUser
|
|
isNewUser: boolean
|
|
hasNewChats?: boolean
|
|
}
|
|
|
|
export enum GroupSettingChange {
|
|
messageSend = 'announcement',
|
|
settingsChange = 'locked',
|
|
}
|
|
export interface PresenceUpdate {
|
|
id: string
|
|
participant?: string
|
|
t?: string
|
|
type?: Presence
|
|
deny?: boolean
|
|
}
|
|
// path to upload the media
|
|
export const MediaPathMap = {
|
|
imageMessage: '/mms/image',
|
|
videoMessage: '/mms/video',
|
|
documentMessage: '/mms/document',
|
|
audioMessage: '/mms/audio',
|
|
stickerMessage: '/mms/image',
|
|
}
|
|
// gives WhatsApp info to process the media
|
|
export const MimetypeMap = {
|
|
imageMessage: Mimetype.jpeg,
|
|
videoMessage: Mimetype.mp4,
|
|
documentMessage: Mimetype.pdf,
|
|
audioMessage: Mimetype.ogg,
|
|
stickerMessage: Mimetype.webp,
|
|
}
|
|
export interface WASendMessageResponse {
|
|
status: number
|
|
messageID: string
|
|
message: WAMessage
|
|
}
|
|
export type WAParticipantAction = 'add' | 'remove' | 'promote' | 'demote'
|
|
export type BaileysEvent =
|
|
'open' |
|
|
'connecting' |
|
|
'close' |
|
|
'ws-close' |
|
|
'qr' |
|
|
'connection-phone-change' |
|
|
'user-status-update' |
|
|
'contacts-received' |
|
|
'chats-received' |
|
|
'chat-new' |
|
|
'chat-update' |
|
|
'message-status-update' |
|
|
'group-participants-update' |
|
|
'group-update' |
|
|
'received-pong' |
|
|
'credentials-updated' |
|
|
'connection-validated' |