async def factioninfo(self, ctx, other=None): g = sql.guild_get_by_faction_name_or_alias(other) if other else sql.guild_get_by_id(ctx.guild.id) if not g: await ctx.send(ctx.s("error.faction_not_found")) return if not g.faction_name: await ctx.send(ctx.s("faction.not_a_faction_yet")) return templates = sql.template_get_all_public_by_guild_id(g.id) canvas_list = set() for t in templates: canvas_list.add(t.canvas) canvases_pretty = [] for c in canvas_list: canvases_pretty.append(canvases.pretty_print[c]) canvases_pretty.sort() canvas_list = '\n'.join(canvases_pretty) e = discord.Embed(color=g.faction_color) if canvas_list: e.add_field(name=ctx.s("bot.canvases"), value='\n'.join(canvases_pretty)) if g.faction_invite: icon_url = self.bot.get_guild(g.id).icon_url e.set_author(name=g.faction_name, url=g.faction_invite, icon_url=icon_url) else: e.set_author(name=g.faction_name) e.description = g.faction_desc if g.faction_desc else "" if g.faction_alias: e.description = "**{}:** {}\n".format(ctx.s("bot.alias"), g.faction_alias) + e.description if g.faction_emblem: e.set_thumbnail(url=g.faction_emblem) await ctx.send(embed=e)
async def unhide(self, ctx, other=None): if other is None: fs = [ x for x in sql.guild_get_all_factions() if x.id not in sql.faction_hides_get_all(ctx.guild.id) ] if len(fs) == 0: await ctx.send(ctx.s("faction.no_factions_hidden")) return out = [ ctx.s("faction.currently_hidden"), "```xl", "{0:<34} {1:<5}".format(ctx.s("bot.name"), ctx.s("bot.alias")) ] for f in fs: alias = '"{}"'.format( f.faction_alias) if f.faction_alias else "" out.append("{0:<34} {1:<5}".format( '"{}"'.format(f.faction_name), alias)) out.append('```') await ctx.send('\n'.join(out)) return other_fac = sql.guild_get_by_faction_name_or_alias(other) if not other_fac: await ctx.send(ctx.s("error.faction_not_found")) return sql.faction_hides_remove(ctx.guild.id, other_fac.id) await ctx.send( ctx.s("faction.clear_hide").format(other_fac.faction_name))
async def hide(self, ctx, other): other_fac = sql.guild_get_by_faction_name_or_alias(other) if not other_fac: await ctx.send(ctx.s("error.faction_not_found")) return sql.faction_hides_add(ctx.guild.id, other_fac.id) await ctx.send(ctx.s("faction.set_hide").format(other_fac.faction_name))
async def _quantize(ctx, args, canvas, palette): gid = ctx.guild.id iter_args = iter(args) name = next(iter_args, None) if name == "-f": faction = sql.guild_get_by_faction_name_or_alias(next(iter_args, None)) if not faction: raise errors.FactionNotFound gid = faction.id name = next(iter_args, None) t = sql.template_get_by_name(gid, name) data = None if t: log.debug("(T:{} | GID:{})".format(t.name, t.gid)) if t.canvas == canvas: raise errors.IdempotentActionError data = await http.get_template(t.url) else: att = await utils.verify_attachment(ctx) if att: data = io.BytesIO() await att.save(data) if data: template, bad_pixels = await render.quantize(data, palette) with io.BytesIO() as bio: template.save(bio, format="PNG") bio.seek(0) f = discord.File(bio, "template.png") return await ctx.send(ctx.s("canvas.quantize").format(bad_pixels), file=f)
async def gridify(self, ctx, *args): faction = None color = 0x808080 iter_args = iter(args) name = next(iter_args, None) while name in ["-f", "-c"]: if name == "-f": fac = next(iter_args, None) if fac is None: await ctx.send(ctx.s("error.missing_arg_faction")) return f = sql.guild_get_by_faction_name_or_alias(fac) if not faction: await ctx.send(ctx.s("error.faction_not_found")) return if name == "-c": try: color = abs(int(next(iter_args, None), 16) % 0xFFFFFF) name = next(iter_args, None) except ValueError: await ctx.send(ctx.s("error.invalid_color")) return def parse_zoom(z): try: if type(z) is int: return z if type(z) is str: if z.startswith("#"): z = z[1:] return int(z) if z is None: return 8 except ValueError: return 8 t = sql.template_get_by_name( faction.id, name) if faction else sql.template_get_by_name( ctx.guild.id, name) if t: log.info("(T:{} | GID:{})".format(t.name, t.gid)) data = await http.get_template(t.url, t.name) max_zoom = int(math.sqrt(4000000 // (t.width * t.height))) zoom = max(1, min(parse_zoom(next(iter_args, 1)), max_zoom)) template = await render.gridify(data, color, zoom) else: att = await utils.verify_attachment(ctx) data = io.BytesIO() await att.save(data) max_zoom = int(math.sqrt(4000000 // (att.width * att.height))) zoom = max(1, min(parse_zoom(name), max_zoom)) template = await render.gridify(data, color, zoom) with io.BytesIO() as bio: template.save(bio, format="PNG") bio.seek(0) f = discord.File(bio, "gridded.png") await ctx.send(file=f)
async def template(self, ctx, *args): gid = ctx.guild.id iter_args = iter(args) page = next(iter_args, 1) if page == "-f": fac = next(iter_args, None) if fac is None: await ctx.send(ctx.s("error.missing_arg_faction")) return faction = sql.guild_get_by_faction_name_or_alias(fac) if not faction: raise FactionNotFoundError gid = faction.id page = next(iter_args, 1) try: page = int(page) except ValueError: page = 1 ts = sql.template_get_all_by_guild_id(gid) if len(ts) < 1: raise NoTemplatesError() pages = 1 + len(ts) // 10 page = min(max(page, 1), pages) w1 = max( max(map(lambda tx: len(tx.name), ts)) + 2, len(ctx.s("bot.name"))) msg = [ "**{}** - {} {}/{}".format(ctx.s("template.list_header"), ctx.s("bot.page"), page, pages), "```xl", "{0:<{w1}} {1:<14} {2}".format(ctx.s("bot.name"), ctx.s("bot.canvas"), ctx.s("bot.coordinates"), w1=w1) ] for t in ts[(page - 1) * 10:page * 10]: coords = "({}, {})".format(t.x, t.y) name = '"{}"'.format(t.name) canvas_name = canvases.pretty_print[t.canvas] msg.append("{0:<{w1}} {1:<14} {2}".format(name, canvas_name, coords, w1=w1)) msg.append("") msg.append("// " + ctx.s("template.list_footer_1").format(ctx.gprefix)) msg.append("// " + ctx.s("template.list_footer_2").format(ctx.gprefix)) msg.append("```") await ctx.send('\n'.join(msg))
async def template_info(self, ctx, *args): gid = ctx.guild.id iter_args = iter(args) name = next(iter_args, 1) image_only = False if name == "-r": image_only = True name = next(iter_args, 1) if name == "-f": fac = next(iter_args, None) if fac is None: await ctx.send(ctx.s("error.missing_arg_faction")) return faction = sql.guild_get_by_faction_name_or_alias(fac) if not faction: raise FactionNotFoundError gid = faction.id name = next(iter_args, 1) else: faction = sql.guild_get_by_id(gid) t = sql.template_get_by_name(gid, name) if not t: raise TemplateNotFoundError if image_only: zoom = next(iter_args, 1) try: if type(zoom) is not int: if zoom.startswith("#"): zoom = zoom[1:] zoom = int(zoom) except ValueError: zoom = 1 max_zoom = int(math.sqrt(4000000 // (t.width * t.height))) zoom = max(1, min(zoom, max_zoom)) img = render.zoom(await http.get_template(t.url, t.name), zoom) with io.BytesIO() as bio: img.save(bio, format="PNG") bio.seek(0) f = discord.File(bio, t.name + ".png") await ctx.send(file=f) return canvas_name = canvases.pretty_print[t.canvas] coords = "({}, {})".format(t.x, t.y) dimensions = "{} x {}".format(t.width, t.height) size = t.size visibility = ctx.s("bot.private") if bool( t.private) else ctx.s("bot.public") owner = self.bot.get_user(t.owner_id) if owner is None: added_by = ctx.s("error.account_deleted") else: added_by = owner.name + "#" + owner.discriminator date_added = datetime.date.fromtimestamp( t.date_created).strftime("%d %b, %Y") date_modified = datetime.date.fromtimestamp( t.date_updated).strftime("%d %b, %Y") color = faction.faction_color description = "[__{}__]({})".format( ctx.s("template.link_to_canvas"), canvases.url_templates[t.canvas].format(*t.center())) if size == 0: t.size = await render.calculate_size(await http.get_template( t.url, t.name)) sql.template_update(t) e = discord.Embed(title=t.name, color=color, description=description) \ .set_image(url=t.url) \ .add_field(name=ctx.s("bot.canvas"), value=canvas_name, inline=True) \ .add_field(name=ctx.s("bot.coordinates"), value=coords, inline=True) \ .add_field(name=ctx.s("bot.dimensions"), value=dimensions, inline=True) \ .add_field(name=ctx.s("bot.size"), value=size, inline=True) \ .add_field(name=ctx.s("bot.visibility"), value=visibility, inline=True) \ .add_field(name=ctx.s("bot.added_by"), value=added_by, inline=True) \ .add_field(name=ctx.s("bot.date_added"), value=date_added, inline=True) \ .add_field(name=ctx.s("bot.date_modified"), value=date_modified, inline=True) if faction.id != ctx.guild.id and faction.faction_name: e = e.set_author(name=faction.faction_name, icon_url=faction.faction_emblem or discord.Embed.Empty) await ctx.send(embed=e)
async def diff(self, ctx, *args): if len(args) < 1: return list_pixels = False iter_args = iter(args) a = next(iter_args, None) if a == "-e": list_pixels = True a = next(iter_args, None) if a == "-f": fac = next(iter_args, None) if fac is None: await ctx.send(ctx.s("error.missing_arg_faction")) return f = sql.guild_get_by_faction_name_or_alias(fac) if not f: await ctx.send(ctx.s("error.faction_not_found")) return name = next(iter_args, None) zoom = next(iter_args, 1) t = sql.template_get_by_name(f.id, name) else: name = a zoom = next(iter_args, 1) t = sql.template_get_by_name(ctx.guild.id, name) try: if type(zoom) is not int: if zoom.startswith("#"): zoom = zoom[1:] zoom = int(zoom) except ValueError: zoom = 1 if t: async with ctx.typing(): log.info("(T:{} | GID:{})".format(t.name, t.gid)) data = await http.get_template(t.url, t.name) max_zoom = int(math.sqrt(4000000 // (t.width * t.height))) zoom = max(1, min(zoom, max_zoom)) fetchers = { 'pixelcanvas': render.fetch_pixelcanvas, 'pixelzone': render.fetch_pixelzone, 'pxlsspace': render.fetch_pxlsspace } diff_img, tot, err, bad, err_list \ = await render.diff(t.x, t.y, data, zoom, fetchers[t.canvas], colors.by_name[t.canvas]) done = tot - err perc = done / tot if perc < 0.00005 and done > 0: perc = ">0.00%" elif perc >= 0.99995 and err > 0: perc = "<100.00%" else: perc = "{:.2f}%".format(perc * 100) out = ctx.s("canvas.diff") if bad == 0 else ctx.s( "canvas.diff_bad_color") out = out.format(done, tot, err, perc, bad=bad) with io.BytesIO() as bio: diff_img.save(bio, format="PNG") bio.seek(0) f = discord.File(bio, "diff.png") await ctx.send(content=out, file=f) if list_pixels and len(err_list) > 0: out = ["```xl"] for p in err_list: x, y, current, target = p current = ctx.s("color.{}.{}".format( t.canvas, current)) target = ctx.s("color.{}.{}".format(t.canvas, target)) out.append("({}, {}) is {}, should be {}".format( x + t.x, y + t.y, current, target)) if err > 15: out.append("...") out.append("```") await ctx.send('\n'.join(out)) return await ctx.invoke_default("diff")
async def preview(self, ctx, *args): if len(args) < 1: return preview_template_region = False iter_args = iter(args) a = next(iter_args, None) if a == "-t": preview_template_region = True a = next(iter_args, None) if a == "-f": fac = next(iter_args, None) if fac is None: await ctx.send(ctx.s("error.missing_arg_faction")) return f = sql.guild_get_by_faction_name_or_alias(fac) if not f: await ctx.send(ctx.s("error.faction_not_found")) return name = next(iter_args, None) zoom = next(iter_args, 1) t = sql.template_get_by_name(f.id, name) else: name = a zoom = next(iter_args, 1) t = sql.template_get_by_name(ctx.guild.id, name) try: if type(zoom) is not int: if zoom.startswith("#"): zoom = zoom[1:] zoom = int(zoom) except ValueError: zoom = 1 if t: async with ctx.typing(): log.info("(T:{} | GID:{})".format(t.name, t.gid)) max_zoom = int(math.sqrt(4000000 // (t.width * t.height))) zoom = max(-8, min(zoom, max_zoom)) fetchers = { 'pixelcanvas': render.fetch_pixelcanvas, 'pixelzone': render.fetch_pixelzone, 'pxlsspace': render.fetch_pxlsspace } if preview_template_region: preview_img = await render.preview(*t.center(), zoom, fetchers[t.canvas]) else: preview_img = await render.preview_template( t, zoom, fetchers[t.canvas]) with io.BytesIO() as bio: preview_img.save(bio, format="PNG") bio.seek(0) f = discord.File(bio, "preview.png") await ctx.send(file=f) return await ctx.invoke_default("preview")
def __call__(self, parser, namespace, values, option_string=None): faction = sql.guild_get_by_faction_name_or_alias(values) if faction == None: raise FactionNotFoundError setattr(namespace, self.dest, faction)