diff --git a/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/controller/ShengWangController.java b/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/controller/ShengWangController.java new file mode 100644 index 00000000..80ce0608 --- /dev/null +++ b/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/controller/ShengWangController.java @@ -0,0 +1,73 @@ +package com.nflg.mobilebroken.admin.controller; + +import com.nflg.mobilebroken.admin.pojo.dto.ShengWangChannelDTO; +import com.nflg.mobilebroken.admin.pojo.dto.ShengWangKickingRuleListItemDTO; +import com.nflg.mobilebroken.admin.service.ShengWangService; +import com.nflg.mobilebroken.common.pojo.ApiResult; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import javax.validation.Valid; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * 声网音视频相关接口 + * @author 曹鹏飞 + */ +@RestController +@RequestMapping("/shengwang") +public class ShengWangController { + + @Resource + private ShengWangService shengWangService; + + /** + * 获取频道 + * @return 频道列表 + */ + @GetMapping("/getAllChannels") + public ApiResult getAllChannels() throws Exception { + return ApiResult.success(shengWangService.getAllChannels()); + } + + /** + * 获取规则 + * @return 规则道列表 + */ + @GetMapping("/getKickingRules") + public ApiResult> getKickingRules() throws Exception { + return ApiResult.success(shengWangService.getKickingRule()); + } + + /** + * 踢人 + * @param uid 用户id + * @param cname 频道名称,如果频道名称为空,则从所有频道踢出 + */ + @GetMapping("/kickOutChannel") + public ApiResult kickOutChannel(@Valid @RequestParam @NotNull Integer uid,@RequestParam String cname) throws Exception { + shengWangService.addKickingRule(cname,uid,0, List.of("join_channel")); + return ApiResult.success(); + } + + /** + * 添加黑名单规则(规则有效期为1天) + */ + @GetMapping("/addBlacklist") + public ApiResult addBlacklist(@Valid @RequestParam @NotNull Integer uid) throws Exception { + return ApiResult.success(shengWangService.addKickingRule(null,uid,1440, List.of("join_channel"))); + } + + /** + * 删除规则 + */ + @GetMapping("/deleteKickingRules") + public ApiResult deleteKickingRules(@Valid @RequestParam @NotNull Long id) throws Exception { + shengWangService.deleteKickingRule(id); + return ApiResult.success(); + } +} diff --git a/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/pojo/dto/ShengWangKickingRuleAddDTO.java b/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/pojo/dto/ShengWangKickingRuleAddDTO.java new file mode 100644 index 00000000..1f9ce1b9 --- /dev/null +++ b/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/pojo/dto/ShengWangKickingRuleAddDTO.java @@ -0,0 +1,11 @@ +package com.nflg.mobilebroken.admin.pojo.dto; + +import lombok.Data; + +@Data +public class ShengWangKickingRuleAddDTO { + + private String status; + + private Long id; +} diff --git a/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/pojo/dto/ShengWangKickingRuleListItemDTO.java b/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/pojo/dto/ShengWangKickingRuleListItemDTO.java new file mode 100644 index 00000000..e1c1979d --- /dev/null +++ b/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/pojo/dto/ShengWangKickingRuleListItemDTO.java @@ -0,0 +1,83 @@ +package com.nflg.mobilebroken.admin.pojo.dto; + +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.util.StrUtil; +import lombok.Data; + +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +@Data +public class ShengWangKickingRuleListItemDTO { + + /** + * 规则 ID。当更新或删除封禁用户权限规则时,需要传入规则 ID + */ + private Long id; + + /** + * 用户 ID + */ + private Integer uid; + + /** + * 频道名 + */ + private String cname; + + /** + * 该规则过期时间 + */ + private String ts; + /** + * 被封禁的用户权限 + */ + private List privileges; + /** + * 该规则的创建时间 + */ + private String createAt; + + public String getTs() { + if (StrUtil.isBlank(ts)) { + return null; + } + Instant instant = Instant.parse(ts); + LocalDateTime localDateTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime(); + return localDateTime.format(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)); + } + + public List getPrivileges() { + if (Objects.isNull(privileges)) { + return null; + } + return privileges.stream() + .map(privilege -> { + switch (privilege) { + case "join_channel": + return "加入频道"; + case "publish_audio": + return "发送音频流"; + case "publish_video": + return "发送视频流"; + default: + return privilege; + } + }) + .collect(Collectors.toList()); + } + + public String getCreateAt() { + if (StrUtil.isBlank(createAt)) { + return null; + } + Instant instant = Instant.parse(createAt); + LocalDateTime localDateTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime(); + return localDateTime.format(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)); + } +} diff --git a/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/pojo/dto/ShengWangKickingRuleListResponseDTO.java b/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/pojo/dto/ShengWangKickingRuleListResponseDTO.java new file mode 100644 index 00000000..cfa66bb5 --- /dev/null +++ b/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/pojo/dto/ShengWangKickingRuleListResponseDTO.java @@ -0,0 +1,13 @@ +package com.nflg.mobilebroken.admin.pojo.dto; + +import lombok.Data; + +import java.util.List; + +@Data +public class ShengWangKickingRuleListResponseDTO { + + private String status; + + private List rules; +} diff --git a/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/service/ShengWangService.java b/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/service/ShengWangService.java index 820d0ec7..342f1f1c 100644 --- a/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/service/ShengWangService.java +++ b/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/service/ShengWangService.java @@ -1,24 +1,29 @@ package com.nflg.mobilebroken.admin.service; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONObject; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; -import com.nflg.mobilebroken.admin.pojo.dto.ShengWangChannelDTO; -import com.nflg.mobilebroken.admin.pojo.dto.ShengWangResponse; +import com.nflg.mobilebroken.admin.pojo.dto.*; import com.nflg.mobilebroken.common.util.VUtils; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.util.Base64; +import java.util.List; /** * 声网服务 */ +@Slf4j @Component @RefreshScope public class ShengWangService { @@ -40,19 +45,89 @@ public class ShengWangService { @Value("${shengwang.rtc.customerSecret}") private String customerSecret; - public ShengWangChannelDTO getAllChannels() throws Exception { + public ShengWangChannelDTO getAllChannels() throws IOException, InterruptedException { HttpRequest request = HttpRequest.newBuilder() .GET() .header("Authorization",generateAuthorization(customerKey,customerSecret)) .uri(URI.create(baseUrl+"/v1/channel/"+appId)) .build(); HttpResponse response=httpClient.send(request, HttpResponse.BodyHandlers.ofString()); - VUtils.trueThrowBusinessError(response.statusCode()!=200).throwMessage(""); - ShengWangResponse result= objectMapper.readValue(response.body(), new TypeReference<>() {}); + log.debug("getAllChannels Response:"+response.body()); + VUtils.trueThrowBusinessError(response.statusCode()!=200).throwMessage("请求失败"); + ShengWangResponse result = objectMapper.readValue(response.body(), new TypeReference<>() {}); VUtils.trueThrowBusinessError(!result.isSuccess()).throwMessage("获取频道信息失败"); return result.getData(); } + /** + * 创建规则 + * @param channelName 频道名称 + * @param uid 用户ID + * @param time 封禁时间,单位为分钟,取值范围为 [1,1440]。当设置的值为 0 时,表示不封禁。服务端会对频道内符合设定规则的用户进行下线一次的操作。用户可以重新登录进入频道。 + * @param privileges 要封禁的用户权限,取值包括【join_channel】加入频道,表示禁止用户加入频道或将用户踢出频道。【publish_audio】发送音频,表示禁止用户发送音频流。可以与 publish_video 同时设置,表示禁止用户发送音视流和视频流。【publish_video】发送视频,表示禁止用户发送视频流。可以与 publish_audio 同时设置,表示禁止用户发送音视流和视频流。 + * @return 规则ID + */ + public Long addKickingRule(String channelName, Integer uid, Integer time, List privileges) throws Exception { + JSONObject json=new JSONObject(); + json.putOpt("appid",appId); + json.putOpt("cname",channelName); + json.putOpt("uid",uid); + json.putOpt("time",time); + json.putOpt("privileges",privileges); + HttpRequest request = HttpRequest.newBuilder() + .POST(HttpRequest.BodyPublishers.ofString(json.toString())) + .header("Authorization",generateAuthorization(customerKey,customerSecret)) + .header("Content-Type", "application/json") + .uri(URI.create(baseUrl+"/v1/kicking-rule")) + .build(); + HttpResponse response=httpClient.send(request, HttpResponse.BodyHandlers.ofString()); + log.debug("addKickingRule Response:"+response.body()); + VUtils.trueThrowBusinessError(response.statusCode()!=200).throwMessage("请求失败"); + ShengWangKickingRuleAddDTO result= objectMapper.readValue(response.body(), ShengWangKickingRuleAddDTO.class); + VUtils.trueThrowBusinessError(!StrUtil.equals(result.getStatus(),"success")).throwMessage("创建规则失败"); + return result.getId(); + } + + /** + * 获取规则 + * @return 规则列表 + */ + public List getKickingRule() throws IOException, InterruptedException { + HttpRequest request = HttpRequest.newBuilder() + .GET() + .header("Authorization",generateAuthorization(customerKey,customerSecret)) + .uri(URI.create(baseUrl+"/v1/kicking-rule?appid="+appId)) + .build(); + HttpResponse response=httpClient.send(request, HttpResponse.BodyHandlers.ofString()); + log.debug("getKickingRule Response:"+response.body()); + VUtils.trueThrowBusinessError(response.statusCode()!=200).throwMessage("请求失败"); + ShengWangKickingRuleListResponseDTO result= objectMapper.readValue(response.body(), ShengWangKickingRuleListResponseDTO.class); + VUtils.trueThrowBusinessError(!StrUtil.equals(result.getStatus(),"success")).throwMessage("获取规则失败"); + return result.getRules(); + } + + /** + * 删除规则 + * @param id 规则ID + */ + public void deleteKickingRule(long id) throws IOException, InterruptedException { + JSONObject json=new JSONObject(); + json.putOpt("appid",appId); + json.putOpt("id",id); + HttpRequest request = HttpRequest.newBuilder() + .method("DELETE", HttpRequest.BodyPublishers.ofString(json.toString())) + .header("Authorization",generateAuthorization(customerKey,customerSecret)) + .header("Content-Type", "application/json") + .uri(URI.create(baseUrl+"/v1/kicking-rule")) + .build(); + HttpResponse response=httpClient.send(request, HttpResponse.BodyHandlers.ofString()); + log.debug("deleteKickingRule Response:"+response.body()); + VUtils.trueThrowBusinessError(response.statusCode()==404).throwMessage("规则不存在"); + VUtils.trueThrowBusinessError(response.statusCode()!=200).throwMessage("请求失败"); + ShengWangKickingRuleAddDTO result= objectMapper.readValue(response.body(), ShengWangKickingRuleAddDTO.class); + VUtils.trueThrowBusinessError(!StrUtil.equals(result.getStatus(),"success")).throwMessage("删除规则失败"); + } + /** * 生成鉴权信息 * @param customerKey 客户ID