Spaces:
Runtime error
Runtime error
File size: 10,142 Bytes
46252cd | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 | import { Controller, Get, Post, Put, Delete, Param, Body, HttpCode, HttpStatus } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiBody } from '@nestjs/swagger';
import { GroupService } from './group.service';
import {
CreateGroupDto,
ParticipantsDto,
GroupSubjectDto,
GroupDescriptionDto,
JoinGroupDto,
GroupSettingsDto,
} from './dto/group.dto';
import { RequireRole } from '../auth/decorators/auth.decorators';
import { ApiKeyRole } from '../auth/entities/api-key.entity';
// NOTE: the session→groups LIST lives on the SessionController at GET /sessions/:id/groups (it
// registered first and owns the canonical narrow projection). A bare @Get() here would collide on
// the same path pattern (/sessions/{x}/groups) and be shadowed, so this controller owns only the
// group sub-resource routes (:groupId/...) under the same mount.
@ApiTags('groups')
@Controller('sessions/:sessionId/groups')
export class GroupController {
constructor(private readonly groupService: GroupService) {}
@Get(':groupId')
@ApiOperation({ summary: 'Get detailed group info' })
@ApiParam({ name: 'sessionId', description: 'Session ID' })
@ApiParam({ name: 'groupId', description: 'Group ID (e.g., 120363xxx@g.us)' })
@ApiResponse({ status: 200, description: 'Group details with participants' })
@ApiResponse({ status: 404, description: 'Group not found' })
async findOne(@Param('sessionId') sessionId: string, @Param('groupId') groupId: string) {
return this.groupService.getGroupInfo(sessionId, groupId);
}
@Post('join')
@RequireRole(ApiKeyRole.OPERATOR)
@HttpCode(HttpStatus.OK)
@ApiOperation({ summary: 'Join a group via invite code' })
@ApiParam({ name: 'sessionId', description: 'Session ID' })
@ApiBody({ type: JoinGroupDto })
@ApiResponse({ status: 200, description: 'Joined the group' })
@ApiResponse({ status: 400, description: 'Invalid or expired invite code, or session is not started' })
async join(@Param('sessionId') sessionId: string, @Body() dto: JoinGroupDto) {
const groupId = await this.groupService.joinGroupViaInviteCode(sessionId, dto.inviteCode);
return { success: true, groupId };
}
@Get(':groupId/settings')
@ApiOperation({ summary: 'Get group settings (announce / locked / ephemeral timer)' })
@ApiParam({ name: 'sessionId', description: 'Session ID' })
@ApiParam({ name: 'groupId', description: 'Group ID' })
@ApiResponse({ status: 200, description: 'Group settings' })
@ApiResponse({ status: 404, description: 'Group not found' })
async getSettings(@Param('sessionId') sessionId: string, @Param('groupId') groupId: string) {
return this.groupService.getGroupSettings(sessionId, groupId);
}
@Put(':groupId/settings')
@RequireRole(ApiKeyRole.OPERATOR)
@ApiOperation({ summary: 'Update group settings (announce / locked / ephemeral timer)' })
@ApiParam({ name: 'sessionId', description: 'Session ID' })
@ApiParam({ name: 'groupId', description: 'Group ID' })
@ApiBody({ type: GroupSettingsDto })
@ApiResponse({ status: 200, description: 'Group settings updated' })
@ApiResponse({ status: 400, description: 'No setting provided, or a value is not a boolean' })
@ApiResponse({ status: 403, description: 'The engine refused the change (the account is not a group admin)' })
@ApiResponse({ status: 404, description: 'Group not found' })
@ApiResponse({ status: 501, description: 'The active engine does not support a requested setting' })
async updateSettings(
@Param('sessionId') sessionId: string,
@Param('groupId') groupId: string,
@Body() dto: GroupSettingsDto,
) {
await this.groupService.updateGroupSettings(sessionId, groupId, dto);
return { success: true, message: 'Group settings updated' };
}
@Post()
@RequireRole(ApiKeyRole.OPERATOR)
@ApiOperation({ summary: 'Create a new group' })
@ApiParam({ name: 'sessionId', description: 'Session ID' })
@ApiBody({ type: CreateGroupDto })
@ApiResponse({ status: 201, description: 'Group created' })
async create(@Param('sessionId') sessionId: string, @Body() dto: CreateGroupDto) {
return this.groupService.createGroup(sessionId, dto.name, dto.participants);
}
@Post(':groupId/participants')
@RequireRole(ApiKeyRole.OPERATOR)
@ApiOperation({ summary: 'Add participants to a group' })
@ApiParam({ name: 'sessionId', description: 'Session ID' })
@ApiParam({ name: 'groupId', description: 'Group ID' })
@ApiBody({ type: ParticipantsDto })
@ApiResponse({ status: 200, description: 'Participants added' })
@HttpCode(HttpStatus.OK)
async addParticipants(
@Param('sessionId') sessionId: string,
@Param('groupId') groupId: string,
@Body() dto: ParticipantsDto,
) {
await this.groupService.addParticipants(sessionId, groupId, dto.participants);
return { success: true, message: 'Participants added' };
}
@Delete(':groupId/participants')
@RequireRole(ApiKeyRole.OPERATOR)
@ApiOperation({ summary: 'Remove participants from a group' })
@ApiParam({ name: 'sessionId', description: 'Session ID' })
@ApiParam({ name: 'groupId', description: 'Group ID' })
@ApiBody({ type: ParticipantsDto })
@ApiResponse({ status: 200, description: 'Participants removed' })
async removeParticipants(
@Param('sessionId') sessionId: string,
@Param('groupId') groupId: string,
@Body() dto: ParticipantsDto,
) {
await this.groupService.removeParticipants(sessionId, groupId, dto.participants);
return { success: true, message: 'Participants removed' };
}
@Post(':groupId/participants/promote')
@RequireRole(ApiKeyRole.OPERATOR)
@ApiOperation({ summary: 'Promote participants to admin' })
@ApiParam({ name: 'sessionId', description: 'Session ID' })
@ApiParam({ name: 'groupId', description: 'Group ID' })
@ApiBody({ type: ParticipantsDto })
@ApiResponse({ status: 200, description: 'Participants promoted' })
@HttpCode(HttpStatus.OK)
async promoteParticipants(
@Param('sessionId') sessionId: string,
@Param('groupId') groupId: string,
@Body() dto: ParticipantsDto,
) {
await this.groupService.promoteParticipants(sessionId, groupId, dto.participants);
return { success: true, message: 'Participants promoted to admin' };
}
@Post(':groupId/participants/demote')
@RequireRole(ApiKeyRole.OPERATOR)
@ApiOperation({ summary: 'Demote participants from admin' })
@ApiParam({ name: 'sessionId', description: 'Session ID' })
@ApiParam({ name: 'groupId', description: 'Group ID' })
@ApiBody({ type: ParticipantsDto })
@ApiResponse({ status: 200, description: 'Participants demoted' })
@HttpCode(HttpStatus.OK)
async demoteParticipants(
@Param('sessionId') sessionId: string,
@Param('groupId') groupId: string,
@Body() dto: ParticipantsDto,
) {
await this.groupService.demoteParticipants(sessionId, groupId, dto.participants);
return { success: true, message: 'Participants demoted from admin' };
}
@Put(':groupId/subject')
@RequireRole(ApiKeyRole.OPERATOR)
@ApiOperation({ summary: 'Change group name/subject' })
@ApiParam({ name: 'sessionId', description: 'Session ID' })
@ApiParam({ name: 'groupId', description: 'Group ID' })
@ApiBody({ type: GroupSubjectDto })
@ApiResponse({ status: 200, description: 'Subject updated' })
async setSubject(
@Param('sessionId') sessionId: string,
@Param('groupId') groupId: string,
@Body() dto: GroupSubjectDto,
) {
await this.groupService.setGroupSubject(sessionId, groupId, dto.subject);
return { success: true, message: 'Group subject updated' };
}
@Put(':groupId/description')
@RequireRole(ApiKeyRole.OPERATOR)
@ApiOperation({ summary: 'Change group description' })
@ApiParam({ name: 'sessionId', description: 'Session ID' })
@ApiParam({ name: 'groupId', description: 'Group ID' })
@ApiBody({ type: GroupDescriptionDto })
@ApiResponse({ status: 200, description: 'Description updated' })
async setDescription(
@Param('sessionId') sessionId: string,
@Param('groupId') groupId: string,
@Body() dto: GroupDescriptionDto,
) {
await this.groupService.setGroupDescription(sessionId, groupId, dto.description);
return { success: true, message: 'Group description updated' };
}
@Post(':groupId/leave')
@RequireRole(ApiKeyRole.OPERATOR)
@ApiOperation({ summary: 'Leave a group' })
@ApiParam({ name: 'sessionId', description: 'Session ID' })
@ApiParam({ name: 'groupId', description: 'Group ID' })
@ApiResponse({ status: 200, description: 'Left the group' })
@HttpCode(HttpStatus.OK)
async leave(@Param('sessionId') sessionId: string, @Param('groupId') groupId: string) {
await this.groupService.leaveGroup(sessionId, groupId);
return { success: true, message: 'Left the group' };
}
// ========== Gap Quick Wins: Invite Link ==========
@Get(':groupId/invite-code')
@ApiOperation({ summary: 'Get group invite code/link' })
@ApiParam({ name: 'sessionId', description: 'Session ID' })
@ApiParam({ name: 'groupId', description: 'Group ID' })
@ApiResponse({ status: 200, description: 'Group invite code' })
async getInviteCode(@Param('sessionId') sessionId: string, @Param('groupId') groupId: string) {
const inviteCode = await this.groupService.getGroupInviteCode(sessionId, groupId);
return {
inviteCode,
inviteLink: `https://chat.whatsapp.com/${inviteCode}`,
};
}
@Post(':groupId/invite-code/revoke')
@RequireRole(ApiKeyRole.OPERATOR)
@HttpCode(HttpStatus.OK)
@ApiOperation({ summary: 'Revoke group invite code and generate new one' })
@ApiParam({ name: 'sessionId', description: 'Session ID' })
@ApiParam({ name: 'groupId', description: 'Group ID' })
@ApiResponse({ status: 200, description: 'New invite code generated' })
async revokeInviteCode(@Param('sessionId') sessionId: string, @Param('groupId') groupId: string) {
const newCode = await this.groupService.revokeGroupInviteCode(sessionId, groupId);
return {
inviteCode: newCode,
inviteLink: `https://chat.whatsapp.com/${newCode}`,
message: 'Invite code revoked and new one generated',
};
}
}
|