-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit e8201d5
Showing
12 changed files
with
1,750 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
/persist | ||
/images | ||
/node_modules | ||
.env | ||
/.idea |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
|
||
|
||
})(); | ||
|
||
|
Oops, something went wrong.