This commit is contained in:
wells
2026-08-05 13:48:48 +08:00
commit 1303bf37dc
80 changed files with 5154 additions and 0 deletions
@@ -0,0 +1,189 @@
package com.tailbet.openim;
import com.tailbet.model.dto.OpenIMCallbackDTO;
import com.tailbet.model.vo.R;
import com.tailbet.service.BetService;
import com.tailbet.service.GameService;
import com.tailbet.service.RedPacketService;
import com.tailbet.service.GroupService;
import com.tailbet.openim.OpenIMClient;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
/**
* OpenIM回调接口
*/
@Slf4j
@RestController
@RequestMapping("/openim/callback")
@RequiredArgsConstructor
public class OpenIMCallbackController {
private final BetService betService;
private final GameService gameService;
private final RedPacketService redPacketService;
private final GroupService groupService;
private final OpenIMClient openIMClient;
/**
* 接收群消息回调
*/
@PostMapping("/group_msg")
public R<?> onGroupMessage(@RequestBody OpenIMCallbackDTO dto) {
try {
log.info("收到群消息: msgId={}, sendId={}, groupId={}, content={}",
dto.getMsgId(), dto.getSendId(), dto.getGroupId(), dto.getContent());
String content = dto.getContent();
if (content == null || content.isEmpty()) {
return R.ok();
}
// 处理@机器人指令
if (content.contains("@机器人") || content.contains("@robot")) {
handleBotCommand(dto);
}
return R.ok();
} catch (Exception e) {
log.error("处理群消息回调失败: {}", e.getMessage(), e);
return R.fail(e.getMessage());
}
}
/**
* 接收单聊消息回调
*/
@PostMapping("/single_msg")
public R<?> onSingleMessage(@RequestBody OpenIMCallbackDTO dto) {
try {
log.info("收到单聊消息: msgId={}, sendId={}, recvId={}, content={}",
dto.getMsgId(), dto.getSendId(), dto.getRecvId(), dto.getContent());
return R.ok();
} catch (Exception e) {
log.error("处理单聊消息回调失败: {}", e.getMessage(), e);
return R.fail(e.getMessage());
}
}
/**
* 处理机器人指令
*/
private void handleBotCommand(OpenIMCallbackDTO dto) {
String content = dto.getContent();
String groupId = dto.getGroupId();
String sendId = dto.getSendId();
// 解析指令: @机器人 单 100 或 @机器人 大 50
String message = content.replace("@机器人", "").replace("@robot", "").trim();
if (message.startsWith("统计")) {
// 统计指令
handleStatCommand(groupId);
} else {
// 下注指令
handleBetCommand(message, groupId, sendId, dto.getMsgId());
}
}
/**
* 处理下注指令
*/
private void handleBetCommand(String message, String groupId, String sendId, String msgId) {
try {
// 格式: 单 100, 双 50, 大 100, 小 50, 7 20
String[] parts = message.trim().split("\\s+");
if (parts.length != 2) {
sendGroupMessage(groupId, "格式错误,请使用: @机器人 单/双/大/小/数字 金额");
return;
}
String playType = parts[0];
Integer betAmount;
try {
betAmount = Integer.parseInt(parts[1]);
} catch (NumberFormatException e) {
sendGroupMessage(groupId, "金额格式错误");
return;
}
// 验证玩法
if (!isValidPlayType(playType)) {
sendGroupMessage(groupId, "玩法错误,请使用: 单/双/大/小/数字(0-9)");
return;
}
// 获取业务groupId
Long bizGroupId = getBizGroupId(groupId);
if (bizGroupId == null) {
sendGroupMessage(groupId, "群未配置");
return;
}
// 执行下注
Long userId = getBizUserId(sendId);
var bet = betService.placeBet(userId, bizGroupId, msgId, playType, betAmount);
if (bet != null) {
sendGroupMessage(groupId, String.format("已记录: %s %d", playType, betAmount));
}
} catch (RuntimeException e) {
sendGroupMessage(groupId, e.getMessage());
}
}
/**
* 处理统计指令
*/
private void handleStatCommand(String groupId) {
try {
// TODO: 返回统计信息
sendGroupMessage(groupId, "统计功能开发中...");
} catch (Exception e) {
log.error("处理统计指令失败: {}", e.getMessage());
}
}
/**
* 发送群消息
*/
private void sendGroupMessage(String openimGroupId, String message) {
try {
openIMClient.sendGroupMessage(openimGroupId, message);
} catch (Exception e) {
log.error("发送群消息失败: {}", e.getMessage());
}
}
/**
* 验证玩法是否有效
*/
private boolean isValidPlayType(String playType) {
return "".equals(playType) || "".equals(playType)
|| "".equals(playType) || "".equals(playType)
|| playType.matches("[0-9]");
}
/**
* 将OpenIM用户ID转换为业务用户ID
* 这里需要根据实际实现来转换
*/
private Long getBizUserId(String openimUserId) {
try {
return Long.parseLong(openimUserId);
} catch (NumberFormatException e) {
// 如果不是数字,需要通过映射表查询
return null;
}
}
/**
* 将OpenIM群ID转换为业务群ID
*/
private Long getBizGroupId(String openimGroupId) {
// TODO: 通过映射表查询
return 1L;
}
}
@@ -0,0 +1,152 @@
package com.tailbet.openim;
import com.tailbet.config.OpenIMConfig;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.Map;
/**
* OpenIM客户端
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class OpenIMClient {
private final OpenIMConfig config;
private final RestTemplate restTemplate;
/**
* 发送群消息
*/
public void sendGroupMessage(String groupId, String message) {
String url = config.getApiUrl() + "/msg/send_msg";
Map<String, Object> body = new HashMap<>();
body.put("groupId", groupId);
body.put("msg", message);
body.put("msgType", "text");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("token", config.getAdminToken());
HttpEntity<Map<String, Object>> request = new HttpEntity<>(body, headers);
try {
restTemplate.postForEntity(url, request, String.class);
log.info("OpenIM群消息发送成功: groupId={}, message={}", groupId, message);
} catch (Exception e) {
log.error("OpenIM群消息发送失败: groupId={}, message={}, error={}",
groupId, message, e.getMessage());
}
}
/**
* 发送单聊消息
*/
public void sendUserMessage(String toUserId, String message) {
String url = config.getApiUrl() + "/msg/send_msg";
Map<String, Object> body = new HashMap<>();
body.put("to", toUserId);
body.put("msg", message);
body.put("msgType", "text");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("token", config.getAdminToken());
HttpEntity<Map<String, Object>> request = new HttpEntity<>(body, headers);
try {
restTemplate.postForEntity(url, request, String.class);
log.info("OpenIM单聊消息发送成功: to={}, message={}", toUserId, message);
} catch (Exception e) {
log.error("OpenIM单聊消息发送失败: to={}, message={}, error={}",
toUserId, message, e.getMessage());
}
}
/**
* 创建用户
*/
public boolean createUser(String userId, String nickname) {
String url = config.getApiUrl() + "/user/user_register";
Map<String, Object> body = new HashMap<>();
body.put("userID", userId);
body.put("nickname", nickname);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("token", config.getAdminToken());
HttpEntity<Map<String, Object>> request = new HttpEntity<>(body, headers);
try {
restTemplate.postForEntity(url, request, String.class);
return true;
} catch (Exception e) {
log.error("创建OpenIM用户失败: userId={}, error={}", userId, e.getMessage());
return false;
}
}
/**
* 创建群组
*/
public String createGroup(String groupName) {
String url = config.getApiUrl() + "/group/create_group";
Map<String, Object> body = new HashMap<>();
body.put("groupName", groupName);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("token", config.getAdminToken());
HttpEntity<Map<String, Object>> request = new HttpEntity<>(body, headers);
try {
ResponseEntity<Map> response = restTemplate.postForEntity(url, request, Map.class);
if (response.getBody() != null) {
return (String) response.getBody().get("groupID");
}
} catch (Exception e) {
log.error("创建OpenIM群组失败: groupName={}, error={}", groupName, e.getMessage());
}
return null;
}
/**
* 拉用户入群
*/
public boolean inviteUserToGroup(String groupId, String userId) {
String url = config.getApiUrl() + "/group/invite_user_to_group";
Map<String, Object> body = new HashMap<>();
body.put("groupId", groupId);
body.put("userIDs", new String[]{userId});
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("token", config.getAdminToken());
HttpEntity<Map<String, Object>> request = new HttpEntity<>(body, headers);
try {
restTemplate.postForEntity(url, request, String.class);
return true;
} catch (Exception e) {
log.error("拉用户入群失败: groupId={}, userId={}, error={}",
groupId, userId, e.getMessage());
return false;
}
}
}