diff --git a/generate.py b/generate.py
new file mode 100644
index 0000000..e92533e
--- /dev/null
+++ b/generate.py
@@ -0,0 +1,26 @@
+from poe_api_wrapper import PoeApi
+import os
+client = PoeApi(os.environ['pb'])
+import asyncio
+
+#from revChatGPT.V1 import AsyncChatbot
+#chatbot = AsyncChatbot(config={
+# "email": os.environ['email'],
+# "password": os.environ['pass']
+#})
+
+
+#Auth
+async def GetText(prompt,bot = "chinchilla"):
+ prev_text = ""
+ #code = ""
+ for chunk in client.send_message(bot, prompt, suggest_replies=True):
+ await asyncio.sleep(0.05)
+ prev_text = chunk["text"]
+ client.delete_chat(bot, del_all=True)
+ #client.chat_break(bot, chatCode = code)
+ #async for data in chatbot.ask(prompt):
+ # message = data["message"][len(prev_text) :]
+ # #print(message, end="", flush=True)
+ # prev_text = data["message"]
+ return prev_text
\ No newline at end of file
diff --git a/itemname.py b/itemname.py
new file mode 100644
index 0000000..7b55567
--- /dev/null
+++ b/itemname.py
@@ -0,0 +1,509 @@
+import random
+
+bases = """sword
+axe
+hammer
+amulet
+potion
+broom
+orb
+cloak
+armor
+circlet
+boots
+bag
+shield
+shackles
+glasses
+helmet
+book
+bow
+ring
+socks
+ointment
+deck
+fork
+cart
+boat
+paper
+arrows
+apparatus
+slippers
+greaves
+staff
+skull
+head
+hand
+glue
+quiver
+token
+instrument
+mirror
+flask
+keg
+javelin
+dagger
+maul
+shuriken
+spiked chain
+dust
+gem
+gate
+carpet
+candle
+crystal ball
+fortress
+figurine
+hat
+portable ram
+trap
+box
+ioun stone
+horn
+trinket
+machine"""
+
+locations = """
+fantasy village
+magic forest
+dragon's lair
+enchanted castle
+elven city
+dwarven mine
+wizard's tower
+haunted graveyard
+orc stronghold
+goblin cave
+dark swamp
+knight's training ground
+sorcerer's academy
+thieves' guild hideout
+mermaid's cove
+troll bridge
+fairy glen
+undead crypt
+wizard's library
+druidic grove
+witch's hut
+treasure-filled dungeon
+mystical ruins
+celestial observatory
+elemental plane
+astral realm
+planar crossroads
+forgotten temple
+abyssal rift
+angelic citadel
+shadowy underworld
+lycanthrope den
+necromancer's sanctum
+clockwork workshop
+warlock's pact realm
+underground city
+beastman encampment
+mysterious island
+underwater cavern
+timeless pocket dimension
+arcane battleground
+demon-infested wasteland
+divine garden
+floating fortress
+jungle temple
+mad alchemist's laboratory
+phoenix nest
+twisted labyrinth
+ghost ship
+oracle's sanctuary
+giant's stronghold
+golem foundry
+dreamwalker's realm
+vampire's castle
+plague-ridden village
+wandering nomad camp
+entangled thicket
+celestial court
+abandoned celestial city
+forgotten astral prison"""
+
+creatures = """
+dragon
+goblin
+orc
+elf
+dwarf
+troll
+gnome
+kobold
+centaur
+minotaur
+harpy
+siren
+merfolk
+sphinx
+unicorn
+phoenix
+werewolf
+vampire
+zombie
+skeleton
+ghost
+demon
+angel
+fairy
+giant
+ogre
+cyclops
+hydra
+chimera
+griffin
+wyvern
+elemental
+golem
+gargoyle
+lich
+beholder
+mind flayer
+nymph
+satyr
+kraken
+manticore
+djinn
+mummy
+wraith
+gorgon
+kraken
+pegasus
+treant
+lamia
+basilisk
+rakshasa
+salamander
+changeling
+hobgoblin
+tengu
+mimic
+rust monster
+blink dog
+displacer beast"""
+
+spells = """
+enchantment
+evocation
+illusion
+conjuration
+abjuration
+transmutation
+necromancy
+divination
+charm
+hex
+curse
+blessing
+summoning
+compulsion
+protection
+fire
+ice
+lightning
+earth
+wind
+water
+shadow
+light
+healing
+banishment
+augmentation
+teleportation
+mind control
+time manipulation
+creation
+destruction
+hexbreaking
+illusion
+shape-shifting
+warding
+fortune-telling
+invisibility
+mind reading
+telekinesis
+fear
+love
+truth
+memory manipulation
+elemental manipulation
+fate weaving
+spiritual communion
+phasing
+soulbinding
+telepathy
+dreamwalking
+alchemy
+curses
+blessings
+illusion
+prophecy
+necromancy
+weather manipulation
+energy drain
+astral projection
+illusion
+healing
+enhancement
+demonology
+angelic intervention
+teleportation
+creation
+hexbreaking
+warding
+fey magic
+geomancy
+songweaving
+runecasting
+starcalling
+chronomancy
+geomancy
+psionics
+planar manipulation
+mind melding
+polymorphing
+molecular disruption
+pyromancy
+aquamancy
+aeromancy
+terramancy
+cryomancy
+celestial magic
+transfiguration
+curse-breaking
+illusion
+portal manipulation
+spirit calling
+divine intervention
+time dilation
+cosmic manipulation
+cataclysmic spells
+reanimation
+perception alteration
+dimensional manipulation
+soul manipulation"""
+
+
+enchantments = """flaming
+frost
+healing
+adamantine
+death
+commanding elementals
+flying
+talking
+awakened
+teleportation
+unlocking
+lucky
+unlucky
+instant
+illusion
+illusionary
+many things
+dwarven
+draconic
+disguise
+feindish
+knowledge
+toughness
+serpentine
+folding
+theives
+holding
+devouring
+alien
+eldritch
+fireball
+archmage
+cubic
+crab
+stars
+wild
+natural
+lycanthrope (wolf)
+ursanthrope (bear)
+felinethrope (tiger)
+smashing
+horripilating
+revivification
+holy
+unholy
+gravity
+paper
+mechanical
+electricity
+sonic
+endless water
+cursed (make something up)
+jousting
+charming
+swarming
+swarming insects
+snake
+fuzzy
+soft
+lifestealing
+vorpal
+the sphere
+ultimate evil
+pure good
+true neutral
+tentacle
+enemy detection
+secret
+wonder
+vecna
+fish command
+sticky
+creative
+rulership
+eyes
+fire resistance
+telekinesis
+wishes
+x-ray vision
+animal influence
+limitless
+wild magic
+the sewers
+todd
+love
+life trapping
+soul trapping
+tripping
+psychadelic
+berserker
+dry
+elvenkind
+displacement
+winterlands
+northern
+levitating
+arrow attraction
+bat
+manta ray
+arachnida
+drow
+glamerous
+free action
+jumping
+warmth
+regeneration
+annihilation
+refridgeration
+spherical
+monkey
+primal
+psychic
+woodlands
+sharpness
+smiting
+bane of arthropods
+fear
+web
+plane shift
+winged
+sun
+son
+spellguard
+gaseous form
+gaseous
+valhalla
+horned
+golden lion
+purple
+enlargement
+shrinking
+slaying
+tricky
+awakened
+unsheathed
+prime
+mystical
+gleaming
+enchanted
+cursed
+ancient
+radiant
+shadowy
+whispering
+ornate
+runed
+ethereal
+intricate
+glowing
+forgotten
+dreadful
+celestial
+fiery
+frozen
+arcane
+serrated
+ebon
+gilded
+luminous
+sacrificial
+arcane
+malevolent
+resplendent
+vorpal
+vengeful
+vibrant
+timeless
+abyssal
+otherworldly
+necrotic
+transcendent
+perfected
+empyreal
+crimson
+iridescent
+eldritch
+corrupted
+thunderous
+prismatic
+harmonious
+molten
+umbral
+blighted
+harbinger
+fey
+pristine
+titanic
+ethereal
+phantom
+penumbral
+verdant
+infernal"""
+
+#basesList = bases.split("\n")
+#print(basesList)
+enchantmentsList = enchantments.split("\n")
+#print(enchantmentsList)
+
+magicItemList = []
+
+def makeItem(baseString = bases):
+ base = getBase(baseString.split("\n"))
+ enchantment = getEnchantment()
+ magicItem = ""
+ roll = random.randint(0,20) #rolls to see if it's
+ if roll < 10: #[ENCHANTMENT] [BASE] (10/21)
+ magicItem += enchantment+" "+base
+ elif roll == 20:#[ENCHANTMENT] [BASE] of [ENCHANTMENT 2] (1/21)
+ enchantment2 = getEnchantment()
+ magicItem += enchantment+" "+base+" of "+enchantment2
+ else: #or [BASE] of [ENCHANTMENT] (10/21)
+ magicItem += base+" of "+enchantment
+ return magicItem
+
+def getEnchantment():
+ return enchantmentsList[random.randint(0,len(enchantmentsList)-1)]
+
+def getBase(ls):
+ return ls[random.randint(0,len(ls)-1)]
diff --git a/keep_alive.py b/keep_alive.py
new file mode 100644
index 0000000..f7d5f18
--- /dev/null
+++ b/keep_alive.py
@@ -0,0 +1,21 @@
+from flask import Flask
+from threading import Thread
+
+app = Flask('')
+
+header = "None"
+body = "The next thing generated will show here!"
+
+@app.route('/')
+def home():
+ return f"""
Latest - {header}
+
+ {body}
+ """
+
+def run():
+ app.run(host='0.0.0.0',port=8080)
+
+def keep_alive():
+ t = Thread(target=run)
+ t.start()
\ No newline at end of file
diff --git a/license.txt b/license.txt
new file mode 100644
index 0000000..7401b1b
--- /dev/null
+++ b/license.txt
@@ -0,0 +1,22 @@
+For the contents of itemname.py
+MIT License
+
+Copyright (c) 2019 Michaelofthepi
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/main.py b/main.py
new file mode 100644
index 0000000..e79fb77
--- /dev/null
+++ b/main.py
@@ -0,0 +1,180 @@
+import os
+
+import discord
+import generate
+import neural
+import itemname
+import random
+import re
+from discord import app_commands
+from discord.ext import tasks
+import keep_alive
+from keep_alive import keep_alive
+
+client = discord.Client(intents=discord.Intents.all())
+tree = app_commands.CommandTree(client)
+
+queue = []
+
+guildID = 1081397933276155977
+magicForum = 1144040531240964256
+raceForum = 1144075835217825868
+subclassForum = 1144075898870579290
+locationForum = 1144075950749925457
+monsterForum = 1144081512724176947
+npcForum = 1144425240018034878
+otherForum = 1144426051720724602
+botID = 1144041248303366314
+logChannel = 1144064721922834582
+
+@client.event
+async def on_message(message):
+ if message.author != client.user:
+ pass
+
+@client.event
+async def on_thread_create(thread):
+ # await thread.send("## Sample Concept Art Being Generated")
+ await neural.Generate(f"art of the '{thread.name}', a form of {thread.parent.name}",thread)
+
+@tree.command(name = "magicitem", description = "Generate a new magic item!", guild=discord.Object(id=guildID))
+async def magicitem(interaction, name:str, desc: str = ""):
+ queue.append(["magic item", name,desc + ", and Give detailed rules for item effects and flavor accordingly. Keep non-artifact, non-legendary magic items simple.", magicForum, interaction.user.id])
+ embedVar = discord.Embed(title=f'Queue position: {len(queue)}', description=f"It won't be long until we get around to the '{name}'!", color=0xffff00)
+ await interaction.response.send_message(embed=embedVar)
+
+@tree.command(name = "race", description = "Generate a new race!", guild=discord.Object(id=guildID))
+async def race(interaction, name:str, desc: str = ""):
+ queue.append(["race", name,desc, , interaction.user.id])
+ embedVar = discord.Embed(title=f'Queue position: {len(queue)}', description=f"It won't be long until we get around to the '{name}'!", color=0xffff00)
+ await interaction.response.send_message(embed=embedVar)
+
+@tree.command(name = "subclass", description = "Generate a new subclass!", guild=discord.Object(id=guildID))
+async def subclass(interaction, name:str, desc: str = ""):
+ queue.append(["subclass", name,desc, , interaction.user.id])
+ embedVar = discord.Embed(title=f'Queue position: {len(queue)}', description=f"It won't be long until we get around to the '{name}'!", color=0xffff00)
+ await interaction.response.send_message(embed=embedVar)
+
+@tree.command(name = "location", description = "Generate a new location!", guild=discord.Object(id=guildID))
+async def location(interaction, name:str, desc: str = ""):
+ queue.append(["location", name,desc+", and Describe the location in detail. Provide key locations and any necessary information on NPCs.", locationForum, interaction.user.id])
+ embedVar = discord.Embed(title=f'Queue position: {len(queue)}', description=f"It won't be long until we get around to the '{name}'!", color=0xffff00)
+ await interaction.response.send_message(embed=embedVar)
+
+@tree.command(name = "monster", description = "Generate a new monster!", guild=discord.Object(id=guildID))
+async def monster(interaction, name:str, desc: str = ""):
+ queue.append(["living being", name,desc + ", and Give adequate description to both the flavoring of the monster AND the stat block.", monsterForum, interaction.user.id])
+ embedVar = discord.Embed(title=f'Queue position: {len(queue)}', description=f"It won't be long until we get around to the '{name}'!", color=0xffff00)
+ await interaction.response.send_message(embed=embedVar)
+
+@tree.command(name = "npc", description = "Generate a new npc!", guild=discord.Object(id=guildID))
+async def npc(interaction, name:str, desc: str = ""):
+ queue.append(["NPC", name,desc + ". Provide a stat block for the NPC, but also include a bond, ideal, personality trait, and flaw. Offer a potential quest involving the NPC.", , interaction.user.id])
+ embedVar = discord.Embed(title=f'Queue position: {len(queue)}', description=f"It won't be long until we get around to the '{name}'!", color=0xffff00)
+ await interaction.response.send_message(embed=embedVar)
+
+@tree.command(name = "other", description = "Generate a new npc!", guild=discord.Object(id=guildID))
+async def other(interaction, name:str, type:str = "spell", desc: str = ""):
+ queue.append([type, name,f"Be sure to follow all rules surrounding the {type}.", 1144426051720724602, interaction.user.id])
+ embedVar = discord.Embed(title=f'Queue position: {len(queue)}', description=f"It won't be long until we get around to the '{name}'!", color=0xffff00)
+ await interaction.response.send_message(embed=embedVar)
+
+@tree.command(name = "ask", description = "Use in a thread to get more details!", guild=discord.Object(id=guildID))
+async def ask(interaction, question:str):
+ if interaction.channel.type == discord.ChannelType.public_thread or interaction.channel.type == discord.ChannelType.forum:
+ embedVar = discord.Embed(title=f'Reply inbound', description=f"Question: {question}", color=0xffffff)
+ await interaction.response.send_message(embed=embedVar)
+ #The important code
+ ctx = ""
+ async for message in interaction.channel.history(limit=100,oldest_first=True):
+ if str(message.author.id) == str(botID):
+ ctx += message.content
+ await interaction.channel.send(await generate.GetText(f"You are being asked a question about a piece of DND 5E content. The piece of content is: \n{ctx} \n\nThe question is: {question}. Answer the question thoroughly, but keep it less than 200 words. You do not need to restate any of the content's material nor that this is for DND 5E."))
+ else :
+ embedVar = discord.Embed(title=f'Invalid location', description=f"Do this inside of a forum post for context-specific results!", color=0xff0000)
+ await interaction.response.send_message(embed=embedVar)
+
+@tree.command(name = "conceptart", description = "Generate concept art!", guild=discord.Object(id=guildID))
+async def conceptart(interaction, prompt:str):
+ embedVar = discord.Embed(title=f'Art inbound!', description=f"Prompt: '{prompt}'", color=0xffffff)
+ await interaction.response.send_message(embed=embedVar)
+ await neural.Generate(f"{prompt}", interaction.channel)
+
+intervals = 0
+alreadyGenerating = False
+
+async def AddAutoGen(amount):
+ if amount > 10:
+ return
+ for i in range(amount):
+ v = random.choice([0,1,2,3 ])
+ if v == 0:
+ queue.append(["magic item", itemname.makeItem().title(),"Give detailed rules for item effects and mechanics.", magicForum, -1])
+ elif v == 1:
+ queue.append(["living being", itemname.makeItem(itemname.creatures).title(),"Give adequate description to both the flavoring of the monster AND the stat block.", monsterForum, -1])
+ elif v == 2:
+ queue.append(["location", itemname.makeItem(itemname.locations).title(),"Describe the location in detail. Provide key locations and any necessary information on NPCs.", locationForum, -1])
+ elif v == 3:
+ queue.append(["spell", itemname.makeItem(itemname.spells).title(),"Be sure to follow all rules surrounding the spell.", otherForum, -1])
+
+@tasks.loop(minutes=0.25)
+async def FlushQueue():
+ global alreadyGenerating
+ global intervals
+ try:
+ if alreadyGenerating:
+ return
+ alreadyGenerating = True
+
+ if len(queue) == 0:
+ intervals = (intervals+1)%10
+ if intervals == 0:
+ await AddAutoGen(1)
+
+ if len(queue) > 0:
+ obj = queue.pop(0)
+ keep_alive.header = obj[1]
+ obj[1] = re.sub('[^A-Za-z0-9 ]+', '', obj[1])
+ log = client.get_channel(logChannel)
+ await log.send(f"**Now generating the {obj[0]} '{obj[1]}'**")
+ channel = client.get_channel(obj[3])
+ st = f"Create a DND 5e {obj[0]} named the '{obj[1]}'. {obj[2]} Keep the final text under 300 words. Use markdown text formatting."
+ c = await generate.GetText(st)
+ keep_alive.body = c
+ if len(c) > 1900:
+ c2 = c[1899:(len(c)-1)]
+ c = c[0:1899]
+ thread = await channel.create_thread(name = obj[1], content = c + " (Truncated)")
+ await thread.thread.send(c2)
+ if (obj[4]!=-1):
+ await thread.thread.send("<@" + str(obj[4]) + ">")
+ else:
+ await thread.thread.send("Autogenerated by the bot")
+ else:
+ thread = await channel.create_thread(name = obj[1], content = c)
+ if (obj[4]!=-1):
+ await thread.thread.send("<@" + str(obj[4]) + ">")
+ else:
+ await thread.thread.send("Autogenerated by the bot")
+
+ alreadyGenerating = False
+ except Exception as e:
+
+ log = client.get_channel(logChannel)
+ await log.send("I'm just as confused as you are, there was an error somehow! The next time it should work though.")
+ await log.send("Error message: " + str(e))
+ alreadyGenerating = False
+
+@client.event
+async def on_ready():
+ print("I'm in")
+ print(client.user)
+ await tree.sync(guild=discord.Object(id=guildID))
+ log = client.get_channel(logChannel)
+ await log.send("Bot now online")
+ FlushQueue.start()
+
+keep_alive()
+
+my_secret = os.environ['discordbot']
+client.run(my_secret)
diff --git a/neural.py b/neural.py
new file mode 100644
index 0000000..366c0f3
--- /dev/null
+++ b/neural.py
@@ -0,0 +1,86 @@
+import asyncio
+import os
+import requests
+from io import BytesIO
+from PIL import Image
+import discord
+
+def create_image(links):
+
+ images=[]
+ for index in links:
+ response = requests.get(index)
+ images.append(Image.open(BytesIO(response.content)))
+ image = Image.new("RGB", (images[0].width*len(images), images[0].height))
+ i=0
+ for img in images:
+ image.paste(images[i], (images[i].width*i, 0))
+ i+=1
+ return image
+
+async def Generate(prompt, channel, count=2, negativePrompt = "",size="square"):
+ url = "https://api.neural.love/v1/ai-art/generate"
+ payload = {
+ "amount": count,
+ "isPublic": True,
+ "isPriority": False,
+ "isHd": False,
+ "steps": 25,
+ "cfgScale": 7.5,
+ "prompt": prompt,
+ "style": "anything",
+ "layout": size,
+ "negativePrompt": negativePrompt
+ }
+ headers = {
+ "accept":
+ "application/json",
+ "content-type":
+ "application/json",
+ "authorization":
+ os.environ['neural']
+ }
+ response = requests.post(url, json=payload, headers=headers)
+ data = response.json()
+
+ if not "orderId" in data.keys():
+ await channel.send("**Error while generating, try again?**")
+ return
+ orderId = data["orderId"]
+ print(orderId)
+ url2 = "https://api.neural.love/v1/ai-art/orders/" + orderId
+ print(url2)
+ headers2 = {
+ "accept":
+ "application/json",
+ "authorization":
+ os.environ['neural']
+ }
+ count = 0
+ while True:
+ await asyncio.sleep(3)
+ response2 = requests.get(url2, headers=headers2)
+
+ count += 1
+
+ data2 = response2.json()
+ if data2["status"]["isReady"]:
+ links = []
+ for i in range(data2["input"]["amount"]):
+ data3 = data2["output"][i]
+ links.append(data3["full"])
+ with BytesIO() as image_binary:
+ create_image(links).save(image_binary, 'PNG')
+ image_binary.seek(0)
+ await channel.send(file=discord.File(fp=image_binary, filename='image.png'))
+ break
+ elif data2["status"]["code"] == 998:
+ await channel.send("All results were NSFW, aborting!")
+ break
+ elif count > 10:
+ await channel.send("Taking too long, aborting!")
+ break
+ else:
+ #await message.channel.send("Not done, waiting 10 seconds to retry..."
+
+ await asyncio.sleep(7)
\ No newline at end of file