[core] Add group endpoints

This commit is contained in:
allburov committed 2023-02-24 19:57:48 +07:00
1 parent 936e2d0863
commit ba1afa2569
9 files changed
+390 -10

No files matched your search

+5 -8
View File
@@ -18,8 +18,8 @@
* [Sessions](#sessions)
* [Security](#security)
* [Updates](#updates)
* [Groups [soon]](#groups-soon)
* [Contacts [soon]](#contacts-soon)
* [Groups](#groups)
* [Contacts](#contacts)
- [Quick start](#quick-start)
* [Requirements](#requirements)
* [Send your first message](#send-your-first-message)
@@ -64,22 +64,19 @@
- One month delay in bug fixes and updates.
## Groups [soon]
- Join groups by invite
## Groups
- Create a group
- Get invite for group
- Modify group info (subject, description)
- Modify group settings (send messages, edit info)
- Add group participants
- Kick group participants
- Promote/demote group participants
## Contacts [soon]
- Mention users
## Contacts
- Mute/unmute chats
- Block/unblock contacts
- Get contact info
- Get profile pictures
- Set user status message
# Quick start
+165
View File
@@ -0,0 +1,165 @@
import {Body, Controller, Delete, Get, Param, Post, Put} from '@nestjs/common';
import {ApiOperation, ApiSecurity, ApiTags} from "@nestjs/swagger";
import {SessionManager} from "../core/abc/manager.abc";
import {CreateGroupRequest, DescriptionRequest, ParticipantsRequest, SubjectRequest} from "../structures/groups.dto";
import {WhatsappSession} from "../core/abc/session.abc";
import {SessionApiParam, SessionParam} from "./helpers";
@ApiSecurity('api_key')
@Controller('api/:session/groups')
@ApiTags('groups')
export class GroupsController {
constructor(private manager: SessionManager) {
}
@Post('')
@SessionApiParam
@ApiOperation({summary: "Create a new group."})
createGroup(
@SessionParam session: WhatsappSession,
@Body() request: CreateGroupRequest,
) {
return session.createGroup(request)
}
@Get('')
@SessionApiParam
@ApiOperation({summary: "Get all groups."})
getGroups(
@SessionParam session: WhatsappSession,
) {
return session.getGroups()
}
@Get(':id')
@SessionApiParam
@ApiOperation({summary: "Get the group."})
getGroup(
@SessionParam session: WhatsappSession,
@Param('id') id: string,
) {
return session.getGroup(id)
}
@Delete(':id')
@SessionApiParam
@ApiOperation({summary: "Delete the group."})
deleteGroup(
@SessionParam session: WhatsappSession,
@Param('id') id: string,
) {
return session.deleteGroup(id)
}
@Post(':id/leave')
@SessionApiParam
@ApiOperation({summary: "Leave the group."})
leaveGroup(
@SessionParam session: WhatsappSession,
@Param('id') id: string,
) {
return session.leaveGroup(id)
}
@Put(':id/description')
@ApiOperation({
summary: "Updates the group description.\n" +
"Returns true if the subject was properly updated. This can return false if the user does not have the necessary permissions.\n"
})
@SessionApiParam
setDescription(
@SessionParam session: WhatsappSession,
@Param('id') id: string,
@Body() request: DescriptionRequest
) {
return session.setDescription(id, request.description)
}
@Put(':id/subject')
@SessionApiParam
@ApiOperation({
summary: "Updates the group subject.\n" +
"Returns true if the subject was properly updated. This can return false if the user does not have the necessary permissions.\n"
})
setSubject(
@SessionParam session: WhatsappSession,
@Param('id') id: string,
@Body() request: SubjectRequest
) {
return session.setSubject(id, request.subject)
}
@Get(':id/invite-code')
@SessionApiParam
@ApiOperation({summary: "Gets the invite code for a specific group."})
getInviteCode(
@SessionParam session: WhatsappSession,
@Param('id') id: string,
): Promise<string> {
return session.getInviteCode(id)
}
@Post(':id/invite-code/revoke')
@SessionApiParam
@ApiOperation({summary: "Invalidates the current group invite code and generates a new one."})
revokeInviteCode(
@SessionParam session: WhatsappSession,
@Param('id') id: string,
): Promise<string> {
return session.revokeInviteCode(id)
}
@Get(':id/participants/')
@SessionApiParam
@ApiOperation({summary: 'Get a list of participants by in the group.'})
getParticipants(
@SessionParam session: WhatsappSession,
@Param('id') id: string,
) {
return session.getParticipants(id)
}
@Post(':id/participants/add')
@SessionApiParam
@ApiOperation({summary: 'Adds a list of participants by ID to the group.'})
addParticipants(
@SessionParam session: WhatsappSession,
@Param('id') id: string,
@Body() request: ParticipantsRequest
) {
return session.addParticipants(id, request)
}
@Post(':id/participants/remove')
@SessionApiParam
@ApiOperation({summary: 'Removes a list of participants by ID to the group.'})
removeParticipants(
@SessionParam session: WhatsappSession,
@Param('id') id: string,
@Body() request: ParticipantsRequest
) {
return session.removeParticipants(id, request)
}
@Post(':id/admin/promote')
@SessionApiParam
@ApiOperation({summary: 'Promote participants to admin users.'})
promoteToAdmin(
@SessionParam session: WhatsappSession,
@Param('id') id: string,
@Body() request: ParticipantsRequest
) {
return session.promoteParticipantsToAdmin(id, request)
}
@Post(':id/admin/demote')
@SessionApiParam
@ApiOperation({summary: 'Demotes participants by to regular users.'})
demoteToAdmin(
@SessionParam session: WhatsappSession,
@Param('id') id: string,
@Body() request: ParticipantsRequest
) {
return session.demoteParticipantsToUser(id, request)
}
}
+35
View File
@@ -0,0 +1,35 @@
import {ApiParam} from "@nestjs/swagger";
import {Injectable, Param, PipeTransform} from "@nestjs/common";
import {SessionManager} from "../core/abc/manager.abc";
import {WhatsappSession} from "../core/abc/session.abc";
/**
* Get session name and return Whatsapp session back (if exists)
* use it as
@Param('session', SessionPipe) session: WhatsappSession,
*/
@Injectable()
export class SessionPipe implements PipeTransform<WhatsappSession> {
constructor(private manager: SessionManager) {
}
async transform(value: any) {
return this.manager.getSession(value)
}
}
/**
* Decorator for a method that uses SessionPipe above
*/
export const SessionApiParam = ApiParam({
name: 'session',
required: true,
type: "string",
description: "WhatsApp session name",
})
/**
* Session param
@SessionParam session: WhatsappSession,
*/
export const SessionParam = Param('session', SessionPipe)
+60
View File
@@ -18,6 +18,7 @@ import {MediaStorage} from "./storage.abc";
import {MessageId} from "whatsapp-web.js";
import {ContactQuery, ContactRequest} from "../../structures/contacts.dto";
import {NotImplementedByEngineError} from "../exceptions";
import {CreateGroupRequest, ParticipantsRequest} from "../../structures/groups.dto";
export abstract class WhatsappSession {
public status: WhatsappStatus;
@@ -132,6 +133,65 @@ export abstract class WhatsappSession {
throw new NotImplementedByEngineError()
}
/**
* Group methods
*/
public createGroup(request: CreateGroupRequest) {
throw new NotImplementedByEngineError()
}
public getGroups() {
throw new NotImplementedByEngineError()
}
public getGroup(id) {
throw new NotImplementedByEngineError()
}
public deleteGroup(id) {
throw new NotImplementedByEngineError()
}
public leaveGroup(id) {
throw new NotImplementedByEngineError()
}
public setDescription(id, description) {
throw new NotImplementedByEngineError()
}
public setSubject(id, description) {
throw new NotImplementedByEngineError()
}
public getInviteCode(id): Promise<string> {
throw new NotImplementedByEngineError()
}
public revokeInviteCode(id): Promise<string> {
throw new NotImplementedByEngineError()
}
public getParticipants(id) {
throw new NotImplementedByEngineError()
}
public addParticipants(id, request: ParticipantsRequest) {
throw new NotImplementedByEngineError()
}
public removeParticipants(id, request: ParticipantsRequest) {
throw new NotImplementedByEngineError()
}
public promoteParticipantsToAdmin(id, request: ParticipantsRequest) {
throw new NotImplementedByEngineError()
}
public demoteParticipantsToUser(id, request: ParticipantsRequest) {
throw new NotImplementedByEngineError()
}
/**
* END - Methods for API
+2
View File
@@ -10,6 +10,7 @@ import {VersionController} from "../api/version.controller";
import {PassportModule} from "@nestjs/passport";
import {SessionManager} from "./abc/manager.abc";
import {SessionManagerCore} from "./manager.core";
import {GroupsController} from "../api/groups.controller";
export const IMPORTS = [
ConfigModule.forRoot({
@@ -32,6 +33,7 @@ export const CONTROLLERS = [
SessionsController,
ChattingController,
ContactsController,
GroupsController,
ScreenshotController,
VersionController,
]
+78 -1
View File
@@ -1,5 +1,5 @@
import {UnprocessableEntityException} from "@nestjs/common/exceptions/unprocessable-entity.exception";
import {Buttons, Chat, Client, Contact, Events, Location, Message} from "whatsapp-web.js";
import {Buttons, Chat, Client, Contact, Events, GroupChat, Location, Message} from "whatsapp-web.js";
import {Message as MessageInstance} from "whatsapp-web.js/src/structures"
import {WAEvents, WhatsappStatus} from "../structures/enums.dto";
import {WhatsappSession} from "./abc/session.abc";
@@ -20,6 +20,7 @@ import {
} from "../structures/chatting.dto";
import {AvailableInPlusVersion, NotImplementedByEngineError} from "./exceptions";
import {ContactQuery, ContactRequest} from "../structures/contacts.dto";
import {CreateGroupRequest, ParticipantsRequest} from "../structures/groups.dto";
// eslint-disable-next-line @typescript-eslint/no-var-requires
const qrcode = require('qrcode-terminal');
@@ -184,6 +185,82 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
await contact.unblock()
}
/**
* Group methods
*/
public createGroup(request: CreateGroupRequest) {
const participantIds = request.participants.map(participant => participant.id)
return this.whatsapp.createGroup(request.name, participantIds)
}
public getGroups() {
return this.whatsapp.getChats().then(chats => chats.filter(chat => chat.isGroup))
}
public getGroup(id) {
return this.whatsapp.getChatById(id)
}
public async deleteGroup(id) {
const groupChat = await this.whatsapp.getChatById(id) as GroupChat
return groupChat.delete()
}
public async leaveGroup(id) {
const groupChat = await this.whatsapp.getChatById(id) as GroupChat
return groupChat.leave()
}
public async setDescription(id, description) {
const groupChat = await this.whatsapp.getChatById(id) as GroupChat
return groupChat.setDescription(description)
}
public async setSubject(id, subject) {
const groupChat = await this.whatsapp.getChatById(id) as GroupChat
return groupChat.setSubject(subject)
}
public async getInviteCode(id): Promise<string> {
const groupChat = await this.whatsapp.getChatById(id) as GroupChat
return groupChat.getInviteCode()
}
public async revokeInviteCode(id): Promise<string> {
const groupChat = await this.whatsapp.getChatById(id) as GroupChat
await groupChat.revokeInvite()
return groupChat.getInviteCode()
}
public async getParticipants(id) {
const groupChat = await this.whatsapp.getChatById(id) as GroupChat
return groupChat.participants
}
public async addParticipants(id, request: ParticipantsRequest) {
const groupChat = await this.whatsapp.getChatById(id) as GroupChat
const participantIds = request.participants.map(participant => participant.id)
return groupChat.addParticipants(participantIds)
}
public async removeParticipants(id, request: ParticipantsRequest) {
const groupChat = await this.whatsapp.getChatById(id) as GroupChat
const participantIds = request.participants.map(participant => participant.id)
return groupChat.removeParticipants(participantIds)
}
public async promoteParticipantsToAdmin(id, request: ParticipantsRequest) {
const groupChat = await this.whatsapp.getChatById(id) as GroupChat
const participantIds = request.participants.map(participant => participant.id)
return groupChat.promoteParticipants(participantIds)
}
public async demoteParticipantsToUser(id, request: ParticipantsRequest) {
const groupChat = await this.whatsapp.getChatById(id) as GroupChat
const participantIds = request.participants.map(participant => participant.id)
return groupChat.demoteParticipants(participantIds)
}
/**
* END - Methods for API
*/
+4
View File
@@ -20,6 +20,10 @@ export class SwaggerModuleCore {
Use phone number (without +) or phone number and \`@c.us\` at the end as \`contactId\`.<br>
'E.g: \`12312312310\` OR \`12312312310@c.us\`<br>`
)
.addTag(
'groups',
`Groups methods.<br>`
)
.addTag('other', 'Other methods')
.addApiKey({
type: 'apiKey',
+1 -1
View File
@@ -1,5 +1,5 @@
import {IsString} from "class-validator";
import {SessionBaseRequest, SessionQuery, WHATSAPP_DEFAULT_SESSION_NAME} from "./base.dto";
import {SessionBaseRequest, SessionQuery} from "./base.dto";
/**
+40
View File
@@ -0,0 +1,40 @@
import {IsArray, IsString} from "class-validator";
/**
* Structures
*/
export class Participant {
@IsString()
id: string
}
/**
* Queries
*/
/**
* Requests
*/
export class ParticipantsRequest {
@IsArray()
participants: Array<Participant>
}
export class DescriptionRequest {
@IsString()
description: string
}
export class SubjectRequest {
@IsString()
subject: string
}
export class CreateGroupRequest {
@IsString()
name: string
@IsArray()
participants: Array<Participant>
}