async def tome(self, ctx, *, name=None): """Commands to manage homebrew spells. When called without an argument, lists the current tome and its description. When called with a name, switches to a different tome.""" user_tomes = await self.bot.mdb.tomes.count_documents( Tome.view_query(str(ctx.author.id))) if not user_tomes: return await ctx.send( "You have no tomes. You can make one at <https://avrae.io/dashboard/homebrew/spells>!" ) if name is None: tome = await Tome.from_ctx(ctx) else: try: tome = await select_tome(ctx, name) except NoActiveBrew: return await ctx.send( "You have no tomes. You can make one at <https://avrae.io/dashboard/homebrew/spells>!" ) except NoSelectionElements: return await ctx.send("Tome not found.") await tome.set_active(ctx) embed = HomebrewEmbedWithAuthor(ctx) embed.title = tome.name embed.description = tome.desc if tome.image: embed.set_thumbnail(url=tome.image) spellnames = "\n".join(i.name for i in tome.spells) if len(spellnames) < 1020: embed.add_field(name="Spells", value=spellnames) else: embed.add_field(name="Spells", value=f"{len(tome.spells)} spells.") await ctx.send(embed=embed)
async def bestiary_import(self, ctx, url): """Imports a published bestiary from [CritterDB](https://critterdb.com/). If your attacks don't seem to be importing properly, you can add a hidden line to the description to set it: `<avrae hidden>NAME|TOHITBONUS|DAMAGE</avrae>""" # ex: https://critterdb.com//#/publishedbestiary/view/5acb0aa187653a455731b890 # https://critterdb.com/#/publishedbestiary/view/57552905f9865548206b50b0 if not 'critterdb.com' in url: return await ctx.send("This is not a CritterDB link.") if not 'publishedbestiary' in url: return await ctx.send( "This is not a public bestiary. Publish it to import!") loading = await ctx.send( "Importing bestiary (this may take a while for large bestiaries)..." ) bestiary_id = url.split('/view')[1].strip('/ \n') bestiary = await Bestiary.from_critterdb(ctx, bestiary_id) await bestiary.set_active(ctx) await bestiary.load_monsters(ctx) await loading.edit(content=f"Imported {bestiary.name}!") embed = HomebrewEmbedWithAuthor(ctx) embed.title = bestiary.name monnames = '\n'.join(m.name for m in bestiary.monsters) if len(monnames) < 2040: embed.description = monnames else: embed.description = f"{len(bestiary.monsters)} creatures." await ctx.send(embed=embed)
async def pack(self, ctx, *, name=None): """Commands to manage homebrew items. When called without an argument, lists the current pack and its description. When called with a name, switches to a different pack.""" user_packs = await self.bot.mdb.packs.count_documents( Pack.view_query(str(ctx.author.id))) if not user_packs: return await ctx.send( "You have no packs. You can make one at <https://avrae.io/dashboard/homebrew/items>!" ) if name is None: pack = await Pack.from_ctx(ctx) else: try: pack = await select_pack(ctx, name) except NoActiveBrew: return await ctx.send( "You have no packs. You can make one at <https://avrae.io/dashboard/homebrew/items>!" ) except NoSelectionElements: return await ctx.send("Pack not found.") await pack.set_active(ctx) embed = HomebrewEmbedWithAuthor(ctx) embed.title = pack.name embed.description = pack.desc if pack.image: embed.set_thumbnail(url=pack.image) itemnames = "\n".join(i['name'] for i in pack.items) if len(itemnames) < 1020: embed.add_field(name="Items", value=itemnames) else: embed.add_field(name="Items", value=f"{len(pack.items)} items.") await ctx.send(embed=embed)
async def bestiary(self, ctx, *, name=None): """Commands to manage homebrew monsters. When called without an argument, lists the current bestiary and the monsters in it. When called with a name, switches to a different bestiary.""" user_bestiaries = await Bestiary.num_user(ctx) if not user_bestiaries: return await ctx.send( f"You have no bestiaries. Use `{ctx.prefix}bestiary import` to import one!" ) if name is None: bestiary = await Bestiary.from_ctx(ctx) else: try: bestiary = await select_bestiary(ctx, name) except NoActiveBrew: return await ctx.send( f"You have no bestiaries. Use `{ctx.prefix}bestiary import` to import one!" ) except NoSelectionElements: return await ctx.send("Bestiary not found.") await bestiary.set_active(ctx) embed = HomebrewEmbedWithAuthor(ctx) embed.title = bestiary.name if bestiary.desc: embed.description = bestiary.desc await bestiary.load_monsters(ctx) monnames = '\n'.join(m.name for m in bestiary.monsters) if len(monnames) < 1020: embed.add_field(name="Creatures", value=monnames) else: embed.add_field(name="Creatures", value=f"{len(bestiary.monsters)} creatures.") await ctx.send(embed=embed)
async def bestiary(self, ctx, *, name=None): """Commands to manage homebrew monsters. When called without an argument, lists the current bestiary and the monsters in it. When called with a name, switches to a different bestiary.""" user_bestiaries = await self.bot.mdb.bestiaries.count_documents( {"owner": ctx.message.author.id}) if not user_bestiaries: return await self.bot.say( "You have no bestiaries. Use `!bestiary import` to import one!" ) if name is None: bestiary = await Bestiary.from_ctx(ctx) else: try: bestiary = await self.select_bestiary(ctx, name) except NoBestiary: return await self.bot.say( "You have no bestiaries. Use `!bestiary import` to import one!" ) except NoSelectionElements: return await self.bot.say("Bestiary not found.") await bestiary.set_active(ctx) embed = HomebrewEmbedWithAuthor(ctx) embed.title = bestiary.name embed.description = '\n'.join(m.name for m in bestiary.monsters) await self.bot.say(embed=embed)
async def bestiary_update(self, ctx): """Updates the active bestiary from CritterDB.""" active_bestiary = await self.bot.mdb.bestiaries.find_one({ "owner": ctx.message.author.id, "active": True }) if active_bestiary is None: return await self.bot.say( "You don't have a bestiary active. Add one with `!bestiary import` first!" ) loading = await self.bot.say( "Importing bestiary (this may take a while for large bestiaries)..." ) bestiary = await self.bestiary_from_critterdb( active_bestiary["critterdb_id"]) await bestiary.commit(ctx) await self.bot.edit_message(loading, f"Imported and updated {bestiary.name}!") embed = HomebrewEmbedWithAuthor(ctx) embed.title = bestiary.name embed.description = '\n'.join(m.name for m in bestiary.monsters) await self.bot.say(embed=embed)
async def bestiary_update(self, ctx): """Updates the active bestiary from CritterDB.""" try: active_bestiary = await Bestiary.from_ctx(ctx) except NoActiveBrew: return await ctx.send( f"You don't have a bestiary active. Add one with `{ctx.prefix}bestiary import` first!" ) loading = await ctx.send( "Updating bestiary (this may take a while for large bestiaries)..." ) old_server_subs = await active_bestiary.server_subscriptions(ctx) await active_bestiary.unsubscribe(ctx) bestiary = await Bestiary.from_critterdb(ctx, active_bestiary.upstream, active_bestiary.published) await bestiary.add_server_subscriptions(ctx, old_server_subs) await bestiary.set_active(ctx) await bestiary.load_monsters(ctx) await loading.edit(content=f"Imported and updated {bestiary.name}!") embed = HomebrewEmbedWithAuthor(ctx) embed.title = bestiary.name embed.description = '\n'.join(m.name for m in bestiary.monsters) await ctx.send(embed=embed)
async def bestiary_import(self, ctx, url): """Imports a published bestiary from [CritterDB](http://www.critterdb.com/).""" # ex: http://www.critterdb.com/#/publishedbestiary/view/5acb0aa187653a455731b890 # http://www.critterdb.com/#/publishedbestiary/view/57552905f9865548206b50b0 if not 'critterdb.com' in url: return await self.bot.say("This is not a CritterDB link.") if not 'publishedbestiary' in url: return await self.bot.say( "This is not a public bestiary. Publish it to import!") loading = await self.bot.say( "Importing bestiary (this may take a while for large bestiaries)..." ) bestiary_id = url.split('/view')[1].strip('/ \n') bestiary = await self.bestiary_from_critterdb(bestiary_id) bestiary.set_active(ctx).commit(ctx) await self.bot.edit_message(loading, f"Imported {bestiary.name}!") embed = HomebrewEmbedWithAuthor(ctx) embed.title = bestiary.name embed.description = '\n'.join(m.name for m in bestiary.monsters) await self.bot.say(embed=embed)
class Homebrew(commands.Cog): """Commands to manage homebrew in Avrae.""" def __init__(self, bot): self.bot = bot @commands.group(invoke_without_command=True) async def bestiary(self, ctx, *, name=None): """Commands to manage homebrew monsters. When called without an argument, lists the current bestiary and the monsters in it. When called with a name, switches to a different bestiary.""" user_bestiaries = await Bestiary.num_user(ctx) if not user_bestiaries: return await ctx.send( f"You have no bestiaries. Use `{ctx.prefix}bestiary import` to import one!" ) if name is None: bestiary = await Bestiary.from_ctx(ctx) else: try: bestiary = await select_bestiary(ctx, name) except NoActiveBrew: return await ctx.send( f"You have no bestiaries. Use `{ctx.prefix}bestiary import` to import one!" ) except NoSelectionElements: return await ctx.send("Bestiary not found.") await bestiary.set_active(ctx) embed = HomebrewEmbedWithAuthor(ctx) embed.title = bestiary.name if bestiary.desc: embed.description = bestiary.desc await bestiary.load_monsters(ctx) monnames = '\n'.join(m.name for m in bestiary.monsters) if len(monnames) < 1020: embed.add_field(name="Creatures", value=monnames) else: embed.add_field(name="Creatures", value=f"{len(bestiary.monsters)} creatures.") await ctx.send(embed=embed) @bestiary.command(name='list') async def bestiary_list(self, ctx): """Lists your available bestiaries.""" out = [b.name async for b in Bestiary.user_bestiaries(ctx)] await ctx.send(f"Your bestiaries: {', '.join(out)}") @bestiary.command(name='delete') async def bestiary_delete(self, ctx, *, name): """Deletes a bestiary from Avrae.""" try: bestiary = await select_bestiary(ctx, name) except NoActiveBrew: return await ctx.send( f"You have no bestiaries. Use `{ctx.prefix}bestiary import` to import one!" ) except NoSelectionElements: return await ctx.send("Bestiary not found.") resp = await confirm( ctx, 'Are you sure you want to delete {}? (Reply with yes/no)'.format( bestiary.name)) if resp: await bestiary.unsubscribe(ctx) return await ctx.send('{} has been deleted.'.format(bestiary.name)) else: return await ctx.send("OK, cancelling.") @bestiary.command(name='import') async def bestiary_import(self, ctx, url): """ Imports a bestiary from [CritterDB](https://critterdb.com/). To share a bestiary with Avrae, enable Link Sharing in the sharing menu of your bestiary! If your attacks don't seem to be importing properly, you can add a hidden line to the description to set it: `<avrae hidden>NAME|TOHITBONUS|DAMAGE</avrae>` """ # ex: https://critterdb.com//#/publishedbestiary/view/5acb0aa187653a455731b890 # https://critterdb.com/#/publishedbestiary/view/57552905f9865548206b50b0 # https://critterdb.com:443/#/bestiary/view/5acfe382de482a4d0ed57b46 if not (match := re.match( r'https?://(?:www\.)?critterdb.com(?::443|:80)?.*#/(published)?bestiary/view/([0-9a-f]+)', url)): return await ctx.send("This is not a CritterDB link.") loading = await ctx.send( "Importing bestiary (this may take a while for large bestiaries)..." ) bestiary_id = match.group(2) is_published = bool(match.group(1)) bestiary = await Bestiary.from_critterdb(ctx, bestiary_id, published=is_published) await bestiary.set_active(ctx) await bestiary.load_monsters(ctx) await loading.edit(content=f"Imported {bestiary.name}!") embed = HomebrewEmbedWithAuthor(ctx) embed.title = bestiary.name monnames = '\n'.join(m.name for m in bestiary.monsters) if len(monnames) < 2040: embed.description = monnames else: embed.description = f"{len(bestiary.monsters)} creatures." await ctx.send(embed=embed)