@mymj/midjourney
Version:
Node.js client for the unofficial MidJourney API.
201 lines (189 loc) • 5.06 kB
text/typescript
import { DiscordImage, MJConfig } from "./interfaces";
export const Commands = [
"ask",
"blend",
"describe",
"fast",
"turbo",
"help",
"imagine",
"info",
"prefer",
"private",
"public",
"relax",
"settings",
"show",
"stealth",
"shorten",
"subscribe",
] as const;
export type CommandName = (typeof Commands)[number];
function getCommandName(name: string): CommandName | undefined {
for (const command of Commands) {
if (command === name) {
return command;
}
}
}
export class Command {
constructor(public config: MJConfig) {}
cache: Partial<Record<CommandName, any>> = {};
async cacheCommand(name: CommandName) {
if (this.cache[name] !== undefined) {
return this.cache[name];
}
if (this.config.ChannelId) {
const command = await this.getCommand(name);
this.cache[name] = command;
}
if (this.cache[name] !== undefined) {
return this.cache[name];
}
return await this.getCommand(name);
}
async userCommand() {
let url = `${this.config.DiscordBaseUrl}/api/v9/users//application-command-index`;
const response = await this.config.fetch(url, {
headers: { authorization: this.config.SalaiToken },
});
if (response.status > 300) {
console.error(response);
throw new Error(`Failed to get application_commands of user for command`);
}
const data = await response.json();
if (data?.application_commands) {
data.application_commands.forEach((command: any) => {
const name = getCommandName(command.name);
if (name) {
this.cache[name] = command;
}
});
}
}
async allCommand() {
try {
let url;
if (!this.config.ServerId) {
url = `${this.config.DiscordBaseUrl}/api/v9/channels/${this.config.ChannelId}/application-command-index`;
} else {
url = `${this.config.DiscordBaseUrl}/api/v9/guilds/${this.config.ServerId}/application-command-index`;
}
const response = await this.config.fetch(url, {
headers: { authorization: this.config.SalaiToken },
});
if (response.status > 300) {
console.error(response);
throw new Error(`Failed to get application_commands for command`);
}
const data = await response.json();
if (data?.application_commands) {
data.application_commands.forEach((command: any) => {
const name = getCommandName(command.name);
if (name) {
this.cache[name] = command;
}
});
}
} catch (error) {
console.error('Fail to get command from channel or server');
}
if (!this.cache['info']) {
await this.userCommand();
}
}
async getCommand(name: CommandName) {
if (this.cache[name]) {
return this.cache[name];
}
await this.allCommand();
if (this.cache[name]) {
return this.cache[name];
}
throw new Error(`Missing permission, please make sure you have added MJ Bot.`);
}
async imaginePayload(prompt: string, nonce?: string) {
const data = await this.commandData("imagine", [
{
type: 3,
name: "prompt",
value: prompt,
},
]);
return this.data2Paylod(data, nonce);
}
async PreferPayload(nonce?: string) {
const data = await this.commandData("prefer", [
{
type: 1,
name: "remix",
options: [],
},
]);
return this.data2Paylod(data, nonce);
}
async shortenPayload(prompt: string, nonce?: string) {
const data = await this.commandData("shorten", [
{
type: 3,
name: "prompt",
value: prompt,
},
]);
return this.data2Paylod(data, nonce);
}
async describePayload(image: DiscordImage, nonce?: string) {
const data = await this.commandData(
"describe",
[
{
type: 11,
name: "image",
value: image.id,
},
],
[
{
id: <string>image.id,
filename: image.filename,
uploaded_filename: image.upload_filename,
},
]
);
return this.data2Paylod(data, nonce);
}
async commandPayload(name: CommandName, nonce?:string) {
const data = await this.commandData(name);
return this.data2Paylod(data, nonce);
}
protected async commandData(
name: CommandName,
options: any[] = [],
attachments: any[] = []
) {
const command = await this.getCommand(name);
const data = {
version: command.version,
id: command.id,
name: command.name,
type: command.type,
options,
application_command: command,
attachments,
};
return data;
}
//TODO data type
protected data2Paylod(data: any, nonce?: string) {
const payload = {
type: 2,
application_id: data.application_command.application_id,
guild_id: this.config.ServerId,
channel_id: this.config.ChannelId,
session_id: this.config.SessionId,
nonce,
data,
};
return payload;
}
}