⤴️如何使用 Nest.js 构建 Midjourney API🚀

2025-06-04

⤴️如何使用 Nest.js 构建 Midjourney API🚀

TL;DR

在这篇文章中,我将向您展示使用 Typescript 和 Nest.js 构建非官方 Midjourney API 的架构。

我们走吧


DeepEval——LLM 应用程序的开源评估框架

DeepEval 根据事实一致性、准确性、答案相关性等指标来评估性能

我们才刚刚起步。
能帮我们加个星吗?😽

https://github.com/confident-ai/deepeval

Github 星标


➡️ 请点赞、关注并加星标这篇文章

我们要建造什么?

首先,让我们了解一下 Mindjourney 在 Discord 上的工作原理。人们使用简单的命令与人工智能机器人对话。机器人会接收这些命令,并根据用户的描述创建图片。

为了模拟这种行为,我们需要创建一个与 Discord 机器人交互的 API。该机器人能够与 Discord 交互,从而向 Midjourney 发送命令。命令流的高级设计如下:

旅途中的建筑

重要提示:本教程仅用于教育目的,旨在帮助您了解 Discord 与 Midjourney 的交互方式。不建议将其用作生产服务或任何官方项目。

我选择 Nest.js 的原因是,市面上有很多 Python 示例教你如何为 Midjourney 构建 API,但却没有一个像样的案例能完整地展示如何使用 JavaScript 或 Node.js 完成整个流程。我更喜欢使用 Nest.js,因为它的组织结构清晰,并且易于引导项目启动。

连接 Midjourney 的 Discord 机器人

由于缺乏正式的 API,可以通过 Discord 机器人连接到 Midjourney。该过程包括以下步骤。

重要提示:为了使此功能正常工作,您必须拥有 Midjourney 订阅。


步骤 1:创建 Discord 机器人。

请花点时间帮我一下。我正在努力打造最好的LLM评估开源项目。

请给我一颗星 - 我会非常感激。

🌟 GitHub 上的 DeepEval

构建完整的 Midjourney API 的第一步是创建我们的 Discord 机器人。Discord 提供了一个界面,可用于创建不同用途的机器人。现在就创建你的 MJ 机器人吧

Discord 机器人配置

这是一篇关于创建 Discord 机器人的很棒的文章。

创建机器人后,您将收到一个邀请链接。使用它来邀请机器人加入您的 Discord 服务器——稍后我们将使用它来生成和接收图像。


步骤 2:执行 /Imagine 命令

创建Nest.js应用后,请继续创建discord模块。该模块将与我们的 Discord 服务器和 MidJourney 进行交互。

让我们从我们的控制器开始,它应该看起来像这样:

@Controller('discord')
export class DiscordController {
  constructor(private discordService: DiscordService) {}

  @Post('imagine')
  async imagine(@Body('prompt') prompt: string): Promise<any> {
    return this.discordService.sendImagineCommand(prompt);
  }
}
Enter fullscreen mode Exit fullscreen mode

如你所见,我创建了一个包含单个POST请求的 Discord 模块。我们将向请求传递一个prompt参数discord/imagine

接下来,让我们创建我们的 discord 服务:

@Injectable()
export class DiscordService {

constructor(private readonly httpService: HttpService) {}


  async sendImagineCommand(prompt: string): Promise<any> {
    const postUrl = "https://discord.com/api/v9/interactions";
    const uniqueId = this.generateId();

    const postPayload = {
      type: 2,
      application_id: <APPLICATION_ID>,
      guild_id: <GUILD_ID>,
      channel_id: <CHANNEL_ID>,
      session_id: <SESSION_ID>,
      data: {
        version: <COMMAND_VERSION>,
        id: <IMAGINE_COMMAND_ID>,
        name: "imagine",
        type: 1,
        options: [
          {
            type: 3,
            name: "prompt",
            value: `${prompt} --no ${uniqueId}`
          }
        ],
        application_command: {
          id: <IMAGINE_COMMAND_ID>,
          application_id: <APPLICATION_ID>,
          version: <COMMAND_VERSION>,
          default_member_permissions: null,
          type: 1,
          nsfw: false,
          name: "imagine",
          description: "Create images with Midjourney",
          dm_permission: true,
          contexts: [0, 1, 2],
          options: [
            {
              type: 3,
              name: "prompt",
              description: "The prompt to imagine",
              required: true
            }
          ]
        },
        attachments: []
      }
    };


    const postHeaders = {
      authorization: <your auth token>,
      "Content-Type": "application/json"
    };

    this.httpService
      .post(postUrl, postPayload, { headers: postHeaders })
      .toPromise()
      .then(console.log);


    return uniqueId;
  }


  generateId(): number {
    return Math.floor(Math.random() * 1000);
  }
}
Enter fullscreen mode Exit fullscreen mode

您会注意到以下几点:

  • 我们使用https://discord.com/api/v9/interactionsDiscord 端点与 Discord 服务器交互并发送命令。这是处理 Midjourney 请求的主要入口点。

  • 我们模拟了网页浏览器向 Discord 发出的请求,真正的“魔法”来了——/imagine登录 Midjourney 网页后,从 Discord 网页界面向 Midjourney 发送命令。
    发送请求后,您会注意到Networktab 中也发送了 imagine 命令,这与上面的非常相似。

  • 复制相关字段:IMAGINE_COMMAND_ID、、、。这些字段将在我们的服务中使用。我们还需要复制作为请求一部分发送的字段COMMAND_VERSIONSESSION_IDGUILD_IDCHANNEL_IDAPPLICATION_IDMIDJOURNEY_TOKEN

  • 从我们之前创建的机器人应用程序页面复制BOT_TOKEN。这对于与我们的机器人进行通信非常重要。

  • 您还会注意到uniqueId我们使用generateId()函数生成的。这是使用 Midjourney 的--no命令,以便我们稍后可以追溯发送到 Discord 的唯一请求并获取生成的图像。

完成此步骤后,您现在可以使用/imagine命令调用 Discord 并使用 Midjourney 生成图像。

提醒:这只是一篇描述此流程如何工作的技术文章,不建议用于任何项目。


步骤 3:获取生成的图像。

让我们创建一个新的控制器来获取图像:

@Get('mj/results/:id')
  async getMidjourneyResults(@Param('id') id: string) {
    const image = await this.discordService.getResultFromMidjourney(id);
    const attachmentUrl = get(image[0].attachments[0], 'url');

    if (attachmentUrl) {
      const urls = await this.discordService.processAndUpload(attachmentUrl);
      return urls;
    }
    return image;
  }


Enter fullscreen mode Exit fullscreen mode

我们将使用id创建/imagine请求时生成的唯一信息来从 Discord 获取结果。


async getResultFromMidjourney(id: string): Promise<any> {
    const headers = {
      "Authorization": MIDJOURNEY_TOKEN,
      "Content-Type": "application/json"
    };
    const channelUrl = `https://discord.com/api/v9/channels/${CHANNEL_ID}/messages?limit=50`;

    try {
      const response = await this.httpService.get(channelUrl, { headers: headers }).toPromise();
      const data = response.data;


      const matchingMessage = data.filter(message =>
        message.content.includes(id) &&
        message
          .components
          .some(component => component.components.some(c => c.label === "U1") ) // means that we can upscale results
      ) || [];

      if (!matchingMessage.length) {
        return null;
      }

      if (matchingMessage.attachments && matchingMessage.attachments.length > 0) {
        for (const attachment of matchingMessage.attachments) {
          attachment.url = await this.fetchAndEncodeImage(attachment.url);
        }
      }

      return matchingMessage;

    } catch (error) {
     // do something 
    }
  }

  async fetchAndEncodeImage(url: string): Promise<string> {
    const response: AxiosResponse<any> = await this.httpService.get(url, {
      responseType: 'arraybuffer',
    }).toPromise();

    const base64 = Buffer.from(response.data, 'binary').toString('base64');
    return `data:${response.headers['content-type']};base64,${base64}`;
  }
Enter fullscreen mode Exit fullscreen mode

https://discord.com/api/v9/channels/${CHANNEL_ID}/messages?limit=50端点用于获取我们的 Discord 频道并获取响应以检索我们的图像。

由于 Midjourney 生成大约需要 60 秒或更长时间,我们需要每 x 秒轮询一次该通道以检查结果。

让我们尝试一下{ prompt: "a cat" }

Midjourney API 猫


就这样!现在你应该拥有一个功能齐全的 Midjourney API,可以用于测试和娱乐,并且你也了解了 Discord 机器人架构的工作原理。

最后的想法

现在,您已经拥有一个引导项目,它演示了 Discord 如何与 MidJourney 通信,从而生成令人惊叹的 AI 图像。
您可以构建一个美观的 UI,并拥有自己的生成式 AI 平台。祝您好运!

文章来源:https://dev.to/confidentai/how-to-build-unofficial-midjourney-api-with-nestjs-1lnd
PREV
在 Windows 11 上使用 WSL2 安装 Zsh 和 Oh-my-zsh
NEXT
产品和开发最佳实践及价值结论