diff --git a/rc-service/rc-service-external/external-inner-endpoint/src/main/java/com/red/circle/external/inner/service/message/impl/ImGroupClientServiceImpl.java b/rc-service/rc-service-external/external-inner-endpoint/src/main/java/com/red/circle/external/inner/service/message/impl/ImGroupClientServiceImpl.java index 8b9256c2..dea56b3d 100644 --- a/rc-service/rc-service-external/external-inner-endpoint/src/main/java/com/red/circle/external/inner/service/message/impl/ImGroupClientServiceImpl.java +++ b/rc-service/rc-service-external/external-inner-endpoint/src/main/java/com/red/circle/external/inner/service/message/impl/ImGroupClientServiceImpl.java @@ -1,6 +1,5 @@ package com.red.circle.external.inner.service.message.impl; -import com.alibaba.fastjson.JSON; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.red.circle.common.business.core.enums.SysOriginPlatformEnum; @@ -39,8 +38,10 @@ import org.springframework.stereotype.Service; @Slf4j @Service @RequiredArgsConstructor -public class ImGroupClientServiceImpl implements ImGroupClientService { - +public class ImGroupClientServiceImpl implements ImGroupClientService { + + private static final Integer GROUP_ALREADY_EXISTS_ERROR_CODE = 10025; + private final RcMessageProperties rcMessageProperties; private final ImGroupMemberService imGroupMemberService; private final ImGroupMessageService imGroupMessageService; @@ -159,25 +160,33 @@ public class ImGroupClientServiceImpl implements ImGroupClientService { ); } - @Override - public boolean createAVChatRoomGroup(CreateGroupCmd cmd) { - RcHttpClient.ResponseMono group = imGroupManagerService.createGroup( + @Override + public boolean createAVChatRoomGroup(CreateGroupCmd cmd) { + RcHttpClient.ResponseMono group = imGroupManagerService.createGroup( CreateGroupParam.builder() .type(GroupType.AVChatRoom) .ownerAccount(cmd.getOwnerAccount()) .groupId(cmd.getGroupId()) .name(cmd.getName()) .introduction(cmd.getIntroduction()) - .notification(cmd.getNotification()) - .faceUrl(cmd.getFaceUrl()) - .build() - ); - log.info("createAVChatRoomGroup: {}", JSON.toJSONString(group)); - return TencentIMStatusUtils.isSuccess( - group.block() - ); - - } + .notification(cmd.getNotification()) + .faceUrl(cmd.getFaceUrl()) + .build() + ); + String response = group.block(); + log.info("createAVChatRoomGroup groupId={}, response={}", cmd.getGroupId(), response); + Integer errorCode = parseErrorCode(response); + if (Objects.equals(errorCode, 0)) { + return true; + } + if (Objects.equals(errorCode, GROUP_ALREADY_EXISTS_ERROR_CODE)) { + log.warn("createAVChatRoomGroup duplicate groupId={}, treat as success", cmd.getGroupId()); + return true; + } + + return TencentIMStatusUtils.isSuccess(response); + + } @Override public void addGroupMembers(CreateGroupAddMemberCmd cmd) { diff --git a/rc-service/rc-service-external/external-inner-endpoint/src/test/java/com/red/circle/external/inner/service/message/impl/ImGroupClientServiceImplTest.java b/rc-service/rc-service-external/external-inner-endpoint/src/test/java/com/red/circle/external/inner/service/message/impl/ImGroupClientServiceImplTest.java index 227a8b73..227d2cc7 100644 --- a/rc-service/rc-service-external/external-inner-endpoint/src/test/java/com/red/circle/external/inner/service/message/impl/ImGroupClientServiceImplTest.java +++ b/rc-service/rc-service-external/external-inner-endpoint/src/test/java/com/red/circle/external/inner/service/message/impl/ImGroupClientServiceImplTest.java @@ -4,6 +4,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; @@ -16,6 +17,7 @@ import com.red.circle.external.inner.model.cmd.message.CreateGroupCmd; import com.red.circle.framework.dto.ResultResponse; import com.red.circle.other.inner.endpoint.live.RoomManagerClient; import com.red.circle.other.inner.model.dto.live.RoomProfileManagerDTO; +import com.red.circle.tool.core.http.RcHttpClient; import org.junit.jupiter.api.Test; class ImGroupClientServiceImplTest { @@ -68,6 +70,30 @@ class ImGroupClientServiceImplTest { verifyNoInteractions(roomManagerClient); } + @Test + void createAvChatRoomGroupShouldTreatDuplicateGroupAsSuccess() { + ImGroupManagerService imGroupManagerService = mock(ImGroupManagerService.class); + @SuppressWarnings("unchecked") + RcHttpClient.ResponseMono responseMono = mock(RcHttpClient.ResponseMono.class); + when(imGroupManagerService.createGroup(any())).thenReturn(responseMono); + when(responseMono.block()).thenReturn("{\"ErrorCode\":10025,\"ErrorInfo\":\"group id in use\"}"); + + ImGroupClientServiceImpl service = new ImGroupClientServiceImpl( + mock(RcMessageProperties.class), + mock(ImGroupMemberService.class), + mock(ImGroupMessageService.class), + imGroupManagerService, + mock(RoomManagerClient.class) + ); + + boolean created = service.createAVChatRoomGroup(new CreateGroupCmd() + .setOwnerAccount("2046161571540955138") + .setGroupId("1001268") + .setName("room1001268")); + + assertTrue(created); + } + private static final class TestableImGroupClientServiceImpl extends ImGroupClientServiceImpl { private boolean createResult; diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/room/LiveVoiceRoomCreateCmdExe.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/room/LiveVoiceRoomCreateCmdExe.java index fea64f95..2bc7397a 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/room/LiveVoiceRoomCreateCmdExe.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/room/LiveVoiceRoomCreateCmdExe.java @@ -1,14 +1,16 @@ package com.red.circle.other.app.command.room; import com.alibaba.fastjson.JSON; -import com.red.circle.common.business.core.ReplaceString; -import com.red.circle.common.business.core.SensitiveWordFilter; -import com.red.circle.common.business.dto.cmd.AppExtCommand; -import com.red.circle.component.core.i18n.I18nMessageUtils; -import com.red.circle.framework.core.asserts.ResponseAssert; -import com.red.circle.live.inner.endpoint.LiveMicClient; -import com.red.circle.mq.business.model.event.room.RoomVoiceCreateSuccessEvent; -import com.red.circle.mq.rocket.business.producer.RoomMqMessageService; +import com.red.circle.common.business.core.ReplaceString; +import com.red.circle.common.business.core.SensitiveWordFilter; +import com.red.circle.common.business.dto.cmd.AppExtCommand; +import com.red.circle.component.core.i18n.I18nMessageUtils; +import com.red.circle.external.inner.endpoint.message.ImGroupClient; +import com.red.circle.external.inner.model.cmd.message.CreateGroupCmd; +import com.red.circle.framework.core.asserts.ResponseAssert; +import com.red.circle.live.inner.endpoint.LiveMicClient; +import com.red.circle.mq.business.model.event.room.RoomVoiceCreateSuccessEvent; +import com.red.circle.mq.rocket.business.producer.RoomMqMessageService; import com.red.circle.other.app.convertor.live.RoomProfileAppConvertor; import com.red.circle.other.app.convertor.user.UserProfileAppConvertor; import com.red.circle.other.app.dto.clientobject.room.RoomVoiceProfileCO; @@ -50,13 +52,14 @@ import org.springframework.stereotype.Component; @Slf4j @Component @RequiredArgsConstructor -public class LiveVoiceRoomCreateCmdExe { - - private final LiveMicClient liveMicClient; - private final RoomMemberService roomMemberService; - private final UserProfileGateway userProfileGateway; - private final RoomMqMessageService roomMqMessageService; - private final PropsNobleVipGateway propsNobleVipGateway; +public class LiveVoiceRoomCreateCmdExe { + + private final LiveMicClient liveMicClient; + private final ImGroupClient imGroupClient; + private final RoomMemberService roomMemberService; + private final UserProfileGateway userProfileGateway; + private final RoomMqMessageService roomMqMessageService; + private final PropsNobleVipGateway propsNobleVipGateway; private final SysCountryCodeService sysCountryCodeService; private final UserProfileAppConvertor userProfileAppConvertor; private final RoomProfileAppConvertor roomProfileAppConvertor; @@ -133,11 +136,23 @@ public class LiveVoiceRoomCreateCmdExe { roomMqMessageService .createVoiceRoomSuccess(toRoomVoiceCreateSuccessEvent(roomProfile, cmd)); - - // 创建麦克风记录 - liveMicClient.create(roomProfile.getId(), roomProfile.getSetting().getMikeSize()); - return roomProfile; - } + + // 创建麦克风记录 + liveMicClient.create(roomProfile.getId(), roomProfile.getSetting().getMikeSize()); + + // 创建群聊 + Boolean isSuccess = imGroupClient.createAVChatRoomGroup(new CreateGroupCmd() + .setOwnerAccount(Objects.toString(roomProfile.getUserId())) + .setGroupId(roomProfile.getRoomAccount()) + .setFaceUrl(roomProfile.getRoomCover()) + .setName(roomProfile.getRoomName()) + ).getBody(); + + if (!Objects.equals(isSuccess, Boolean.TRUE)) { + log.warn("创建群聊失败: {}", roomProfile.getUserId()); + } + return roomProfile; + } private RoomSetting createRoomSetting(UserProfile userProfile) { RoomSetting settingV2 = RoomSetting.createDefaultRoomSetting(); diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/room/RoomEnterCmdExe.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/room/RoomEnterCmdExe.java index 702faccf..3b98aaa8 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/room/RoomEnterCmdExe.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/room/RoomEnterCmdExe.java @@ -1,13 +1,16 @@ package com.red.circle.other.app.command.room; -import com.red.circle.common.business.core.enums.SysOriginPlatformEnum; -import com.red.circle.external.inner.endpoint.message.TrtcClient; -import com.red.circle.framework.core.asserts.ResponseAssert; -import com.red.circle.framework.core.response.CommonErrorCode; -import com.red.circle.framework.core.response.ResponseErrorCode; -import com.red.circle.mq.business.model.event.task.TaskApprovalEvent; -import com.red.circle.mq.rocket.business.producer.TaskMqMessage; -import com.red.circle.other.app.command.rocket.RocketRewardClaimCmdExe; +import com.red.circle.common.business.core.enums.SysOriginPlatformEnum; +import com.red.circle.external.inner.endpoint.message.ImGroupClient; +import com.red.circle.external.inner.endpoint.message.TrtcClient; +import com.red.circle.external.inner.model.cmd.message.CreateGroupCmd; +import com.red.circle.framework.core.asserts.ResponseAssert; +import com.red.circle.framework.core.response.CommonErrorCode; +import com.red.circle.framework.core.response.ResponseErrorCode; +import com.red.circle.framework.dto.ResultResponse; +import com.red.circle.mq.business.model.event.task.TaskApprovalEvent; +import com.red.circle.mq.rocket.business.producer.TaskMqMessage; +import com.red.circle.other.app.command.rocket.RocketRewardClaimCmdExe; import com.red.circle.other.app.convertor.live.RoomProfileAppConvertor; import com.red.circle.other.app.convertor.user.UserProfileAppConvertor; import com.red.circle.other.app.dto.clientobject.room.EntryRoomEntrantsCO; @@ -62,10 +65,9 @@ import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicReference; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.stereotype.Component; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; /** * 加入房间检测. @@ -75,11 +77,14 @@ import org.springframework.stereotype.Component; @Slf4j @Component @RequiredArgsConstructor -public class RoomEnterCmdExe { - - private final UserRegionGateway userRegionGateway; - private final UserProfileGateway userProfileGateway; - private final RoomTouristService roomTouristService; +public class RoomEnterCmdExe { + + private static final String ROOM_IM_GROUP_READY_KEY_PREFIX = "ROOM:IM:GROUP:READY:"; + private static final long ROOM_IM_GROUP_READY_SECONDS = 60L; + + private final UserRegionGateway userRegionGateway; + private final UserProfileGateway userProfileGateway; + private final RoomTouristService roomTouristService; private final AdministratorService administratorService; private final PropsRoomLockService propsRoomLockService; private final UserProfileAppConvertor userProfileAppConvertor; @@ -88,10 +93,12 @@ public class RoomEnterCmdExe { private final RoomUserBlacklistService roomUserBlacklistService; private final RoomProfileManagerService roomProfileManagerService; private final TrtcClient trtcClient; - private final UserAgoraTokenCacheService userAgoraTokenCacheService; - private final TaskMqMessage taskMqMessage; - private final AdministratorAuthService administratorAuthService; - private final RocketRewardClaimCmdExe rocketRewardClaimCmdExe; + private final UserAgoraTokenCacheService userAgoraTokenCacheService; + private final TaskMqMessage taskMqMessage; + private final AdministratorAuthService administratorAuthService; + private final RocketRewardClaimCmdExe rocketRewardClaimCmdExe; + private final ImGroupClient imGroupClient; + private final RedisService redisService; public EntryRoomResponseCO execute(RoomEntryCmd cmd) { //checkEntryUserId(cmd); @@ -102,11 +109,12 @@ public class RoomEnterCmdExe { .userId(cmd.getReqUserId()) .build()); - RoomProfileManager manager = roomProfileManagerService.getById(cmd.getRoomId()); - - entryRoomCheck(cmd, manager); - - setDefaultRoomSettingTakeMicRole(manager); + RoomProfileManager manager = roomProfileManagerService.getById(cmd.getRoomId()); + + entryRoomCheck(cmd, manager); + ensureRoomImGroup(manager); + + setDefaultRoomSettingTakeMicRole(manager); UserProfileDTO ownUserProfile = userProfileAppConvertor.toUserProfileDTO( userProfileGateway.getByUserId(manager.getUserId()) @@ -148,18 +156,57 @@ public class RoomEnterCmdExe { .setLayoutCode(getLayoutCode(ownUserProfile)) .setRoomTheme(getRoomThemeCO(ownUserProfile)) ) - .setEntrants( - new EntryRoomEntrantsCO() - .setRoles(roomManagerCacheService.getRoomUserRoles(cmd.getReqUserId(), + .setEntrants( + new EntryRoomEntrantsCO() + .setRoles(roomManagerCacheService.getRoomUserRoles(cmd.getReqUserId(), cmd.getRoomId())) .setLevel(getUserLevel(cmd.requireReqSysOriginEnum(), cmd.getReqUserId())) .setNobleVipAbility(listUserPropsVipActualEquity(cmd)) - .setRoomToken(token) - ); - } - - /** - * 异步拿声网观众token,5分钟拿不到就返回默认一串字符串 + .setRoomToken(token) + ); + } + + private void ensureRoomImGroup(RoomProfileManager manager) { + if (Objects.isNull(manager) || Objects.isNull(manager.getUserId()) + || StringUtils.isBlank(manager.getRoomAccount())) { + return; + } + + String roomAccount = manager.getRoomAccount().trim(); + if (!roomAccount.chars().allMatch(Character::isDigit)) { + return; + } + + String cacheKey = ROOM_IM_GROUP_READY_KEY_PREFIX + roomAccount; + if (StringUtils.isNotBlank(redisService.getString(cacheKey))) { + return; + } + + try { + Boolean ensured = Optional.ofNullable( + imGroupClient.createAVChatRoomGroup(new CreateGroupCmd() + .setOwnerAccount(Objects.toString(manager.getUserId())) + .setGroupId(roomAccount) + .setFaceUrl(manager.getRoomCover()) + .setName(manager.getRoomName())) + ) + .map(ResultResponse::getBody) + .orElse(Boolean.FALSE); + + if (Objects.equals(ensured, Boolean.TRUE)) { + redisService.setIfAbsent(cacheKey, "1", ROOM_IM_GROUP_READY_SECONDS, TimeUnit.SECONDS); + return; + } + + log.warn("ensureRoomImGroup fail roomId={}, roomAccount={}", manager.getId(), roomAccount); + } catch (Exception ex) { + log.warn("ensureRoomImGroup exception roomId={}, roomAccount={}", manager.getId(), + roomAccount, ex); + } + } + + /** + * 异步拿声网观众token,5分钟拿不到就返回默认一串字符串 * @param cmd * @return */ diff --git a/rc-service/rc-service-other/other-application/src/test/java/com/red/circle/other/app/command/room/LiveVoiceRoomCreateCmdExeTest.java b/rc-service/rc-service-other/other-application/src/test/java/com/red/circle/other/app/command/room/LiveVoiceRoomCreateCmdExeTest.java new file mode 100644 index 00000000..44b5cdd0 --- /dev/null +++ b/rc-service/rc-service-other/other-application/src/test/java/com/red/circle/other/app/command/room/LiveVoiceRoomCreateCmdExeTest.java @@ -0,0 +1,100 @@ +package com.red.circle.other.app.command.room; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.red.circle.common.business.dto.cmd.AppExtCommand; +import com.red.circle.external.inner.endpoint.message.ImGroupClient; +import com.red.circle.external.inner.model.cmd.message.CreateGroupCmd; +import com.red.circle.framework.dto.ResultResponse; +import com.red.circle.live.inner.endpoint.LiveMicClient; +import com.red.circle.mq.business.model.event.room.RoomVoiceCreateSuccessEvent; +import com.red.circle.mq.rocket.business.producer.RoomMqMessageService; +import com.red.circle.other.app.convertor.live.RoomProfileAppConvertor; +import com.red.circle.other.app.convertor.user.UserProfileAppConvertor; +import com.red.circle.other.app.dto.clientobject.room.RoomVoiceProfileCO; +import com.red.circle.other.domain.gateway.props.PropsNobleVipGateway; +import com.red.circle.other.domain.gateway.user.UserProfileGateway; +import com.red.circle.other.domain.model.user.UserProfile; +import com.red.circle.other.infra.database.cache.service.other.EnumConfigCacheService; +import com.red.circle.other.infra.database.mongo.entity.live.RoomSetting; +import com.red.circle.other.infra.database.mongo.service.live.RoomProfileManagerService; +import com.red.circle.other.infra.database.rds.entity.sys.SysCountryCode; +import com.red.circle.other.infra.database.rds.service.live.RoomMemberService; +import com.red.circle.other.infra.database.rds.service.sys.SysCountryCodeService; +import com.red.circle.other.inner.model.dto.user.UserProfileDTO; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; + +class LiveVoiceRoomCreateCmdExeTest { + + @Test + void executeShouldCreateImRoomGroupForNormalRoom() { + LiveMicClient liveMicClient = mock(LiveMicClient.class); + ImGroupClient imGroupClient = mock(ImGroupClient.class); + RoomMemberService roomMemberService = mock(RoomMemberService.class); + UserProfileGateway userProfileGateway = mock(UserProfileGateway.class); + RoomMqMessageService roomMqMessageService = mock(RoomMqMessageService.class); + PropsNobleVipGateway propsNobleVipGateway = mock(PropsNobleVipGateway.class); + SysCountryCodeService sysCountryCodeService = mock(SysCountryCodeService.class); + UserProfileAppConvertor userProfileAppConvertor = mock(UserProfileAppConvertor.class); + RoomProfileAppConvertor roomProfileAppConvertor = mock(RoomProfileAppConvertor.class); + RoomProfileManagerService roomProfileManagerService = mock(RoomProfileManagerService.class); + EnumConfigCacheService enumConfigCacheService = mock(EnumConfigCacheService.class); + LiveVoiceRoomCreateCmdExe exe = new LiveVoiceRoomCreateCmdExe( + liveMicClient, + imGroupClient, + roomMemberService, + userProfileGateway, + roomMqMessageService, + propsNobleVipGateway, + sysCountryCodeService, + userProfileAppConvertor, + roomProfileAppConvertor, + roomProfileManagerService, + enumConfigCacheService + ); + + UserProfile userProfile = new UserProfile(); + userProfile.setId(2046161571540955138L); + userProfile.setAccount("1001268"); + userProfile.setUserNickname("room-owner"); + userProfile.setCountryCode("SA"); + userProfile.setCountryName("Saudi Arabia"); + userProfile.setOriginSys("LIKEI"); + + AppExtCommand cmd = mock(AppExtCommand.class); + when(cmd.requiredReqUserId()).thenReturn(2046161571540955138L); + when(cmd.requireReqSysOrigin()).thenReturn("LIKEI"); + when(roomProfileManagerService.existsUserRoom(2046161571540955138L)).thenReturn(false); + when(userProfileGateway.getByUserId(2046161571540955138L)).thenReturn(userProfile); + when(enumConfigCacheService.getValue(any(), any())).thenReturn("room-cover.png"); + when(imGroupClient.createAVChatRoomGroup(any(CreateGroupCmd.class))) + .thenReturn(ResultResponse.success(Boolean.TRUE)); + when(roomProfileAppConvertor.toRoomVoiceCreateSuccessEvent(any())) + .thenReturn(new RoomVoiceCreateSuccessEvent()); + when(roomProfileAppConvertor.toRoomVoiceProfileCO(any())) + .thenReturn(new RoomVoiceProfileCO()); + when(roomProfileAppConvertor.toRoomSettingCO(any(RoomSetting.class))) + .thenReturn(null); + UserProfileDTO userProfileDTO = new UserProfileDTO(); + userProfileDTO.setId(userProfile.getId()); + when(userProfileAppConvertor.toUserProfileDTO(userProfile)) + .thenReturn(userProfileDTO); + when(sysCountryCodeService.getByCode("SA")).thenReturn(new SysCountryCode()); + + exe.execute(cmd); + + ArgumentCaptor captor = ArgumentCaptor.forClass(CreateGroupCmd.class); + verify(imGroupClient).createAVChatRoomGroup(captor.capture()); + CreateGroupCmd createGroupCmd = captor.getValue(); + assertEquals("2046161571540955138", createGroupCmd.getOwnerAccount()); + assertEquals("1001268", createGroupCmd.getGroupId()); + assertEquals("room-cover.png", createGroupCmd.getFaceUrl()); + assertEquals("room1001268", createGroupCmd.getName()); + verify(liveMicClient).create(any(), any()); + } +} diff --git a/rc-service/rc-service-other/other-application/src/test/java/com/red/circle/other/app/command/room/RoomEnterCmdExeTest.java b/rc-service/rc-service-other/other-application/src/test/java/com/red/circle/other/app/command/room/RoomEnterCmdExeTest.java new file mode 100644 index 00000000..5a15423e --- /dev/null +++ b/rc-service/rc-service-other/other-application/src/test/java/com/red/circle/other/app/command/room/RoomEnterCmdExeTest.java @@ -0,0 +1,149 @@ +package com.red.circle.other.app.command.room; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anySet; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.red.circle.common.business.core.enums.SysOriginPlatformEnum; +import com.red.circle.component.redis.service.RedisService; +import com.red.circle.external.inner.endpoint.message.ImGroupClient; +import com.red.circle.external.inner.endpoint.message.TrtcClient; +import com.red.circle.external.inner.model.cmd.message.CreateGroupCmd; +import com.red.circle.framework.dto.ResultResponse; +import com.red.circle.mq.rocket.business.producer.TaskMqMessage; +import com.red.circle.other.app.command.rocket.RocketRewardClaimCmdExe; +import com.red.circle.other.app.convertor.live.RoomProfileAppConvertor; +import com.red.circle.other.app.convertor.user.UserProfileAppConvertor; +import com.red.circle.other.app.dto.clientobject.room.EntryRoomResponseCO; +import com.red.circle.other.app.dto.cmd.room.RoomEntryCmd; +import com.red.circle.other.domain.gateway.user.UserProfileGateway; +import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway; +import com.red.circle.other.infra.database.cache.service.other.RoomManagerCacheService; +import com.red.circle.other.infra.database.cache.service.user.UserAgoraTokenCacheService; +import com.red.circle.other.infra.database.mongo.entity.live.RoomCounter; +import com.red.circle.other.infra.database.mongo.entity.live.RoomProfileManager; +import com.red.circle.other.infra.database.mongo.entity.live.RoomSetting; +import com.red.circle.other.infra.database.mongo.service.live.RoomProfileManagerService; +import com.red.circle.other.infra.database.mongo.service.live.RoomTouristService; +import com.red.circle.other.infra.database.mongo.service.live.RoomUserBlacklistService; +import com.red.circle.other.infra.database.rds.service.props.PropsRoomLockService; +import com.red.circle.other.infra.database.rds.service.sys.AdministratorAuthService; +import com.red.circle.other.infra.database.rds.service.sys.AdministratorService; +import com.red.circle.other.inner.enums.room.RoomEventEnum; +import com.red.circle.other.inner.enums.room.RoomTakeMicRoleEnum; +import com.red.circle.other.inner.enums.live.RoomUserRolesEnum; +import com.red.circle.other.inner.model.dto.live.RoomProfileDTO; +import com.red.circle.other.inner.model.dto.user.UserProfileDTO; +import java.util.Collections; +import java.util.concurrent.TimeUnit; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; + +class RoomEnterCmdExeTest { + + @Test + void executeShouldEnsureImRoomGroupBeforeReturn() { + UserRegionGateway userRegionGateway = mock(UserRegionGateway.class); + UserProfileGateway userProfileGateway = mock(UserProfileGateway.class); + RoomTouristService roomTouristService = mock(RoomTouristService.class); + AdministratorService administratorService = mock(AdministratorService.class); + PropsRoomLockService propsRoomLockService = mock(PropsRoomLockService.class); + UserProfileAppConvertor userProfileAppConvertor = mock(UserProfileAppConvertor.class); + RoomProfileAppConvertor roomProfileAppConvertor = mock(RoomProfileAppConvertor.class); + RoomManagerCacheService roomManagerCacheService = mock(RoomManagerCacheService.class); + RoomUserBlacklistService roomUserBlacklistService = mock(RoomUserBlacklistService.class); + RoomProfileManagerService roomProfileManagerService = mock(RoomProfileManagerService.class); + TrtcClient trtcClient = mock(TrtcClient.class); + UserAgoraTokenCacheService userAgoraTokenCacheService = mock(UserAgoraTokenCacheService.class); + TaskMqMessage taskMqMessage = mock(TaskMqMessage.class); + AdministratorAuthService administratorAuthService = mock(AdministratorAuthService.class); + RocketRewardClaimCmdExe rocketRewardClaimCmdExe = mock(RocketRewardClaimCmdExe.class); + ImGroupClient imGroupClient = mock(ImGroupClient.class); + RedisService redisService = mock(RedisService.class); + + RoomEnterCmdExe exe = new RoomEnterCmdExe( + userRegionGateway, + userProfileGateway, + roomTouristService, + administratorService, + propsRoomLockService, + userProfileAppConvertor, + roomProfileAppConvertor, + roomManagerCacheService, + roomUserBlacklistService, + roomProfileManagerService, + trtcClient, + userAgoraTokenCacheService, + taskMqMessage, + administratorAuthService, + rocketRewardClaimCmdExe, + imGroupClient, + redisService + ); + + Long roomId = 2046489424769904642L; + Long userId = 2046161571540955138L; + RoomEntryCmd cmd = mock(RoomEntryCmd.class); + when(cmd.getRoomId()).thenReturn(roomId); + when(cmd.getReqUserId()).thenReturn(userId); + when(cmd.requiredReqUserId()).thenReturn(userId); + when(cmd.requireReqSysOrigin()).thenReturn("LIKEI"); + when(cmd.requireReqSysOriginEnum()).thenReturn(SysOriginPlatformEnum.LIKEI); + when(cmd.reqIsSelf(userId)).thenReturn(true); + + RoomProfileManager manager = new RoomProfileManager(); + manager.setId(roomId); + manager.setUserId(userId); + manager.setRoomAccount("1001268"); + manager.setRoomName("Teams stay blessed"); + manager.setRoomCover("room-cover.png"); + manager.setDel(Boolean.FALSE); + manager.setSysOrigin("LIKEI"); + manager.setEvent(RoomEventEnum.WAITING_CONFIRMED.name()); + manager.setCounter(new RoomCounter().setAdminCount(0).setMemberCount(1)); + manager.setSetting(RoomSetting.createDefaultRoomSetting().setTakeMicRole(RoomTakeMicRoleEnum.ALL.name())); + + when(roomProfileManagerService.getById(roomId)).thenReturn(manager); + when(roomProfileManagerService.listProfileByRoomIds(anySet())).thenReturn(Collections.emptyList()); + when(roomProfileManagerService.getRoomSysOrigin(roomId)).thenReturn("LIKEI"); + when(userProfileGateway.getSysOrigin(userId)).thenReturn("LIKEI"); + when(userProfileGateway.getUserNobleAbility(userId)).thenReturn(Collections.emptyList()); + when(userProfileGateway.getByUserId(userId)).thenReturn(new com.red.circle.other.domain.model.user.UserProfile()); + when(userProfileGateway.getUserConsumptionLevel(SysOriginPlatformEnum.LIKEI, userId)).thenReturn(null); + when(userProfileGateway.listUserActualEquityEnum(userId)).thenReturn(Collections.emptyList()); + when(administratorService.existsSupperAdmin(userId)).thenReturn(false); + when(administratorService.existsManager(userId)).thenReturn(false); + when(userAgoraTokenCacheService.getUserAgoraToken(userId, roomId)).thenReturn("agora-token"); + when(redisService.getString("ROOM:IM:GROUP:READY:1001268")).thenReturn(null); + when(imGroupClient.createAVChatRoomGroup(any(CreateGroupCmd.class))) + .thenReturn(ResultResponse.success(Boolean.TRUE)); + + UserProfileDTO userProfileDTO = new UserProfileDTO(); + userProfileDTO.setId(userId); + userProfileDTO.setCountryCode("SA"); + userProfileDTO.setCountryName("Saudi Arabia"); + when(userProfileAppConvertor.toUserProfileDTO(any())).thenReturn(userProfileDTO); + when(userRegionGateway.getRegionCode(userId)).thenReturn("SA"); + when(roomProfileAppConvertor.toRoomProfileDTO(manager)).thenReturn(new RoomProfileDTO()); + when(roomProfileAppConvertor.toRoomSettingCO(any())).thenReturn(null); + when(roomProfileAppConvertor.toRoomCounterDTO(any())).thenReturn(null); + when(roomManagerCacheService.getRoomUserRoles(userId, roomId)) + .thenReturn(RoomUserRolesEnum.HOMEOWNER); + + EntryRoomResponseCO response = exe.execute(cmd); + + assertNotNull(response); + ArgumentCaptor captor = ArgumentCaptor.forClass(CreateGroupCmd.class); + verify(imGroupClient).createAVChatRoomGroup(captor.capture()); + verify(redisService).setIfAbsent("ROOM:IM:GROUP:READY:1001268", "1", 60L, TimeUnit.SECONDS); + CreateGroupCmd createGroupCmd = captor.getValue(); + org.junit.jupiter.api.Assertions.assertEquals("2046161571540955138", + createGroupCmd.getOwnerAccount()); + org.junit.jupiter.api.Assertions.assertEquals("1001268", createGroupCmd.getGroupId()); + org.junit.jupiter.api.Assertions.assertEquals("room-cover.png", createGroupCmd.getFaceUrl()); + org.junit.jupiter.api.Assertions.assertEquals("Teams stay blessed", createGroupCmd.getName()); + } +}