ChatGptAccountServiceImpl.java 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974
  1. package com.cyksj.service.chatgpt.impl;
  2. import cn.hutool.core.date.DateTime;
  3. import cn.hutool.core.date.DateUnit;
  4. import cn.hutool.core.date.DateUtil;
  5. import cn.hutool.core.lang.UUID;
  6. import cn.hutool.core.util.RandomUtil;
  7. import cn.hutool.core.util.StrUtil;
  8. import cn.hutool.http.HttpRequest;
  9. import cn.hutool.http.HttpResponse;
  10. import cn.hutool.http.HttpUtil;
  11. import cn.hutool.http.Method;
  12. import cn.hutool.json.JSONObject;
  13. import cn.hutool.json.JSONUtil;
  14. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  15. import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  16. import com.cyksj.common.constant.Constant;
  17. import com.cyksj.common.exception.BusinessRuntimeException;
  18. import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
  19. import com.cyksj.common.util.StringUtil;
  20. import com.cyksj.mapper.*;
  21. import com.cyksj.mapper.station.CollegeStudentStationUseTicketRecordMapper;
  22. import com.cyksj.model.entity.*;
  23. import com.cyksj.model.request.gpt.ConversationRequest;
  24. import com.cyksj.model.response.ConversationLimitResponse;
  25. import com.cyksj.model.views.ChatGptUserView;
  26. import com.cyksj.model.views.ChatgptCarInfoView;
  27. import com.cyksj.redis.RedisService;
  28. import com.cyksj.service.chatgpt.ChatGptAccountService;
  29. import com.cyksj.service.sys.SysConfigService;
  30. import com.cyksj.service.user.UserBindRelationService;
  31. import com.ejlchina.searcher.BeanSearcher;
  32. import com.ejlchina.searcher.SearchResult;
  33. import com.ejlchina.searcher.util.MapUtils;
  34. import lombok.RequiredArgsConstructor;
  35. import lombok.extern.slf4j.Slf4j;
  36. import org.apache.commons.lang3.StringUtils;
  37. import org.springframework.beans.factory.annotation.Value;
  38. import org.springframework.dao.DuplicateKeyException;
  39. import org.springframework.data.redis.core.ZSetOperations;
  40. import org.springframework.stereotype.Service;
  41. import javax.annotation.PostConstruct;
  42. import javax.imageio.stream.FileImageOutputStream;
  43. import javax.servlet.http.HttpServletRequest;
  44. import java.math.BigDecimal;
  45. import java.nio.file.Files;
  46. import java.nio.file.Path;
  47. import java.time.LocalDateTime;
  48. import java.util.*;
  49. import java.util.stream.Collectors;
  50. /**
  51. * @author chan
  52. * @date 2024/3/19 11:01
  53. */
  54. @Service
  55. @Slf4j
  56. @RequiredArgsConstructor
  57. public class ChatGptAccountServiceImpl implements ChatGptAccountService {
  58. @Value("${chatgpt.domain}")
  59. private String GPT_DOMAIN;
  60. @Value("${chatgpt.car.domain}")
  61. private String CAR_GPT_DOMAIN;
  62. private static final String GPT_PROXY = "https://chat-chan-87jztgkf257d.xyhelper.net";
  63. private static final int MAX_REQUESTS = 40; // 3小时内最大请求次数
  64. private static final long WINDOW_SIZE = 3 * 60 * 60; // 3小时窗口的秒数
  65. private static final List<String> LOW_GPT_MODEL = List.of("gpt-4o-mini","text-davinci-002-render-sha");
  66. private static final GlobalThreadPoolTaskExecutor TASK_EXECUTOR = GlobalThreadPoolTaskExecutor.getInstance();
  67. private final RedisService redisService;
  68. private final ChatgptUserMapper chatgptUserMapper;
  69. private final ChatgptSessionMapper chatgptSessionMapper;
  70. private final GroupsRelationMapper groupsRelationMapper;
  71. private final GroupsMapper groupsMapper;
  72. private final GoodsDonSkuMapper skuMapper;
  73. private final UserMapper userMapper;
  74. private final UserBindRelationService userBindRelationService;
  75. private final ChatgptUserConversationRecordMapper chatgptUserConversationRecordMapper;
  76. private final ChatgptUserConversationMapper chatgptUserConversationMapper;
  77. private final AccountMapper accountMapper;
  78. private final BeanSearcher beanSearcher;
  79. private final ChatgptUserTokenPrepareMapper chatgptUserTokenPrepareMapper;
  80. private final ChatgptUserCarUsedRecordMapper chatgptUserCarUsedRecordMapper;
  81. private final CollegeStudentStationUseTicketRecordMapper collegeStudentStationUseTicketRecordMapper;
  82. private final UpgradePackageMapper upgradePackageMapper;
  83. private final OrderDonMapper orderDonMapper;
  84. private final SysConfigService sysConfigService;
  85. private final HttpServletRequest request;
  86. @Override
  87. public String addAccount(Account account) {
  88. if (isAccountExists(account)) {
  89. throw BusinessRuntimeException.getInstance("镜像服务该账号已存在.");
  90. }
  91. String refreshToken = "";
  92. String officialSession = "";
  93. try {
  94. JSONObject loginResult = getLoginResult(account);
  95. if (StringUtils.isBlank(loginResult.getStr("accessToken"))) {
  96. throw BusinessRuntimeException.getInstance(loginResult.getStr("detail"));
  97. }
  98. refreshToken = loginResult.getStr("refresh_token");
  99. officialSession = loginResult.toString();
  100. } catch (Exception e) {
  101. throw BusinessRuntimeException.getInstance("登录获取token错误 error:" + e.getMessage());
  102. }
  103. createChatgptSession(account, officialSession);
  104. return refreshToken;
  105. }
  106. @Override
  107. public String getGptSession(String account, String password) {
  108. String officialSession = "";
  109. try {
  110. Account at = new Account();
  111. at.setAccount(account);
  112. at.setPassword(password);
  113. JSONObject loginResult = getLoginResult(at);
  114. if (StringUtils.isBlank(loginResult.getStr("accessToken"))) {
  115. throw BusinessRuntimeException.getInstance(loginResult.getStr("detail"));
  116. }
  117. officialSession = loginResult.toString();
  118. } catch (Exception e) {
  119. throw BusinessRuntimeException.getInstance("登录获取token错误 error:" + e.getMessage());
  120. }
  121. return officialSession;
  122. }
  123. /**
  124. * 判断账号是否存在
  125. *
  126. * @param account 账号
  127. * @return 是否存在
  128. */
  129. private boolean isAccountExists(Account account) {
  130. Integer count = chatgptSessionMapper.selectCount(Wrappers.lambdaQuery(ChatgptSession.class).eq(ChatgptSession::getEmail, account.getAccount()));
  131. return count > 0;
  132. }
  133. /**
  134. * 获取登录结果
  135. *
  136. * @param account
  137. * @return
  138. * @throws Exception
  139. */
  140. private JSONObject getLoginResult(Account account) throws Exception {
  141. HttpRequest request = new HttpRequest(GPT_PROXY + "/applelogin");
  142. request.form("username", account.getAccount());
  143. request.form("password", account.getPassword());
  144. request.header("Content-Type", "application/x-www-form-urlencoded");
  145. HttpResponse execute = request.method(Method.POST).execute();
  146. return new JSONObject(execute.body());
  147. }
  148. /**
  149. * 创建chatgptSession
  150. *
  151. * @param account
  152. * @param officialSession
  153. */
  154. private void createChatgptSession(Account account, String officialSession) {
  155. ChatgptSession chatgptSession = new ChatgptSession();
  156. chatgptSession.setOfficialSession(officialSession);
  157. chatgptSession.setEmail(account.getAccount());
  158. chatgptSession.setPassword(account.getPassword());
  159. chatgptSession.setIsPlus(1);
  160. chatgptSession.setAccountId(account.getId());
  161. chatgptSession.setStatus(1);
  162. chatgptSessionMapper.insert(chatgptSession);
  163. }
  164. /**
  165. * 更新账号
  166. *
  167. * @param account
  168. */
  169. @Override
  170. public void upAccount(Account account) {
  171. ChatgptSession chatgptSession = chatgptSessionMapper.selectOne(Wrappers.lambdaQuery(ChatgptSession.class).eq(ChatgptSession::getEmail, account.getAccount()));
  172. if (chatgptSession != null) {
  173. if (StringUtils.isNotBlank(account.getGptRefreshToken())) {
  174. chatgptSession.setOfficialSession(account.getGptRefreshToken());
  175. }
  176. chatgptSession.setEmail(account.getAccount());
  177. chatgptSession.setPassword(account.getPassword());
  178. chatgptSession.setIsPlus(1);
  179. chatgptSession.setAccountId(account.getId());
  180. chatgptSession.setStatus(1);
  181. chatgptSessionMapper.updateById(chatgptSession);
  182. }
  183. }
  184. /**
  185. * 获取登录url
  186. *
  187. * @param userId
  188. * @param relationId
  189. * @return
  190. */
  191. @Override
  192. public String getLoginUrl(Long userId, Long relationId) {
  193. GroupsRelation groupsRelation = getGroupsRelation(userId, relationId);
  194. GroupsTrips groupsTrips = getGroupsTrips(groupsRelation);
  195. GoodsDonSku goodsDonSku = skuMapper.selectById(groupsTrips.getSkuId());
  196. log.info("用户:{},所在车次:{},座位id:{},在{}获取跳转GPT镜像的登录url", userId, groupsTrips.getId(), relationId, DateTime.now());
  197. if (goodsDonSku != null && goodsDonSku.getIsMirror()) {
  198. ChatgptUser chatgptUser = getChatgptUser(userId, relationId, groupsRelation, groupsTrips, goodsDonSku);
  199. if (214610L == relationId) {
  200. return "https://cdn.galaxydvd.com/login_token?access_token=" + chatgptUser.getUserToken();
  201. }
  202. return GPT_DOMAIN + "/login_token?access_token=" + chatgptUser.getUserToken();
  203. } else {
  204. throw BusinessRuntimeException.getInstance("服务器出了点问题");
  205. }
  206. }
  207. /**
  208. * 获取车队登录url
  209. *
  210. * @param userId
  211. * @param carId
  212. * @return
  213. */
  214. @Override
  215. public String getCarLoginUrl(String domain, Long userId, Long relationId, String carId) {
  216. GroupsRelation groupsRelation = getGroupsRelation(userId, relationId);
  217. GroupsTrips groupsTrips = getGroupsTrips(groupsRelation);
  218. GoodsDonSku goodsDonSku = skuMapper.selectById(groupsTrips.getSkuId());
  219. if (goodsDonSku != null && goodsDonSku.getIsMirror() && goodsDonSku.getIsCar()) {
  220. ChatgptUser chatgptUser = getChatgptCarUser(userId, relationId, groupsRelation, goodsDonSku);
  221. String DOMAIN = getGptDomain(domain, goodsDonSku);
  222. log.info("domain:{},用户:{},所在车次:{},座位id:{},在{}获取跳转GPT镜像的登录url", DOMAIN, userId, groupsTrips.getId(), relationId, DateTime.now());
  223. return DOMAIN + "/auth/logintoken?carid=" + carId + "&usertoken=" + chatgptUser.getUserToken();
  224. } else {
  225. throw BusinessRuntimeException.getInstance("服务器出了点问题");
  226. }
  227. }
  228. /**
  229. * 根据userToken获取车队登录url
  230. */
  231. @Override
  232. public String getCarLoginUrlWithToken(String domain, String userToken, String carId) {
  233. ChatgptUser chatgptUser = getCarChatGptUserWithToken(userToken);
  234. if (chatgptUser != null) {
  235. ChatgptUserTokenPrepare chatgptUserTokenPrepare = chatgptUserTokenPrepareMapper.selectOne(Wrappers.lambdaQuery(ChatgptUserTokenPrepare.class)
  236. .eq(ChatgptUserTokenPrepare::getUserToken, userToken)
  237. .last("limit 1"));
  238. Long skuId = chatgptUserTokenPrepare.getSkuId();
  239. GoodsDonSku goodsDonSku = skuMapper.selectById(skuId);
  240. String DOMAIN = getGptDomain(domain, goodsDonSku);
  241. log.info("domain:{},渠道用户:{},在{}获取跳转GPT镜像的登录url", DOMAIN, userToken, DateTime.now());
  242. return DOMAIN + "/auth/logintoken?carid=" + carId + "&usertoken=" + chatgptUser.getUserToken();
  243. } else {
  244. throw BusinessRuntimeException.getInstance("服务出了点问题");
  245. }
  246. }
  247. /**
  248. * 获取车位信息
  249. *
  250. * @param userId
  251. * @param relationId
  252. * @return
  253. */
  254. private GroupsRelation getGroupsRelation(Long userId, Long relationId) {
  255. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  256. GroupsRelation groupsRelation = groupsRelationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class).in(GroupsRelation::getUserId, userIdList).eq(GroupsRelation::getId, relationId));
  257. if (groupsRelation == null) {
  258. throw BusinessRuntimeException.getInstance("车票不存在");
  259. }
  260. return groupsRelation;
  261. }
  262. /**
  263. * 获取车队信息
  264. *
  265. * @param groupsRelation
  266. * @return
  267. */
  268. private GroupsTrips getGroupsTrips(GroupsRelation groupsRelation) {
  269. GroupsTrips groupsTrips = groupsMapper.selectById(groupsRelation.getGroupsId());
  270. if (groupsTrips == null) {
  271. throw BusinessRuntimeException.getInstance("车队异常");
  272. }
  273. return groupsTrips;
  274. }
  275. private ChatgptUser getChatgptUser(Long userId, Long relationId, GroupsRelation groupsRelation, GroupsTrips groupsTrips, GoodsDonSku goodsDonSku) {
  276. ChatgptUser chatgptUser = chatgptUserMapper.selectOne(Wrappers.lambdaQuery(ChatgptUser.class).eq(ChatgptUser::getRelationId, relationId));
  277. User user = userMapper.selectById(userId);
  278. if (chatgptUser == null) {
  279. chatgptUser = createChatgptUser(groupsRelation, groupsTrips, user, goodsDonSku);
  280. } else {
  281. updateChatgptUser(groupsRelation, user, chatgptUser);
  282. }
  283. return chatgptUser;
  284. }
  285. private ChatgptUser getChatgptCarUser(Long userId, Long relationId, GroupsRelation groupsRelation, GoodsDonSku goodsDonSku) {
  286. ChatgptUser chatgptUser = chatgptUserMapper.selectOne(Wrappers.lambdaQuery(ChatgptUser.class).eq(ChatgptUser::getRelationId, relationId));
  287. User user = userMapper.selectById(userId);
  288. if (chatgptUser == null) {
  289. chatgptUser = createChatgptUser(groupsRelation, null, user, goodsDonSku);
  290. } else {
  291. updateChatgptUser(groupsRelation, user, chatgptUser);
  292. }
  293. return chatgptUser;
  294. }
  295. /**
  296. * 创建chatgptUser
  297. */
  298. private synchronized ChatgptUser createChatgptUser(GroupsRelation groupsRelation, GroupsTrips groupsTrips, User user, GoodsDonSku goodsDonSku) {
  299. ChatgptUser chatgptUser = new ChatgptUser();
  300. if (!goodsDonSku.getIsCar()) {
  301. ChatgptSession chatgptSession = chatgptSessionMapper.selectOne(Wrappers.lambdaQuery(ChatgptSession.class).eq(ChatgptSession::getAccountId, groupsTrips.getAccountId()));
  302. if (chatgptSession == null) {
  303. Account account = accountMapper.selectById(groupsTrips.getAccountId());
  304. String officialSession = "";
  305. try {
  306. JSONObject loginResult = getLoginResult(account);
  307. if (StringUtils.isBlank(loginResult.getStr("accessToken"))) {
  308. throw BusinessRuntimeException.getInstance(loginResult.getStr("detail"));
  309. }
  310. officialSession = loginResult.toString();
  311. } catch (Exception e) {
  312. throw BusinessRuntimeException.getInstance("配置账号错误 msg: " + e.getMessage());
  313. }
  314. createChatgptSession(account, officialSession);
  315. chatgptSession = chatgptSessionMapper.selectOne(Wrappers.lambdaQuery(ChatgptSession.class).eq(ChatgptSession::getAccountId, groupsTrips.getAccountId()));
  316. }
  317. chatgptUser.setSessionId(chatgptSession.getId());
  318. }
  319. if (goodsDonSku.getIsCar()) {
  320. chatgptUser.setIsCar(true);
  321. chatgptUser.setLimitNum(goodsDonSku.getGptLimitNum());
  322. chatgptUser.setLimitTime(goodsDonSku.getGptLimitTime());
  323. }
  324. try {
  325. chatgptUser.setExpireTime(groupsRelation.getExpiryTime());
  326. chatgptUser.setIsPlus(1);
  327. chatgptUser.setName(user.getNickname());
  328. chatgptUser.setImg(getWxImg(user.getHeadimgurl(), user));
  329. chatgptUser.setRelationId(groupsRelation.getId());
  330. chatgptUser.setUserToken(UUID.randomUUID().toString());
  331. chatgptUserMapper.insert(chatgptUser);
  332. //是否是大学生限时车队
  333. Date expiryTime = groupsRelation.getExpiryTime();
  334. Date startTime = groupsRelation.getStartTime();
  335. //大学生站 1天免费试用
  336. if (DateUtil.between(startTime, expiryTime, DateUnit.DAY) <= 1) {
  337. CollegeStudentStationUseTicketRecord useTicketRecord = new CollegeStudentStationUseTicketRecord();
  338. useTicketRecord.setUserId(user.getId());
  339. useTicketRecord.setUserToken(chatgptUser.getUserToken());
  340. collegeStudentStationUseTicketRecordMapper.insert(useTicketRecord);
  341. }
  342. } catch (DuplicateKeyException e) {
  343. log.error("重复插入镜像用户:{}token,errmsg:{}", user.getNickname(), StringUtil.getErrorText(e));
  344. }
  345. return chatgptUser;
  346. }
  347. /**
  348. * 创建chatgptUser 无需车队
  349. */
  350. public ChatgptUser generateChatGptUserUnderPrepare(ChatgptUserTokenPrepare prepare) {
  351. ChatgptUser chatgptUser = new ChatgptUser();
  352. GoodsDonSku goodsDonSku = skuMapper.selectById(prepare.getSkuId());
  353. if (goodsDonSku == null) {
  354. throw BusinessRuntimeException.getInstance("车队规格不存在,请联系客服..");
  355. }
  356. if (goodsDonSku.getIsCar()) {
  357. chatgptUser.setIsCar(true);
  358. chatgptUser.setLimitNum(goodsDonSku.getGptLimitNum());
  359. chatgptUser.setLimitTime(goodsDonSku.getGptLimitTime());
  360. }
  361. try {
  362. chatgptUser.setExpireTime(DateUtil.offsetMonth(DateTime.now(), goodsDonSku.getMonths()));
  363. chatgptUser.setIsPlus(1);
  364. chatgptUser.setName(prepare.getName());
  365. chatgptUser.setImg(prepare.getImg());
  366. chatgptUser.setUserToken(prepare.getUserToken());
  367. chatgptUserMapper.insert(chatgptUser);
  368. prepare.setStatus(true);
  369. chatgptUserTokenPrepareMapper.updateById(prepare);
  370. log.info("用户激活userToken:{}成功", prepare.getUserToken());
  371. } catch (DuplicateKeyException e) {
  372. log.error("重复插入镜像车队用户:{}token,errmsg:{}" + chatgptUser.getId(), StringUtil.getErrorText(e));
  373. }
  374. return chatgptUser;
  375. }
  376. private void updateChatgptUser(GroupsRelation groupsRelation, User user, ChatgptUser chatgptUser) {
  377. chatgptUser.setName(user.getNickname());
  378. chatgptUser.setImg(getWxImg(user.getHeadimgurl(), user));
  379. chatgptUser.setExpireTime(groupsRelation.getExpiryTime());
  380. chatgptUserMapper.updateById(chatgptUser);
  381. }
  382. /**
  383. * 更换wx头像至oss
  384. */
  385. private String getWxImg(String headimgurl, User user) {
  386. if (headimgurl.contains("thirdwx.qlogo.cn")) {
  387. try {
  388. byte[] body = HttpUtil.downloadBytes(headimgurl);
  389. Path tempFile = Files.createTempFile("wxheadimg-" + user.getId(), ".jpeg");
  390. try (FileImageOutputStream imageOutput = new FileImageOutputStream(tempFile.toFile())) {
  391. imageOutput.write(body, 0, body.length);
  392. }
  393. Map<String, Object> paramMap = new HashMap<>();
  394. paramMap.put("file", tempFile.toFile());
  395. JSONObject result = JSONUtil.parseObj(HttpUtil.post("https://files.liuliangbang.vip/pic/ups", paramMap));
  396. return result.getJSONObject("value").getJSONArray("saved").getJSONObject(0).getJSONObject("info").getStr("cdnUrl");
  397. } catch (Exception ex) {
  398. log.error("上传微信头像错误!msg:{}", StringUtil.getErrorText(ex));
  399. return "./avatars.png";
  400. }
  401. } else {
  402. return user.getHeadimgurl();
  403. }
  404. }
  405. @Override
  406. public ChatgptUser findByUserTokenAndExpireTimeAfter(String userToken, LocalDateTime now) {
  407. return chatgptUserMapper.selectOne(Wrappers.lambdaQuery(ChatgptUser.class).eq(ChatgptUser::getUserToken, userToken).gt(ChatgptUser::getExpireTime, now));
  408. }
  409. @Override
  410. public void saveConversationRecord(String userToken, ConversationRequest conversationRequest) {
  411. LambdaQueryWrapper<ChatgptSession> wrapper = Wrappers.lambdaQuery(ChatgptSession.class);
  412. ChatgptUser chatgptUser = chatgptUserMapper.selectOne(Wrappers.lambdaQuery(ChatgptUser.class).eq(ChatgptUser::getUserToken, userToken));
  413. if (StringUtils.isNotBlank(conversationRequest.getCarId())) {
  414. wrapper.eq(ChatgptSession::getCarId, conversationRequest.getCarId());
  415. } else {
  416. if (chatgptUser.getSessionId() != null) {
  417. wrapper.eq(ChatgptSession::getId, chatgptUser.getSessionId());
  418. }
  419. }
  420. ChatgptSession chatgptSession = chatgptSessionMapper.selectOne(wrapper);
  421. ChatgptUserConversationRecord chatgptUserConversationRecord = new ChatgptUserConversationRecord();
  422. chatgptUserConversationRecord.setUserToken(userToken);
  423. chatgptUserConversationRecord.setCarId(chatgptSession.getCarId());
  424. chatgptUserConversationRecord.setCarName(chatgptSession.getCarName());
  425. if (StringUtils.isNotBlank(conversationRequest.getConversation_id())) {
  426. chatgptUserConversationRecord.setConversationId(conversationRequest.getConversation_id());
  427. }
  428. chatgptUserConversationRecord.setModel(conversationRequest.getModel());
  429. chatgptUserConversationRecordMapper.insert(chatgptUserConversationRecord);
  430. if(!LOW_GPT_MODEL.contains(conversationRequest.getModel())){
  431. String key = RedisService.key.CHATGPT_CONVERSATION_LIMIT.getName() + ":" + userToken;
  432. long currentTimeMillis = System.currentTimeMillis();
  433. redisService.del();
  434. if(redisService.hasKey("chatgpt:team:clears_in:" + chatgptSession.getCarId())){
  435. redisService.del("chatgpt:team:clears_in:" + chatgptSession.getCarId());
  436. }
  437. if (redisService.hasKey("chatgpt:clears_in:" + chatgptSession.getCarId())) {
  438. redisService.del("chatgpt:clears_in:" + chatgptSession.getCarId());
  439. }
  440. // 如果未超过限制,记录当前请求的时间戳
  441. redisService.zAdd(key, currentTimeMillis, currentTimeMillis);
  442. // 设置ZSet的过期时间,窗口大小加上一段冗余时间
  443. redisService.expire(key, (chatgptUser.getLimitTime() * 60 * 60) + 20);
  444. }
  445. if (StringUtils.isNotBlank(chatgptSession.getCarId())) {
  446. updateExperienceAndScore(chatgptSession.getCarId(), !LOW_GPT_MODEL.contains(conversationRequest.getModel()), System.currentTimeMillis());
  447. }
  448. }
  449. @Override
  450. public ConversationLimitResponse conversationLimit(String userToken, String model, String carId, ChatgptUser chatgptUser, Boolean isCar) {
  451. ConversationLimitResponse conversationLimitResponse = new ConversationLimitResponse();
  452. conversationLimitResponse.setLimited(false);
  453. if (!LOW_GPT_MODEL.contains(model)) {
  454. //如果不为车队 直接返回
  455. if (chatgptUser.getIsCar()) {
  456. conversationLimitResponse = isConversationAllowed(userToken, chatgptUser.getLimitNum(), chatgptUser.getLimitTime());
  457. }
  458. }
  459. return conversationLimitResponse;
  460. }
  461. /**
  462. * 检查是否允许进行进行提问
  463. *
  464. * @param userToken 用户token
  465. * @return true 如果允许请求,false 如果请求被限制
  466. */
  467. public ConversationLimitResponse isConversationAllowed(String userToken, int limit, Long limitTime) {
  468. String key = RedisService.key.CHATGPT_CONVERSATION_LIMIT.getName() + ":" + userToken;
  469. long currentTimeMillis = System.currentTimeMillis();
  470. long windowStartMillis = currentTimeMillis - (limitTime * 60 * 60) * 1000;
  471. ConversationLimitResponse conversationLimitResponse = new ConversationLimitResponse();
  472. // 清除时间窗口之前的请求记录
  473. redisService.zRemoveRangeByScore(key, 0, windowStartMillis);
  474. Long currentSize = redisService.zCard(key);
  475. if (currentSize != null && currentSize >= limit) {
  476. // 如果当前请求次数超过限制,则拒绝请求
  477. Set<Object> times = redisService.zRangeByScore(key, 0, currentTimeMillis, 0, 1);
  478. Long oldestTime = (Long) times.stream().findFirst().orElse(null);
  479. if (oldestTime != null) {
  480. // 下一次可用时间是最早请求时间之后的3小时
  481. long nextAvailableTime = oldestTime + (limitTime * 60 * 60 * 1000);
  482. conversationLimitResponse.setNextAvailableTime(nextAvailableTime);
  483. }
  484. conversationLimitResponse.setLimited(true);
  485. //用户次数使用限制
  486. ChatgptUserCarUsedRecord chatgptUserCarUsedRecord = new ChatgptUserCarUsedRecord();
  487. chatgptUserCarUsedRecord.setUserToken(userToken);
  488. chatgptUserCarUsedRecord.setIsUserLimit(true);
  489. chatgptUserCarUsedRecordMapper.insert(chatgptUserCarUsedRecord);
  490. return conversationLimitResponse;
  491. } else {
  492. conversationLimitResponse.setLimited(false);
  493. return conversationLimitResponse;
  494. }
  495. }
  496. /**
  497. * 获取指定用户ID在滑动窗口内的提问次数
  498. *
  499. * @param userToken 用户token
  500. * @return 滑动窗口内的请求次数
  501. */
  502. @Override
  503. public Long getConversationCount(String userToken, Long limitTime) {
  504. String key = RedisService.key.CHATGPT_CONVERSATION_LIMIT.getName() + ":" + userToken;
  505. long currentTimeMillis = System.currentTimeMillis();
  506. long windowStartMillis = currentTimeMillis - (limitTime * 60 * 60) * 1000;
  507. // 清除时间窗口之前的请求记录(可选,根据需要决定是否在此处清理过期记录)
  508. redisService.zRemoveRangeByScore(key, 0, windowStartMillis);
  509. // 获取当前窗口内的请求次数
  510. Long currentSize = redisService.zCard(key);
  511. return currentSize != null ? currentSize : 0L;
  512. }
  513. /**
  514. * 获取指定车队ID在滑动窗口内的提问次数
  515. *
  516. * @param carId 车队ID
  517. * @return 滑动窗口内的请求次数
  518. */
  519. private Long getCarConversationCount(String carId, Long limitTime) {
  520. // 定义键名
  521. String key = RedisService.key.CHATGPT_CAR_HIGH_CHAT.getName() + carId;
  522. long timestamp = System.currentTimeMillis();
  523. long windowStartMillis = timestamp - (limitTime * 60 * 60 * 1000);
  524. // 清除时间窗口之前的请求记录(可选,根据需要决定是否在此处清理过期记录)
  525. redisService.zRemoveRangeByScore(key, 0, windowStartMillis);
  526. // 获取当前窗口内的请求次数
  527. Long currentSize = redisService.zCard(key);
  528. return currentSize != null ? currentSize : 0L;
  529. }
  530. @Override
  531. public ChatgptSession checkSession(String carId) {
  532. ChatgptSession chatgptSession = chatgptSessionMapper.selectOne(Wrappers.lambdaQuery(ChatgptSession.class).eq(ChatgptSession::getCarId, carId).eq(ChatgptSession::getIsCar, true).last(" limit 1"));
  533. if (chatgptSession == null) {
  534. throw BusinessRuntimeException.getInstance("车队不存在");
  535. }
  536. return chatgptSession;
  537. }
  538. private Long carOaiLimit(String carId, Boolean isTeam) {
  539. if(isTeam && redisService.hasKey("chatgpt:team:clears_in:" + carId)){
  540. return redisService.getExpire("chatgpt:team:clears_in:" + carId);
  541. }
  542. if (redisService.hasKey("chatgpt:clears_in:" + carId)) {
  543. return redisService.getExpire("chatgpt:clears_in:" + carId);
  544. }
  545. return 0L;
  546. }
  547. @Override
  548. public Boolean checkCarAccount(long userId, Long relationId) {
  549. GroupsRelation groupsRelation = getGroupsRelation(userId, relationId);
  550. GroupsTrips groupsTrips = getGroupsTrips(groupsRelation);
  551. GoodsDonSku goodsDonSku = skuMapper.selectById(groupsTrips.getSkuId());
  552. if (goodsDonSku != null && goodsDonSku.getGoodsId() == 18 && goodsDonSku.getIsMirror() && goodsDonSku.getIsCar()) {
  553. ChatgptUser chatgptUser = getChatgptCarUser(userId, relationId, groupsRelation, goodsDonSku);
  554. return true;
  555. } else {
  556. return false;
  557. }
  558. }
  559. @Override
  560. public Boolean checkCarAccountWithToken(String userToken) {
  561. ChatgptUser chatgptUser = getCarChatGptUserWithToken(userToken);
  562. return chatgptUser != null;
  563. }
  564. @Override
  565. public ChatgptUser getCarChatGptUser(long userId, Long relationId) {
  566. GroupsRelation groupsRelation = getGroupsRelation(userId, relationId);
  567. GroupsTrips groupsTrips = getGroupsTrips(groupsRelation);
  568. GoodsDonSku goodsDonSku = skuMapper.selectById(groupsTrips.getSkuId());
  569. if (goodsDonSku != null && goodsDonSku.getIsMirror() && goodsDonSku.getIsCar()) {
  570. return getChatgptCarUser(userId, relationId, groupsRelation, goodsDonSku);
  571. }
  572. return null;
  573. }
  574. @Override
  575. public ChatgptUser getCarChatGptUserWithToken(String userToken) {
  576. ChatgptUser chatgptUser = chatgptUserMapper.selectOne(Wrappers.lambdaQuery(ChatgptUser.class).eq(ChatgptUser::getUserToken, userToken).last(" limit 1"));
  577. if (chatgptUser == null) {
  578. //是否是用户token预备账号
  579. ChatgptUserTokenPrepare chatgptUserTokenPrepare = chatgptUserTokenPrepareMapper.selectOne(Wrappers.lambdaQuery(ChatgptUserTokenPrepare.class)
  580. .eq(ChatgptUserTokenPrepare::getUserToken, userToken).last("limit 1"));
  581. if (chatgptUserTokenPrepare != null) {
  582. chatgptUser = generateChatGptUserUnderPrepare(chatgptUserTokenPrepare);
  583. }
  584. }
  585. if (chatgptUser != null) {
  586. if(!chatgptUser.getIsCar()){
  587. throw BusinessRuntimeException.getInstance("您非车队用户,请购买车队套餐");
  588. }
  589. if (chatgptUser.getRelationId() != null) {
  590. throw BusinessRuntimeException.getInstance("非渠道用户,请通过官网登录!");
  591. }
  592. return chatgptUser;
  593. }
  594. return null;
  595. }
  596. /**
  597. * 获取车队分页信息
  598. */
  599. @Override
  600. public SearchResult<ChatgptCarInfoView> getCarInfoPage(String userToken, Integer limit, Boolean isPlus) {
  601. SearchResult<ChatgptCarInfoView> chatgptCarInfoViews = beanSearcher.search(ChatgptCarInfoView.class, MapUtils.flatBuilder(request.getParameterMap()).field(ChatgptCarInfoView::getIsPlus, isPlus).orderBy(ChatgptCarInfoView::getScore).asc().build());
  602. chatgptCarInfoViews.getDataList().forEach(this::buildChatgptCarInfoView);
  603. return chatgptCarInfoViews;
  604. }
  605. /**
  606. * 获取车队信息
  607. */
  608. @Override
  609. public List<ChatgptCarInfoView> getCarInfoList(String userToken, Integer limit, Boolean isPlus) {
  610. List<ChatgptCarInfoView> lowestScoreFleets = getLowestScoreFleets(limit, isPlus);
  611. return lowestScoreFleets;
  612. }
  613. // 更新体验并计算评分
  614. public void updateExperienceAndScore(String carId, boolean isHighLevel, long timestamp) {
  615. // 定义键名
  616. String key = isHighLevel ? RedisService.key.CHATGPT_CAR_HIGH_CHAT.getName() + carId : RedisService.key.CHATGPT_CAR_LOW_CHAT.getName() + carId;
  617. double scoreToAdd = isHighLevel ? 2.0 : 1.0; // 分数更新规则
  618. // 更新体验数据
  619. redisService.zAdd(key, timestamp, String.valueOf(timestamp));
  620. // 清理旧数据(可选)和重新计算评分(根据需要实现)
  621. cleanupOldExperiencesAndRecalculateScore(carId, timestamp);
  622. }
  623. // 清理旧数据和重新计算评分
  624. public void cleanupOldExperiencesAndRecalculateScore(String carId, long currentTimestamp) {
  625. long threeHoursAgo = currentTimestamp - (3 * 60 * 60 * 1000); // 3小时前的时间戳
  626. // 清理高级体验旧数据
  627. redisService.zRemoveRangeByScore(RedisService.key.CHATGPT_CAR_HIGH_CHAT.getName() + carId, 0, threeHoursAgo);
  628. // 清理低级体验旧数据
  629. redisService.zRemoveRangeByScore(RedisService.key.CHATGPT_CAR_LOW_CHAT.getName() + carId, 0, threeHoursAgo);
  630. // 重新计算评分
  631. recalculateScore(carId, currentTimestamp);
  632. }
  633. // 重新计算指定车队的评分
  634. private void recalculateScore(String carId, long currentTimestamp) {
  635. // 实际应用中,你需要根据高级体验和低级体验的数量重新计算得分
  636. Double highExperienceScore = (double) redisService.zCount(RedisService.key.CHATGPT_CAR_HIGH_CHAT.getName() + carId, currentTimestamp - (3 * 60 * 60 * 1000), currentTimestamp) * 2;
  637. Double lowExperienceScore = (double) redisService.zCount(RedisService.key.CHATGPT_CAR_LOW_CHAT.getName() + carId, currentTimestamp - (3 * 60 * 60 * 1000), currentTimestamp);
  638. double newScore = highExperienceScore + lowExperienceScore;
  639. if(carId.contains("T")){
  640. newScore = BigDecimal.valueOf(newScore).divide(BigDecimal.valueOf(5), 2, BigDecimal.ROUND_HALF_UP).doubleValue();
  641. }
  642. redisService.zAdd(RedisService.key.CHATGPT_CAR_SCORES.getName(), newScore, carId);
  643. }
  644. // 获取得分最低的N个车队的方法
  645. public List<ChatgptCarInfoView> getLowestScoreFleets(int count, Boolean isPlus) {
  646. List<ChatgptCarInfoView> chatgptCarInfoViews = beanSearcher.searchList(ChatgptCarInfoView.class, MapUtils.builder().field(ChatgptCarInfoView::getIsPlus, isPlus).orderBy(ChatgptCarInfoView::getScore).asc().limit(0, count).build());
  647. chatgptCarInfoViews.forEach(this::buildChatgptCarInfoView);
  648. return chatgptCarInfoViews;
  649. }
  650. public void initFleets(Boolean flag) {
  651. LambdaQueryWrapper<ChatgptSession> wrapper = Wrappers.lambdaQuery(ChatgptSession.class);
  652. if (flag) {
  653. Set<ZSetOperations.TypedTuple<Object>> fleets = redisService.zRangeWithScores(RedisService.key.CHATGPT_CAR_SCORES.getName(), 0L, -1);
  654. List<Object> collect = fleets.stream().map(ZSetOperations.TypedTuple::getValue).collect(Collectors.toList());
  655. wrapper.notIn(collect.size() > 0, ChatgptSession::getCarId, collect);
  656. }
  657. //如果存在未存在redis中的车辆则同步进 chatgpt:car:scores
  658. List<ChatgptSession> chatgptSessions = chatgptSessionMapper.selectList(wrapper.eq(ChatgptSession::getIsCar, true));
  659. chatgptSessions.forEach((chatgptSession) -> {
  660. if (!redisService.checkValueExistsInZSet(RedisService.key.CHATGPT_CAR_SCORES.getName(), chatgptSession.getCarId())) {
  661. redisService.zAdd(RedisService.key.CHATGPT_CAR_SCORES.getName(), 0, chatgptSession.getCarId());
  662. }
  663. });
  664. }
  665. // 构建ChatgptCarInfoView对象
  666. private ChatgptCarInfoView buildChatgptCarInfoView(ChatgptCarInfoView view) {
  667. // 在这里根据carId获取相关信息并填充到ChatgptCarInfoView对象中
  668. view.setStatus(view.getScore() >= 50 ? "繁忙" : "空闲"); // 或“繁忙”
  669. if(view.getCarName().contains("T") && view.getIsPlus() == 1){
  670. view.setType("Team");
  671. Long team = carOaiLimit(view.getCarId(), true);
  672. if (team != 0L) {
  673. view.setTeamExpTime(new DateTime(System.currentTimeMillis() + team * 1000));
  674. }
  675. Long aLong = carOaiLimit(view.getCarId(), false);
  676. if (aLong != 0L) {
  677. view.setExpTime(new DateTime(System.currentTimeMillis() + aLong * 1000));
  678. }
  679. if (view.getExpTime() != null && view.getTeamExpTime() != null) {
  680. view.setStatus("全部停运");
  681. }else if(view.getExpTime() != null || view.getTeamExpTime() != null) {
  682. view.setStatus("部分停运");
  683. }
  684. }else {
  685. view.setType(view.getIsPlus() == 1 ? "Plus" : "3.5");
  686. Long aLong = carOaiLimit(view.getCarId(), false);
  687. if (aLong != 0L) {
  688. view.setStatus("停运");
  689. view.setExpTime(new DateTime(System.currentTimeMillis() + aLong * 1000));
  690. }
  691. }
  692. int use = getCarConversationCount(view.getCarId(), 3L).intValue();
  693. view.setUse(use);
  694. view.setScore(Math.min(view.getScore(), 200));
  695. return view;
  696. }
  697. @Override
  698. public ChatGptUserView getUserInfo(long userId, Long relationId) {
  699. if (checkCarAccount(userId, relationId)) {
  700. GroupsRelation groupsRelation = getGroupsRelation(userId, relationId);
  701. GroupsTrips groupsTrips = getGroupsTrips(groupsRelation);
  702. GoodsDonSku goodsDonSku = skuMapper.selectById(groupsTrips.getSkuId());
  703. ChatgptUser chatgptUser = chatgptUserMapper.selectOne(Wrappers.lambdaQuery(ChatgptUser.class).eq(ChatgptUser::getRelationId, relationId));
  704. Integer count = upgradePackageMapper.selectCount(Wrappers.lambdaQuery(UpgradePackage.class).apply("JSON_CONTAINS(sku_ids,'\"" + groupsTrips.getSkuId() + "\"')")
  705. .gt(UpgradePackage::getNum, chatgptUser.getLimitNum())
  706. .eq(UpgradePackage::getStatus, Boolean.TRUE)
  707. .eq(UpgradePackage::getGptType, 0)
  708. .eq(UpgradePackage::getDeleted, Boolean.TRUE));
  709. Boolean upgrade = count > 0 ? true : false;
  710. OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class)
  711. .eq(OrderDon::getRelationId, relationId)
  712. .eq(OrderDon::getUserId, groupsRelation.getUserId())
  713. .notIn(OrderDon::getStatus, Constant.noOrderAllStatus)
  714. .orderByDesc(OrderDon::getId)
  715. .last("limit 1"));
  716. Long orderId = null;
  717. if (orderDon != null) {
  718. orderId = orderDon.getId();
  719. }
  720. BigDecimal packagePrice = null;
  721. if (chatgptUser.getPackageId() != 0) {
  722. UpgradePackage upgradePackage = upgradePackageMapper.selectById(chatgptUser.getPackageId());
  723. packagePrice = upgradePackage.getPrice();
  724. }
  725. return ChatGptUserView.builder()
  726. .skuName(goodsDonSku.getSubTitle())
  727. .expireTime(chatgptUser.getExpireTime())
  728. .limitNum(chatgptUser.getLimitNum())
  729. .limitTime(chatgptUser.getLimitTime())
  730. .upgrade(upgrade)
  731. .orderId(orderId)
  732. .goodsId(goodsDonSku.getGoodsId())
  733. .skuId(goodsDonSku.getId())
  734. .months(goodsDonSku.getMonths())
  735. .use(Math.min(chatgptUser.getLimitNum(), getConversationCount(chatgptUser.getUserToken(), chatgptUser.getLimitTime())))
  736. .packageId(chatgptUser.getPackageId())
  737. .packagePrice(packagePrice)
  738. .isRenewPackage(chatgptUser.getRenewOrderId() != null ? true : false)
  739. .build();
  740. } else {
  741. throw BusinessRuntimeException.getInstance("您还未购买该车票");
  742. }
  743. }
  744. @Override
  745. public ChatGptUserView getUserInfoWithToken(String userToken) {
  746. if (checkCarAccountWithToken(userToken)) {
  747. ChatgptUser chatgptUser = getCarChatGptUserWithToken(userToken);
  748. return ChatGptUserView.builder()
  749. .skuName("")
  750. .expireTime(chatgptUser.getExpireTime())
  751. .limitNum(chatgptUser.getLimitNum())
  752. .limitTime(chatgptUser.getLimitTime())
  753. .use(getConversationCount(chatgptUser.getUserToken(), chatgptUser.getLimitTime()))
  754. .build();
  755. } else {
  756. throw BusinessRuntimeException.getInstance("您还未购买该车票");
  757. }
  758. }
  759. @Override
  760. public void genTitleSync(String conversationId, String carid, String userToken) {
  761. //同步对话
  762. if (!StringUtils.isAnyBlank(conversationId, carid, userToken)) {
  763. ChatgptUserConversationRecord chatgptUserConversationRecord = chatgptUserConversationRecordMapper.selectOne(Wrappers.lambdaQuery(ChatgptUserConversationRecord.class)
  764. .isNull(ChatgptUserConversationRecord::getConversationId)
  765. .eq(ChatgptUserConversationRecord::getCarId, carid)
  766. .eq(ChatgptUserConversationRecord::getUserToken, userToken)
  767. .orderByDesc(ChatgptUserConversationRecord::getId)
  768. .last(" limit 1"));
  769. if (chatgptUserConversationRecord != null) {
  770. chatgptUserConversationRecord.setConversationId(conversationId);
  771. chatgptUserConversationRecordMapper.updateById(chatgptUserConversationRecord);
  772. }
  773. }
  774. }
  775. @Override
  776. public void carLimited(String carId, String userToken, Long expTime, Boolean isTeam) {
  777. if (carId == null) {
  778. if (StringUtils.isNotBlank(userToken)) {
  779. ChatgptUser chatgptUser = chatgptUserMapper.selectOne(Wrappers.lambdaQuery(ChatgptUser.class).eq(ChatgptUser::getUserToken, userToken));
  780. if (chatgptUser != null && chatgptUser.getSessionId() != null) {
  781. ChatgptSession chatgptSession = chatgptSessionMapper.selectById(chatgptUser.getSessionId());
  782. if (chatgptSession != null) {
  783. carId = chatgptSession.getCarId();
  784. }
  785. }
  786. }
  787. }
  788. if(isTeam){
  789. redisService.set("chatgpt:team:clears_in:" + carId, expTime, expTime);
  790. }else {
  791. redisService.set("chatgpt:clears_in:" + carId, expTime, expTime);
  792. }
  793. try {
  794. //记录用户触发限制
  795. ChatgptUserCarUsedRecord chatgptUserCarUsedRecord = new ChatgptUserCarUsedRecord();
  796. chatgptUserCarUsedRecord.setUserToken(userToken);
  797. chatgptUserCarUsedRecord.setCarId(carId);
  798. String highCarChatKey = RedisService.key.CHATGPT_CAR_HIGH_CHAT.getName() + carId;
  799. String lowCarChatKey = RedisService.key.CHATGPT_CAR_LOW_CHAT.getName() + carId;
  800. Long highCarChatNum = redisService.zCard(highCarChatKey);
  801. if (highCarChatNum != null) {
  802. chatgptUserCarUsedRecord.setGptFour(Integer.parseInt(highCarChatNum.toString()));
  803. }
  804. Long lowCarChatNum = redisService.zCard(lowCarChatKey);
  805. if (lowCarChatNum != null) {
  806. chatgptUserCarUsedRecord.setGpt(Integer.parseInt(lowCarChatNum.toString()));
  807. }
  808. chatgptUserCarUsedRecordMapper.insert(chatgptUserCarUsedRecord);
  809. log.info("记录userToken:{}访问对应镜像车队carId:{}操作成功", userToken, carId);
  810. } catch (Exception e) {
  811. log.info("记录userToken:{}访问对应镜像车队carId:{}操作失败e:{}", userToken, carId, StringUtil.getErrorText(e));
  812. }
  813. }
  814. @PostConstruct
  815. public void init() {
  816. //如果存在未存在redis中的车辆则同步进 chatgpt:car:scores
  817. TASK_EXECUTOR.execute(() -> {
  818. Set<ZSetOperations.TypedTuple<Object>> lowestScorecarIds = redisService.zRangeWithScores(RedisService.key.CHATGPT_CAR_SCORES.getName(), 0L, -1);
  819. List<Object> collect = lowestScorecarIds.stream().map(ZSetOperations.TypedTuple::getValue).collect(Collectors.toList());
  820. List<ChatgptSession> chatgptSessions = chatgptSessionMapper.selectList(Wrappers.lambdaQuery(ChatgptSession.class).notIn(collect.size() > 0, ChatgptSession::getCarId, collect).eq(ChatgptSession::getIsPlus, 1).eq(ChatgptSession::getIsCar, true));
  821. chatgptSessions.forEach((chatgptSession) -> {
  822. if (!redisService.checkValueExistsInZSet(RedisService.key.CHATGPT_CAR_SCORES.getName(), chatgptSession.getCarId())) {
  823. redisService.zAdd(RedisService.key.CHATGPT_CAR_SCORES.getName(), 0, chatgptSession.getCarId());
  824. }
  825. });
  826. });
  827. }
  828. public String getGptDomain(String domain, GoodsDonSku goodsDonSku) {
  829. String DOMAIN = domain;
  830. if (StrUtil.isEmpty(DOMAIN)) {
  831. DOMAIN = "https://chat.galaxydvd.com";
  832. try {
  833. SysConfig sysConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, goodsDonSku != null && goodsDonSku.getId() == 444 ? "zhihu_gpt_domain" : "mirror_gpt_domain"));
  834. if (sysConfig != null) {
  835. String sysValue = sysConfig.getSysValue();
  836. if (JSONUtil.isJsonArray(sysValue)) {
  837. List<String> domainList = JSONUtil.parseArray(sysValue).toList(String.class);
  838. DOMAIN = domainList.get(RandomUtil.randomInt(domainList.size()));
  839. }
  840. }
  841. } catch (Exception e) {
  842. log.error("随机抽取域名错误. msg:{}", StringUtil.getErrorText(e));
  843. }
  844. }
  845. return DOMAIN;
  846. }
  847. }