MidJourneyAccountServiceImpl.java 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. package com.cyksj.service.midjourney.impl;
  2. import cn.hutool.core.collection.CollectionUtil;
  3. import cn.hutool.core.lang.UUID;
  4. import cn.hutool.core.map.MapUtil;
  5. import cn.hutool.http.HttpRequest;
  6. import cn.hutool.http.HttpUtil;
  7. import cn.hutool.json.JSONObject;
  8. import cn.hutool.json.JSONUtil;
  9. import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  10. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  11. import com.cyksj.common.exception.BusinessRuntimeException;
  12. import com.cyksj.common.util.Jsons;
  13. import com.cyksj.common.util.StringUtil;
  14. import com.cyksj.mapper.*;
  15. import com.cyksj.model.entity.*;
  16. import com.cyksj.redis.RedisService;
  17. import com.cyksj.service.midjourney.MidjourneyAccountService;
  18. import com.cyksj.service.user.UserBindRelationService;
  19. import lombok.RequiredArgsConstructor;
  20. import lombok.extern.slf4j.Slf4j;
  21. import org.springframework.dao.DuplicateKeyException;
  22. import org.springframework.stereotype.Service;
  23. import org.springframework.transaction.annotation.Transactional;
  24. import javax.imageio.stream.FileImageOutputStream;
  25. import java.io.IOException;
  26. import java.nio.file.Files;
  27. import java.nio.file.Path;
  28. import java.util.*;
  29. /**
  30. * @author zwhui
  31. * @date 2024/4/12 15:54
  32. */
  33. @Service
  34. @Slf4j
  35. @RequiredArgsConstructor
  36. public class MidJourneyAccountServiceImpl extends ServiceImpl<MidjourneyAccountMapper, MidjourneyAccount> implements MidjourneyAccountService {
  37. private static final String HOST = "http://43.154.230.104:8080";
  38. private final GroupsRelationMapper groupsRelationMapper;
  39. private final GroupsMapper groupsMapper;
  40. private final GoodsDonSkuMapper skuMapper;
  41. private final UserMapper userMapper;
  42. private final UserBindRelationService userBindRelationService;
  43. private final MidjourneyUserMapper midjourneyUserMapper;
  44. private final RedisService redisService;
  45. @Override
  46. @Transactional(rollbackFor = Throwable.class)
  47. public void addAccount(MidjourneyAccount midjourneyAccount) throws Exception {
  48. baseMapper.insert(midjourneyAccount);
  49. addAcount(midjourneyAccount);
  50. //拉取plus服务账号实例id
  51. Long instanceId = getAccount(midjourneyAccount.getId());
  52. midjourneyAccount.setInstanceId(instanceId);
  53. baseMapper.updateById(midjourneyAccount);
  54. String key = RedisService.key.MIDJOURNEY_ACCOUNT.getName();
  55. Map<Object, Object> accountsUsage = redisService.hmget(key);
  56. if (MapUtil.isNotEmpty(accountsUsage)) {
  57. redisService.hset(key,midjourneyAccount.getInstanceId().toString(),accountsUsage.values().toArray()[0]);
  58. }
  59. }
  60. @Override
  61. @Transactional(rollbackFor = Throwable.class)
  62. public void removeAccount(Long id) {
  63. MidjourneyAccount midjourneyAccount = baseMapper.selectById(id);
  64. if (midjourneyAccount == null) {
  65. throw BusinessRuntimeException.getInstance("账号不存在");
  66. }
  67. baseMapper.deleteById(id);
  68. //删除plus服务账号信息
  69. delAcount(midjourneyAccount.getInstanceId());
  70. redisService.hdel(RedisService.key.MIDJOURNEY_ACCOUNT.getName(),midjourneyAccount.getInstanceId());
  71. }
  72. @Override
  73. @Transactional(rollbackFor = Throwable.class)
  74. public void updateAccount(MidjourneyAccount midjourneyAccount) {
  75. MidjourneyAccount account = baseMapper.selectById(midjourneyAccount.getId());
  76. if (account == null) {
  77. throw BusinessRuntimeException.getInstance("账号不存在");
  78. }
  79. baseMapper.updateById(midjourneyAccount);
  80. midjourneyAccount.setInstanceId(account.getInstanceId());
  81. updAccount(midjourneyAccount);
  82. }
  83. @Override
  84. public void updateStatus(Long id) {
  85. MidjourneyAccount midjourneyAccount = baseMapper.selectById(id);
  86. if (midjourneyAccount == null) {
  87. throw BusinessRuntimeException.getInstance("账号不存在");
  88. }
  89. midjourneyAccount.setStatus(!midjourneyAccount.getStatus());
  90. baseMapper.updateById(midjourneyAccount);
  91. updAccount(midjourneyAccount);
  92. String key = RedisService.key.MIDJOURNEY_ACCOUNT.getName();
  93. if (!midjourneyAccount.getStatus()) {
  94. redisService.hdel(key,midjourneyAccount.getInstanceId());
  95. }else {
  96. Map<Object, Object> accountsUsage = redisService.hmget(key);
  97. if (MapUtil.isNotEmpty(accountsUsage)) {
  98. redisService.hset(key,midjourneyAccount.getInstanceId().toString(),accountsUsage.values().toArray()[0]);
  99. }
  100. }
  101. }
  102. @Override
  103. public void syncAccount(Long id) {
  104. MidjourneyAccount midjourneyAccount = baseMapper.selectById(id);
  105. if (midjourneyAccount == null) {
  106. throw BusinessRuntimeException.getInstance("账号不存在");
  107. }
  108. String fastRemainTime = syncInfo(midjourneyAccount.getInstanceId());
  109. midjourneyAccount.setFastRemainTime(fastRemainTime);
  110. baseMapper.updateById(midjourneyAccount);
  111. }
  112. private void addAcount(MidjourneyAccount midjourneyAccount) throws Exception {
  113. Map<String, Object> accountParam = createAccountParam(midjourneyAccount);
  114. String body = HttpRequest.post(HOST + "/mj/account/create").body(Jsons.toJson(accountParam)).execute().body();
  115. log.info("addAccount body:{}", body);
  116. JSONObject jsonObject = JSONUtil.parseObj(body);
  117. if (jsonObject.getInt("code") != 1) {
  118. throw BusinessRuntimeException.getInstance("addAccount error message:" + jsonObject.getStr("description"));
  119. }
  120. }
  121. private static final List<String> User_Agent_LIST = List.of(
  122. "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
  123. "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)",
  124. "Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
  125. "Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)",
  126. "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)",
  127. "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)",
  128. "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)",
  129. "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)",
  130. "Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6",
  131. "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1",
  132. "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0",
  133. "Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5",
  134. "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6",
  135. "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
  136. "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20",
  137. "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52",
  138. "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.11 TaoBrowser/2.0 Safari/536.11",
  139. "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER",
  140. "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; LBBROWSER)",
  141. "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E; LBBROWSER)",
  142. "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.84 Safari/535.11 LBBROWSER",
  143. "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)",
  144. "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; QQBrowser/7.0.3698.400)",
  145. "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)",
  146. "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SV1; QQDownload 732; .NET4.0C; .NET4.0E; 360SE)",
  147. "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)",
  148. "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)",
  149. "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1",
  150. "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1",
  151. "Mozilla/5.0 (iPad; U; CPU OS 4_2_1 like Mac OS X; zh-cn) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5",
  152. "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0b13pre) Gecko/20110307 Firefox/4.0b13pre",
  153. "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:16.0) Gecko/20100101 Firefox/16.0",
  154. "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11",
  155. "Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10");
  156. private Map<String, Object> createAccountParam(MidjourneyAccount midjourneyAccount) {
  157. Map<String, Object> param = new HashMap<>();
  158. param.put("channelId", midjourneyAccount.getChannelId());
  159. param.put("guildId", midjourneyAccount.getGuildId());
  160. param.put("userToken", midjourneyAccount.getUserToken());
  161. param.put("remark", midjourneyAccount.getId());
  162. param.put("userAgent", User_Agent_LIST.get(new Random().nextInt(User_Agent_LIST.size())));
  163. param.put("timeoutMinutes", 10);
  164. return param;
  165. }
  166. private void delAcount(Long id) {
  167. String body = HttpRequest.delete(HOST + "/mj/account/"+id+"/delete").execute().body();
  168. log.info("delAcount body:{}", body);
  169. JSONObject jsonObject = JSONUtil.parseObj(body);
  170. if (jsonObject.getInt("code") != 1) {
  171. throw BusinessRuntimeException.getInstance("delAcount error message:" + jsonObject.getStr("description"));
  172. }
  173. }
  174. private Long getAccount(Long id) throws Exception {
  175. String body = HttpRequest.post(HOST + "/mj/account/query").body(Jsons.toJson(MapUtil.of("remark", id))).execute().body();
  176. log.info("getAccount body:{}", body);
  177. JSONObject jsonObject = JSONUtil.parseObj(body);
  178. return JSONUtil.parseObj(JSONUtil.parseArray(jsonObject.getStr("content")).get(0)).get("id", Long.class);
  179. }
  180. private void updAccount(MidjourneyAccount midjourneyAccount){
  181. Map<String, Object> accountParam = createAccountParam(midjourneyAccount);
  182. String body = HttpRequest.put(HOST + "/mj/account/"+midjourneyAccount.getInstanceId()+"/update-reconnect")
  183. .body(JSONUtil.toJsonStr(accountParam)).execute().body();
  184. log.info("updAccount body:{}", body);
  185. JSONObject jsonObject = JSONUtil.parseObj(body);
  186. if (jsonObject.getInt("code") != 1) {
  187. throw BusinessRuntimeException.getInstance("updAccount error message:" + jsonObject.getStr("description"));
  188. }
  189. }
  190. private String syncInfo(Long id){
  191. String body = HttpRequest.post(HOST + "/mj/account/"+id+"/sync-info").execute().body();
  192. log.info("syncInfo body:{}", body);
  193. JSONObject jsonObject = JSONUtil.parseObj(body);
  194. if (jsonObject.getInt("code") != 1) {
  195. throw BusinessRuntimeException.getInstance("syncInfo error message:" + jsonObject.getStr("description"));
  196. }
  197. return JSONUtil.parseObj(jsonObject.getStr("result")).getStr("fastTimeRemaining");
  198. }
  199. @Override
  200. public MidjourneyUser getMidjourneyUserToken(Long userId, Long relationId) {
  201. GroupsRelation groupsRelation = getGroupsRelation(userId, relationId);
  202. GroupsTrips groupsTrips = getGroupsTrips(groupsRelation);
  203. GoodsDonSku goodsDonSku = skuMapper.selectById(groupsTrips.getSkuId());
  204. if (goodsDonSku != null && goodsDonSku.getGoodsId() == 26 && goodsDonSku.getIsMirror()) {
  205. return getMidjourneyUser(userId, relationId, groupsRelation, goodsDonSku);
  206. } else {
  207. throw BusinessRuntimeException.getInstance("服务器出了点问题");
  208. }
  209. }
  210. /**
  211. * 获取车位信息
  212. *
  213. * @param userId
  214. * @param relationId
  215. * @return
  216. */
  217. private GroupsRelation getGroupsRelation(Long userId, Long relationId) {
  218. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  219. GroupsRelation groupsRelation = groupsRelationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class).in(GroupsRelation::getUserId, userIdList).eq(GroupsRelation::getId, relationId));
  220. if (groupsRelation == null) {
  221. throw BusinessRuntimeException.getInstance("车票不存在");
  222. }
  223. return groupsRelation;
  224. }
  225. /**
  226. * 获取车队信息
  227. *
  228. * @param groupsRelation
  229. * @return
  230. */
  231. private GroupsTrips getGroupsTrips(GroupsRelation groupsRelation) {
  232. GroupsTrips groupsTrips = groupsMapper.selectById(groupsRelation.getGroupsId());
  233. if (groupsTrips == null) {
  234. throw BusinessRuntimeException.getInstance("车队异常");
  235. }
  236. return groupsTrips;
  237. }
  238. private MidjourneyUser getMidjourneyUser(Long userId, Long relationId, GroupsRelation groupsRelation, GoodsDonSku goodsDonSku) {
  239. MidjourneyUser midjourneyUser = midjourneyUserMapper.selectOne(Wrappers.lambdaQuery(MidjourneyUser.class).eq(MidjourneyUser::getRelationId, relationId));
  240. User user = userMapper.selectById(userId);
  241. if (midjourneyUser == null) {
  242. midjourneyUser = createMidjourneyUser(groupsRelation, user, goodsDonSku);
  243. } else {
  244. updateMidjourneyUser(groupsRelation, user, midjourneyUser);
  245. }
  246. return midjourneyUser;
  247. }
  248. /**
  249. * 创建MidjourneyUser
  250. */
  251. private synchronized MidjourneyUser createMidjourneyUser(GroupsRelation groupsRelation, User user, GoodsDonSku goodsDonSku) {
  252. MidjourneyUser midjourneyUser = new MidjourneyUser();
  253. midjourneyUser.setExpireTime(groupsRelation.getExpiryTime());
  254. midjourneyUser.setName(user.getNickname());
  255. midjourneyUser.setImg(getWxImg(user.getHeadimgurl(), user));
  256. midjourneyUser.setRelationId(groupsRelation.getId());
  257. midjourneyUser.setUserToken(UUID.randomUUID().toString());
  258. if (groupsRelation.getAqType() == 2) {
  259. //fast模式 5次
  260. midjourneyUser.setMjFastNum(5);
  261. midjourneyUser.setMjRelaxNum(0);
  262. } else {
  263. midjourneyUser.setMjFastNum(goodsDonSku.getMjFastNum());
  264. midjourneyUser.setMjRelaxNum((goodsDonSku.getMjRelaxNum() == null || goodsDonSku.getMjRelaxNum() == 0) ? null : goodsDonSku.getMjRelaxNum());
  265. }
  266. midjourneyUser.setAqType(groupsRelation.getAqType());
  267. try {
  268. midjourneyUserMapper.insert(midjourneyUser);
  269. } catch (DuplicateKeyException e) {
  270. }
  271. redisService.set(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + midjourneyUser.getId(), midjourneyUser.getMjFastNum(), RedisService.key.MIDJOURNEY_FAST_LIMIT.getTimeout());
  272. redisService.set(RedisService.key.MIDJOURNEY_USER.getName() + midjourneyUser.getUserToken(), midjourneyUser, RedisService.key.MIDJOURNEY_USER.getTimeout());
  273. if (midjourneyUser.getMjRelaxNum() != null) {
  274. redisService.set(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + midjourneyUser.getId(), midjourneyUser.getMjRelaxNum(), RedisService.key.MIDJOURNEY_RELAX_LIMIT.getTimeout());
  275. }
  276. return midjourneyUser;
  277. }
  278. private void updateMidjourneyUser(GroupsRelation groupsRelation, User user, MidjourneyUser midjourneyUser) {
  279. midjourneyUser.setName(user.getNickname());
  280. midjourneyUser.setImg(getWxImg(user.getHeadimgurl(), user));
  281. midjourneyUser.setExpireTime(groupsRelation.getExpiryTime());
  282. midjourneyUserMapper.updateById(midjourneyUser);
  283. midjourneyUser.setAqType(groupsRelation.getAqType());
  284. redisService.set(RedisService.key.MIDJOURNEY_USER.getName() + midjourneyUser.getUserToken(), midjourneyUser,RedisService.key.MIDJOURNEY_USER.getTimeout());
  285. }
  286. /**
  287. * 更换wx头像至oss
  288. */
  289. private String getWxImg(String headimgurl, User user) {
  290. if (headimgurl.contains("thirdwx.qlogo.cn")) {
  291. try {
  292. return uploadPic(headimgurl, "wxheadimg-" + user.getId());
  293. } catch (Exception ex) {
  294. log.error("上传微信头像错误!msg:{}", StringUtil.getErrorText(ex));
  295. return "./avatars.png";
  296. }
  297. } else {
  298. return user.getHeadimgurl();
  299. }
  300. }
  301. private static String uploadPic(String url, String prefix) throws IOException {
  302. byte[] body = HttpUtil.downloadBytes(url);
  303. Path tempFile = Files.createTempFile(prefix, ".jpeg");
  304. try (FileImageOutputStream imageOutput = new FileImageOutputStream(tempFile.toFile())) {
  305. imageOutput.write(body, 0, body.length);
  306. }
  307. Map<String, Object> paramMap = new HashMap<>();
  308. paramMap.put("file", tempFile.toFile());
  309. JSONObject result = JSONUtil.parseObj(HttpUtil.post("https://files.liuliangbang.vip/pic/ups", paramMap));
  310. return result.getJSONObject("value").getJSONArray("saved").getJSONObject(0).getJSONObject("info").getStr("cdnUrl");
  311. }
  312. }