Skip to content

Commit

Permalink
[core] Add labels CRUD
Browse files Browse the repository at this point in the history
fix #607
  • Loading branch information
devlikepro committed Nov 4, 2024
1 parent fb80933 commit 9969966
Show file tree
Hide file tree
Showing 7 changed files with 283 additions and 7 deletions.
93 changes: 91 additions & 2 deletions src/api/labels.controller.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,29 @@
import { Body, Controller, Get, Param, Put } from '@nestjs/common';
import {
Body,
Controller,
Delete,
Get,
NotFoundException,
Param,
Post,
Put,
UnprocessableEntityException,
UsePipes,
ValidationPipe,
} from '@nestjs/common';
import { ApiOperation, ApiSecurity, ApiTags } from '@nestjs/swagger';
import { WhatsappSession } from '@waha/core/abc/session.abc';
import { ChatIdApiParam } from '@waha/nestjs/params/ChatIdApiParam';
import {
SessionApiParam,
WorkingSessionParam,
} from '@waha/nestjs/params/SessionApiParam';
import { Label, SetLabelsRequest } from '@waha/structures/labels.dto';
import {
Label,
LabelBody,
SetLabelsRequest,
} from '@waha/structures/labels.dto';
import * as lodash from 'lodash';

import { SessionManager } from '../core/abc/manager.abc';

Expand All @@ -23,6 +40,78 @@ export class LabelsController {
return session.getLabels();
}

@Post('/')
@SessionApiParam
@ApiOperation({ summary: 'Create a new label' })
@UsePipes(new ValidationPipe({ transform: true, whitelist: true }))
async create(
@WorkingSessionParam session: WhatsappSession,
@Body() body: LabelBody,
): Promise<Label> {
const labelDto = body.toDTO();

const labels = await session.getLabels();
if (labels.length >= 20) {
throw new UnprocessableEntityException('Maximum 20 labels allowed');
}

const labelByName = lodash.find(labels, { name: labelDto.name });
if (labelByName) {
throw new UnprocessableEntityException(
`Label with '${labelByName.name}' already exists, id: ${labelByName.id}`,
);
}

return session.createLabel(labelDto);
}

@Put('/:labelId')
@SessionApiParam
@ApiOperation({ summary: 'Update a label' })
@UsePipes(new ValidationPipe({ transform: true, whitelist: true }))
async update(
@WorkingSessionParam session: WhatsappSession,
@Param('labelId') labelId: string,
@Body() body: LabelBody,
): Promise<Label> {
const label = await session.getLabel(labelId);
if (!label) {
throw new NotFoundException('Label not found');
}

const labelDto = body.toDTO();
const labels = await session.getLabels();

const labelByName = lodash.find(labels, { name: labelDto.name });
if (labelByName) {
throw new UnprocessableEntityException(
`Label with '${labelByName.name}' already exists, id: ${labelByName.id}`,
);
}

label.name = labelDto.name;
label.color = labelDto.color;
label.colorHex = Label.toHex(label.color);
await session.updateLabel(label);
return label;
}

@Delete('/:labelId')
@SessionApiParam
@ApiOperation({ summary: 'Delete a label' })
@UsePipes(new ValidationPipe({ transform: true, whitelist: true }))
async delete(
@WorkingSessionParam session: WhatsappSession,
@Param('labelId') labelId: string,
): Promise<any> {
const label = await session.getLabel(labelId);
if (!label) {
throw new NotFoundException('Label not found');
}
await session.deleteLabel(label);
return { result: true };
}

@Get('/chats/:chatId')
@SessionApiParam
@ChatIdApiParam
Expand Down
20 changes: 18 additions & 2 deletions src/core/abc/session.abc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ import {
GetChatMessagesQuery,
} from '@waha/structures/chats.dto';
import { SendButtonsRequest } from '@waha/structures/chatting.buttons.dto';
import { Label, LabelID } from '@waha/structures/labels.dto';
import { Label, LabelDTO, LabelID } from '@waha/structures/labels.dto';
import { PaginationParams } from '@waha/structures/pagination.dto';
import { WAMessage } from '@waha/structures/responses.dto';
import { LoggerBuilder } from '@waha/utils/logging';
import { EventEmitter } from 'events';
import * as fs from 'fs';
import * as lodash from 'lodash';
import { Logger } from 'pino';
import { MessageId } from 'whatsapp-web.js';

Expand Down Expand Up @@ -66,7 +67,6 @@ import { NotImplementedByEngineError } from '../exceptions';
import { IMediaManager } from '../media/IMediaManager';
import { QR } from '../QR';
import { DataStore } from './DataStore';

// eslint-disable-next-line @typescript-eslint/no-var-requires
const qrcode = require('qrcode-terminal');

Expand Down Expand Up @@ -387,11 +387,27 @@ export abstract class WhatsappSession {
/**
* Labels methods
*/
public async getLabel(labelId: string): Promise<Label | undefined> {
const labels = await this.getLabels();
return lodash.find(labels, { id: labelId });
}

public getLabels(): Promise<Label[]> {
throw new NotImplementedByEngineError();
}

public async createLabel(label: LabelDTO): Promise<Label> {
throw new NotImplementedByEngineError();
}

public async updateLabel(label: Label): Promise<Label> {
throw new NotImplementedByEngineError();
}

public async deleteLabel(label: Label): Promise<void> {
throw new NotImplementedByEngineError();
}

public getChatsByLabelId(labelId: string) {
throw new NotImplementedByEngineError();
}
Expand Down
52 changes: 51 additions & 1 deletion src/core/engines/noweb/session.noweb.core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ import makeWASocket, {
WAMessageKey,
} from '@adiwajshing/baileys';
import { WACallEvent } from '@adiwajshing/baileys/lib/Types/Call';
import { Label as NOWEBLabel } from '@adiwajshing/baileys/lib/Types/Label';
import {
Label as NOWEBLabel,
LabelActionBody,
} from '@adiwajshing/baileys/lib/Types/Label';
import { LabelAssociationType } from '@adiwajshing/baileys/lib/Types/LabelAssociation';
import { isLidUser } from '@adiwajshing/baileys/lib/WABinary/jid-utils';
import { Logger as BaileysLogger } from '@adiwajshing/baileys/node_modules/pino';
Expand Down Expand Up @@ -49,6 +52,7 @@ import { BinaryFile, RemoteFile } from '@waha/structures/files.dto';
import {
Label,
LabelChatAssociation,
LabelDTO,
LabelID,
} from '@waha/structures/labels.dto';
import { ReplyToMessage } from '@waha/structures/message.dto';
Expand Down Expand Up @@ -875,6 +879,52 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
return labels.map(this.toLabel);
}

public async createLabel(label: LabelDTO): Promise<Label> {
const labels = await this.store.getLabels();
const highestLabelId = lodash.max(
labels.map((label) => parseInt(label.id)),
);
const labelId = highestLabelId ? highestLabelId + 1 : 1;
const labelAction: LabelActionBody = {
id: labelId.toString(),
name: label.name,
color: label.color,
deleted: false,
predefinedId: undefined,
};
await this.sock.addLabel(undefined, labelAction);

return {
id: labelId.toString(),
name: label.name,
color: label.color,
colorHex: Label.toHex(label.color),
};
}

public async updateLabel(label: Label): Promise<Label> {
const labelAction: LabelActionBody = {
id: label.id,
name: label.name,
color: label.color,
deleted: false,
predefinedId: undefined,
};
await this.sock.addLabel(undefined, labelAction);
return label;
}

public async deleteLabel(label: Label): Promise<void> {
const labelAction: LabelActionBody = {
id: label.id,
name: label.name,
color: label.color,
deleted: true,
predefinedId: undefined,
};
await this.sock.addLabel(undefined, labelAction);
}

public async getChatsByLabelId(labelId: string) {
const chats = await this.store.getChatsByLabelId(labelId);
// Remove unreadCount, it's not ready yet
Expand Down
39 changes: 39 additions & 0 deletions src/core/engines/webjs/WebjsClient.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { GetChatMessagesFilter } from '@waha/structures/chats.dto';
import { Label } from '@waha/structures/labels.dto';
import { PaginationParams } from '@waha/structures/pagination.dto';
import * as lodash from 'lodash';
import { Client } from 'whatsapp-web.js';
Expand Down Expand Up @@ -45,6 +46,44 @@ export class WebjsClient extends Client {
});
}

async createLabel(name: string, color: number): Promise<number> {
const labelId: number = await this.pupPage.evaluate(
async (name, color) => {
// @ts-ignore
return await window.WAHA.WAWebBizLabelEditingAction.labelAddAction(
name,
color,
);
},
name,
color,
);
return labelId;
}

async deleteLabel(label: Label) {
return await this.pupPage.evaluate(async (label) => {
// @ts-ignore
return await window.WAHA.WAWebBizLabelEditingAction.labelDeleteAction(
label.id,
label.name,
label.color,
);
}, label);
}

async updateLabel(label: Label) {
return await this.pupPage.evaluate(async (label) => {
// @ts-ignore
return await window.WAHA.WAWebBizLabelEditingAction.labelEditAction(
label.id,
label.name,
undefined, // predefinedId
label.color,
);
}, label);
}

async getChats(pagination?: PaginationParams) {
if (lodash.isEmpty(pagination)) {
return await super.getChats();
Expand Down
3 changes: 3 additions & 0 deletions src/core/engines/webjs/_WAHA.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
exports.LoadWAHA = () => {
window.WAHA = {};
window.WAHA.WAWebBizLabelEditingAction = window.require(
'WAWebBizLabelEditingAction',
);

window.WAHA.getChats = async (pagination) => {
let chats = window.Store.Chat.getModelsArray().slice();
Expand Down
20 changes: 19 additions & 1 deletion src/core/engines/webjs/session.webjs.core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ import {
ParticipantsRequest,
SettingsSecurityChangeInfo,
} from '@waha/structures/groups.dto';
import { Label, LabelID } from '@waha/structures/labels.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 { WAMessage, WAMessageReaction } from '@waha/structures/responses.dto';
Expand Down Expand Up @@ -632,6 +632,24 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
return labels.map(this.toLabel);
}

public async createLabel(label: LabelDTO): Promise<Label> {
const labelId = await this.whatsapp.createLabel(label.name, label.color);
return {
id: labelId.toString(),
name: label.name,
color: label.color,
colorHex: Label.toHex(label.color),
};
}

public async updateLabel(label: Label): Promise<Label> {
return await this.whatsapp.updateLabel(label);
}

public deleteLabel(label: Label): Promise<void> {
return this.whatsapp.deleteLabel(label);
}

public getChatsByLabelId(labelId: string) {
return this.whatsapp.getChatsByLabelId(labelId);
}
Expand Down
Loading

0 comments on commit 9969966

Please sign in to comment.