Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eaf2bca44e | ||
|
|
af8f537f58 | ||
|
|
bc7ff472be | ||
|
|
9b9a2b5203 | ||
|
|
347259394b | ||
|
|
ead61b5e37 | ||
|
|
c9f7814f5d | ||
|
|
3ee3355e81 | ||
|
|
ce8f8b0ce9 | ||
|
|
cae35cf3b9 | ||
|
|
900e3c23bc | ||
|
|
aaeffeb983 | ||
|
|
15600324be | ||
|
|
da4913edb5 | ||
|
|
e8cc1e4906 | ||
|
|
801fc3f9fd |
No files matched your search
+1
-1
@@ -26,7 +26,7 @@ RUN yarn build && find ./dist -name "*.d.ts" -delete
|
||||
FROM node:${NODE_VERSION} AS dashboard
|
||||
|
||||
# Download WAHA Dashboard
|
||||
ENV WAHA_DASHBOARD_SHA 45db5b46a944f4320136f2409d8b970483c8bd9d
|
||||
ENV WAHA_DASHBOARD_SHA fed4e50e88e4d26c610e3289fd0d8657cb866543
|
||||
RUN \
|
||||
wget https://github.com/devlikeapro/dashboard/archive/${WAHA_DASHBOARD_SHA}.zip \
|
||||
&& unzip ${WAHA_DASHBOARD_SHA}.zip -d /tmp/dashboard \
|
||||
|
||||
@@ -34,6 +34,9 @@ for-swagger:
|
||||
up-noweb:
|
||||
. ${NVM_DIR}/nvm.sh && nvm exec yarn up @adiwajshing/baileys@github:devlikeapro/Baileys#fork-master-channels-678
|
||||
|
||||
up-noweb-libsignal:
|
||||
. ${NVM_DIR}/nvm.sh && nvm exec yarn up libsignal@github:devlikeapro/libsignal-node#fork-master
|
||||
|
||||
up-webjs:
|
||||
. ${NVM_DIR}/nvm.sh && nvm exec yarn up whatsapp-web.js@github:devlikeapro/whatsapp-web.js#fork-main-channels
|
||||
|
||||
|
||||
+3
-1
@@ -59,6 +59,7 @@
|
||||
"joi": "^17.13.3",
|
||||
"knex": "^3.1.0",
|
||||
"libphonenumber-js": "^1.10.36",
|
||||
"libsignal": "github:devlikeapro/libsignal-node#fork-master",
|
||||
"link-preview-js": "^3.0.4",
|
||||
"lodash": "^4.17.21",
|
||||
"mime-types": "^2.1.27",
|
||||
@@ -88,7 +89,8 @@
|
||||
"bufferutil": "^4.0.8",
|
||||
"ws": "^8.18.0",
|
||||
"puppeteer": "^23.6.0",
|
||||
"whatwg-url": "13.0.0"
|
||||
"whatwg-url": "13.0.0",
|
||||
"libsignal": "github:devlikeapro/libsignal-node#fork-master"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nestjs/cli": "^9.0.0",
|
||||
|
||||
@@ -21,12 +21,15 @@ import {
|
||||
|
||||
import { SessionManager } from '../core/abc/manager.abc';
|
||||
import { WhatsappSession } from '../core/abc/session.abc';
|
||||
import { parseBool } from '../helpers';
|
||||
import {
|
||||
ChatPictureQuery,
|
||||
ChatPictureResponse,
|
||||
ChatsPaginationParams,
|
||||
ChatSummary,
|
||||
GetChatMessageQuery,
|
||||
GetChatMessagesFilter,
|
||||
GetChatMessagesQuery,
|
||||
OverviewPaginationParams,
|
||||
PinMessageRequest,
|
||||
} from '../structures/chats.dto';
|
||||
import { EditMessageRequest } from '../structures/chatting.dto';
|
||||
@@ -48,6 +51,20 @@ class ChatsController {
|
||||
return session.getChats(pagination);
|
||||
}
|
||||
|
||||
@Get('overview')
|
||||
@SessionApiParam
|
||||
@ApiOperation({
|
||||
summary:
|
||||
'Get chats overview. Includes all necessary things to build UI "your chats overview" page - chat id, name, picture, last message. Sorting by last message timestamp',
|
||||
})
|
||||
@UsePipes(new ValidationPipe({ transform: true, whitelist: true }))
|
||||
getChatsOverview(
|
||||
@WorkingSessionParam session: WhatsappSession,
|
||||
@Query() pagination: OverviewPaginationParams,
|
||||
): Promise<ChatSummary[]> {
|
||||
return session.getChatsOverview(pagination);
|
||||
}
|
||||
|
||||
@Delete(':chatId')
|
||||
@SessionApiParam
|
||||
@ApiOperation({ summary: 'Deletes the chat' })
|
||||
@@ -59,6 +76,19 @@ class ChatsController {
|
||||
return session.deleteChat(chatId);
|
||||
}
|
||||
|
||||
@Get(':chatId/picture')
|
||||
@SessionApiParam
|
||||
@ApiOperation({ summary: 'Gets chat picture' })
|
||||
@UsePipes(new ValidationPipe({ transform: true, whitelist: true }))
|
||||
async getChatPicture(
|
||||
@WorkingSessionParam session: WhatsappSession,
|
||||
@Param('chatId') chatId: string,
|
||||
@Query() query: ChatPictureQuery,
|
||||
): Promise<ChatPictureResponse> {
|
||||
const url = await session.getContactProfilePicture(chatId, query.refresh);
|
||||
return { url: url };
|
||||
}
|
||||
|
||||
@Get(':chatId/messages')
|
||||
@SessionApiParam
|
||||
@ApiOperation({ summary: 'Gets messages in the chat' })
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
WANumberExistResult,
|
||||
} from '../structures/chatting.dto';
|
||||
import {
|
||||
ContactProfilePictureQuery,
|
||||
ContactQuery,
|
||||
ContactRequest,
|
||||
ContactsPaginationParams,
|
||||
@@ -75,9 +76,14 @@ export class ContactsController {
|
||||
description:
|
||||
'If privacy settings do not allow to get the picture, the method will return null.',
|
||||
})
|
||||
async getProfilePicture(@Query() query: ContactQuery) {
|
||||
@UsePipes(new ValidationPipe({ transform: true, whitelist: true }))
|
||||
async getProfilePicture(@Query() query: ContactProfilePictureQuery) {
|
||||
const whatsapp = await this.manager.getWorkingSession(query.session);
|
||||
return whatsapp.getContactProfilePicture(query);
|
||||
const url = await whatsapp.getContactProfilePicture(
|
||||
query.contactId,
|
||||
query.refresh,
|
||||
);
|
||||
return { profilePictureURL: url };
|
||||
}
|
||||
|
||||
@Post('/block')
|
||||
|
||||
@@ -23,6 +23,8 @@ import {
|
||||
CreateGroupRequest,
|
||||
DescriptionRequest,
|
||||
GroupsPaginationParams,
|
||||
JoinGroupRequest,
|
||||
JoinGroupResponse,
|
||||
ParticipantsRequest,
|
||||
SettingsSecurityChangeInfo,
|
||||
SubjectRequest,
|
||||
@@ -44,6 +46,31 @@ export class GroupsController {
|
||||
return session.createGroup(request);
|
||||
}
|
||||
|
||||
@Get('join-info')
|
||||
@SessionApiParam
|
||||
@ApiOperation({ summary: 'Get info about the group before joining.' })
|
||||
async joinInfoGroup(
|
||||
@WorkingSessionParam session: WhatsappSession,
|
||||
@Query() query: JoinGroupRequest,
|
||||
): Promise<any> {
|
||||
// https://chat.whatsapp.com/123 => 123
|
||||
const code = query.code.split('/').pop();
|
||||
return session.joinInfoGroup(code);
|
||||
}
|
||||
|
||||
@Post('join')
|
||||
@SessionApiParam
|
||||
@ApiOperation({ summary: 'Join group via code' })
|
||||
async joinGroup(
|
||||
@WorkingSessionParam session: WhatsappSession,
|
||||
@Body() request: JoinGroupRequest,
|
||||
): Promise<JoinGroupResponse> {
|
||||
// https://chat.whatsapp.com/123 => 123
|
||||
const code = request.code.split('/').pop();
|
||||
const id = await session.joinGroup(code);
|
||||
return { id: id };
|
||||
}
|
||||
|
||||
@Get('')
|
||||
@SessionApiParam
|
||||
@ApiOperation({ summary: 'Get all groups.' })
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
ListChannelsQuery,
|
||||
} from '@waha/structures/channels.dto';
|
||||
import {
|
||||
ChatSummary,
|
||||
GetChatMessageQuery,
|
||||
GetChatMessagesFilter,
|
||||
GetChatMessagesQuery,
|
||||
@@ -19,6 +20,7 @@ import { complete } from '@waha/utils/reactive/complete';
|
||||
import { SwitchObservable } from '@waha/utils/reactive/SwitchObservable';
|
||||
import * as fs from 'fs';
|
||||
import * as lodash from 'lodash';
|
||||
import * as NodeCache from 'node-cache';
|
||||
import { Logger } from 'pino';
|
||||
import {
|
||||
BehaviorSubject,
|
||||
@@ -132,6 +134,9 @@ export abstract class WhatsappSession {
|
||||
private shouldPrintQR: boolean;
|
||||
protected events2: DefaultMap<WAHAEvents, SwitchObservable<any>>;
|
||||
private status$: Subject<WAHASessionStatus>;
|
||||
protected profilePictures: NodeCache = new NodeCache({
|
||||
stdTTL: 24 * 60 * 60, // 1 day
|
||||
});
|
||||
|
||||
public constructor({
|
||||
name,
|
||||
@@ -393,6 +398,12 @@ export abstract class WhatsappSession {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public getChatsOverview(
|
||||
pagination: PaginationParams,
|
||||
): Promise<ChatSummary[]> {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public deleteChat(chatId) {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
@@ -504,8 +515,32 @@ export abstract class WhatsappSession {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public getContactProfilePicture(query: ContactQuery) {
|
||||
throw new NotImplementedByEngineError();
|
||||
/**
|
||||
* Fetch the latest profile picture of the contact (group, newsletter, etc.)
|
||||
* @param id
|
||||
*/
|
||||
abstract fetchContactProfilePicture(id: string): Promise<string | null>;
|
||||
|
||||
public async getContactProfilePicture(
|
||||
id: string,
|
||||
refresh: boolean,
|
||||
): Promise<string | null> {
|
||||
const has: boolean = this.profilePictures.has(id);
|
||||
if (!has || refresh) {
|
||||
await this.refreshProfilePicture(id);
|
||||
}
|
||||
return this.profilePictures.get(id);
|
||||
}
|
||||
|
||||
protected async refreshProfilePicture(id: string) {
|
||||
this.profilePictures.del(id);
|
||||
const url = await this.fetchContactProfilePicture(id).catch((err) => {
|
||||
this.logger.error('Error fetching profile picture');
|
||||
this.logger.error(err, err.stack);
|
||||
return null;
|
||||
});
|
||||
this.profilePictures.set(id, url);
|
||||
return url;
|
||||
}
|
||||
|
||||
public blockContact(request: ContactRequest) {
|
||||
@@ -523,6 +558,14 @@ export abstract class WhatsappSession {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public joinGroup(code: string): Promise<string> {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public joinInfoGroup(code: string): Promise<any> {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public getGroups(pagination: PaginationParams) {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import makeWASocket, {
|
||||
Browsers,
|
||||
Chat,
|
||||
Contact,
|
||||
DisconnectReason,
|
||||
downloadMediaMessage,
|
||||
@@ -9,7 +10,9 @@ import makeWASocket, {
|
||||
getKeyAuthor,
|
||||
getUrlFromDirectPath,
|
||||
isJidGroup,
|
||||
isJidNewsletter,
|
||||
isJidStatusBroadcast,
|
||||
isJidUser,
|
||||
isRealMessage,
|
||||
jidNormalizedUser,
|
||||
makeCacheableSignalKeyStore,
|
||||
@@ -50,6 +53,7 @@ import {
|
||||
ListChannelsQuery,
|
||||
} from '@waha/structures/channels.dto';
|
||||
import {
|
||||
ChatSummary,
|
||||
GetChatMessageQuery,
|
||||
GetChatMessagesFilter,
|
||||
GetChatMessagesQuery,
|
||||
@@ -369,6 +373,7 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
this.connectStore();
|
||||
this.listenConnectionEvents();
|
||||
this.subscribeEngineEvents2();
|
||||
this.listenContactsUpdatePictureProfile();
|
||||
this.enableAutoRestart();
|
||||
}
|
||||
|
||||
@@ -901,12 +906,46 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
*/
|
||||
|
||||
async getChats(pagination: PaginationParams) {
|
||||
const chats = await this.store.getChats(pagination);
|
||||
const chats = await this.store.getChats(pagination, true);
|
||||
// Remove unreadCount, it's not ready yet
|
||||
chats.forEach((chat) => delete chat.unreadCount);
|
||||
return chats;
|
||||
}
|
||||
|
||||
public async getChatsOverview(
|
||||
pagination: PaginationParams,
|
||||
): Promise<ChatSummary[]> {
|
||||
const chats = await this.store.getChats(pagination, false);
|
||||
// Remove unreadCount, it's not ready yet
|
||||
chats.forEach((chat) => delete chat.unreadCount);
|
||||
|
||||
const promises = [];
|
||||
for (const chat of chats) {
|
||||
promises.push(this.fetchChatSummary(chat));
|
||||
}
|
||||
const result = await Promise.all(promises);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected async fetchChatSummary(chat: Chat): Promise<ChatSummary> {
|
||||
const id = toCusFormat(chat.id);
|
||||
const name = chat.name;
|
||||
const picture = await this.getContactProfilePicture(chat.id, false);
|
||||
const messages = await this.getChatMessages(
|
||||
chat.id,
|
||||
{ limit: 1, offset: 0, downloadMedia: false },
|
||||
{},
|
||||
);
|
||||
const message = messages.length > 0 ? messages[0] : null;
|
||||
return {
|
||||
id: id,
|
||||
name: name || null,
|
||||
picture: picture,
|
||||
lastMessage: message,
|
||||
_chat: chat,
|
||||
};
|
||||
}
|
||||
|
||||
protected async chatsPutArchive(
|
||||
chatId: string,
|
||||
archive: boolean,
|
||||
@@ -1062,10 +1101,16 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public async getContactProfilePicture(query: ContactQuery) {
|
||||
const contact = this.ensureSuffix(query.contactId);
|
||||
public async fetchContactProfilePicture(id: string) {
|
||||
const contact = this.ensureSuffix(id);
|
||||
if (isJidNewsletter(id)) {
|
||||
return null;
|
||||
}
|
||||
if (isJidStatusBroadcast(id)) {
|
||||
return null;
|
||||
}
|
||||
const url = await this.sock.profilePictureUrl(contact, 'image');
|
||||
return { profilePictureURL: url };
|
||||
return url;
|
||||
}
|
||||
|
||||
public async blockContact(request: ContactRequest) {
|
||||
@@ -1084,6 +1129,14 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
return this.sock.groupCreate(request.name, participants);
|
||||
}
|
||||
|
||||
public joinGroup(code: string) {
|
||||
return this.sock.groupAcceptInvite(code);
|
||||
}
|
||||
|
||||
public joinInfoGroup(code: string) {
|
||||
return this.sock.groupGetInviteInfo(code);
|
||||
}
|
||||
|
||||
public async getGroups(pagination: PaginationParams) {
|
||||
const groups = await this.store.getGroups(pagination);
|
||||
// return {id: group} mapping for backward compatability
|
||||
@@ -1512,6 +1565,26 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
);
|
||||
}
|
||||
|
||||
protected listenContactsUpdatePictureProfile() {
|
||||
this.sock.ev.on('contacts.update', async (updates) => {
|
||||
for (const update of updates) {
|
||||
if (update.imgUrl !== 'changed') {
|
||||
continue;
|
||||
}
|
||||
|
||||
this.logger.debug({ jid: update.id }, 'Profile picture updated');
|
||||
const url = await this.refreshProfilePicture(update.id);
|
||||
if (isJidUser(update.id)) {
|
||||
// update 123@c.us and 123 profiles as well
|
||||
const cus = toCusFormat(update.id);
|
||||
this.profilePictures.set(cus, url);
|
||||
const phone = update.id.split('@')[0];
|
||||
this.profilePictures.set(phone, url);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* END - Methods for API
|
||||
*/
|
||||
|
||||
@@ -6,7 +6,10 @@ export interface IChatRepository {
|
||||
|
||||
getAllByIds(ids: string[]): Promise<Chat[]>;
|
||||
|
||||
getAllWithMessages(pagination: PaginationParams): Promise<Chat[]>;
|
||||
getAllWithMessages(
|
||||
pagination: PaginationParams,
|
||||
broadcast: boolean,
|
||||
): Promise<Chat[]>;
|
||||
|
||||
getById(id: string): Promise<Chat | null>;
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ export interface INowebStore {
|
||||
|
||||
getMessageById(chatId: string, messageId: string): Promise<any>;
|
||||
|
||||
getChats(pagination: PaginationParams): Promise<Chat[]>;
|
||||
getChats(pagination: PaginationParams, broadcast: boolean): Promise<Chat[]>;
|
||||
|
||||
getContacts(pagination: PaginationParams): Promise<Contact[]>;
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ export class NowebInMemoryStore implements INowebStore {
|
||||
throw new BadRequestException(this.errorMessage);
|
||||
}
|
||||
|
||||
getChats(pagination: PaginationParams): Promise<Chat[]> {
|
||||
getChats(pagination: PaginationParams, broadcast: boolean): Promise<Chat[]> {
|
||||
throw new BadRequestException(this.errorMessage);
|
||||
}
|
||||
|
||||
|
||||
@@ -448,10 +448,10 @@ export class NowebPersistentStore implements INowebStore {
|
||||
return this.messagesRepo.getByJidById(chatId, messageId);
|
||||
}
|
||||
|
||||
getChats(pagination: PaginationParams): Promise<Chat[]> {
|
||||
getChats(pagination: PaginationParams, broadcast: boolean): Promise<Chat[]> {
|
||||
pagination.sortBy ||= 'conversationTimestamp';
|
||||
pagination.sortOrder ||= SortOrder.DESC;
|
||||
return this.chatRepo.getAllWithMessages(pagination);
|
||||
return this.chatRepo.getAllWithMessages(pagination, broadcast);
|
||||
}
|
||||
|
||||
private shouldFetchGroup(): boolean {
|
||||
|
||||
@@ -15,9 +15,18 @@ export class Sqlite3ChatRepository
|
||||
{
|
||||
protected Paginator = ChatPaginator;
|
||||
|
||||
async getAllWithMessages(pagination: PaginationParams): Promise<Chat[]> {
|
||||
async getAllWithMessages(
|
||||
pagination: PaginationParams,
|
||||
broadcast: boolean,
|
||||
): Promise<Chat[]> {
|
||||
// Get chats with conversationTimestamp is not Null
|
||||
let query = this.select().whereNotNull('conversationTimestamp');
|
||||
if (!broadcast) {
|
||||
// filter out chat by id if it ends at @newsletter or @broadcast
|
||||
query = query
|
||||
.andWhereNot('id', 'like', '%@broadcast')
|
||||
.andWhereNot('id', 'like', '%@newsletter');
|
||||
}
|
||||
query = this.pagination(query, pagination);
|
||||
return await this.all(query);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ import { IMediaEngineProcessor } from '@waha/core/media/IMediaEngineProcessor';
|
||||
import { QR } from '@waha/core/QR';
|
||||
import { splitAt } from '@waha/helpers';
|
||||
import { PairingCodeResponse } from '@waha/structures/auth.dto';
|
||||
import { CallData } from '@waha/structures/calls.dto';
|
||||
import {
|
||||
Channel,
|
||||
ChannelRole,
|
||||
@@ -21,8 +20,8 @@ import {
|
||||
ListChannelsQuery,
|
||||
} from '@waha/structures/channels.dto';
|
||||
import {
|
||||
ChatArchiveEvent,
|
||||
ChatSortField,
|
||||
ChatSummary,
|
||||
GetChatMessageQuery,
|
||||
GetChatMessagesFilter,
|
||||
GetChatMessagesQuery,
|
||||
@@ -61,14 +60,10 @@ import {
|
||||
} from '@waha/structures/groups.dto';
|
||||
import { Label, LabelDTO, LabelID } from '@waha/structures/labels.dto';
|
||||
import { ReplyToMessage } from '@waha/structures/message.dto';
|
||||
import { PaginationParams } from '@waha/structures/pagination.dto';
|
||||
import { PaginationParams, SortOrder } from '@waha/structures/pagination.dto';
|
||||
import { WAMessage, WAMessageReaction } from '@waha/structures/responses.dto';
|
||||
import { MeInfo } from '@waha/structures/sessions.dto';
|
||||
import {
|
||||
BROADCAST_ID,
|
||||
StatusRequest,
|
||||
TextStatus,
|
||||
} from '@waha/structures/status.dto';
|
||||
import { StatusRequest, TextStatus } from '@waha/structures/status.dto';
|
||||
import {
|
||||
EnginePayload,
|
||||
WAMessageRevokedBody,
|
||||
@@ -573,6 +568,41 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
return this.whatsapp.getChats(pagination);
|
||||
}
|
||||
|
||||
public async getChatsOverview(
|
||||
pagination: PaginationParams,
|
||||
): Promise<ChatSummary[]> {
|
||||
pagination = {
|
||||
...pagination,
|
||||
sortBy: ChatSortField.CONVERSATION_TIMESTAMP,
|
||||
sortOrder: SortOrder.DESC,
|
||||
};
|
||||
const chats = await this.getChats(pagination);
|
||||
|
||||
const promises = [];
|
||||
for (const chat of chats) {
|
||||
promises.push(this.fetchChatSummary(chat));
|
||||
}
|
||||
const result = await Promise.all(promises);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected async fetchChatSummary(chat: Chat): Promise<ChatSummary> {
|
||||
const picture = await this.getContactProfilePicture(
|
||||
chat.id._serialized,
|
||||
false,
|
||||
);
|
||||
const lastMessage = !!chat.lastMessage
|
||||
? this.toWAMessage(chat.lastMessage)
|
||||
: null;
|
||||
return {
|
||||
id: chat.id._serialized,
|
||||
name: chat.name || null,
|
||||
picture: picture,
|
||||
lastMessage: lastMessage,
|
||||
_chat: chat,
|
||||
};
|
||||
}
|
||||
|
||||
public async getChatMessages(
|
||||
chatId: string,
|
||||
query: GetChatMessagesQuery,
|
||||
@@ -731,11 +761,10 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
return { about: await contact.getAbout() };
|
||||
}
|
||||
|
||||
public async getContactProfilePicture(query: ContactQuery) {
|
||||
const contact = await this.whatsapp.getContactById(
|
||||
this.ensureSuffix(query.contactId),
|
||||
);
|
||||
return { profilePictureURL: await contact.getProfilePicUrl() };
|
||||
public async fetchContactProfilePicture(id: string) {
|
||||
const contact = await this.whatsapp.getContactById(this.ensureSuffix(id));
|
||||
const url = await contact.getProfilePicUrl();
|
||||
return url;
|
||||
}
|
||||
|
||||
public async blockContact(request: ContactRequest) {
|
||||
@@ -762,6 +791,14 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
return this.whatsapp.createGroup(request.name, participantIds);
|
||||
}
|
||||
|
||||
public joinGroup(code: string) {
|
||||
return this.whatsapp.acceptInvite(code);
|
||||
}
|
||||
|
||||
public joinInfoGroup(code: string) {
|
||||
return this.whatsapp.getInviteInfo(code);
|
||||
}
|
||||
|
||||
public async getInfoAdminsOnly(id): Promise<SettingsSecurityChangeInfo> {
|
||||
const groupChat = (await this.whatsapp.getChatById(id)) as GroupChat;
|
||||
return {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IsNotEmpty } from 'class-validator';
|
||||
import { IsNotEmpty, IsString } from 'class-validator';
|
||||
|
||||
export const WHATSAPP_DEFAULT_SESSION_NAME = 'default';
|
||||
|
||||
@@ -7,6 +7,7 @@ export const WHATSAPP_DEFAULT_SESSION_NAME = 'default';
|
||||
*/
|
||||
export class SessionQuery {
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
session: string = WHATSAPP_DEFAULT_SESSION_NAME;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { BooleanString } from '@waha/nestjs/validation/BooleanString';
|
||||
import { PaginationParams } from '@waha/structures/pagination.dto';
|
||||
import {
|
||||
LimitOffsetParams,
|
||||
PaginationParams,
|
||||
} from '@waha/structures/pagination.dto';
|
||||
import { ChatIdProperty } from '@waha/structures/properties.dto';
|
||||
import { Transform, Type } from 'class-transformer';
|
||||
import { IsBoolean, IsEnum, IsNumber, IsOptional } from 'class-validator';
|
||||
@@ -38,6 +41,23 @@ export class GetChatMessagesFilter {
|
||||
'filter.fromMe'?: boolean;
|
||||
}
|
||||
|
||||
export class ChatPictureQuery {
|
||||
@Transform(BooleanString)
|
||||
@IsBoolean()
|
||||
@IsOptional()
|
||||
@ApiProperty({
|
||||
example: false,
|
||||
required: false,
|
||||
description:
|
||||
'Refresh the picture from the server (24h cache by default). Do not refresh if not needed, you can get rate limit error',
|
||||
})
|
||||
refresh?: boolean = false;
|
||||
}
|
||||
|
||||
export class ChatPictureResponse {
|
||||
url: string;
|
||||
}
|
||||
|
||||
export class GetChatMessagesQuery {
|
||||
@IsNumber()
|
||||
@IsOptional()
|
||||
@@ -105,6 +125,21 @@ export class PinMessageRequest {
|
||||
duration: number;
|
||||
}
|
||||
|
||||
export class OverviewPaginationParams extends LimitOffsetParams {
|
||||
@IsNumber()
|
||||
@IsOptional()
|
||||
@Type(() => Number)
|
||||
limit?: number = 20;
|
||||
}
|
||||
|
||||
export class ChatSummary {
|
||||
id: string;
|
||||
name: string | null;
|
||||
picture: string | null;
|
||||
lastMessage: any;
|
||||
_chat: any;
|
||||
}
|
||||
|
||||
/**
|
||||
* Events
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { BooleanString } from '@waha/nestjs/validation/BooleanString';
|
||||
import { PaginationParams } from '@waha/structures/pagination.dto';
|
||||
import { ChatIdProperty } from '@waha/structures/properties.dto';
|
||||
import { IsEnum, IsOptional, IsString } from 'class-validator';
|
||||
import { Transform } from 'class-transformer';
|
||||
import { IsBoolean, IsEnum, IsOptional, IsString } from 'class-validator';
|
||||
|
||||
import { SessionBaseRequest, SessionQuery } from './base.dto';
|
||||
|
||||
@@ -15,6 +17,19 @@ export class ContactQuery extends SessionQuery {
|
||||
contactId: string;
|
||||
}
|
||||
|
||||
export class ContactProfilePictureQuery extends ContactQuery {
|
||||
@Transform(BooleanString)
|
||||
@IsBoolean()
|
||||
@IsOptional()
|
||||
@ApiProperty({
|
||||
example: false,
|
||||
required: false,
|
||||
description:
|
||||
'Refresh the picture from the server (24h cache by default). Do not refresh if not needed, you can get rate limit error',
|
||||
})
|
||||
refresh?: boolean = false;
|
||||
}
|
||||
|
||||
enum ContactSortField {
|
||||
ID = 'id',
|
||||
NAME = 'name',
|
||||
|
||||
@@ -57,6 +57,23 @@ export class CreateGroupRequest {
|
||||
participants: Array<Participant>;
|
||||
}
|
||||
|
||||
export class JoinGroupRequest {
|
||||
@ApiProperty({
|
||||
description: 'Group code (123) or url (https://chat.whatsapp.com/123)',
|
||||
example: 'https://chat.whatsapp.com/1234567890abcdef',
|
||||
})
|
||||
@IsString()
|
||||
code: string;
|
||||
}
|
||||
|
||||
export class JoinGroupResponse {
|
||||
@ApiProperty({
|
||||
description: 'Group ID',
|
||||
example: '123@g.us',
|
||||
})
|
||||
id: string;
|
||||
}
|
||||
|
||||
export enum GroupSortField {
|
||||
ID = 'id',
|
||||
SUBJECT = 'subject',
|
||||
|
||||
@@ -6,8 +6,7 @@ export enum SortOrder {
|
||||
DESC = 'desc',
|
||||
ASC = 'asc',
|
||||
}
|
||||
|
||||
export class PaginationParams {
|
||||
export class LimitOffsetParams {
|
||||
@IsNumber()
|
||||
@IsOptional()
|
||||
@Type(() => Number)
|
||||
@@ -17,7 +16,9 @@ export class PaginationParams {
|
||||
@IsOptional()
|
||||
@Type(() => Number)
|
||||
offset?: number;
|
||||
}
|
||||
|
||||
export class PaginationParams extends LimitOffsetParams {
|
||||
@ApiProperty({
|
||||
description: 'Sort by field',
|
||||
})
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ export function getEngineName(): string {
|
||||
}
|
||||
|
||||
export const VERSION: WAHAEnvironment = {
|
||||
version: '2024.12.3',
|
||||
version: '2024.12.6',
|
||||
engine: getEngineName(),
|
||||
tier: getWAHAVersion(),
|
||||
browser: getBrowserExecutablePath(),
|
||||
|
||||
@@ -7,7 +7,7 @@ __metadata:
|
||||
|
||||
"@adiwajshing/baileys@github:devlikeapro/Baileys#fork-master-channels-678":
|
||||
version: 6.7.8
|
||||
resolution: "@adiwajshing/baileys@https://github.com/devlikeapro/Baileys.git#commit=ea7f0f4365508d272809458b3e9094c7bb56cf3a"
|
||||
resolution: "@adiwajshing/baileys@https://github.com/devlikeapro/Baileys.git#commit=04738f528321857efe837e3f93c73059878ecdcb"
|
||||
dependencies:
|
||||
"@adiwajshing/keyed-db": ^0.2.4
|
||||
"@hapi/boom": ^9.1.3
|
||||
@@ -39,7 +39,7 @@ __metadata:
|
||||
optional: true
|
||||
sharp:
|
||||
optional: true
|
||||
checksum: c765057d3978dae6e25218324f2e1d969a0173822b3a62f4677342cb94a08feaefa936d0ed6effb34bc2a5a340a938c51d7ac9dff8e6ecaf121d8e6dfa950119
|
||||
checksum: 0f7b2031eeb25137c65aee3151028f7a8637cfed0763c7426817415ec818ca71f55267b9de88511905bd266f4006301a26206dac9bdb1821d13f1a0cbf075e32
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -8474,13 +8474,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"libsignal@github:WhiskeySockets/libsignal-node":
|
||||
"libsignal@github:devlikeapro/libsignal-node#fork-master":
|
||||
version: 2.0.1
|
||||
resolution: "libsignal@https://github.com/WhiskeySockets/libsignal-node.git#commit=83a3e3a3864511cb74df1b796373f0d49d071134"
|
||||
resolution: "libsignal@https://github.com/devlikeapro/libsignal-node.git#commit=83bc9236ee3d96ae1747cf3ca2e505b10cf97250"
|
||||
dependencies:
|
||||
curve25519-js: ^0.0.4
|
||||
protobufjs: 6.8.8
|
||||
checksum: bc8a8c4d54395e6b3f7224e72fe0c447859eed688cc28da3a56d76dcd5bf1ea71b25b3ff0da96646b636f2bb679898ca38eff909cb83ef3e3b017fe81e06ed50
|
||||
checksum: 3ee39bc7cbd123fa2c1f84ff53ab4e3dacfb5a00d10944960fd72156b24a5eb5af1fa5ca31b9f25b26aab107c712d8c295c85b0bed26ad6eba6d0e3f26f38927
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -12272,6 +12272,7 @@ __metadata:
|
||||
joi: ^17.13.3
|
||||
knex: ^3.1.0
|
||||
libphonenumber-js: ^1.10.36
|
||||
libsignal: "github:devlikeapro/libsignal-node#fork-master"
|
||||
link-preview-js: ^3.0.4
|
||||
lodash: ^4.17.21
|
||||
mime-types: ^2.1.27
|
||||
@@ -12394,7 +12395,7 @@ __metadata:
|
||||
|
||||
"whatsapp-web.js@github:devlikeapro/whatsapp-web.js#fork-main-channels":
|
||||
version: 1.26.0
|
||||
resolution: "whatsapp-web.js@https://github.com/devlikeapro/whatsapp-web.js.git#commit=73288b43a3a346520867ffcbf0de0867dd07b343"
|
||||
resolution: "whatsapp-web.js@https://github.com/devlikeapro/whatsapp-web.js.git#commit=a8683b0d1a5b8025ac1e7deb3476042ceadb4c07"
|
||||
dependencies:
|
||||
"@pedroslopez/moduleraid": ^5.0.2
|
||||
archiver: ^5.3.1
|
||||
@@ -12412,7 +12413,7 @@ __metadata:
|
||||
optional: true
|
||||
unzipper:
|
||||
optional: true
|
||||
checksum: 2513fe75b213a8c78650c61abd1671a2f671ba4f5423fb949fda2d45cd2c24cf414dfdde5222adb6582cda264983f15a3701d0dfd8a6cf7918d70cfdfd5a7d58
|
||||
checksum: 637e53dffdaa80813a5cdd72e519f8f68978e00db17b39b471f39c8e2b98bc85643fe74168255a1dfdc655c71803e3d01b4ca6635bc6159c429dd59232ac07d4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
Reference in new issue
Block a user