Skip to content

Commit

Permalink
initial
Browse files Browse the repository at this point in the history
  • Loading branch information
johanneslo1 committed Apr 16, 2023
0 parents commit e8201d5
Show file tree
Hide file tree
Showing 12 changed files with 1,750 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
OPENAI_API_KEY=
OPENAI_ORGANIZATION=
DISCORD_AUTHORIZATION_TOKEN=
GUILD_ID=
CHANNEL_ID=
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/persist
/images
/node_modules
.env
/.idea
81 changes: 81 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Automatic image generation with Midjourney and GPT-3.5-Turbo

[![GitHub stars](https://img.shields.io/github/stars/johanneslo1/midjourney-automatic-image-generation)](https://github.com/johanneslo1/midjourney-automatic-image-generation/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/johanneslo1/midjourney-automatic-image-generation)](https://github.com/johanneslo1/midjourney-automatic-image-generation/network)
[![GitHub issues](https://img.shields.io/github/issues/johanneslo1/midjourney-automatic-image-generation)](https://github.com/johanneslo1/midjourney-automatic-image-generation/issues)
[![GitHub license](https://img.shields.io/github/license/johanneslo1/midjourney-automatic-image-generation)](https://github.com/johanneslo1/midjourney-automatic-image-generation/blob/main/LICENSE)

This is a Node.js application for automatically generating images using Midjourney. This repository is for educational purposes only.

Disclaimer: This project is the result of a short tinkering. The code is not really well structured, but worked for my use case. When I find the time, I will do a refactoring. In the meantime, maybe the code will help you as a starting point for other projects.

## Getting Started

Follow the steps below to set up the application.

### Prerequisites

- Node.js
- npm

### Before Installation

1. Invite the Midjourney bot to your own Discord server.
2. Create a new text channel on your server.
3. Copy the text channel ID for later use in the `.env` file.
4. Set Midjourney generation to public using the `/public` command.
5. Adjust your desired Midjourney version and quality settings using the `/settings` command.

### Installation

1. Clone the repository:

```
git clone https://github.com/johanneslo1/midjourney-automatic-image-generation.git
```

2. Navigate to the project directory:

```
cd midjourney-automatic-image-generation
```

3. Install the dependencies:

```
npm install
```

4. Copy the `.env.example` file and rename it to `.env`:

```
cp .env.example .env
```

5. Open the `.env` file and set the required environment variables:

- `CHANNEL_ID`: The Discord channel ID where the images will be posted (from step 3 of "Before Installation").
- `GUILD_ID`: The Discord server ID.
- `OPENAI_API_KEY`: [Your OpenAI API key.](https://platform.openai.com/account/api-keys)
- `OPENAI_ORGANIZATION`: [Your OpenAI organization ID.](https://platform.openai.com/account/org-settings)
- `DISCORD_AUTHORIZATION_TOKEN`: Your Discord authorization token. [Here is a guide on how to get yours.](https://www.androidauthority.com/get-discord-token-3149920/)

### Usage

Run the application:

```
npm run start
```

The application will generate images using Midjourney and post them to the specified Discord channel.

## Important Note

Using this application with your personal Discord account to automate tasks is against Discord's Terms of Service. This repository is for educational purposes only, and you should not use it in a way that violates Discord's policies.



## Acknowledgements

- [Wildric-Auric/MidJourney-Wrapper](https://github.com/Wildric-Auric/MidJourney-Wrapper)
130 changes: 130 additions & 0 deletions index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import {Interaction,} from "./src/Interaction";
import {addItemToStore, addMessagesToStorage, extractTitle, findItemFromStorage, sleep} from "./src/helpers";
import './src/bootstrap';
import signale, {Signale} from "signale";
import {ImageCreator} from "./src/ImageCreator";
import axios from "axios";
import sharp from "sharp";
import piexif from "piexifjs";
import {generatePrompts} from "./src/PromptGenerator";

const imageCreator = new ImageCreator();


async function createBaseImages() {

const prompts = await generatePrompts();

for (const prompt of prompts) {
await imageCreator.imagine(prompt);
}
}


async function saveUpscaledImages(messages: any[]) {
const alreadyUpscaledMessages = messages.filter((message: any) => {
// check if any of the components have a label of U1
return message.components[0]?.components?.find((component: any) => component.label === 'Web');
});

signale.info('%s are already upscaled messages', alreadyUpscaledMessages.length);


const urls = alreadyUpscaledMessages.map((message: any) => message.attachments[0]?.url);

signale.success('Here are the already upscaled images: %s', urls)


for (const alreadyUpscaledMessage of alreadyUpscaledMessages) {
const filePath = `images/${alreadyUpscaledMessage.id}.png`;

if (await findItemFromStorage('savedImages', filePath)) {
signale.warn(`Image ${filePath} was already saved. Skipping...`)
continue;
}

const url = alreadyUpscaledMessage.attachments[0]?.url;

const input = (await axios({url, responseType: "arraybuffer"})).data;

await sleep(1000);

// Bild mit Sharp verarbeiten
const image = await sharp(input);

const jpg = await image.toFormat('jpg')

// Bild in einen Buffer konvertieren
const imageBuffer = await jpg.toBuffer();
const dataUrl = 'data:image/jpeg;base64,' + imageBuffer.toString('base64');

// EXIF-Metadaten aus dem Bild extrahieren
const exifObj = piexif.load(dataUrl);

// Copyright-Informationen hinzufügen
// exifObj['0th'][piexif.ImageIFD.Artist] = 'Bevnt';
// exifObj['0th'][piexif.ImageIFD.Copyright] = 'Bevnt';
exifObj['0th'][piexif.ImageIFD.ImageDescription] = extractTitle(alreadyUpscaledMessage.content);
// exifObj['0th'][piexif.ImageIFD.XPTitle] = 'Ihr Bildtitel';

// Aktualisierte EXIF-Metadaten in einen Puffer schreiben
const exifBytes = piexif.dump(exifObj);
const updatedImageData = piexif.insert(exifBytes, imageBuffer.toString('binary'));

// Bild mit aktualisierten EXIF-Metadaten speichern
await sharp(Buffer.from(updatedImageData, 'binary'))
.withMetadata()
.toFile(filePath);

await addItemToStore('savedImages', filePath);
signale.success(`Saved image to ${filePath}`)

}
}


(async () => {

const interactive = new Signale({interactive: true});

let counter = 0;
// await createBaseImages();



while (true) {

const messages = await Interaction.getMidjoruneyMessages();
await saveUpscaledImages(messages);

const baseMessages = await Interaction.getBaseMessages(messages);

if(baseMessages.length === 0) {
counter = counter + 10;
}


for (const message of baseMessages) {
const status = await imageCreator.upscaleBaseImage(message);

if (status) {
counter = 0;
} else {
counter++;
}
}
interactive.info(`No images to upscale %s/40`, counter)


if(counter > 30) {
interactive.complete(`Start to create new base images`);
await createBaseImages();
}

await sleep(10000);
}


})();


Loading

0 comments on commit e8201d5

Please sign in to comment.