package com.cyksj.service.grok.impl; import cn.hutool.core.date.DateTime; import cn.hutool.core.lang.UUID; import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpUtil; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.cyksj.common.exception.BusinessRuntimeException; import com.cyksj.common.util.StringUtil; import com.cyksj.mapper.*; import com.cyksj.model.entity.*; import com.cyksj.model.response.GrokConversationCountResponse; import com.cyksj.model.views.GrokCarInfoView; import com.cyksj.model.views.GrokUserView; import com.cyksj.service.grok.GrokService; import com.cyksj.service.sys.SysConfigService; import com.cyksj.service.user.UserBindRelationService; import com.ejlchina.searcher.BeanSearcher; import com.ejlchina.searcher.SearchResult; import com.ejlchina.searcher.util.MapBuilder; import com.ejlchina.searcher.util.MapUtils; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DuplicateKeyException; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDateTime; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; /** * @author chan * @date 2025/3/20 18:20 */ @Service @Slf4j @RequiredArgsConstructor public class GrokServiceImpl implements GrokService { private final GoodsDonSkuMapper skuMapper; private final GrokUserMapper grokUserMapper; private final UserBindRelationService userBindRelationService; private final GroupsRelationMapper groupsRelationMapper; private final UserMapper userMapper; private final GroupsMapper groupsMapper; private final SysConfigService sysConfigService; private final BeanSearcher beanSearcher; @Override public GrokUserView getUserInfo(long userId, Long relationId) { GrokUser grokUser = checkCarAccount(userId, relationId); if (grokUser != null) { GroupsRelation groupsRelation = getGroupsRelation(userId, relationId); GroupsTrips groupsTrips = getGroupsTrips(groupsRelation); GoodsDonSku goodsDonSku = skuMapper.selectById(groupsTrips.getSkuId()); GrokUserView view =GrokUserView.builder() .skuName(goodsDonSku.getSubTitle()) .expireTime(grokUser.getExpireTime()) .limitNum(grokUser.getLimitNum()) .limitTime(grokUser.getLimitTime()) //.use(Math.min(grokUser.getLimitNum(), getConversationCount(grokUser.getUserToken(),grokUser.getLimitTime()))) .build(); return view; } else { throw BusinessRuntimeException.getInstance("您还未购买该车票"); } } @Override public GrokUser findByUserTokenAndExpireTimeAfter(String userToken, LocalDateTime now) { return grokUserMapper.selectOne(Wrappers.lambdaQuery(GrokUser.class).eq(GrokUser::getUserToken, userToken).gt(GrokUser::getExpireTime, now)); } @Override public GrokUser checkCarAccount(Long userId, Long relationId) { GroupsRelation groupsRelation = getGroupsRelation(userId, relationId); GroupsTrips groupsTrips = getGroupsTrips(groupsRelation); GoodsDonSku goodsDonSku = skuMapper.selectById(groupsTrips.getSkuId()); if (goodsDonSku != null && goodsDonSku.getIsMirror()) { return getGrokUser(userId, relationId, groupsRelation, goodsDonSku); } else { return null; } } @Override public Long getConversationCount(String userToken, Long limitTime) { JSONObject conversationCount = getConversationCount(userToken); Long count = Optional.ofNullable(conversationCount.getLong("count")).orElse(0l); return new BigDecimal(count).divide(BigDecimal.valueOf(4000),0, RoundingMode.HALF_UP).longValue(); } @Override public String getCarLoginUrl(String domain, Long userId, Long relationId) { GroupsRelation groupsRelation = getGroupsRelation(userId, relationId); GroupsTrips groupsTrips = getGroupsTrips(groupsRelation); GoodsDonSku goodsDonSku = skuMapper.selectById(groupsTrips.getSkuId()); if (goodsDonSku != null && goodsDonSku.getIsMirror()) { GrokUser grokUser = getGrokUser(userId, relationId, groupsRelation, goodsDonSku); String DOMAIN = domain; if (StrUtil.isEmpty(DOMAIN)) { DOMAIN = "https://grok.bestaistore.com"; try { SysConfig sysConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, "mirror_grok_domain")); if (sysConfig != null) { String sysValue = sysConfig.getSysValue(); if (JSONUtil.isJsonArray(sysValue)) { List domainList = JSONUtil.parseArray(sysValue).toList(String.class); DOMAIN = domainList.get(RandomUtil.randomInt(domainList.size())); } } } catch (Exception e) { log.error("随机抽取域名错误. msg:{}", StringUtil.getErrorText(e)); } } log.info("domain:{},用户:{},所在车次:{},座位id:{},在{}获取跳转Grok镜像的登录url", DOMAIN, userId, groupsTrips.getId(), relationId, DateTime.now()); return DOMAIN + "/signtoken" + "?userToken=" + grokUser.getUserToken(); } else { throw BusinessRuntimeException.getInstance("服务器出了点问题"); } } @Override public String getCarLoginUrl(String domain, Long userId, Long relationId, String carId) { GroupsRelation groupsRelation = getGroupsRelation(userId, relationId); GroupsTrips groupsTrips = getGroupsTrips(groupsRelation); GoodsDonSku goodsDonSku = skuMapper.selectById(groupsTrips.getSkuId()); if (goodsDonSku != null && goodsDonSku.getIsMirror() && goodsDonSku.getIsCar()) { GrokUser grokUser = getGrokUser(userId, relationId, groupsRelation, goodsDonSku); String DOMAIN = domain; if (StrUtil.isEmpty(DOMAIN)) { DOMAIN = "https://groknode.nf.video"; try { SysConfig sysConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, "mirror_xy_grok_domain")); if (sysConfig != null) { String sysValue = sysConfig.getSysValue(); if (JSONUtil.isJsonArray(sysValue)) { List domainList = JSONUtil.parseArray(sysValue).toList(String.class); DOMAIN = domainList.get(RandomUtil.randomInt(domainList.size())); } } } catch (Exception e) { log.error("随机抽取域名错误. msg:{}", StringUtil.getErrorText(e)); } } log.info("domain:{},用户:{},所在车次:{},座位id:{},车队id:{},在{}获取跳转Grok镜像车队的登录url", DOMAIN, userId, groupsTrips.getId(), relationId, carId, DateTime.now()); return DOMAIN + "/auth/login?userToken=" + grokUser.getUserToken() + "&carid=" + carId; } else { throw BusinessRuntimeException.getInstance("服务器出了点问题"); } } @Override public SearchResult getCarInfoList(Map parameterMap, Integer limit) { Map params = new HashMap<>(parameterMap); if (params.containsKey("status")) { params.put("csStatus", params.remove("status")); } MapBuilder builder = MapUtils.flatBuilder(params) .orderBy(GrokCarInfoView::getSort).asc() .orderBy(GrokCarInfoView::getScore).asc(); if (!params.containsKey("limit")) { builder.limit(0, limit); } SearchResult carInfoList = beanSearcher.search(GrokCarInfoView.class, builder.build()); carInfoList.getDataList().forEach(this::buildGrokCarInfoView); return carInfoList; } private void buildGrokCarInfoView(GrokCarInfoView view) { view.setCarName(view.getCarId()); view.setStatus("空闲"); Double score = Optional.ofNullable(view.getScore()).orElse(0D); view.setStatus(score >= 100 ? "繁忙" : "空闲"); view.setScore(Math.min(BigDecimal.valueOf(score).multiply(BigDecimal.valueOf(0.5)).setScale(0, RoundingMode.DOWN).doubleValue(), 200)); } /** * 获取车位信息 * * @param userId * @param relationId * @return */ @Override public GrokConversationCountResponse getConversationCountDetail(String userToken) { GrokUser grokUser = grokUserMapper.selectOne(Wrappers.lambdaQuery(GrokUser.class) .eq(GrokUser::getUserToken, userToken) .last("limit 1")); if (grokUser == null) { throw BusinessRuntimeException.getInstance("用户不存在或已过期"); } try { JSONObject json = getConversationCount(userToken); if (json.containsKey("message")) { throw BusinessRuntimeException.getInstance(json.getStr("message")); } Long count = Optional.ofNullable(json.getLong("count")).orElse(0L); Integer limit = Optional.ofNullable(json.getInt("limit")).orElse(grokUser.getLimitNum()); Long time = Optional.ofNullable(json.getLong("time")).orElse(grokUser.getLimitTime()); Boolean isVip = Optional.ofNullable(json.getBool("isVip")).orElse(Boolean.TRUE.equals(grokUser.getIsVip())); Long remaining = Optional.ofNullable(json.getLong("remaining")) .orElse(limit == null ? 0L : Math.max(0L, limit - count)); GrokConversationCountResponse response = new GrokConversationCountResponse(); response.setCount(count); response.setLimit(limit); response.setRemaining(remaining); response.setTime(time); response.setIsVip(isVip); return response; } catch (BusinessRuntimeException e) { throw e; } catch (Exception e) { log.error("调用Grok getConversationCount接口失败: {}", StringUtil.getErrorText(e)); throw BusinessRuntimeException.getInstance("获取对话次数失败"); } } private GroupsRelation getGroupsRelation(Long userId, Long relationId) { List userIdList = userBindRelationService.getRelationUserIdList(userId, null); GroupsRelation groupsRelation = groupsRelationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class).in(GroupsRelation::getUserId, userIdList).eq(GroupsRelation::getId, relationId)); if (groupsRelation == null) { throw BusinessRuntimeException.getInstance("车票不存在"); } return groupsRelation; } /** * 获取车队信息 * * @param groupsRelation * @return */ private GroupsTrips getGroupsTrips(GroupsRelation groupsRelation) { GroupsTrips groupsTrips = groupsMapper.selectById(groupsRelation.getGroupsId()); if (groupsTrips == null) { throw BusinessRuntimeException.getInstance("车队异常"); } return groupsTrips; } private GrokUser getGrokUser(Long userId, Long relationId, GroupsRelation groupsRelation, GoodsDonSku goodsDonSku) { GrokUser grokUser = grokUserMapper.selectOne(Wrappers.lambdaQuery(GrokUser.class).eq(GrokUser::getRelationId, relationId)); User user = userMapper.selectById(userId); if (grokUser == null) { grokUser = createGrokUser(groupsRelation, user, goodsDonSku); } else { updateGrokUser(groupsRelation, user, grokUser); } return grokUser; } /** * 创建chatgptUser */ private synchronized GrokUser createGrokUser(GroupsRelation groupsRelation, User user, GoodsDonSku goodsDonSku) { GrokUser grokUser = new GrokUser(); if (goodsDonSku.getIsCar()) { grokUser.setLimitNum(goodsDonSku.getGptLimitNum()); grokUser.setLimitTime(goodsDonSku.getGptLimitTime()); } try { grokUser.setExpireTime(groupsRelation.getExpiryTime()); grokUser.setIsPlus(true); grokUser.setName(user.getNickname()); grokUser.setRelationId(groupsRelation.getId()); grokUser.setUserToken(UUID.randomUUID().toString()); grokUserMapper.insert(grokUser); } catch (DuplicateKeyException e) { log.error("重复插入Grok镜像用户:{}token,errmsg:{}", user.getNickname(), StringUtil.getErrorText(e)); } return grokUser; } private void updateGrokUser(GroupsRelation groupsRelation, User user, GrokUser grokUser) { grokUser.setName(user.getNickname()); grokUser.setExpireTime(groupsRelation.getExpiryTime()); grokUserMapper.updateById(grokUser); } public JSONObject getConversationCount(String userToken) { try { String res = HttpUtil.get("http://147.79.20.183:9611/grok/getConversationCount?userToken=" + userToken); return new JSONObject(res); }catch (Exception e){ return new JSONObject("{\"count\": 0}"); } } }