[core] add chats limit and offset

This commit is contained in:
devlikepro committed 2024-06-17 10:36:51 +07:00
1 parent e48c76397c
commit 74b6a8fdba
15 files changed
+169 -85

No files matched your search

+2 -1
View File
@@ -39,7 +39,8 @@
"async-lock": "^1.4.1",
"better-sqlite3": "9.6.0",
"check-disk-space": "^3.4.0",
"class-validator": "^0.12.2",
"class-transformer": "^0.5.1",
"class-validator": "0.14.0",
"del": "^6.0.0",
"express-basic-auth": "^1.2.1",
"file-type": "16.5.4",
+10 -5
View File
@@ -4,16 +4,17 @@ import {
Delete,
Get,
Param,
Post,
Put,
Query,
UsePipes,
ValidationPipe,
} 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 { parseBool } from '../helpers';
import { GetChatMessagesQuery } from '../structures/chats.dto';
import { GetChatMessagesQuery, GetChatsQuery } from '../structures/chats.dto';
import { EditMessageRequest } from '../structures/chatting.dto';
import {
ChatIdApiParam,
@@ -25,14 +26,18 @@ import {
@ApiSecurity('api_key')
@Controller('api/:session/chats')
@ApiTags('chats')
@UsePipes(new ValidationPipe({ transform: true }))
class ChatsController {
constructor(private manager: SessionManager) {}
@Get('')
@SessionApiParam
@ApiOperation({ summary: 'Get all chats' })
getAllChats(@SessionParam session: WhatsappSession) {
return session.getChats();
@ApiOperation({ summary: 'Get chats' })
getChats(
@SessionParam session: WhatsappSession,
@Query() query: GetChatsQuery,
) {
return session.getChats(query);
}
@Delete(':chatId')
+2 -1
View File
@@ -1,4 +1,5 @@
import { ConsoleLogger } from '@nestjs/common';
import { GetChatsQuery } from '@waha/structures/chats.dto';
import { EventEmitter } from 'events';
import * as fs from 'fs';
import { MessageId } from 'whatsapp-web.js';
@@ -285,7 +286,7 @@ export abstract class WhatsappSession {
/**
* Chats methods
*/
public getChats() {
public getChats(query: GetChatsQuery) {
throw new NotImplementedByEngineError();
}
+3 -2
View File
@@ -20,6 +20,7 @@ import { UnprocessableEntityException } from '@nestjs/common';
import { NowebInMemoryStore } from '@waha/core/engines/noweb/store/NowebInMemoryStore';
import { flipObject, getLogLevels, parseBool, splitAt } from '@waha/helpers';
import { PairingCodeResponse } from '@waha/structures/auth.dto';
import { GetChatsQuery } from '@waha/structures/chats.dto';
import { ContactQuery, ContactRequest } from '@waha/structures/contacts.dto';
import {
PollVote,
@@ -623,8 +624,8 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
* Chats methods
*/
async getChats() {
const chats = await this.store.getChats();
async getChats(query: GetChatsQuery) {
const chats = await this.store.getChats(query.limit, query.offset);
// Remove unreadCount, it's not ready yet
chats.forEach((chat) => delete chat.unreadCount);
return chats;
@@ -3,7 +3,7 @@ import { Chat } from '@adiwajshing/baileys';
export interface IChatRepository {
getAll(): Promise<Chat[]>;
getAllWithMessages(): Promise<Chat[]>;
getAllWithMessages(limit?: number, offset?: number): Promise<Chat[]>;
getById(id: string): Promise<Chat | null>;
+1 -1
View File
@@ -18,7 +18,7 @@ export interface INowebStore {
getMessagesByJid(chatId: string, limit: number): Promise<any>;
getChats(): Promise<Chat[]>;
getChats(limit?: number, offset?: number): Promise<Chat[]>;
getContacts(): Promise<Contact[]>;
@@ -40,7 +40,7 @@ export class NowebInMemoryStore implements INowebStore {
throw new BadRequestException(this.errorMessage);
}
getChats(): Promise<Chat[]> {
getChats(limit?: number, offset?: number): Promise<Chat[]> {
throw new BadRequestException(this.errorMessage);
}
@@ -291,8 +291,8 @@ export class NowebPersistentStore implements INowebStore {
return this.messagesRepo.getAllByJid(toJID(chatId), toNumber(limit));
}
getChats() {
return this.chatRepo.getAllWithMessages();
getChats(limit?: number, offset?: number): Promise<Chat[]> {
return this.chatRepo.getAllWithMessages(limit, offset);
}
getContactById(jid) {
@@ -7,11 +7,17 @@ export class Sqlite3ChatRepository
extends Sqlite3KVRepository<Chat>
implements IChatRepository
{
getAllWithMessages(): Promise<Chat[]> {
async getAllWithMessages(limit?: number, offset?: number): Promise<Chat[]> {
// Get chats with conversationTimestamp is not Null
const query = this.select()
let query = this.select()
.whereNotNull('conversationTimestamp')
.orderBy('conversationTimestamp', 'desc');
return this.all(query);
if (limit != null) {
query = query.limit(limit);
}
if (offset != null) {
query = query.offset(offset);
}
return await this.all(query);
}
}
+15
View File
@@ -0,0 +1,15 @@
exports.LoadUtils = () => {
window.WAHA = {};
window.WAHA.getChats = async (limit, offset) => {
let chats = window.Store.Chat.getModelsArray();
if (limit || offset) {
offset = offset || 0;
limit = limit || Infinity;
chats = chats.slice(offset, offset + limit);
}
const chatPromises = chats.map((chat) => window.WWebJS.getChatModel(chat));
return await Promise.all(chatPromises);
};
};
+35
View File
@@ -0,0 +1,35 @@
import { Client } from 'whatsapp-web.js';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { LoadUtils } = require('./WahaInjected');
// eslint-disable-next-line @typescript-eslint/no-var-requires
const ChatFactory = require('whatsapp-web.js/src/factories/ChatFactory');
export class WebjsClient extends Client {
async initialize() {
await super.initialize();
//Load util functions (serializers, helper functions)
await this.pupPage.evaluate(LoadUtils);
}
async getChats(limit?: number, offset?: number) {
if (limit == null && offset == null) {
return await super.getChats();
}
return await this.getChats2(limit, offset);
}
private async getChats2(limit?: number, offset?: number) {
const chats = await this.pupPage.evaluate(
async (limit, offset) => {
// @ts-ignore
return await window.WAHA.getChats(limit, offset);
},
limit,
offset,
);
return chats.map((chat) => ChatFactory.create(this, chat));
}
}
+30 -36
View File
@@ -1,18 +1,14 @@
import { UnprocessableEntityException } from '@nestjs/common/exceptions/unprocessable-entity.exception';
import { IEngineMediaProcessor } from '@waha/core/abc/media.abc';
import { WAHAInternalEvent, WhatsappSession } from '@waha/core/abc/session.abc';
import { WebjsClient } from '@waha/core/engines/webjs/WebjsClient';
import {
Chat,
Client,
ClientOptions,
Contact,
Events,
GroupChat,
Location,
Message,
Reaction,
} from 'whatsapp-web.js';
import { Message as MessageInstance } from 'whatsapp-web.js/src/structures';
import { parseBool } from '../../../helpers';
AvailableInPlusVersion,
NotImplementedByEngineError,
} from '@waha/core/exceptions';
import { QR } from '@waha/core/QR';
import { parseBool } from '@waha/helpers';
import { GetChatsQuery } from '@waha/structures/chats.dto';
import {
ChatRequest,
CheckNumberStatusQuery,
@@ -28,8 +24,8 @@ import {
MessageVoiceRequest,
SendSeenRequest,
WANumberExistResult,
} from '../../../structures/chatting.dto';
import { ContactQuery, ContactRequest } from '../../../structures/contacts.dto';
} from '@waha/structures/chatting.dto';
import { ContactQuery, ContactRequest } from '@waha/structures/contacts.dto';
import {
ACK_UNKNOWN,
SECOND,
@@ -38,32 +34,30 @@ import {
WAHAPresenceStatus,
WAHASessionStatus,
WAMessageAck,
} from '../../../structures/enums.dto';
} from '@waha/structures/enums.dto';
import {
CreateGroupRequest,
ParticipantsRequest,
SettingsSecurityChangeInfo,
} from '../../../structures/groups.dto';
} from '@waha/structures/groups.dto';
import { WAMessage, WAMessageReaction } from '@waha/structures/responses.dto';
import { MeInfo } from '@waha/structures/sessions.dto';
import { WAMessageRevokedBody } from '@waha/structures/webhooks.dto';
import {
WAMessage,
WAMessageReaction,
} from '../../../structures/responses.dto';
import { MeInfo } from '../../../structures/sessions.dto';
import { WAMessageRevokedBody } from '../../../structures/webhooks.dto';
import { IEngineMediaProcessor } from '../../abc/media.abc';
import { WAHAInternalEvent, WhatsappSession } from '../../abc/session.abc';
import {
AvailableInPlusVersion,
NotImplementedByEngineError,
} from '../../exceptions';
import { QR } from '../../QR';
Chat,
ClientOptions,
Contact,
Events,
GroupChat,
Location,
Message,
Reaction,
} from 'whatsapp-web.js';
import { Message as MessageInstance } from 'whatsapp-web.js/src/structures';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const QRCode = require('qrcode');
// eslint-disable-next-line @typescript-eslint/no-var-requires
const qrcode = require('qrcode-terminal');
export interface WebJSConfig {
webVersion?: string;
}
@@ -77,7 +71,7 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
private startTimeoutId: null | ReturnType<typeof setTimeout> = null;
private shouldRestart: boolean;
whatsapp: Client;
whatsapp: WebjsClient;
protected qr: QR;
public constructor(config) {
@@ -116,7 +110,7 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
protected async buildClient() {
const clientOptions = this.getClientOptions();
this.addProxyConfig(clientOptions);
return new Client(clientOptions);
return new WebjsClient(clientOptions);
}
private restartClient() {
@@ -417,8 +411,8 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
/**
* Chats methods
*/
getChats() {
return this.whatsapp.getChats();
getChats(query: GetChatsQuery) {
return this.whatsapp.getChats(query.limit, query.offset);
}
async getChatMessages(chatId: string, limit: number, downloadMedia: boolean) {
+4
View File
@@ -1,3 +1,4 @@
import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { json, urlencoded } from 'express';
@@ -47,6 +48,9 @@ async function bootstrap() {
app.enableShutdownHooks();
app.useGlobalFilters(new AllExceptionsFilter());
app.enableCors();
// Ideally, we should apply it globally.
// but for now we added it ValidationPipe on Controller or endpoint level
// app.useGlobalPipes(new ValidationPipe({ transform: true }));
// Allow to send big body - for images and attachments
app.use(json({ limit: '50mb' }));
+16 -1
View File
@@ -1,6 +1,8 @@
import { ApiProperty } from '@nestjs/swagger';
import { Type } from 'class-transformer';
import { IsNumber, IsOptional } from 'class-validator';
import { SessionBaseRequest, SessionQuery } from './base.dto';
import { SessionQuery } from './base.dto';
/**
* Queries
@@ -8,6 +10,7 @@ import { SessionBaseRequest, SessionQuery } from './base.dto';
export class GetChatMessagesQuery extends SessionQuery {
limit: number = 100;
@ApiProperty({
example: true,
required: false,
@@ -16,6 +19,18 @@ export class GetChatMessagesQuery extends SessionQuery {
downloadMedia: boolean = true;
}
export class GetChatsQuery {
@IsNumber()
@IsOptional()
@Type(() => Number)
limit?: number;
@IsNumber()
@IsOptional()
@Type(() => Number)
offset?: number;
}
/**
* Requests
*/
+38 -31
View File
@@ -2401,10 +2401,10 @@ __metadata:
languageName: node
linkType: hard
"@types/validator@npm:13.0.0":
version: 13.0.0
resolution: "@types/validator@npm:13.0.0"
checksum: 7001e96e663daa28f45120339ea4478cdf74cadfe74aba8b8de4c56bdaab559ab65de2eb334ce9026bba153231b96d9e6506b5d5dff8fea4e6c1a6babec523b3
"@types/validator@npm:^13.7.10":
version: 13.12.0
resolution: "@types/validator@npm:13.12.0"
checksum: 1d814a4a9f8fbd01f834bf45215aa8111879e71045391eec8e8fda6a7acf71d8b7839a0d312098c2b9c8285963203dfb3e3680a41484d1e9b3d576f95b6d71c0
languageName: node
linkType: hard
@@ -4211,15 +4211,21 @@ __metadata:
languageName: node
linkType: hard
"class-validator@npm:^0.12.2":
version: 0.12.2
resolution: "class-validator@npm:0.12.2"
"class-transformer@npm:^0.5.1":
version: 0.5.1
resolution: "class-transformer@npm:0.5.1"
checksum: f191c8b4cc4239990f5efdd790cabdd852c243ed66248e39f6616a349c910c6eed2d9fd1fbf7ee6ea89f69b4f1d0b493b27347fe0cd0ae26b47c3745a805b6d3
languageName: node
linkType: hard
"class-validator@npm:0.14.0":
version: 0.14.0
resolution: "class-validator@npm:0.14.0"
dependencies:
"@types/validator": 13.0.0
google-libphonenumber: ^3.2.8
tslib: ">=1.9.0"
validator: 13.0.0
checksum: 37a806f62794d0c473045b8a77bc48892e87a959d57588b52774385058a862e77952c3af4c02d61db5fd863ff08d19935b1bdd38851028e1460bb94eb97ffec7
"@types/validator": ^13.7.10
libphonenumber-js: ^1.10.14
validator: ^13.7.0
checksum: f62e4a0ad24cee68f4b2bc70d32b96de90cb598f96bde362b4dbf4234151af8eb6ae225458312a38fc49fa3959844cf61c60e731a8205e9a570454cff8de2710
languageName: node
linkType: hard
@@ -6740,13 +6746,6 @@ __metadata:
languageName: node
linkType: hard
"google-libphonenumber@npm:^3.2.8":
version: 3.2.34
resolution: "google-libphonenumber@npm:3.2.34"
checksum: a14579bb8d4934dc6b9cfb33f818375ccdc67be12f13f842a4c16d7c3bd8ef9f2aacc30d368770f33a97ba8674e23b318cb59f26616c7fa2ce60fae52b2f6ebf
languageName: node
linkType: hard
"gopd@npm:^1.0.1":
version: 1.0.1
resolution: "gopd@npm:1.0.1"
@@ -8433,6 +8432,13 @@ __metadata:
languageName: node
linkType: hard
"libphonenumber-js@npm:^1.10.14":
version: 1.11.3
resolution: "libphonenumber-js@npm:1.11.3"
checksum: c6b73b64b69aeea42f031dd56d6b51d1a1ccda5a079bad4bc6357f4e7ed5cf7f9303e0545fd6d30e08245d8c0f3140216d9130336aeaebb32494b5b567715326
languageName: node
linkType: hard
"libphonenumber-js@npm:^1.10.20, libphonenumber-js@npm:^1.10.36":
version: 1.10.56
resolution: "libphonenumber-js@npm:1.10.56"
@@ -12331,13 +12337,6 @@ __metadata:
languageName: node
linkType: hard
"tslib@npm:>=1.9.0, tslib@npm:^2.0.1, tslib@npm:^2.1.0, tslib@npm:^2.4.0":
version: 2.6.2
resolution: "tslib@npm:2.6.2"
checksum: 329ea56123005922f39642318e3d1f0f8265d1e7fcb92c633e0809521da75eeaca28d2cf96d7248229deb40e5c19adf408259f4b9640afd20d13aecc1430f3ad
languageName: node
linkType: hard
"tslib@npm:^1.8.1":
version: 1.14.1
resolution: "tslib@npm:1.14.1"
@@ -12345,6 +12344,13 @@ __metadata:
languageName: node
linkType: hard
"tslib@npm:^2.0.1, tslib@npm:^2.1.0, tslib@npm:^2.4.0":
version: 2.6.2
resolution: "tslib@npm:2.6.2"
checksum: 329ea56123005922f39642318e3d1f0f8265d1e7fcb92c633e0809521da75eeaca28d2cf96d7248229deb40e5c19adf408259f4b9640afd20d13aecc1430f3ad
languageName: node
linkType: hard
"tsutils@npm:^3.17.1, tsutils@npm:^3.21.0":
version: 3.21.0
resolution: "tsutils@npm:3.21.0"
@@ -12743,10 +12749,10 @@ __metadata:
languageName: node
linkType: hard
"validator@npm:13.0.0":
version: 13.0.0
resolution: "validator@npm:13.0.0"
checksum: 7b5df6d0aec660ad12089fbcdd07cf506181ca2cd711d6e2bec7502c5cac1b31e8eb03875d23bcbc1b81a93648d5aacd52e2dc7b62cf02e71d3768533630f4c5
"validator@npm:^13.7.0":
version: 13.12.0
resolution: "validator@npm:13.12.0"
checksum: fb8f070724770b1449ea1a968605823fdb112dbd10507b2802f8841cda3e7b5c376c40f18c84e6a7b59de320a06177e471554101a85f1fa8a70bac1a84e48adf
languageName: node
linkType: hard
@@ -12856,7 +12862,8 @@ __metadata:
async-lock: ^1.4.1
better-sqlite3: 9.6.0
check-disk-space: ^3.4.0
class-validator: ^0.12.2
class-transformer: ^0.5.1
class-validator: 0.14.0
del: ^6.0.0
eslint: 7.7.0
eslint-config-prettier: ^6.10.0