|
@@ -1,6 +1,5 @@
|
|
|
package com.yonge.cooleshow.biz.dal.service.impl;
|
|
|
|
|
|
-import static com.yonge.cooleshow.biz.dal.constant.LiveRoomConstant.COOLESHOW;
|
|
|
import static com.yonge.cooleshow.biz.dal.constant.LiveRoomConstant.LIVE_ROOM_HEART_BEAT;
|
|
|
import static com.yonge.cooleshow.biz.dal.constant.LiveRoomConstant.LIVE_ROOM_INFO;
|
|
|
import static com.yonge.cooleshow.biz.dal.constant.LiveRoomConstant.LIVE_ROOM_LIKE;
|
|
@@ -15,14 +14,10 @@ import static com.yonge.cooleshow.biz.dal.constant.LiveRoomConstant.USER_ID;
|
|
|
import static com.yonge.cooleshow.common.constant.SysConfigConstant.DESTROY_EXPIRED_LIVE_ROOM_MINUTE;
|
|
|
import static com.yonge.cooleshow.common.constant.SysConfigConstant.PRE_CREATE_LIVE_ROOM_MINUTE;
|
|
|
|
|
|
+import java.text.MessageFormat;
|
|
|
import java.time.LocalDate;
|
|
|
-import java.util.Collections;
|
|
|
-import java.util.Date;
|
|
|
-import java.util.HashMap;
|
|
|
-import java.util.List;
|
|
|
-import java.util.Map;
|
|
|
-import java.util.Objects;
|
|
|
-import java.util.Optional;
|
|
|
+import java.time.ZoneId;
|
|
|
+import java.util.*;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
import java.util.function.BiFunction;
|
|
|
import java.util.function.BiPredicate;
|
|
@@ -31,10 +26,20 @@ import java.util.function.Function;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
import com.alibaba.fastjson.JSON;
|
|
|
+import com.microsvc.toolkit.middleware.live.LivePluginContext;
|
|
|
+import com.microsvc.toolkit.middleware.live.LivePluginService;
|
|
|
+import com.microsvc.toolkit.middleware.live.impl.RongCloudLivePlugin;
|
|
|
+import com.microsvc.toolkit.middleware.live.impl.TencentCloudLivePlugin;
|
|
|
+import com.microsvc.toolkit.middleware.live.message.*;
|
|
|
+import com.yonge.cooleshow.biz.dal.dto.TencentData;
|
|
|
+import com.yonge.cooleshow.biz.dal.entity.*;
|
|
|
import com.yonge.cooleshow.biz.dal.mapper.SysUserMapper;
|
|
|
+import com.yonge.cooleshow.biz.dal.service.*;
|
|
|
import com.yonge.cooleshow.biz.dal.wrapper.liveroom.LiveRoomWrapper;
|
|
|
+import com.yonge.cooleshow.common.enums.EGroupDefinedDataType;
|
|
|
import org.apache.commons.collections.CollectionUtils;
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.joda.time.DateTime;
|
|
|
import org.redisson.api.RBucket;
|
|
|
import org.redisson.api.RMap;
|
|
|
import org.redisson.api.RedissonClient;
|
|
@@ -52,17 +57,6 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
|
|
|
import com.yonge.cooleshow.auth.api.entity.SysUser;
|
|
|
import com.yonge.cooleshow.biz.dal.dao.LiveRoomDao;
|
|
|
-import com.yonge.cooleshow.biz.dal.entity.CourseSchedule;
|
|
|
-import com.yonge.cooleshow.biz.dal.entity.CourseScheduleStudentPayment;
|
|
|
-import com.yonge.cooleshow.biz.dal.entity.CourseScheduleTeacherSalary;
|
|
|
-import com.yonge.cooleshow.biz.dal.entity.IMApiResultInfo;
|
|
|
-import com.yonge.cooleshow.biz.dal.entity.ImRoomMessage;
|
|
|
-import com.yonge.cooleshow.biz.dal.entity.ImUserStateSync;
|
|
|
-import com.yonge.cooleshow.biz.dal.entity.LiveRoom;
|
|
|
-import com.yonge.cooleshow.biz.dal.entity.RoomInfoCache;
|
|
|
-import com.yonge.cooleshow.biz.dal.entity.RoomUserInfoCache;
|
|
|
-import com.yonge.cooleshow.biz.dal.entity.StudentAttendance;
|
|
|
-import com.yonge.cooleshow.biz.dal.entity.TeacherAttendance;
|
|
|
import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
|
|
|
import com.yonge.cooleshow.biz.dal.enums.CourseScheduleEnum;
|
|
|
import com.yonge.cooleshow.biz.dal.enums.InOrOutEnum;
|
|
@@ -70,17 +64,6 @@ import com.yonge.cooleshow.biz.dal.enums.MessageTypeEnum;
|
|
|
import com.yonge.cooleshow.biz.dal.enums.OrderStatusEnum;
|
|
|
import com.yonge.cooleshow.biz.dal.enums.RoomTypeEnum;
|
|
|
import com.yonge.cooleshow.biz.dal.enums.TeacherSalaryEnum;
|
|
|
-import com.yonge.cooleshow.biz.dal.service.CourseGroupService;
|
|
|
-import com.yonge.cooleshow.biz.dal.service.CourseScheduleService;
|
|
|
-import com.yonge.cooleshow.biz.dal.service.CourseScheduleStudentPaymentService;
|
|
|
-import com.yonge.cooleshow.biz.dal.service.CourseScheduleTeacherSalaryService;
|
|
|
-import com.yonge.cooleshow.biz.dal.service.LiveBroadcastRoomMemberService;
|
|
|
-import com.yonge.cooleshow.biz.dal.service.LiveRoomService;
|
|
|
-import com.yonge.cooleshow.biz.dal.service.StudentAttendanceService;
|
|
|
-import com.yonge.cooleshow.biz.dal.service.SysConfigService;
|
|
|
-import com.yonge.cooleshow.biz.dal.service.SysMessageService;
|
|
|
-import com.yonge.cooleshow.biz.dal.service.TeacherAttendanceService;
|
|
|
-import com.yonge.cooleshow.biz.dal.service.UserOrderService;
|
|
|
import com.yonge.cooleshow.biz.dal.support.IMHelper;
|
|
|
import com.yonge.cooleshow.biz.dal.support.WrapperUtil;
|
|
|
import com.yonge.cooleshow.biz.dal.vo.TeacherLivingInfoVo;
|
|
@@ -131,6 +114,14 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
|
|
|
private LiveBroadcastRoomMemberService liveBroadcastRoomMemberService;
|
|
|
@Autowired
|
|
|
private SysUserMapper sysUserMapper;
|
|
|
+ @Autowired
|
|
|
+ private LivePluginContext livePluginContext;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private LiveRoomService liveRoomService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private LiveRoomVideoService liveRoomVideoService;
|
|
|
/**
|
|
|
* 生成房间UID
|
|
|
*
|
|
@@ -138,7 +129,7 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
|
|
|
* <p> en :房间类型
|
|
|
*/
|
|
|
private final BiFunction<Long, RoomTypeEnum, String> GenRoomUid = (userId, en) -> String
|
|
|
- .join("-", COOLESHOW, en.getCode(), userId.toString(), new Date().getTime() + "");
|
|
|
+ .join("-", en.getCode(), userId.toString(), new Date().getTime() + "");
|
|
|
|
|
|
@Override
|
|
|
public LiveRoomDao getDao() {
|
|
@@ -253,38 +244,49 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
|
|
|
RoomTypeEnum en = RoomTypeEnum.LIVE;
|
|
|
Date now = new Date();
|
|
|
courseScheduleList.forEach(c -> {
|
|
|
- //课程开始时间-提前创建时间 = 创建房间时间
|
|
|
- Date createRoomTime = DateUtil.addMinutes(c.getStartTime(), -Integer.parseInt(preCreateRoomMinute));
|
|
|
- if (now.getTime() < createRoomTime.getTime()) {
|
|
|
- return;
|
|
|
- }
|
|
|
- //避免重复创建直播间
|
|
|
- int count = this.count(Wrappers.<LiveRoom>lambdaQuery().eq(LiveRoom::getCourseId, c.getId()));
|
|
|
- if (count > 0) {
|
|
|
- return;
|
|
|
+ try {
|
|
|
+ liveRoomService.updateLiveCourseSchedule(preCreateRoomMinute, titleMap, remarkMap, en, now, c);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("createCourseLiveRoom>>>生成直播间失败:{}", c, e);
|
|
|
}
|
|
|
- LiveRoom room = new LiveRoom();
|
|
|
- room.setCourseGroupId(c.getCourseGroupId());
|
|
|
- room.setCourseId(c.getId());
|
|
|
- room.setRoomUid(GenRoomUid.apply(c.getTeacherId(), en));
|
|
|
- room.setRoomTitle(titleMap.get(c.getCourseGroupId()));
|
|
|
- room.setLiveRemark(remarkMap.get(c.getCourseGroupId()));
|
|
|
- room.setSpeakerId(c.getTeacherId());
|
|
|
- room.setLiveStartTime(c.getStartTime());
|
|
|
- room.setLiveEndTime(c.getEndTime());
|
|
|
- room.setLiveState(1);
|
|
|
- room.setRoomState(0);
|
|
|
- room.setType(en.getCode());
|
|
|
- room.setCreatedBy(-2L);
|
|
|
- room.setCreatedTime(now);
|
|
|
- this.save(room);
|
|
|
- //去融云创建房间及创建房间缓存信息
|
|
|
- this.createLiveRoomInfo(room);
|
|
|
- //开课提醒
|
|
|
- this.pushLiveCreateRoom(room);
|
|
|
});
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void updateLiveCourseSchedule(String preCreateRoomMinute, Map<Long, String> titleMap, Map<Long, String> remarkMap, RoomTypeEnum en, Date now, CourseSchedule c) {
|
|
|
+ //课程开始时间-提前创建时间 = 创建房间时间
|
|
|
+ Date createRoomTime = DateUtil.addMinutes(c.getStartTime(), -Integer.parseInt(preCreateRoomMinute));
|
|
|
+ if (now.getTime() < createRoomTime.getTime()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //避免重复创建直播间
|
|
|
+ if (StringUtils.isNotBlank(c.getRoomUid())) {
|
|
|
+ log.info("createCourseLiveRoom>>>roomUid:{} 已存在", c.getRoomUid());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ LiveRoom room = new LiveRoom();
|
|
|
+ room.setRoomUid(GenRoomUid.apply(c.getTeacherId(), en));
|
|
|
+ room.setRoomTitle(titleMap.get(c.getCourseGroupId()));
|
|
|
+ room.setLiveRemark(remarkMap.get(c.getCourseGroupId()));
|
|
|
+ room.setSpeakerId(c.getTeacherId());
|
|
|
+ room.setLiveStartTime(c.getStartTime());
|
|
|
+ room.setLiveEndTime(c.getEndTime());
|
|
|
+ room.setLiveState(1);
|
|
|
+ room.setRoomState(0);
|
|
|
+ room.setType(en.getCode());
|
|
|
+ room.setCreatedBy(-2L);
|
|
|
+ room.setCreatedTime(now);
|
|
|
+ this.save(room);
|
|
|
+ // 更新课程房间信息
|
|
|
+ c.setRoomUid(room.getRoomUid());
|
|
|
+ courseScheduleService.updateById(c);
|
|
|
+ //去融云创建房间及创建房间缓存信息
|
|
|
+ this.createLiveRoomInfo(room);
|
|
|
+ //开课提醒
|
|
|
+ this.pushLiveCreateRoom(room);
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 开课提醒
|
|
|
*/
|
|
@@ -342,8 +344,6 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
|
|
|
RoomTypeEnum en = RoomTypeEnum.TEMP;
|
|
|
String roomUid = GenRoomUid.apply(teacherId, en);
|
|
|
LiveRoom room = new LiveRoom();
|
|
|
- room.setCourseGroupId(-1L);
|
|
|
- room.setCourseId(-1L);
|
|
|
room.setRoomUid(roomUid);
|
|
|
room.setRoomTitle(roomTitle);
|
|
|
room.setLiveRemark(liveRemark);
|
|
@@ -380,12 +380,111 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
|
|
|
//生成主讲人信息
|
|
|
this.createRoomInfoCache(room, sysUser);
|
|
|
//去融云创建房间
|
|
|
- this.createLiveRoom(room.getRoomUid(), room.getRoomTitle());
|
|
|
+
|
|
|
+ //去融云创建房间
|
|
|
+ LivePluginService pluginService = livePluginContext.getPluginService(room.getServiceProvider());
|
|
|
+
|
|
|
+ // 注册主播用户信息到三方平台
|
|
|
+ pluginService.register(sysUser.getId().toString(), sysUser.getUsername(), sysUser.getAvatar());
|
|
|
+ // 创建直播间IM群
|
|
|
+ pluginService.chatRoomCreate(room.getRoomUid(), room.getRoomTitle(),sysUser.getId().toString());
|
|
|
+ // 腾讯云直播,提前生成录制规则
|
|
|
+ if (room.getServiceProvider().equals(TencentCloudLivePlugin.PLUGIN_NAME)) {
|
|
|
+
|
|
|
+ DateTime now = DateTime.now();
|
|
|
+
|
|
|
+ RTCRequest.RecordStart recordStart = RTCRequest.RecordStart.builder()
|
|
|
+ .streamName(MessageFormat.format("{0}_{1}", room.getRoomUid(), room.getSpeakerId().toString()))
|
|
|
+ .extra("")
|
|
|
+ .startTime(now.toDateTime().getMillis())
|
|
|
+ .endTime(now.plusDays(1).toDateTime().getMillis())
|
|
|
+ .build();
|
|
|
+
|
|
|
+ if (StringUtils.isBlank(room.getVideoRecord())) {
|
|
|
+
|
|
|
+ // 生成录制任务
|
|
|
+ log.info("createLiveRoom>>>>>> recordStart:{}", recordStart.jsonString());
|
|
|
+ RTCRoom.RecordResp resp = pluginService.rtcRoomRecordStart(recordStart);
|
|
|
+
|
|
|
+ // 设置录制任务Id
|
|
|
+ LiveRoom update = new LiveRoom();
|
|
|
+ update.setId(room.getId());
|
|
|
+ if (StringUtils.isBlank(room.getVideoRecord())) {
|
|
|
+ update.setVideoRecord(resp.getRecordId());
|
|
|
+ } else {
|
|
|
+ update.setVideoRecord(room.getVideoRecord() + "," + resp.getRecordId());
|
|
|
+ }
|
|
|
+ updateById(update);
|
|
|
+ }
|
|
|
+ // 设置直播间房间属性默认值
|
|
|
+ setDefaultRoomDefinedInfo(room);
|
|
|
+ }
|
|
|
} catch (Exception e) {
|
|
|
throw new BizException("创建直播间失败!", e.getCause());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ private void setDefaultRoomDefinedInfo(LiveRoom roomVo) {
|
|
|
+ List<TencentRequest.ChatRoomGroupDefinedData> appDefinedData = new ArrayList<>();
|
|
|
+ Arrays.stream(EGroupDefinedDataType.values()).forEach(key -> {
|
|
|
+ switch (key) {
|
|
|
+ case ANCHOR_STATUS:
|
|
|
+ appDefinedData.add(TencentRequest.ChatRoomGroupDefinedData.builder()
|
|
|
+ .key(key.getCode())
|
|
|
+ .value("OFFLINE")
|
|
|
+ .build());
|
|
|
+ break;
|
|
|
+ case GLOBAL_BAN:
|
|
|
+ appDefinedData.add(TencentRequest.ChatRoomGroupDefinedData.builder()
|
|
|
+ .key(key.getCode())
|
|
|
+ .value("OFF")
|
|
|
+ .build());
|
|
|
+ break;
|
|
|
+ case LIKES:
|
|
|
+ appDefinedData.add(TencentRequest.ChatRoomGroupDefinedData.builder()
|
|
|
+ .key(key.getCode())
|
|
|
+ .value("0")
|
|
|
+ .build());
|
|
|
+ break;
|
|
|
+
|
|
|
+ case MEMBER_ONLINE:
|
|
|
+ appDefinedData.add(TencentRequest.ChatRoomGroupDefinedData.builder()
|
|
|
+ .key(key.getCode())
|
|
|
+ .value("0")
|
|
|
+ .build());
|
|
|
+ break;
|
|
|
+ case MEMBER_TOTAL:
|
|
|
+ appDefinedData.add(TencentRequest.ChatRoomGroupDefinedData.builder()
|
|
|
+ .key(key.getCode())
|
|
|
+ .value("0")
|
|
|
+ .build());
|
|
|
+ break;
|
|
|
+ case LIVE_STATUS:
|
|
|
+ appDefinedData.add(TencentRequest.ChatRoomGroupDefinedData.builder()
|
|
|
+ .key(key.getCode())
|
|
|
+ .value("OFF")
|
|
|
+ .build());
|
|
|
+ break;
|
|
|
+ case ANCHOR_CAMERA:
|
|
|
+ appDefinedData.add(TencentRequest.ChatRoomGroupDefinedData.builder()
|
|
|
+ .key(key.getCode())
|
|
|
+ .value("ON")
|
|
|
+ .build());
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ try {
|
|
|
+ livePluginContext.getPluginService(roomVo.getServiceProvider())
|
|
|
+ .chatRoomGroupDefinedData(TencentRequest.ChatRoomGroup.builder()
|
|
|
+ .groupId(roomVo.getRoomUid())
|
|
|
+ .appDefinedData(appDefinedData)
|
|
|
+ .build());
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("设置直播群配置失败", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
//生成主讲人信息
|
|
|
private void createRoomInfoCache(LiveRoom room, SysUser sysUser) {
|
|
|
RoomInfoCache roomCache = new RoomInfoCache();
|
|
@@ -404,8 +503,8 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
|
|
|
roomCache.setExpiredMinute(Integer.parseInt(configValue));
|
|
|
roomCache.setExpiredCloseMinute(Integer.parseInt(expireCloseMinute));
|
|
|
roomCache.setRoomType(room.getType());
|
|
|
- roomCache.setCourseId(room.getCourseId());
|
|
|
- roomCache.setCourseGroupId(room.getCourseGroupId());
|
|
|
+// roomCache.setCourseId(room.getCourseId());
|
|
|
+// roomCache.setCourseGroupId(room.getCourseGroupId());
|
|
|
|
|
|
//写入房间信息
|
|
|
getLiveRoomInfo(room.getRoomUid()).set(roomCache, 2L, TimeUnit.DAYS);
|
|
@@ -439,6 +538,7 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
|
|
|
/**
|
|
|
* 定时任务-清理过期的房间
|
|
|
*/
|
|
|
+ @Override
|
|
|
public void destroyExpiredLiveRoom() {
|
|
|
//查询房间过期时间
|
|
|
String expiredMinuteStr = sysConfigService.findConfigValue(DESTROY_EXPIRED_LIVE_ROOM_MINUTE);
|
|
@@ -464,7 +564,7 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
|
|
|
}
|
|
|
//当前时间 大于 直播间过期时间
|
|
|
if (now.getTime() >= expiredDate.getTime()) {
|
|
|
- this.destroyLiveRoom(room);
|
|
|
+ liveRoomService.destroyLiveRoom(room.getRoomUid());
|
|
|
}
|
|
|
});
|
|
|
}
|
|
@@ -481,6 +581,20 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
|
|
|
this.destroyLiveRoom(liveRoom);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ private CourseSchedule getCourseScheduleByRoomUid(String roomUid) {
|
|
|
+ CourseSchedule one = courseScheduleService.lambdaQuery()
|
|
|
+ .eq(CourseSchedule::getRoomUid, roomUid)
|
|
|
+ .last("limit 1")
|
|
|
+ .one();
|
|
|
+ if (Objects.isNull(one)) {
|
|
|
+ one = new CourseSchedule();
|
|
|
+ one.setId(-1L);
|
|
|
+ one.setCourseGroupId(-1L);
|
|
|
+ }
|
|
|
+
|
|
|
+ return one;
|
|
|
+ }
|
|
|
/**
|
|
|
* 关闭直播间
|
|
|
*
|
|
@@ -490,11 +604,12 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
|
|
|
if (Objects.isNull(room)) {
|
|
|
return;
|
|
|
}
|
|
|
+ CourseSchedule schedule = getCourseScheduleByRoomUid(room.getRoomUid());
|
|
|
//直播课
|
|
|
if (room.getType().equals(RoomTypeEnum.LIVE.getCode())) {
|
|
|
//查询老师分润表
|
|
|
List<CourseScheduleTeacherSalary> salaryList = courseScheduleTeacherSalaryService.list(Wrappers.<CourseScheduleTeacherSalary>lambdaQuery()
|
|
|
- .eq(CourseScheduleTeacherSalary::getCourseScheduleId, room.getCourseId())
|
|
|
+ .eq(CourseScheduleTeacherSalary::getCourseScheduleId,schedule.getId())
|
|
|
);
|
|
|
if (CollectionUtils.isEmpty(salaryList)) {
|
|
|
return;
|
|
@@ -532,7 +647,7 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
|
|
|
//给老师签退
|
|
|
teacherAttendanceService.update(Wrappers.<TeacherAttendance>lambdaUpdate()
|
|
|
.eq(TeacherAttendance::getTeacherId, room.getSpeakerId())
|
|
|
- .eq(TeacherAttendance::getCourseScheduleId, room.getCourseId())
|
|
|
+ .eq(TeacherAttendance::getCourseScheduleId, schedule.getId())
|
|
|
.set(TeacherAttendance::getSignOutTime, now));
|
|
|
//删除老师与房间关联关系
|
|
|
deleteUserRoomCache.accept(speakerIdStr);
|
|
@@ -544,7 +659,7 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
|
|
|
//观看者签退
|
|
|
studentAttendanceService.update(Wrappers.<StudentAttendance>lambdaUpdate()
|
|
|
.eq(StudentAttendance::getStudentId, id)
|
|
|
- .eq(StudentAttendance::getCourseScheduleId, room.getCourseId())
|
|
|
+ .eq(StudentAttendance::getCourseScheduleId,schedule.getId())
|
|
|
.set(StudentAttendance::getSignOutTime, now));
|
|
|
});
|
|
|
//删除房间在线人员缓存
|
|
@@ -603,7 +718,7 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
|
|
|
if (!userRoom.isExists()) {
|
|
|
return;
|
|
|
}
|
|
|
- String roomUid = userRoom.get();
|
|
|
+ String roomUid = Optional.ofNullable(user.getRoomUid()).orElse(userRoom.get());
|
|
|
|
|
|
Date now = new Date();
|
|
|
//获取当前用户状态变更的时间
|
|
@@ -613,6 +728,7 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
|
|
|
//缓存的时间比当前传入时间大则放弃这条数据
|
|
|
long cacheTime = userStateTimeCache.get();
|
|
|
if (cacheTime > userStateTime) {
|
|
|
+ log.debug("opsRoom>>>> cacheTime > userStateTime, cacheTime: {}, userStateTime: {}", cacheTime, userStateTime);
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
@@ -623,6 +739,19 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
|
|
|
if (!roomInfoCache.isExists()) {
|
|
|
return;
|
|
|
}
|
|
|
+
|
|
|
+ // 查询房间信息
|
|
|
+ LiveRoom roomVo = getByRoomUid(roomUid);
|
|
|
+ if (Objects.isNull(roomVo)) {
|
|
|
+ log.info("opsRoom>>>> roomVo is null, userState: {}", JSON.toJSONString(userState));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 腾讯云直播不需要处理融云im的消息
|
|
|
+ if (roomVo.getServiceProvider().equals(TencentCloudLivePlugin.PLUGIN_NAME) && StringUtils.isNotBlank(user.getClientIp())) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
RoomInfoCache roomInfo = roomInfoCache.get();
|
|
|
// 查询userId是不是主讲人 ,如果是主讲人则返回
|
|
|
if (roomInfo.getSpeakerId().toString().equals(userIdStr)) {
|
|
@@ -654,13 +783,14 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
|
|
|
if (!onlineUserInfo.isExists()) {
|
|
|
return;
|
|
|
}
|
|
|
+ CourseSchedule schedule = getCourseScheduleByRoomUid(roomUid);
|
|
|
liveBroadcastRoomMemberService.saveRecord(roomUid,userId, InOrOutEnum.OUT, YesOrNoEnum.NO);
|
|
|
//从在线人员列表删除该人员
|
|
|
onlineUserInfo.fastRemove(userId);
|
|
|
//学员退出 写学生考勤表
|
|
|
studentAttendanceService.update(Wrappers.<StudentAttendance>lambdaUpdate()
|
|
|
.eq(StudentAttendance::getStudentId, userId)
|
|
|
- .eq(StudentAttendance::getCourseScheduleId, roomInfo.getCourseId())
|
|
|
+ .eq(StudentAttendance::getCourseScheduleId, schedule.getId())
|
|
|
.set(StudentAttendance::getSignOutTime, now));
|
|
|
//向直播间发送当前在线人数消息
|
|
|
this.sendOnlineUserCount(roomUid, userId, onlineUserInfo.size());
|
|
@@ -682,16 +812,26 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
|
|
|
|
|
|
}
|
|
|
|
|
|
+ private LiveRoom getByRoomUid(String roomUid) {
|
|
|
+ return this.lambdaQuery()
|
|
|
+ .eq(LiveRoom::getRoomUid, roomUid)
|
|
|
+ .last("limit 1")
|
|
|
+ .one() ;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 主讲人
|
|
|
*/
|
|
|
private void opsSpeaker(RBucket<RoomInfoCache> roomInfoCache, ImUserStateSync user, Date now, String userIdStr) {
|
|
|
RoomInfoCache roomInfo = roomInfoCache.get();
|
|
|
String roomUid = roomInfo.getRoomUid();
|
|
|
+
|
|
|
+
|
|
|
+ CourseSchedule schedule = getCourseScheduleByRoomUid(roomUid);
|
|
|
//进退房间写老师考勤表
|
|
|
TeacherAttendance teacherAttendance = teacherAttendanceService.getOne(Wrappers.<TeacherAttendance>lambdaQuery()
|
|
|
.eq(TeacherAttendance::getTeacherId, userIdStr)
|
|
|
- .eq(TeacherAttendance::getCourseScheduleId, roomInfo.getCourseId()));
|
|
|
+ .eq(TeacherAttendance::getCourseScheduleId, schedule.getId()));
|
|
|
|
|
|
//最后一次进入房间的clientIp
|
|
|
RBucket<String> lastClientIp = redissonClient.getBucket(LIVE_USER_LAST_CLIENT_IP.replace(ROOM_UID, roomUid).replace(USER_ID, userIdStr));
|
|
@@ -703,9 +843,9 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
|
|
|
if (StringUtils.isNotBlank(user.getClientIp())) {
|
|
|
lastClientIp.set(user.getClientIp());
|
|
|
}
|
|
|
- //查询老师是否有进入过放假,没有则写老师考勤表的进入时间
|
|
|
+ //查询老师是否有进入过房间,没有则写老师考勤表的进入时间
|
|
|
if (Objects.isNull(teacherAttendance)) {
|
|
|
- this.setTeacherAttendance(Long.parseLong(userIdStr), roomInfo.getCourseGroupId(), roomInfo.getCourseId());
|
|
|
+ this.setTeacherAttendance(Long.parseLong(userIdStr), schedule.getCourseGroupId(), schedule.getId());
|
|
|
}
|
|
|
roomInfoCache.set(roomInfo);
|
|
|
log.info("opsRoom>>>> join speakerCache {}", JSONObject.toJSONString(roomInfo));
|
|
@@ -731,8 +871,8 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
|
|
|
teacherAttendance = new TeacherAttendance();
|
|
|
teacherAttendance.setTeacherId(Long.parseLong(userIdStr));
|
|
|
teacherAttendance.setCourseGroupType(CourseScheduleEnum.LIVE.getCode());
|
|
|
- teacherAttendance.setCourseGroupId(roomInfo.getCourseGroupId());
|
|
|
- teacherAttendance.setCourseScheduleId(roomInfo.getCourseId());
|
|
|
+ teacherAttendance.setCourseGroupId(schedule.getCourseGroupId());
|
|
|
+ teacherAttendance.setCourseScheduleId(schedule.getId());
|
|
|
teacherAttendance.setSignInTime(now);
|
|
|
teacherAttendance.setSignOutTime(now);
|
|
|
teacherAttendance.setCreateTime(now);
|
|
@@ -745,6 +885,29 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
|
|
|
}
|
|
|
log.info("opsRoom>>>> exit speakerCache {}", JSONObject.toJSONString(roomInfo));
|
|
|
roomInfoCache.set(roomInfo);
|
|
|
+
|
|
|
+
|
|
|
+ // 设置直播群组自定义数据
|
|
|
+ setGroupDefinedData(getByRoomUid(roomUid),EGroupDefinedDataType.ANCHOR_STATUS,"OFFLINE");
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private void setGroupDefinedData(LiveRoom roomVo, EGroupDefinedDataType type, String value) {
|
|
|
+ List<TencentRequest.ChatRoomGroupDefinedData> appDefinedData = new ArrayList<>();
|
|
|
+ appDefinedData.add(TencentRequest.ChatRoomGroupDefinedData.builder()
|
|
|
+ .key(type.getCode())
|
|
|
+ .value(value)
|
|
|
+ .build());
|
|
|
+ try {
|
|
|
+ livePluginContext.getPluginService(roomVo.getServiceProvider())
|
|
|
+ .chatRoomGroupDefinedData(TencentRequest.ChatRoomGroup.builder()
|
|
|
+ .groupId(roomVo.getRoomUid())
|
|
|
+ .appDefinedData(appDefinedData)
|
|
|
+ .build());
|
|
|
+ log.info("设置直播群配置成功 roomUid:{}, data {}",roomVo.getRoomUid(), JSONObject.toJSONString(appDefinedData));
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("设置直播群配置失败", e);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -780,12 +943,14 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
|
|
|
*/
|
|
|
public RoomInfoCache speakerJoinRoom(String roomUid) {
|
|
|
RoomInfoCache roomInfo = this.speakerCheckRoomInfo(roomUid);
|
|
|
+
|
|
|
+ CourseSchedule schedule = getCourseScheduleByRoomUid(roomUid);
|
|
|
Date now = new Date();
|
|
|
roomInfo.setSpeakerState(0);
|
|
|
roomInfo.setJoinRoomTime(now);
|
|
|
liveBroadcastRoomMemberService.saveRecord(roomUid, roomInfo.getSpeakerId(), InOrOutEnum.IN, YesOrNoEnum.NO);
|
|
|
//查询老师是否有进入过,没有则写老师考勤表的进入时间
|
|
|
- this.setTeacherAttendance(roomInfo.getSpeakerId(), roomInfo.getCourseGroupId(), roomInfo.getCourseId());
|
|
|
+ this.setTeacherAttendance(roomInfo.getSpeakerId(), schedule.getCourseGroupId(), schedule.getId());
|
|
|
//记录当前用户对应的房间uid
|
|
|
redissonClient.getBucket(LIVE_USER_ROOM.replace(USER_ID, roomInfo.getSpeakerId().toString())).set(roomUid, 2L, TimeUnit.DAYS);
|
|
|
return roomInfo;
|
|
@@ -820,8 +985,11 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
|
|
|
userInfo.setUserName(sysUser.getRealName());
|
|
|
userInfo.setFirstJoinTime(now);
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+ CourseSchedule schedule = getCourseScheduleByRoomUid(roomUid);
|
|
|
//查询学生是否有进入过,没有则写学生考勤表的进入时间
|
|
|
- this.setStudentAttendance(userId, roomInfo.getCourseGroupId(), roomInfo.getCourseId());
|
|
|
+ this.setStudentAttendance(userId, schedule.getCourseGroupId(), schedule.getId());
|
|
|
userInfo.setDynamicJoinTime(now);
|
|
|
//用户json信息
|
|
|
String userJsonStr = JSONObject.toJSONString(userInfo);
|
|
@@ -848,13 +1016,15 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
|
|
|
throw new BizException("直播还未开始或已结束!");
|
|
|
}
|
|
|
RoomInfoCache roomInfo = roomInfoCache.get();
|
|
|
+
|
|
|
+ CourseSchedule schedule = getCourseScheduleByRoomUid(roomUid);
|
|
|
//校验观看者是否买过课,如果是非临时直播间,则校验是否已经买过课
|
|
|
if (!roomInfo.getRoomType().equals(RoomTypeEnum.TEMP.getCode())) {
|
|
|
// 查询该学员成功购买课程
|
|
|
CourseScheduleStudentPayment studentPayment = courseScheduleStudentPaymentService.getOne(Wrappers.<CourseScheduleStudentPayment>lambdaQuery()
|
|
|
.eq(CourseScheduleStudentPayment::getUserId, sysUser.getId())
|
|
|
- .eq(CourseScheduleStudentPayment::getCourseId, roomInfo.getCourseId())
|
|
|
- .eq(CourseScheduleStudentPayment::getCourseGroupId, roomInfo.getCourseGroupId())
|
|
|
+ .eq(CourseScheduleStudentPayment::getCourseId, schedule.getId())
|
|
|
+ .eq(CourseScheduleStudentPayment::getCourseGroupId, schedule.getCourseGroupId())
|
|
|
.eq(CourseScheduleStudentPayment::getCourseType, CourseScheduleEnum.LIVE.getCode()));
|
|
|
if (Objects.nonNull(studentPayment)) {
|
|
|
UserOrderVo detail = userOrderService.detail(studentPayment.getOrderNo(), studentPayment.getUserId());
|
|
@@ -967,16 +1137,41 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
|
|
|
public void publishRoomMessage(ImRoomMessage message) {
|
|
|
String msgStr = JSONObject.toJSONString(message);
|
|
|
log.info("publishRoomMessage message : {}", msgStr);
|
|
|
- IMApiResultInfo resultInfo;
|
|
|
+ // 消息发送用户
|
|
|
+ LiveRoomMessage.MessageUser messageUser = null;
|
|
|
+ SysUser sysUser = sysUserFeignService.queryUserById(Long.parseLong(message.getFromUserId()));
|
|
|
+ if (Objects.nonNull(sysUser)) {
|
|
|
+ // 发送用户信息
|
|
|
+ messageUser = LiveRoomMessage.MessageUser
|
|
|
+ .builder()
|
|
|
+ .sendUserId(sysUser.getId().toString())
|
|
|
+ .sendUserName(sysUser.getUsername())
|
|
|
+ .avatarUrl(sysUser.getAvatar())
|
|
|
+ .build();
|
|
|
+ }
|
|
|
+
|
|
|
+ LiveRoomMessage.MessageContent messageContent = LiveRoomMessage.MessageContent
|
|
|
+ .builder()
|
|
|
+ .targetId(sysUser.getId().toString())
|
|
|
+ .sendUserInfo(messageUser)
|
|
|
+ .build();
|
|
|
+
|
|
|
+ LiveRoomMessage build = LiveRoomMessage.builder()
|
|
|
+ .isIncludeSender(1)
|
|
|
+ .objectName(message.getObjectName())
|
|
|
+ .fromUserId(message.getFromUserId())
|
|
|
+ .toChatRoomId(message.getToChatroomId())
|
|
|
+ .content(messageContent)
|
|
|
+ .build();
|
|
|
try {
|
|
|
- resultInfo = imHelper.publishRoomMessage(message.getFromUserId(), message.getToChatroomId(), message);
|
|
|
+
|
|
|
+ LivePluginService pluginService = livePluginContext.getPluginService(message.getServiceProvider());
|
|
|
+ pluginService.sendChatRoomMessage(build);
|
|
|
+ log.info("sendLiveRoomLoginOutMessage>>>> looker {} : roomId={}, userId={}",message.getObjectName(), message.getToChatroomId(), message.getFromUserId());
|
|
|
} catch (Exception e) {
|
|
|
- throw new BizException("消息发送失败" + e.getMessage());
|
|
|
- }
|
|
|
- if (!resultInfo.isSuccess()) {
|
|
|
- throw new BizException("消息发送失败!" + resultInfo.getErrorMessage());
|
|
|
+ log.error("sendLiveRoomMessage>>>> looker error {} {}", message.getObjectName(),e.getMessage());
|
|
|
+ log.error("sendLiveRoomMessage>>>> looker error sendMessage {} : {} : : roomId={}, userId={}",message.getObjectName(), message, message.getToChatroomId(), message.getFromUserId());
|
|
|
}
|
|
|
- log.info("publishRoomMessage success: {}", msgStr);
|
|
|
}
|
|
|
|
|
|
private SysUser getSysUser(Long userId) {
|
|
@@ -1129,10 +1324,10 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
|
|
|
return baseMapper.getLiveInRoomBySpeakerId(speakerId);
|
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
- public List<TeacherLivingInfoVo> queryTeacherLivingList() {
|
|
|
- return baseMapper.queryTeacherLivingList();
|
|
|
- }
|
|
|
+ @Override
|
|
|
+ public List<TeacherLivingInfoVo> queryTeacherLivingList() {
|
|
|
+ return baseMapper.queryTeacherLivingList();
|
|
|
+ }
|
|
|
@Override
|
|
|
public void whetherMic(String roomUid, Integer whetherMic) {
|
|
|
//校验房间是否存在
|
|
@@ -1181,5 +1376,269 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
|
|
|
|
|
|
return roomWrapper;
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成直播录制信息
|
|
|
+ *
|
|
|
+ * @param event TencentData.CallbackSteamRecordEvent
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public void createLiveRoomVideoRecord(TencentData.CallbackSteamRecordEvent event) {
|
|
|
+
|
|
|
+ // 直播间ROOM_UID
|
|
|
+ String roomId = event.getStreamId().split("_")[0];
|
|
|
+
|
|
|
+ // 录制开始时间
|
|
|
+ long startTime = (event.getEndTime() - event.getDuration()) * 1000L;
|
|
|
+ //保存切片
|
|
|
+ LiveRoomVideo imLiveRoomVideo = initImLiveRoomVideo(roomId, event.getTaskId(), DateTime.now().toDate());
|
|
|
+ imLiveRoomVideo.setStartTime(new DateTime(startTime).toDate());
|
|
|
+ imLiveRoomVideo.setEndTime(new DateTime(event.getEndTime() * 1000L).toDate());
|
|
|
+ imLiveRoomVideo.setUrl(event.getVideoUrl());
|
|
|
+ imLiveRoomVideo.setType(2);
|
|
|
+
|
|
|
+ // 回放记录已存在,直接忽略
|
|
|
+ LiveRoomVideo video = liveRoomVideoService.lambdaQuery()
|
|
|
+ .eq(LiveRoomVideo::getRoomUid, imLiveRoomVideo.getRoomUid())
|
|
|
+ .eq(LiveRoomVideo::getRecordId, imLiveRoomVideo.getRecordId())
|
|
|
+ .last("LIMIT 1")
|
|
|
+ .one();
|
|
|
+ if (Objects.isNull(video)) {
|
|
|
+
|
|
|
+ LiveRoom room = this.getByRoomUid(imLiveRoomVideo.getRoomUid());
|
|
|
+
|
|
|
+ if (org.apache.commons.lang.StringUtils.isBlank(room.getVideoRecord()) || Arrays.stream(room.getVideoRecord().split(","))
|
|
|
+ .anyMatch(x -> x.equals(imLiveRoomVideo.getRecordId()))) {
|
|
|
+ liveRoomVideoService.save(imLiveRoomVideo);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ private LiveRoomVideo initImLiveRoomVideo(String roomId, String recordId, Date now) {
|
|
|
+ LiveRoomVideo video = new LiveRoomVideo();
|
|
|
+ video.setRoomUid(roomId);
|
|
|
+ video.setRecordId(recordId);
|
|
|
+ video.setStartTime(now);
|
|
|
+ video.setType(0);
|
|
|
+ video.setCreatedTime(now);
|
|
|
+ return video;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 直播群成员在线状态回调处理
|
|
|
+ *
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ @Transactional
|
|
|
+ public void callbackOnMemberStateChange(TencentData.CallbackOnMemberStateChange callbackOnMemberStateChange) {
|
|
|
+
|
|
|
+ if (callbackOnMemberStateChange == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ int onlineStatus = callbackOnMemberStateChange.getEventType().equals("Online")?1:0;
|
|
|
+
|
|
|
+ // 用户id
|
|
|
+ if (CollectionUtils.isEmpty(callbackOnMemberStateChange.getMemberList())) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ List<Long> userIds = callbackOnMemberStateChange.getMemberList()
|
|
|
+ .stream()
|
|
|
+ .map(o -> Long.parseLong(o.getMemberAccount()))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ List<ImUserStateSync> imUserStates = new ArrayList<>();
|
|
|
+ for (Long userId : userIds) {
|
|
|
+
|
|
|
+ ImUserStateSync imUserState = new ImUserStateSync();
|
|
|
+ imUserState.setUserid(userId.toString());
|
|
|
+ imUserState.setStatus(onlineStatus == 1?"0":"1");
|
|
|
+ imUserState.setOs(callbackOnMemberStateChange.getOptPlatform());
|
|
|
+ imUserState.setTime(new Date().getTime());
|
|
|
+ imUserState.setRoomUid(callbackOnMemberStateChange.getGroupId());
|
|
|
+ imUserStates.add(imUserState);
|
|
|
+ }
|
|
|
+ opsRoom(imUserStates);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional
|
|
|
+ public void callbackAfterMemberExit(TencentData.CallbackAfterMemberExit callbackAfterMemberExit) {
|
|
|
+ if (callbackAfterMemberExit == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 用户id
|
|
|
+ if (CollectionUtils.isEmpty(callbackAfterMemberExit.getExitMemberList())) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ List<Long> userIds = callbackAfterMemberExit.getExitMemberList()
|
|
|
+ .stream()
|
|
|
+ .map(o -> Long.parseLong(o.getMemberAccount()))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+
|
|
|
+ List<ImUserStateSync> imUserStates = new ArrayList<>();
|
|
|
+ for (Long userId : userIds) {
|
|
|
+ ImUserStateSync imUserState = new ImUserStateSync();
|
|
|
+ imUserState.setUserid(userId.toString());
|
|
|
+ imUserState.setStatus("3");
|
|
|
+ imUserState.setOs(callbackAfterMemberExit.getOptPlatform());
|
|
|
+ imUserState.setTime(callbackAfterMemberExit.getEventTime().atZone(ZoneId.systemDefault()).toEpochSecond());
|
|
|
+ imUserState.setRoomUid(callbackAfterMemberExit.getGroupId());
|
|
|
+ imUserStates.add(imUserState);
|
|
|
+ }
|
|
|
+ opsRoom(imUserStates);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional
|
|
|
+ public void callbackAfterNewMemberJoin(TencentData.CallbackAfterNewMemberJoin callbackAfterNewMemberJoin) {
|
|
|
+ if (callbackAfterNewMemberJoin == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 用户id
|
|
|
+ if (CollectionUtils.isEmpty(callbackAfterNewMemberJoin.getNewMemberList())) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ List<Long> userIds = callbackAfterNewMemberJoin.getNewMemberList()
|
|
|
+ .stream()
|
|
|
+ .map(o -> Long.parseLong(o.getMemberAccount()))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ List<ImUserStateSync> imUserStates = new ArrayList<>();
|
|
|
+ for (Long userId : userIds) {
|
|
|
+ ImUserStateSync imUserState = new ImUserStateSync();
|
|
|
+ imUserState.setUserid(userId.toString());
|
|
|
+ imUserState.setStatus("0");
|
|
|
+ imUserState.setOs(callbackAfterNewMemberJoin.getOptPlatform());
|
|
|
+ imUserState.setTime(callbackAfterNewMemberJoin.getEventTime().atZone(ZoneId.systemDefault()).toEpochSecond());
|
|
|
+ imUserState.setRoomUid(callbackAfterNewMemberJoin.getGroupId());
|
|
|
+ imUserStates.add(imUserState);
|
|
|
+ }
|
|
|
+ opsRoom(imUserStates);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 定时任务凌晨2点,关闭腾讯直播间, 融云直播间自动关闭,不做处理
|
|
|
+ @Override
|
|
|
+ public void destroyLiveRoom() {
|
|
|
+ List<LiveRoom> liveRooms = this.lambdaQuery()
|
|
|
+ .eq(LiveRoom::getLiveState, 2)
|
|
|
+ .ne(LiveRoom::getRoomState,2)
|
|
|
+ .list();
|
|
|
+ for (LiveRoom liveRoom : liveRooms) {
|
|
|
+ liveRoomService.tryDestroyLiveRoom(liveRoom);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public boolean tryDestroyLiveRoom(LiveRoom liveRoom) {
|
|
|
+ LivePluginService pluginService = livePluginContext.getPluginService(
|
|
|
+ liveRoom.getServiceProvider());
|
|
|
+ try {
|
|
|
+ if (pluginService == null) {
|
|
|
+ log.error("查询直播间流失败,未找到对应的插件");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (pluginService.pluginName().equals(TencentCloudLivePlugin.PLUGIN_NAME)) {
|
|
|
+ TencentWrapper.LiveStreamState liveStreamState = pluginService.liveStreamState(
|
|
|
+ getStreamId(liveRoom.getRoomUid(), liveRoom.getSpeakerId()));
|
|
|
+ if (liveStreamState == null) {
|
|
|
+ log.error("查询直播间流失败,返回结果为空");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ log.info("查询直播间流状态:{},roomUid:{}", JSON.toJSONString(liveStreamState), liveRoom.getRoomUid());
|
|
|
+ if (!"active".equals(liveStreamState.getStreamState())) {
|
|
|
+ return roomDestroy(liveRoom);
|
|
|
+ }
|
|
|
+ } else if (pluginService.pluginName().equals(RongCloudLivePlugin.PLUGIN_NAME)) {
|
|
|
+ // 融云走原有逻辑 融云自动销毁
|
|
|
+ // 销毁状态改为2
|
|
|
+ LiveRoom liveRoomUpdate = new LiveRoom();
|
|
|
+ liveRoomUpdate.setId(liveRoom.getId());
|
|
|
+ liveRoomUpdate.setRoomState(2);
|
|
|
+ liveRoomService.updateById(liveRoomUpdate);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+
|
|
|
+ log.error("查询直播间流失败", e);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getStreamId(String roomUid, Long speakerId) {
|
|
|
+ return roomUid + "_" + speakerId;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public boolean roomDestroy(LiveRoom room) {
|
|
|
+ //10秒内同一个房间不能重复销毁-防重复销毁
|
|
|
+ RBucket<Object> bucket = redissonClient.getBucket("IM:ROOMDESTROY:" + room.getRoomUid());
|
|
|
+ if (!bucket.trySet(1, 10, TimeUnit.SECONDS)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ log.error("roomDestroy>>>> room : {}", JSONObject.toJSONString(room));
|
|
|
+ String roomUid = room.getRoomUid();
|
|
|
+
|
|
|
+ //将房间状态改为已销毁
|
|
|
+ LiveRoom liveRoomUpdate = new LiveRoom();
|
|
|
+ liveRoomUpdate.setId(room.getId());
|
|
|
+
|
|
|
+ Date date = new Date();
|
|
|
+ liveRoomUpdate.setRoomState(2);
|
|
|
+ liveRoomUpdate.setLiveState(2);
|
|
|
+ Long userId = -1L;
|
|
|
+ try {
|
|
|
+ userId = getSysUser().getId();
|
|
|
+ } catch (Exception ignored) {
|
|
|
+ }
|
|
|
+ liveRoomUpdate.setUpdatedBy(userId);
|
|
|
+ liveRoomUpdate.setUpdatedTime(date);
|
|
|
+ liveRoomUpdate.setLiveEndTime(date);
|
|
|
+
|
|
|
+ this.updateById(liveRoomUpdate);
|
|
|
+
|
|
|
+
|
|
|
+ //向聊天室发自定义消息踢出所有人
|
|
|
+ try {
|
|
|
+ LivePluginService pluginService = livePluginContext.getPluginService(room.getServiceProvider());
|
|
|
+
|
|
|
+ //销毁直播间
|
|
|
+ pluginService.chatRoomDestroy(roomUid);
|
|
|
+
|
|
|
+ TencentWrapper.LiveStreamState liveStreamState = pluginService.liveStreamState(
|
|
|
+ getStreamId(room.getRoomUid(), room.getSpeakerId()));
|
|
|
+ if (liveStreamState == null) {
|
|
|
+ log.error("查询直播间流失败,返回结果为空");
|
|
|
+ } else if ("active".equals(liveStreamState.getStreamState())) {
|
|
|
+ pluginService.liveStreamStop(getStreamId(room.getRoomUid(), room.getSpeakerId()));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 录制任务Id
|
|
|
+ if (room.getServiceProvider().equals(TencentCloudLivePlugin.PLUGIN_NAME)) {
|
|
|
+
|
|
|
+ List<String> collect = liveRoomService.lambdaQuery()
|
|
|
+ .eq(LiveRoom::getRoomUid, roomUid).list().stream()
|
|
|
+ .map(LiveRoom::getVideoRecord)
|
|
|
+ .filter(StringUtils::isNotEmpty)
|
|
|
+ .distinct().collect(Collectors.toList());
|
|
|
+
|
|
|
+ for (String taskId : collect) {
|
|
|
+ // 删除录制任务
|
|
|
+ pluginService.rtcRoomRecordStop(taskId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("roomDestroy>>>> errorMsg{}", e.getMessage(), e.getCause());
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
}
|
|
|
|