Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f6f09747dc | ||
|
|
27a534a605 | ||
|
|
3cbd940843 |
No files matched your search
+2
-2
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# Build
|
||||
#
|
||||
FROM node:18 as build
|
||||
FROM node:20-bullseye as build
|
||||
ENV PUPPETEER_SKIP_DOWNLOAD=True
|
||||
|
||||
# npm packages
|
||||
@@ -20,7 +20,7 @@ RUN yarn build && find ./dist -name "*.d.ts" -delete
|
||||
#
|
||||
# Final
|
||||
#
|
||||
FROM node:18 as release
|
||||
FROM node:20-bullseye as release
|
||||
ENV PUPPETEER_SKIP_DOWNLOAD=True
|
||||
ARG USE_BROWSER=chromium
|
||||
|
||||
|
||||
@@ -12,7 +12,55 @@ weight: 801
|
||||
You can get presence information (online, offline with last seen, typing status) for a contact if they share their
|
||||
presence information.
|
||||
|
||||
{{< alert icon="👉" text="Presence endpoints and webhook is available only in **NOWEB** engine." />}}
|
||||
Possible presence statuses that you can set or get for chats:
|
||||
- `online`
|
||||
- `offline`
|
||||
- `typing`
|
||||
- `recording`
|
||||
- `paused` resets the chat presence after you were `typing`
|
||||
|
||||
|
||||
## Endpoints
|
||||
|
||||
### Set presence
|
||||
You can set your global or chat-related presence with `POST /api/{session}/presence` endpoint
|
||||
|
||||
Start typing to a chat (you can use `POST /startTyping` instead)
|
||||
```json
|
||||
{
|
||||
"chatId": "111111111@c.us",
|
||||
"presence": "typing"
|
||||
}
|
||||
```
|
||||
|
||||
Clear "typing" state (you can use `POST /stopTyping` instead)
|
||||
```json
|
||||
{
|
||||
"chatId": "111111111@c.us",
|
||||
"presence": "paused"
|
||||
}
|
||||
```
|
||||
|
||||
Set global "online", all contacts will see it
|
||||
```json
|
||||
{
|
||||
"presence": "online"
|
||||
}
|
||||
```
|
||||
|
||||
💡 In the multi-device version of WhatsApp - if a desktop client is active, WhatsApp doesn't send push notifications
|
||||
to the device.
|
||||
If you would like to receive said notifications - you need to mark a session's presence as `offline`.
|
||||
|
||||
```json
|
||||
{
|
||||
"presence": "offline"
|
||||
}
|
||||
```
|
||||
|
||||
### Get all chats presence
|
||||
|
||||
{{< alert icon="👉" text="Get presence endpoints and webhook is available only in **NOWEB** engine." />}}
|
||||
[Read more about engines to choose right for you ->]({{< relref "/docs/how-to/engines" >}})
|
||||
|
||||
Here's few notes about fields:
|
||||
@@ -22,9 +70,6 @@ Here's few notes about fields:
|
||||
- `lastKnownPresence` - contains the last known presence status, which can be
|
||||
`offline`, `online`, `typing`, `recording`, or `paused`
|
||||
|
||||
## Endpoints
|
||||
|
||||
### Get all presence
|
||||
|
||||
You can get all presence information available for a session by calling `GET /api/{session}/presence/`.
|
||||
It returns both groups' and personal chats' presence information.
|
||||
|
||||
@@ -12,6 +12,12 @@ menu:
|
||||
weight: 199
|
||||
toc: true
|
||||
---
|
||||
## 2023.8
|
||||
August 2023
|
||||
- Added [set presence endpoint](https://waha.devlike.pro/docs/how-to/presence)!
|
||||
- With `online` presence you can show your status as online [#121](https://github.com/devlikeapro/whatsapp-http-api/issues/121)
|
||||
- With `offline` presence you can get notifications for your device [#28](https://github.com/devlikeapro/whatsapp-http-api/issues/28)
|
||||
|
||||
## 2023.7
|
||||
July 2023
|
||||
- Now session can have their own [Webhooks](https://waha.devlike.pro/docs/how-to/webhooks) -
|
||||
|
||||
@@ -16,6 +16,8 @@ toc: true
|
||||
On this page you're going to install WAHA, run it, authenticate the client using QR code and send the first text message
|
||||
to WhatsApp!
|
||||
|
||||

|
||||
|
||||
## Requirements
|
||||
|
||||
Only thing that you must have - installed docker. Please follow the original
|
||||
|
||||
@@ -1,10 +1,21 @@
|
||||
import { Controller, Get, Param, Post } from '@nestjs/common';
|
||||
import {
|
||||
BadRequestException,
|
||||
Body,
|
||||
Controller,
|
||||
Get,
|
||||
Param,
|
||||
Post,
|
||||
} from '@nestjs/common';
|
||||
import { ApiOperation, ApiSecurity, ApiTags } from '@nestjs/swagger';
|
||||
|
||||
import { SessionManager } from '../core/abc/manager.abc';
|
||||
import { WhatsappSession } from '../core/abc/session.abc';
|
||||
import { WAHAChatPresences } from '../structures/presence.dto';
|
||||
import {
|
||||
WAHAChatPresences,
|
||||
WAHASessionPresence,
|
||||
} from '../structures/presence.dto';
|
||||
import { SessionApiParam, SessionParam } from './helpers';
|
||||
import { WAHAPresenceStatus } from '../structures/enums.dto';
|
||||
|
||||
@ApiSecurity('api_key')
|
||||
@Controller('api/:session/presence')
|
||||
@@ -12,6 +23,36 @@ import { SessionApiParam, SessionParam } from './helpers';
|
||||
export class PresenceController {
|
||||
constructor(private manager: SessionManager) {}
|
||||
|
||||
@Post('')
|
||||
@SessionApiParam
|
||||
@ApiOperation({ summary: 'Set session presence' })
|
||||
setPresence(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@Body() request: WAHASessionPresence,
|
||||
) {
|
||||
// Validate request
|
||||
const presencesWithoutChatId = [
|
||||
WAHAPresenceStatus.ONLINE,
|
||||
WAHAPresenceStatus.OFFLINE,
|
||||
];
|
||||
const requiresNoChatId = presencesWithoutChatId.includes(request.presence);
|
||||
const requiresChatId = !requiresNoChatId;
|
||||
|
||||
if (requiresNoChatId && request.chatId) {
|
||||
const msg = {
|
||||
detail: `'${request.presence}' presence works on the global scope and doesn't require 'chatId' field.`,
|
||||
};
|
||||
throw new BadRequestException(msg);
|
||||
} else if (requiresChatId && !request.chatId) {
|
||||
const msg = {
|
||||
detail: `'${request.presence}' presence requires 'chatId' field.`,
|
||||
};
|
||||
throw new BadRequestException(msg);
|
||||
}
|
||||
|
||||
return session.setPresence(request.presence, request.chatId);
|
||||
}
|
||||
|
||||
@Get('')
|
||||
@SessionApiParam
|
||||
@ApiOperation({ summary: 'Get all subscribed presence information.' })
|
||||
|
||||
@@ -22,6 +22,7 @@ import { ContactQuery, ContactRequest } from '../../structures/contacts.dto';
|
||||
import {
|
||||
WAHAEngine,
|
||||
WAHAEvents,
|
||||
WAHAPresenceStatus,
|
||||
WAHASessionStatus,
|
||||
} from '../../structures/enums.dto';
|
||||
import {
|
||||
@@ -257,6 +258,10 @@ export abstract class WhatsappSession {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public setPresence(presence: WAHAPresenceStatus, chatId?: string) {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public getPresences(): Promise<WAHAChatPresences[]> {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import { Agent } from 'https';
|
||||
import * as lodash from 'lodash';
|
||||
import { Message } from 'whatsapp-web.js';
|
||||
|
||||
import { flipObject } from '../helpers';
|
||||
import {
|
||||
Button,
|
||||
ChatRequest,
|
||||
@@ -78,6 +79,7 @@ const PresenceStatuses = {
|
||||
recording: WAHAPresenceStatus.RECORDING,
|
||||
paused: WAHAPresenceStatus.PAUSED,
|
||||
};
|
||||
const ToEnginePresenceStatus = flipObject(PresenceStatuses);
|
||||
|
||||
export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
engine = WAHAEngine.NOWEB;
|
||||
@@ -414,6 +416,16 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
return this.sock.groupParticipantsUpdate(id, participants, 'demote');
|
||||
}
|
||||
|
||||
public async setPresence(presence: WAHAPresenceStatus, chatId?: string) {
|
||||
const enginePresence = ToEnginePresenceStatus[presence];
|
||||
if (!enginePresence) {
|
||||
throw new NotImplementedByEngineError(
|
||||
`NOWEB engine doesn't support '${presence}' presence.`,
|
||||
);
|
||||
}
|
||||
await this.sock.sendPresenceUpdate(enginePresence, chatId);
|
||||
}
|
||||
|
||||
public async getPresences(): Promise<WAHAChatPresences[]> {
|
||||
const result: WAHAChatPresences[] = [];
|
||||
for (const remoteJid in this.store.presences) {
|
||||
|
||||
@@ -33,6 +33,7 @@ import { ContactQuery, ContactRequest } from '../structures/contacts.dto';
|
||||
import {
|
||||
WAHAEngine,
|
||||
WAHAEvents,
|
||||
WAHAPresenceStatus,
|
||||
WAHASessionStatus,
|
||||
} from '../structures/enums.dto';
|
||||
import {
|
||||
@@ -366,6 +367,34 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
return groupChat.demoteParticipants(participantIds);
|
||||
}
|
||||
|
||||
public async setPresence(presence: WAHAPresenceStatus, chatId?: string) {
|
||||
let chat: Chat;
|
||||
switch (presence) {
|
||||
case WAHAPresenceStatus.ONLINE:
|
||||
await this.whatsapp.sendPresenceAvailable();
|
||||
break;
|
||||
case WAHAPresenceStatus.OFFLINE:
|
||||
await this.whatsapp.sendPresenceUnavailable();
|
||||
break;
|
||||
case WAHAPresenceStatus.TYPING:
|
||||
chat = await this.whatsapp.getChatById(chatId);
|
||||
await chat.sendStateTyping();
|
||||
break;
|
||||
case WAHAPresenceStatus.RECORDING:
|
||||
chat = await this.whatsapp.getChatById(chatId);
|
||||
await chat.sendStateRecording();
|
||||
break;
|
||||
case WAHAPresenceStatus.PAUSED:
|
||||
chat = await this.whatsapp.getChatById(chatId);
|
||||
await chat.clearState();
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedByEngineError(
|
||||
`WEBJS engine doesn't support '${presence}' presence.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* END - Methods for API
|
||||
*/
|
||||
|
||||
@@ -24,10 +24,7 @@ export class SwaggerModuleCore {
|
||||
'E.g: \`12312312310\` OR \`12312312310@c.us\`<br>`,
|
||||
)
|
||||
.addTag('groups', `Groups methods.<br>`)
|
||||
.addTag(
|
||||
'presence',
|
||||
`Presence information. Available in <b>NOWEB</b> engine only.<br>`,
|
||||
)
|
||||
.addTag('presence', `Presence information`)
|
||||
.addTag('other', 'Other methods')
|
||||
.addApiKey({
|
||||
type: 'apiKey',
|
||||
|
||||
+9
-1
@@ -1,4 +1,4 @@
|
||||
export function parseBool(value: any): boolean {
|
||||
function parseBool(value: any): boolean {
|
||||
if (!value) {
|
||||
return false;
|
||||
}
|
||||
@@ -18,3 +18,11 @@ export function parseBool(value: any): boolean {
|
||||
'Error: parseBool got unexpected value - use "true" or "false" values',
|
||||
);
|
||||
}
|
||||
|
||||
function flipObject(object) {
|
||||
return Object.fromEntries(
|
||||
Object.entries(object).map(([key, value]) => [value, key]),
|
||||
);
|
||||
}
|
||||
|
||||
export { flipObject, parseBool };
|
||||
@@ -22,3 +22,13 @@ export class WAHAChatPresences {
|
||||
id: string;
|
||||
presences: WAHAPresenceData[];
|
||||
}
|
||||
|
||||
export class WAHASessionPresence {
|
||||
presence: WAHAPresenceStatus;
|
||||
|
||||
@ApiProperty({
|
||||
description: 'Chat ID - either group id or contact id',
|
||||
example: '11111111111@c.us',
|
||||
})
|
||||
chatId: string;
|
||||
}
|
||||
+1
-1
@@ -26,7 +26,7 @@ export function getWAHAVersion(): WAHAVersion {
|
||||
}
|
||||
|
||||
export const VERSION = {
|
||||
version: '2023.7.1',
|
||||
version: '2023.7.12',
|
||||
tier: getWAHAVersion(),
|
||||
browser: getBrowserExecutablePath(),
|
||||
};
|
||||
Reference in new issue
Block a user