用途介绍
是一个目前优秀的AI画图工具 , 不挂梯无法直接访问
本代码主要用于搭建镜像站使用
适合人群
本代码不适合新手 , 建议使用过、且具有二开能力的同学使用~
实现原理
通过调用发送信息接口发送请求 , 通过轮询房间消息接口判断是否作图完成
发送的时候带上我们存储好的信息即可
轮询房间消息接口是为了避免模拟网页实际的连接 , 那玩意解密没解出来...
准备
【Java调用Midjourney进行AI画图原生版抓包实现支持中文】1. 开通会员的账号
2. 新建很多房间(因为房间消息接口默认就50条数据 , 也就是说每个房间最多并行50个图片生成任务)
功能预览
![Java调用Midjourney进行AI画图原生版抓包实现支持中文](http://img.gansulong.com/230814/143649A30-0.jpg)
文章插图
上代码
代码功能:
1. 调用生成并将生成好的内容发送微信消息给用户(这个是在微信公众号平台做的 , 大家做网页版的话自己改下输出到网页就可以)
2. 进行合规性检测(生成点不得了的东西后果你懂得 , 这里用的是百度的文本审核服务 , 5万次以下免费)
3. 如果用户输入是中文 , 就翻译为英文再发送
表字段如下代码所示
需要使用通用哦~
package com.example.midjourney.bean.pojo;import lombok.Data;import tk.mybatis.mapper.annotation.NameStyle;import tk.mybatis.mapper.code.Style;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.Table;import java.util.Date;@Data@NameStyle(Style.camelhump)@Table(name = "midjourney_log")public class MidjourneyLog {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private Integer memberId;private String channel;private String prompt;private Integer type;private Integer status;private String imgFile;private Integer roomId;private String uuid;private Date createTime;}
请求唯一id没啥规律 , 一段时间内不一致就行 , 试了没啥校验
另外请求头除了需要保证和 、x-super-对应上 , 三者对应上实测2个月都不会掉线!
package com.example.midjourney.biz;import cn.hutool.core.img.ImgUtil;import cn.hutool.core.io.FileUtil;import com.alibaba.fastjson.JSON;import com.example.midjourney.bean.BaiduTextCensor;import com.example.midjourney.bean.BaiduTextCensorData;import com.example.midjourney.bean.MidMsg;import com.example.midjourney.bean.pojo.Discord;import com.example.midjourney.bean.pojo.MidjourneyLog;import com.example.midjourney.bean.pojo.RoomInfo;import com.example.midjourney.contant.Constant;import com.example.midjourney.enums.MedjourneyLogType;import com.example.midjourney.service.DiscordService;import com.example.midjourney.service.MidjourneyLogService;import com.example.midjourney.service.MemberService;import com.example.midjourney.service.RoomInfoService;import com.example.midjourney.util.*;import com.google.common.base.Joiner;import com.google.common.base.Splitter;import com.google.common.collect.Lists;import lombok.SneakyThrows;import lombok.extern.slf4j.Slf4j;import okhttp3.*;import org.apache.logging.log4j.util.Strings;import org.springframework.scheduling.annotation.Scheduled;import org.springframework.stereotype.Service;import javax.annotation.Resource;import javax.imageio.ImageIO;import java.awt.*;import java.awt.image.BufferedImage;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.math.BigDecimal;import java.net.InetSocketAddress;import java.net.Proxy;import java.util.List;import java.util.Objects;import java.util.Set;import java.util.UUID;import java.util.stream.Collectors;import static com.example.midjourney.contant.Constant.*;/*** 启动就运行 , 不停刷新消息列表*/@Slf4j@Servicepublic class MidJourneyBiz {private static BigDecimal bigDecimal = new BigDecimal("1099765990370980513").add(new BigDecimal(System.currentTimeMillis()));@Resourceprivate WeChatBiz weChatBiz;@Resourceprivate TranslateBiz translateBiz;@Resourceprivate MidjourneyLogService midjourneyLogService;@Resourceprivate MemberService memberService;@Resourceprivate RoomInfoService roomInfoService;@Resourceprivate DiscordService discordService;public void buildImg(Long id) {MidjourneyLog midjourneyLog = midjourneyLogService.findById(id);try {if (midjourneyLog.getStatus() != 0) {return;}if (isFailMsg(midjourneyLog.getChannel(), midjourneyLog)) {log.info("[失败提示] 消息校验不通过 log:{}", midjourneyLog);sendBuildFail(midjourneyLog);return;}String prompt = midjourneyLog.getPrompt();if (midjourneyLog.getType() == MedjourneyLogType.BIG_IMG.getCode()) {downImg(midjourneyLog);return;}BaiduTextCensor censor = null;if (TextUtil.isHaveChinese(prompt)) {censor = BaiduUtil.textCensor(prompt);}prompt = cleanMsg(prompt);if (isBlackWord(prompt)) {sendSensitive(midjourneyLog);return;}if (Objects.isNull(censor)) {censor = BaiduUtil.textCensor(prompt);}midjourneyLogService.updatePrompt(midjourneyLog, prompt);if (censor.getConclusionType() == 2 || censor.getConclusionType() == 3) {sendSensitive(midjourneyLog, censor);return;}if (midjourneyLog.getType() == MedjourneyLogType.ITERATIVE.getCode()) {//暂不支持sendBuildFail(midjourneyLog);return;}RoomInfo roomInfo = roomInfoService.findIdleRoom();if (Objects.isNull(roomInfo)) {log.error("[并发超出警报] 当前并发次数已经无法满足!!!");sendBuildFail(midjourneyLog);return;}if (sendMsg(prompt, roomInfo)) {midjourneyLogService.updateRoom(midjourneyLog, roomInfo);} else {log.error("[发送失败] 发送信息失败 , 请检查");sendBuildFail(midjourneyLog);}} catch (Throwable t) {sendBuildFail(midjourneyLog);}}@SneakyThrowsprivate void downImg(MidjourneyLog midjourneyLog) {MidjourneyLog lastLog = midjourneyLogService.findLastNormalLog(midjourneyLog.getMemberId());log.info("[下载图片] {}", lastLog);if (Objects.isNull(lastLog)) {log.info("[失败提示] 找不到上一次的图片 log:{}", midjourneyLog);sendBuildFail(midjourneyLog);return;}String imgFile = lastLog.getImgFile();File file = new File(imgFile);if (!file.exists()) {log.info("[失败提示] 上一次图片不存在 log:{}", lastLog);sendBuildFail(midjourneyLog);return;}cutAndSendImg(midjourneyLog, file);}private void cutAndSendImg(MidjourneyLog midjourneyLog, File oldFile) throws IOException {BufferedImage bufferedImage = ImageIO.read(new FileInputStream(oldFile));int width = bufferedImage.getWidth();int height = bufferedImage.getHeight();String msg = midjourneyLog.getPrompt().trim();String newFileName;if (msg.equalsIgnoreCase("u1")) {newFileName = oldFile.getPath() + "_u1.png";ImgUtil.cut(oldFile, FileUtil.file(newFileName),new Rectangle(0, 0, width / 2, height / 2));} else if (msg.equalsIgnoreCase("u2")) {newFileName = oldFile.getPath() + "_u2.png";ImgUtil.cut(oldFile, FileUtil.file(newFileName),new Rectangle(width / 2, 0, width / 2, height / 2));} else if (msg.equalsIgnoreCase("u3")) {newFileName = oldFile.getPath() + "_u3.png";ImgUtil.cut(oldFile, FileUtil.file(newFileName),new Rectangle(0, height / 2, width / 2, height / 2));} else if (msg.equalsIgnoreCase("u4")) {newFileName = oldFile.getPath() + "_u4.png";ImgUtil.cut(oldFile, FileUtil.file(newFileName),new Rectangle(width / 2, height / 2, width / 2, height / 2));} else {sendBuildFail(midjourneyLog);return;}String mediaId = weChatBiz.sendImg(newFileName, midjourneyLog.getChannel());log.info("[mediaId] {}", mediaId);if (Strings.isNotEmpty(mediaId)) {String wxId = memberService.selectWxidById(midjourneyLog.getMemberId());if (Strings.isEmpty(wxId)) {sendBuildFail(midjourneyLog);return;}midjourneyLogService.updateFinish(midjourneyLog);weChatBiz.sendImgMsg(wxId, mediaId, midjourneyLog.getChannel());}}private boolean isFailMsg(String channel, MidjourneyLog midjourneyLog) {return Objects.isNull(midjourneyLog) || Strings.isEmpty(midjourneyLog.getPrompt()) || Strings.isEmpty(channel)|| Objects.isNull(midjourneyLog.getMemberId()) || checkNotRunMsg(midjourneyLog);}public boolean checkNotRunMsg(MidjourneyLog midjourneyLog) {String prompt = midjourneyLog.getPrompt();if (midjourneyLog.getType() == MedjourneyLogType.BIG_IMG.getCode()) {return !(prompt.equalsIgnoreCase("u1") || prompt.equalsIgnoreCase("u2")|| prompt.equalsIgnoreCase("u3") || prompt.equalsIgnoreCase("u4"));} else if (midjourneyLog.getType() == MedjourneyLogType.ITERATIVE.getCode()) {return !(prompt.equalsIgnoreCase("v1") || prompt.equalsIgnoreCase("v2")|| prompt.equalsIgnoreCase("v3") || prompt.equalsIgnoreCase("v4"));} else {return false;}}private String cleanMsg(String msg) {msg = msg.replace("—", "--").replace("-- ", "--").replace("-- ", "--").replace("-- ", "--").replace(" , ", ",").replace("/", "").replace("--v", " --v ").replace("--niji", " --niji ").replace("--ar", " --ar ").replace("--aspect", " --ar ").replace("--chaos", " --chaos ").replace("--c", " --c ").replace("--no", " --no ").replace("--quality", " --quality ").replace("--q", " --q ").replace("--repeat", " --repeat ").replace("--s", " --s ").replace("--upbeta", " --upbeta ").trim();if (TextUtil.isHaveChinese(msg)) {msg = translateBiz.translate(msg);}msg = msg.replace(" , ", ",").replace("/", "").replace("--v5", " --v 5 ").replace("--niji5", " --niji 5 ").trim();if (!msg.contains("--niji") && !msg.contains("--v") && msg.length() > 3) {msg = msg + " --v 5";}return msg;}public void sendBuildFail(MidjourneyLog midjourneyLog) {String wxId = memberService.selectWxidById(midjourneyLog.getMemberId());CallBackUtil.failCallBack(midjourneyLog.getChannel(), MIDJOURNEY, midjourneyLog.getId());midjourneyLogService.updateFail(midjourneyLog);weChatBiz.sendTextMsg(wxId, "抱歉 , 您的消息【" + midjourneyLog.getPrompt() + "】处理失败 , 已为您退换对应电量",midjourneyLog.getChannel());}@Scheduled(cron = "34 * * * * ? ")public void checkImg() {//房间号清理cleanRoomNumber();//查询所有进行中的任务List
- 1 Python 扩展教程: 调用百度AI
- 【实战教学】用ChatGPT+Midjourney做绘本,太轻松啦!
- Midjourney进阶教程!7大方向快速生成合心意的AI人物形象
- 12步骤:Midjourney 注册流程教学账号手机验证攻略
- Java程序接入ChatGPT
- 只因太美,Midjourney生成画面可以做壁纸了
- Java实战之---旅行钓鱼游戏
- JDK和SDK的区别
- 其一 Java swing简易浏览器页面显示,超链接跳转与手动输入URL跳转
- idea 创建java web项目_使用IDEA创建javaweb项目