当前位置:   article > 正文

Java调用Midjourney进行AI画图原生版抓包实现支持中文_java对接midjourney

java对接midjourney

用途介绍

Midjourney是一个目前优秀的AI画图工具,不挂梯无法直接访问

本代码主要用于搭建镜像站使用

适合人群

本代码不适合新手,建议使用过okhttp、且具有二开能力的同学使用~

实现原理

通过调用发送信息接口发送请求,通过轮询房间消息接口判断是否作图完成

发送的时候带上我们存储好的cookie信息即可

轮询房间消息接口是为了避免模拟网页实际的websocket连接,那玩意解密没解出来...

准备

1. 开通Midjourney会员的Discord账号

2. 新建很多房间(因为房间消息接口默认就50条数据,也就是说每个房间最多并行50个图片生成任务)

功能预览

上代码

代码功能:

1. 调用Midjourney生成并将生成好的内容发送微信消息给用户(这个是在微信公众号平台做的,大家做网页版的话自己改下输出到网页就可以)

2. 进行合规性检测(生成点不得了的东西后果你懂得,这里用的是百度的文本审核服务,5万次以下免费)

3. 如果用户输入是中文,就翻译为英文再发送

midjourneyLog

midjourney_log表字段如下代码所示

需要使用通用mapper哦~

  1. package com.example.midjourney.bean.pojo;
  2. import lombok.Data;
  3. import tk.mybatis.mapper.annotation.NameStyle;
  4. import tk.mybatis.mapper.code.Style;
  5. import javax.persistence.GeneratedValue;
  6. import javax.persistence.GenerationType;
  7. import javax.persistence.Id;
  8. import javax.persistence.Table;
  9. import java.util.Date;
  10. @Data
  11. @NameStyle(Style.camelhump)
  12. @Table(name = "midjourney_log")
  13. public class MidjourneyLog {
  14. @Id
  15. @GeneratedValue(strategy = GenerationType.IDENTITY)
  16. private Long id;
  17. private Integer memberId;
  18. private String channel;
  19. private String prompt;
  20. private Integer type;
  21. private Integer status;
  22. private String imgFile;
  23. private Integer roomId;
  24. private String uuid;
  25. private Date createTime;
  26. }

MidJourneyBiz

请求唯一id没啥规律,一段时间内不一致就行,试了没啥校验

另外请求头除了cookie需要保证和 authorization、x-super-properties对应上,三者对应上实测2个月都不会掉线!

  1. package com.example.midjourney.biz;
  2. import cn.hutool.core.img.ImgUtil;
  3. import cn.hutool.core.io.FileUtil;
  4. import com.alibaba.fastjson.JSON;
  5. import com.example.midjourney.bean.BaiduTextCensor;
  6. import com.example.midjourney.bean.BaiduTextCensorData;
  7. import com.example.midjourney.bean.MidMsg;
  8. import com.example.midjourney.bean.pojo.Discord;
  9. import com.example.midjourney.bean.pojo.MidjourneyLog;
  10. import com.example.midjourney.bean.pojo.RoomInfo;
  11. import com.example.midjourney.contant.Constant;
  12. import com.example.midjourney.enums.MedjourneyLogType;
  13. import com.example.midjourney.service.DiscordService;
  14. import com.example.midjourney.service.MidjourneyLogService;
  15. import com.example.midjourney.service.MemberService;
  16. import com.example.midjourney.service.RoomInfoService;
  17. import com.example.midjourney.util.*;
  18. import com.google.common.base.Joiner;
  19. import com.google.common.base.Splitter;
  20. import com.google.common.collect.Lists;
  21. import lombok.SneakyThrows;
  22. import lombok.extern.slf4j.Slf4j;
  23. import okhttp3.*;
  24. import org.apache.logging.log4j.util.Strings;
  25. import org.springframework.scheduling.annotation.Scheduled;
  26. import org.springframework.stereotype.Service;
  27. import javax.annotation.Resource;
  28. import javax.imageio.ImageIO;
  29. import java.awt.*;
  30. import java.awt.image.BufferedImage;
  31. import java.io.File;
  32. import java.io.FileInputStream;
  33. import java.io.IOException;
  34. import java.math.BigDecimal;
  35. import java.net.InetSocketAddress;
  36. import java.net.Proxy;
  37. import java.util.List;
  38. import java.util.Objects;
  39. import java.util.Set;
  40. import java.util.UUID;
  41. import java.util.stream.Collectors;
  42. import static com.example.midjourney.contant.Constant.*;
  43. /**
  44. * 启动就运行,不停刷新消息列表
  45. */
  46. @Slf4j
  47. @Service
  48. public class MidJourneyBiz {
  49. private static BigDecimal bigDecimal = new BigDecimal("1099765990370980513")
  50. .add(new BigDecimal(System.currentTimeMillis()));
  51. @Resource
  52. private WeChatBiz weChatBiz;
  53. @Resource
  54. private TranslateBiz translateBiz;
  55. @Resource
  56. private MidjourneyLogService midjourneyLogService;
  57. @Resource
  58. private MemberService memberService;
  59. @Resource
  60. private RoomInfoService roomInfoService;
  61. @Resource
  62. private DiscordService discordService;
  63. public void buildImg(Long id) {
  64. MidjourneyLog midjourneyLog = midjourneyLogService.findById(id);
  65. try {
  66. if (midjourneyLog.getStatus() != 0) {
  67. return;
  68. }
  69. if (isFailMsg(midjourneyLog.getChannel(), midjourneyLog)) {
  70. log.info("[失败提示] 消息校验不通过 log:{}", midjourneyLog);
  71. sendBuildFail(midjourneyLog);
  72. return;
  73. }
  74. String prompt = midjourneyLog.getPrompt();
  75. if (midjourneyLog.getType() == MedjourneyLogType.BIG_IMG.getCode()) {
  76. downImg(midjourneyLog);
  77. return;
  78. }
  79. BaiduTextCensor censor = null;
  80. if (TextUtil.isHaveChinese(prompt)) {
  81. censor = BaiduUtil.textCensor(prompt);
  82. }
  83. prompt = cleanMsg(prompt);
  84. if (isBlackWord(prompt)) {
  85. sendSensitive(midjourneyLog);
  86. return;
  87. }
  88. if (Objects.isNull(censor)) {
  89. censor = BaiduUtil.textCensor(prompt);
  90. }
  91. midjourneyLogService.updatePrompt(midjourneyLog, prompt);
  92. if (censor.getConclusionType() == 2 || censor.getConclusionType() == 3) {
  93. sendSensitive(midjourneyLog, censor);
  94. return;
  95. }
  96. if (midjourneyLog.getType() == MedjourneyLogType.ITERATIVE.getCode()) {
  97. //暂不支持
  98. sendBuildFail(midjourneyLog);
  99. return;
  100. }
  101. RoomInfo roomInfo = roomInfoService.findIdleRoom();
  102. if (Objects.isNull(roomInfo)) {
  103. log.error("[并发超出警报] 当前并发次数已经无法满足!!!");
  104. sendBuildFail(midjourneyLog);
  105. return;
  106. }
  107. if (sendMsg(prompt, roomInfo)) {
  108. midjourneyLogService.updateRoom(midjourneyLog, roomInfo);
  109. } else {
  110. log.error("[发送失败] 发送信息失败,请检查");
  111. sendBuildFail(midjourneyLog);
  112. }
  113. } catch (Throwable t) {
  114. sendBuildFail(midjourneyLog);
  115. }
  116. }
  117. @SneakyThrows
  118. private void downImg(MidjourneyLog midjourneyLog) {
  119. MidjourneyLog lastLog = midjourneyLogService.findLastNormalLog(midjourneyLog.getMemberId());
  120. log.info("[下载图片] {}", lastLog);
  121. if (Objects.isNull(lastLog)) {
  122. log.info("[失败提示] 找不到上一次的图片 log:{}", midjourneyLog);
  123. sendBuildFail(midjourneyLog);
  124. return;
  125. }
  126. String imgFile = lastLog.getImgFile();
  127. File file = new File(imgFile);
  128. if (!file.exists()) {
  129. log.info("[失败提示] 上一次图片不存在 log:{}", lastLog);
  130. sendBuildFail(midjourneyLog);
  131. return;
  132. }
  133. cutAndSendImg(midjourneyLog, file);
  134. }
  135. private void cutAndSendImg(MidjourneyLog midjourneyLog, File oldFile) throws IOException {
  136. BufferedImage bufferedImage = ImageIO.read(new FileInputStream(oldFile));
  137. int width = bufferedImage.getWidth();
  138. int height = bufferedImage.getHeight();
  139. String msg = midjourneyLog.getPrompt().trim();
  140. String newFileName;
  141. if (msg.equalsIgnoreCase("u1")) {
  142. newFileName = oldFile.getPath() + "_u1.png";
  143. ImgUtil.cut(oldFile, FileUtil.file(newFileName),
  144. new Rectangle(0, 0, width / 2, height / 2)
  145. );
  146. } else if (msg.equalsIgnoreCase("u2")) {
  147. newFileName = oldFile.getPath() + "_u2.png";
  148. ImgUtil.cut(oldFile, FileUtil.file(newFileName),
  149. new Rectangle(width / 2, 0, width / 2, height / 2)
  150. );
  151. } else if (msg.equalsIgnoreCase("u3")) {
  152. newFileName = oldFile.getPath() + "_u3.png";
  153. ImgUtil.cut(oldFile, FileUtil.file(newFileName),
  154. new Rectangle(0, height / 2, width / 2, height / 2)
  155. );
  156. } else if (msg.equalsIgnoreCase("u4")) {
  157. newFileName = oldFile.getPath() + "_u4.png";
  158. ImgUtil.cut(oldFile, FileUtil.file(newFileName),
  159. new Rectangle(width / 2, height / 2, width / 2, height / 2)
  160. );
  161. } else {
  162. sendBuildFail(midjourneyLog);
  163. return;
  164. }
  165. String mediaId = weChatBiz.sendImg(newFileName, midjourneyLog.getChannel());
  166. log.info("[mediaId] {}", mediaId);
  167. if (Strings.isNotEmpty(mediaId)) {
  168. String wxId = memberService.selectWxidById(midjourneyLog.getMemberId());
  169. if (Strings.isEmpty(wxId)) {
  170. sendBuildFail(midjourneyLog);
  171. return;
  172. }
  173. midjourneyLogService.updateFinish(midjourneyLog);
  174. weChatBiz.sendImgMsg(wxId, mediaId, midjourneyLog.getChannel());
  175. }
  176. }
  177. private boolean isFailMsg(String channel, MidjourneyLog midjourneyLog) {
  178. return Objects.isNull(midjourneyLog) || Strings.isEmpty(midjourneyLog.getPrompt()) || Strings.isEmpty(channel)
  179. || Objects.isNull(midjourneyLog.getMemberId()) || checkNotRunMsg(midjourneyLog);
  180. }
  181. public boolean checkNotRunMsg(MidjourneyLog midjourneyLog) {
  182. String prompt = midjourneyLog.getPrompt();
  183. if (midjourneyLog.getType() == MedjourneyLogType.BIG_IMG.getCode()) {
  184. return !(prompt.equalsIgnoreCase("u1") || prompt.equalsIgnoreCase("u2")
  185. || prompt.equalsIgnoreCase("u3") || prompt.equalsIgnoreCase("u4"));
  186. } else if (midjourneyLog.getType() == MedjourneyLogType.ITERATIVE.getCode()) {
  187. return !(prompt.equalsIgnoreCase("v1") || prompt.equalsIgnoreCase("v2")
  188. || prompt.equalsIgnoreCase("v3") || prompt.equalsIgnoreCase("v4"));
  189. } else {
  190. return false;
  191. }
  192. }
  193. private String cleanMsg(String msg) {
  194. msg = msg.replace("—", "--")
  195. .replace("-- ", "--")
  196. .replace("-- ", "--")
  197. .replace("-- ", "--")
  198. .replace(",", ",")
  199. .replace("/", "")
  200. .replace("--v", " --v ")
  201. .replace("--niji", " --niji ")
  202. .replace("--ar", " --ar ")
  203. .replace("--aspect", " --ar ")
  204. .replace("--chaos", " --chaos ")
  205. .replace("--c", " --c ")
  206. .replace("--no", " --no ")
  207. .replace("--quality", " --quality ")
  208. .replace("--q", " --q ")
  209. .replace("--repeat", " --repeat ")
  210. .replace("--s", " --s ")
  211. .replace("--upbeta", " --upbeta ")
  212. .trim();
  213. if (TextUtil.isHaveChinese(msg)) {
  214. msg = translateBiz.translate(msg);
  215. }
  216. msg = msg.replace(",", ",")
  217. .replace("/", "")
  218. .replace("--v5", " --v 5 ")
  219. .replace("--niji5", " --niji 5 ")
  220. .trim();
  221. if (!msg.contains("--niji") && !msg.contains("--v") && msg.length() > 3) {
  222. msg = msg + " --v 5";
  223. }
  224. return msg;
  225. }
  226. public void sendBuildFail(MidjourneyLog midjourneyLog) {
  227. String wxId = memberService.selectWxidById(midjourneyLog.getMemberId());
  228. CallBackUtil.failCallBack(midjourneyLog.getChannel(), MIDJOURNEY, midjourneyLog.getId());
  229. midjourneyLogService.updateFail(midjourneyLog);
  230. weChatBiz.sendTextMsg(wxId, "抱歉,您的消息【" + midjourneyLog.getPrompt() + "】处理失败,已为您退换对应电量",
  231. midjourneyLog.getChannel());
  232. }
  233. @Scheduled(cron = "34 * * * * ? ")
  234. public void checkImg() {
  235. //房间号清理
  236. cleanRoomNumber();
  237. //查询所有进行中的任务
  238. List<MidjourneyLog> logs = midjourneyLogService.selectAllDoing().stream()
  239. .filter(log -> Objects.nonNull(log.getRoomId())).collect(Collectors.toList());
  240. //找到超时任务进行关闭
  241. List<MidjourneyLog> failLogs = logs.stream()
  242. .filter(log -> System.currentTimeMillis() - log.getCreateTime().getTime() > MAX_WAIT_TIME)
  243. .collect(Collectors.toList());
  244. failLogs.forEach(this::sendBuildFail);
  245. //剩余任务整理出来房间号
  246. logs.removeAll(failLogs);
  247. Set<Integer> roomSet = logs.stream().map(MidjourneyLog::getRoomId).collect(Collectors.toSet());
  248. //轮询当前进度
  249. for (Integer roomId : roomSet) {
  250. RoomInfo roomInfo = roomInfoService.findById(roomId);
  251. if (Objects.isNull(roomInfo)) {
  252. log.error("[room没找到] roomId:{} 没找到对应房间,看一下是不是挂了", roomId);
  253. continue;
  254. }
  255. Discord discord = discordService.findById(roomInfo.getDiscordId());
  256. List<MidMsg> midMsgs = readNowList(roomInfo, discord);
  257. log.info("[消息列表] {}", midMsgs);
  258. checkAndSendMsg(midMsgs, logs, roomInfo);
  259. }
  260. }
  261. private void cleanRoomNumber() {
  262. List<RoomInfo> roomInfos = roomInfoService.findAll();
  263. for (RoomInfo roomInfo : roomInfos) {
  264. int count = midjourneyLogService.selectRoomOnUse(roomInfo.getId());
  265. roomInfo.setNowNumber(count);
  266. roomInfoService.update(roomInfo);
  267. }
  268. }
  269. private void checkAndSendMsg(List<MidMsg> midMsgs, List<MidjourneyLog> logs, RoomInfo roomInfo) {
  270. List<MidjourneyLog> roomLogs = logs.stream()
  271. .filter(log -> log.getRoomId().equals(roomInfo.getId()))
  272. .collect(Collectors.toList());
  273. midMsgs.stream()
  274. .filter(this::isPrintOk)
  275. .forEach(m -> roomLogs.forEach(midjourey -> {
  276. if (m.getContent().startsWith(MID_JOURNEY_HEAD + filterHead(midjourey.getPrompt()))) {
  277. log.info("[Midjourney 配对] msg:{} key:{}", m, midjourey.getPrompt());
  278. String wxid = memberService.selectWxidById(midjourey.getMemberId());
  279. String url = m.getAttachments().get(0).getUrl();
  280. String localPath = Constant.FILE_PATH + UUID.randomUUID() + "." + FileUtil.getSuffix(url);
  281. ImgDownUtil.getImage(url.replace("https://", "http://"), localPath);
  282. localPath = localPath.replace("\\", "/");
  283. if ("webp".equals(FileUtil.getSuffix(localPath))) {
  284. com.example.midjourney.util.ImgUtil.webpToPng(localPath, localPath + ".png");
  285. localPath = localPath + ".png";
  286. }
  287. String mediaId = weChatBiz.sendImg(localPath, midjourey.getChannel());
  288. log.info("[mediaId] {}", mediaId);
  289. if (Strings.isNotEmpty(mediaId)) {
  290. weChatBiz.sendImgMsg(wxid, mediaId, midjourey.getChannel());
  291. weChatBiz.sendTextMsg(wxid, "下载高清大图口令:\n\n☆左上图回复:U1\n\n☆右上图回复:U2" +
  292. "\n\n☆左下图回复:U3\n\n☆右下图回复:U4\n\n下载大图也会扣电量哦~", midjourey.getChannel());
  293. midjourey.setImgFile(localPath);
  294. midjourneyLogService.updateFinish(midjourey);
  295. }
  296. }
  297. }));
  298. }
  299. private String filterHead(String prompt) {
  300. return Lists.newArrayList(Splitter.on("--").split(prompt)).stream().findFirst().orElse("").trim();
  301. }
  302. private boolean isPrintOk(MidMsg midMsg) {
  303. if (Objects.isNull(midMsg)
  304. || Strings.isEmpty(midMsg.getContent())
  305. || !midMsg.getContent().contains(MID_FIND_LEFT)) {
  306. return false;
  307. }
  308. String str = midMsg.getContent().substring(midMsg.getContent().indexOf(MID_FIND_LEFT));
  309. return !str.contains("%") && !str.contains("Waiting");
  310. }
  311. private boolean isBlackWord(String msg) {
  312. msg = msg.toLowerCase();
  313. for (String s : Constant.MidjourneyBlackWord) {
  314. if (msg.contains(s.toLowerCase())) {
  315. return true;
  316. }
  317. }
  318. return false;
  319. }
  320. private void sendSensitive(MidjourneyLog midjourneyLog) {
  321. String wxid = memberService.selectWxidById(midjourneyLog.getMemberId());
  322. midjourneyLogService.updateSensitive(midjourneyLog);
  323. weChatBiz.sendTextMsg(wxid, "【违规提示】输入内容包含违禁词,依法进行屏蔽。", midjourneyLog.getChannel());
  324. }
  325. /**
  326. * 审核不通过通知用户
  327. */
  328. private void sendSensitive(MidjourneyLog midjourneyLog, BaiduTextCensor censor) {
  329. String reason = Joiner.on("、")
  330. .join(Safes.of(censor.getData()).stream()
  331. .map(BaiduTextCensorData::getMsg)
  332. .collect(Collectors.toList()));
  333. reason = Strings.isEmpty(reason) ? "包含敏感信息" : reason;
  334. String fullText = "【违规提示】输入内容因 " + reason + " ,依法进行屏蔽。(百度提供审核能力)";
  335. String wxid = memberService.selectWxidById(midjourneyLog.getMemberId());
  336. midjourneyLogService.updateSensitive(midjourneyLog);
  337. weChatBiz.sendTextMsg(wxid, fullText, midjourneyLog.getChannel());
  338. }
  339. public List<MidMsg> readNowList(RoomInfo roomInfo, Discord discord) {
  340. OkHttpClient client = new OkHttpClient().newBuilder()
  341. .build();
  342. Request request = new Request.Builder()
  343. .url("https://discord.com/api/v9/channels/" + roomInfo.getDiscordChannelId() + "/messages?limit=50")
  344. .get()
  345. .addHeader("authority", "discord.com")
  346. .addHeader("accept", "*/*")
  347. .addHeader("accept-language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6")
  348. .addHeader("authorization", discord.getAuthorization())
  349. .addHeader("cache-control", "no-cache")
  350. .addHeader("cookie", discord.getCookie())
  351. .addHeader("pragma", "no-cache")
  352. .addHeader("referer", "https://discord.com/channels/" + roomInfo.getDiscordGuildId() +
  353. "/" + roomInfo.getDiscordChannelId())
  354. .addHeader("sec-ch-ua", "\"Not_A Brand\";v=\"99\", \"Microsoft Edge\";v=\"109\", \"Chromium\";v=\"109\"")
  355. .addHeader("sec-ch-ua-mobile", "?0")
  356. .addHeader("sec-ch-ua-platform", "\"Windows\"")
  357. .addHeader("sec-fetch-dest", "empty")
  358. .addHeader("sec-fetch-mode", "cors")
  359. .addHeader("sec-fetch-site", "same-origin")
  360. .addHeader("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/109.0.1518.70")
  361. .addHeader("x-debug-options", "bugReporterEnabled")
  362. .addHeader("x-discord-locale", "zh-CN")
  363. .addHeader("x-super-properties", discord.getSuperProperties())
  364. .build();
  365. try {
  366. Response response = client.newCall(request).execute();
  367. String string = Objects.requireNonNull(response.body()).string();
  368. response.close();
  369. return JSON.parseArray(string, MidMsg.class);
  370. } catch (Throwable t) {
  371. log.error("[发生意外 读取消息失败] room: {}", roomInfo);
  372. }
  373. return Lists.newArrayList();
  374. }
  375. @SneakyThrows
  376. public boolean sendMsg(String msg, RoomInfo roomInfo) {
  377. Discord discord = discordService.findById(roomInfo.getDiscordId());
  378. bigDecimal = bigDecimal.add(new BigDecimal(1000));
  379. OkHttpClient client = new OkHttpClient().newBuilder()
  380. .build();
  381. RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
  382. .addFormDataPart("payload_json", "{\"type\":2,\"application_id\":\"936929561302675456\"," +
  383. "\"guild_id\":\"" + roomInfo.getDiscordGuildId() + "\"," +
  384. "\"channel_id\":\"" + roomInfo.getDiscordChannelId() + "\"," +
  385. "\"session_id\":\"" + discord.getSessionId() + "\"," +
  386. "\"data\":{\"version\":\"1077969938624553050\"," +
  387. "\"id\":\"938956540159881230\"," +
  388. "\"name\":\"imagine\"," +
  389. "\"type\":1,\"options\":[" +
  390. "{\"type\":3,\"name\":\"prompt\"," +
  391. "\"value\":\"" + TextUtil.cleanString(msg) + "\"}]," +
  392. "\"application_command\":" +
  393. "{\"id\":\"938956540159881230\",\"application_id\":\"936929561302675456\",\"version\":" +
  394. "\"1077969938624553050\",\"default_member_permissions\":null,\"type\":1,\"nsfw\":false," +
  395. "\"name\":\"imagine\",\"description\":\"Create images with Midjourney\",\"dm_permission\":true," +
  396. "\"contexts\":null,\"options\":[{\"type\":3,\"name\":\"prompt\"," +
  397. "\"description\":\"The prompt to imagine\",\"required\":true}]}," +
  398. "\"attachments\":[]},\"nonce\":\"" + bigDecimal.toString() + "\"} ")
  399. .build();
  400. Request request = new Request.Builder()
  401. .url("https://discord.com/api/v9/interactions")
  402. .method("POST", body)
  403. .addHeader("authority", "discord.com")
  404. .addHeader("accept", "*/*")
  405. .addHeader("accept-language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6")
  406. .addHeader("authorization", discord.getAuthorization())
  407. .addHeader("cache-control", "no-cache")
  408. .addHeader("cookie", discord.getCookie())
  409. .addHeader("origin", "https://discord.com")
  410. .addHeader("pragma", "no-cache")
  411. .addHeader("referer", "https://discord.com/channels/" + roomInfo.getDiscordGuildId() +
  412. "/" + roomInfo.getDiscordChannelId())
  413. .addHeader("sec-ch-ua", "\"Not_A Brand\";v=\"99\", \"Microsoft Edge\";v=\"109\", \"Chromium\";v=\"109\"")
  414. .addHeader("sec-ch-ua-mobile", "?0")
  415. .addHeader("sec-ch-ua-platform", "\"Windows\"")
  416. .addHeader("sec-fetch-dest", "empty")
  417. .addHeader("sec-fetch-mode", "cors")
  418. .addHeader("sec-fetch-site", "same-origin")
  419. .addHeader("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/109.0.1518.70")
  420. .addHeader("x-debug-options", "bugReporterEnabled")
  421. .addHeader("x-discord-locale", "zh-CN")
  422. .addHeader("x-super-properties", discord.getSuperProperties())
  423. .build();
  424. Response response = client.newCall(request).execute();
  425. if (response.code() == 204) {
  426. roomInfoService.addOnce(roomInfo);
  427. response.close();
  428. return true;
  429. }
  430. response.close();
  431. log.info("[midjourney发消息失败] {}", response.code());
  432. return false;
  433. }
  434. }

MidjourneyLogService

  1. package com.example.midjourney.service;
  2. import com.example.midjourney.bean.pojo.MidjourneyLog;
  3. import com.example.midjourney.bean.pojo.RoomInfo;
  4. import java.util.List;
  5. public interface MidjourneyLogService {
  6. MidjourneyLog findById(Long id);
  7. MidjourneyLog findLastNormalLog(Integer memberId);
  8. MidjourneyLog findLastNormalOrIterative(Integer memberId);
  9. void updateRoom(MidjourneyLog midjourneyLog, RoomInfo roomInfo);
  10. List<MidjourneyLog> selectAllDoing();
  11. void updateFail(MidjourneyLog midjourneyLog);
  12. void updateSensitive(MidjourneyLog midjourneyLog);
  13. void updatePrompt(MidjourneyLog midjourneyLog, String prompt);
  14. void updateFinish(MidjourneyLog midjourey);
  15. int selectRoomOnUse(Integer id);
  16. }

MidjourneyLogServiceImpl

  1. package com.example.midjourney.service.impl;
  2. import com.example.midjourney.bean.pojo.MidjourneyLog;
  3. import com.example.midjourney.bean.pojo.RoomInfo;
  4. import com.example.midjourney.mapper.MidjourneyLogMapper;
  5. import com.example.midjourney.service.MidjourneyLogService;
  6. import com.example.midjourney.util.Safes;
  7. import org.springframework.stereotype.Service;
  8. import javax.annotation.Resource;
  9. import java.util.List;
  10. @Service
  11. public class MidjourneyLogServiceImpl implements MidjourneyLogService {
  12. @Resource
  13. private MidjourneyLogMapper midjourneyLogMapper;
  14. @Override
  15. public MidjourneyLog findById(Long id) {
  16. return midjourneyLogMapper.selectByPrimaryKey(id);
  17. }
  18. @Override
  19. public MidjourneyLog findLastNormalLog(Integer memberId) {
  20. return midjourneyLogMapper.findLastNormalLog(memberId);
  21. }
  22. @Override
  23. public MidjourneyLog findLastNormalOrIterative(Integer memberId) {
  24. return midjourneyLogMapper.findLastNormalOrIterative(memberId);
  25. }
  26. @Override
  27. public void updateRoom(MidjourneyLog midjourneyLog, RoomInfo roomInfo) {
  28. midjourneyLog.setRoomId(roomInfo.getId());
  29. midjourneyLogMapper.updateByPrimaryKeySelective(midjourneyLog);
  30. }
  31. @Override
  32. public List<MidjourneyLog> selectAllDoing() {
  33. MidjourneyLog midjourneyLog = new MidjourneyLog();
  34. midjourneyLog.setStatus(0);
  35. return Safes.of(midjourneyLogMapper.select(midjourneyLog));
  36. }
  37. @Override
  38. public void updateFail(MidjourneyLog midjourneyLog) {
  39. midjourneyLog.setStatus(500);
  40. midjourneyLogMapper.updateByPrimaryKeySelective(midjourneyLog);
  41. }
  42. @Override
  43. public void updateSensitive(MidjourneyLog midjourneyLog) {
  44. midjourneyLog.setStatus(-1);
  45. midjourneyLogMapper.updateByPrimaryKeySelective(midjourneyLog);
  46. }
  47. @Override
  48. public void updatePrompt(MidjourneyLog midjourneyLog, String prompt) {
  49. midjourneyLog.setPrompt(prompt);
  50. midjourneyLogMapper.updateByPrimaryKeySelective(midjourneyLog);
  51. }
  52. @Override
  53. public void updateFinish(MidjourneyLog midjourey) {
  54. midjourey.setStatus(1);
  55. midjourneyLogMapper.updateByPrimaryKeySelective(midjourey);
  56. }
  57. @Override
  58. public int selectRoomOnUse(Integer id) {
  59. return midjourneyLogMapper.selectRoomOnUse(id);
  60. }
  61. }

MidjourneyLogMapper 

这里用了通用mapper插件

  1. package com.example.midjourney.mapper;
  2. import com.example.midjourney.bean.pojo.MidjourneyLog;
  3. import org.apache.ibatis.annotations.Param;
  4. import org.apache.ibatis.annotations.Select;
  5. import tk.mybatis.mapper.common.Mapper;
  6. public interface MidjourneyLogMapper extends Mapper<MidjourneyLog> {
  7. String COLUMN = " id, member_id AS memberId, prompt, channel, type, " +
  8. "status, img_file AS imgFile, room_id AS roomId ";
  9. @Select("SELECT " + COLUMN + " FROM midjourney_log WHERE member_id = #{memberId} AND type = 0 ORDER BY id DESC LIMIT 1")
  10. MidjourneyLog findLastNormalLog(@Param("memberId") Integer memberId);
  11. @Select("SELECT " + COLUMN + " FROM midjourney_log WHERE member_id = #{memberId} AND (type = 0 OR type = 2)" +
  12. " ORDER BY id DESC LIMIT 1")
  13. MidjourneyLog findLastNormalOrIterative(Integer memberId);
  14. @Select("SELECT COUNT(*) AS count FROM midjourney_log WHERE room_id = #{id} AND status = 0")
  15. Integer selectRoomOnUse(@Param("id") Integer id);
  16. }

Constant

常量类可以根据需要自定调整敏感词

敏感词写上审核不过,大家自己想想脑补下吧,各种不好的词都往那个敏感词List里面自己加吧!

  1. package com.example.midjourney.contant;
  2. import com.example.midjourney.bean.UserInfo;
  3. import com.example.midjourney.biz.WeChatBiz;
  4. import com.example.midjourney.util.BaiduUtil;
  5. import com.google.common.collect.Lists;
  6. import com.google.common.collect.Maps;
  7. import java.util.List;
  8. import java.util.Map;
  9. import java.util.concurrent.ExecutorService;
  10. import java.util.concurrent.Executors;
  11. public class Constant {
  12. public static ExecutorService threadPool = Executors.newFixedThreadPool(20);
  13. public static Map<String, UserInfo> imgWordUserMap = Maps.newConcurrentMap();
  14. public static String MID_JOURNEY_HEAD = "**";
  15. public static String MID_FIND_LEFT = "** - <";
  16. public static String FILE_PATH = "D:\\000img\\";
  17. public static String CHATGPT = "chatgpt";
  18. public static String MIDJOURNEY = "midjourney";
  19. public static final String INSUFFICIENT = "insufficient_quota";
  20. public static Map<String, String> WX_TOKEN_CHANNEL = Maps.newHashMap();
  21. public static Map<String, String> WX_TOKEN_MAP = Maps.newHashMap();
  22. public static String BAIDU_TOKEN = BaiduUtil.queryBaiduToken();
  23. public static Map<String, String> CHANNEL_CALL_BACK = Maps.newHashMap();
  24. /**
  25. * 最大等待时间15分钟
  26. */
  27. public static long MAX_WAIT_TIME = 1000 * 60 * 15;
  28. public static List<String> MidjourneyBlackWord = Lists.newArrayList("写了审核不过,大家自己发挥想象吧...");
  29. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/272207
推荐阅读
相关标签
  

闽ICP备14008679号