feat(admin): 添加声网音视频相关接口

- 新增 ShengWangController 类,实现声网音视频相关接口
- 添加获取频道、获取规则、踢人、添加黑名单规则、删除规则等功能
-优化 ShengWangService 类,实现声网接口调用的封装
This commit is contained in:
曹鹏飞 2025-04-30 10:24:38 +08:00
parent 9e0e051358
commit 41a5afef72
5 changed files with 260 additions and 5 deletions

View File

@ -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<ShengWangChannelDTO> getAllChannels() throws Exception {
return ApiResult.success(shengWangService.getAllChannels());
}
/**
* 获取规则
* @return 规则道列表
*/
@GetMapping("/getKickingRules")
public ApiResult<List<ShengWangKickingRuleListItemDTO>> getKickingRules() throws Exception {
return ApiResult.success(shengWangService.getKickingRule());
}
/**
* 踢人
* @param uid 用户id
* @param cname 频道名称如果频道名称为空则从所有频道踢出
*/
@GetMapping("/kickOutChannel")
public ApiResult<Void> 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<Long> addBlacklist(@Valid @RequestParam @NotNull Integer uid) throws Exception {
return ApiResult.success(shengWangService.addKickingRule(null,uid,1440, List.of("join_channel")));
}
/**
* 删除规则
*/
@GetMapping("/deleteKickingRules")
public ApiResult<Void> deleteKickingRules(@Valid @RequestParam @NotNull Long id) throws Exception {
shengWangService.deleteKickingRule(id);
return ApiResult.success();
}
}

View File

@ -0,0 +1,11 @@
package com.nflg.mobilebroken.admin.pojo.dto;
import lombok.Data;
@Data
public class ShengWangKickingRuleAddDTO {
private String status;
private Long id;
}

View File

@ -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<String> 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<String> 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));
}
}

View File

@ -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<ShengWangKickingRuleListItemDTO> rules;
}

View File

@ -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<String> response=httpClient.send(request, HttpResponse.BodyHandlers.ofString());
VUtils.trueThrowBusinessError(response.statusCode()!=200).throwMessage("");
ShengWangResponse<ShengWangChannelDTO> result= objectMapper.readValue(response.body(), new TypeReference<>() {});
log.debug("getAllChannels Response:"+response.body());
VUtils.trueThrowBusinessError(response.statusCode()!=200).throwMessage("请求失败");
ShengWangResponse<ShengWangChannelDTO> 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<String> 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<String> 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<ShengWangKickingRuleListItemDTO> 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<String> 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<String> 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