예제 #1
0
    async def add_template(ctx, canvas, name, x, y, url):
        if len(name) > config.MAX_TEMPLATE_NAME_LENGTH:
            await ctx.send(
                ctx.s("template.err.name_too_long").format(
                    config.MAX_TEMPLATE_NAME_LENGTH))
            return
        if sql.template_count_by_guild_id(
                ctx.guild.id) >= config.MAX_TEMPLATES_PER_GUILD:
            await ctx.send(ctx.s("template.err.max_templates"))
            return
        url = await Template.select_url(ctx, url)
        if url is None:
            return

        t = await Template.build_template(ctx, name, x, y, url, canvas)
        if not t:
            return
        log.info("(T:{} | X:{} | Y:{} | Dim:{})".format(
            t.name, t.x, t.y, t.size))
        chk = await Template.check_for_duplicate_by_name(ctx, t)
        if chk is not None:
            if not chk or await Template.check_for_duplicates_by_md5(
                    ctx, t) is False:
                return
            sql.template_update(t)
            await ctx.send(ctx.s("template.updated").format(name))
            return
        elif await Template.check_for_duplicates_by_md5(ctx, t) is False:
            return
        sql.template_add(t)
        await ctx.send(ctx.s("template.added").format(name))
예제 #2
0
async def _build_template_report(ctx, ts: List[DbTemplate]):
    name = ctx.s("bot.name")
    tot = ctx.s("bot.total")
    err = ctx.s("bot.errors")
    perc = ctx.s("bot.percent")

    w1 = max(max(map(lambda tx: len(tx.name), ts)) + 2, len(name))
    w2 = max(max(map(lambda tx: len(str(tx.height * tx.width)), ts)), len(tot))
    w3 = max(max(map(lambda tx: len(str(tx.errors)), ts)), len(err))
    w4 = max(len(perc), 6)

    out = [
        "**{}**".format(ctx.s("template.template_report_header")), "```xl",
        "{0:<{w1}}  {1:>{w2}}  {2:>{w3}}  {3:>{w4}}".format(name,
                                                            tot,
                                                            err,
                                                            perc,
                                                            w1=w1,
                                                            w2=w2,
                                                            w3=w3,
                                                            w4=w4)
    ]
    for t in ts:
        tot = t.size
        if tot == 0:
            t.size = await render.calculate_size(await http.get_template(
                t.url, t.name))
            sql.template_update(t)
        name = '"{}"'.format(t.name)
        perc = "{:>6.2f}%".format(100 * (tot - t.errors) / tot)
        out.append('{0:<{w1}}  {1:>{w2}}  {2:>{w3}}  {3:>{w4}}'.format(
            name, tot, t.errors, perc, w1=w1, w2=w2, w3=w3, w4=w4))
    out.append("```")
    await ctx.send(content='\n'.join(out))
예제 #3
0
    async def add_template(ctx, canvas, name, x, y, url):
        if len(name) > cfg.max_template_name_length:
            await ctx.send(
                ctx.s("template.err.name_too_long").format(
                    cfg.max_template_name_length))
            return
        if sql.template_count_by_guild_id(
                ctx.guild.id) >= cfg.max_templates_per_guild:
            await ctx.send(ctx.s("template.err.max_templates"))
            return
        url = await Template.select_url(ctx, url)
        if url is None:
            return

        t = await Template.build_template(ctx, name, x, y, url, canvas)
        if not t:
            return
        log.debug("(T:{} | X:{} | Y:{} | Dim:{})".format(
            t.name, t.x, t.y, t.size))
        chk = await Template.check_for_duplicate_by_name(ctx, t)
        if chk is not None:
            if not chk or await Template.check_for_duplicates_by_md5(
                    ctx, t) is False:
                return
            sql.template_update(t)
            await ctx.send(ctx.s("template.updated").format(name))
            return
        elif await Template.check_for_duplicates_by_md5(ctx, t) is False:
            return
        sql.template_add(t)
        await ctx.send(ctx.s("template.added").format(name))
예제 #4
0
    async def add_template(ctx, canvas, name, x, y, url):
        """Adds a template to the database.

        Arguments:
        ctx - commands.Context object.
        canvas - The canvas that the template is for, string.
        name - The name of the template, string.
        x - The x coordinate of the template, integer.
        y - The y coordinate of the template, integer.
        url - The url of the template's image, string.
        """
        if len(name) > config.MAX_TEMPLATE_NAME_LENGTH:
            await ctx.send(
                ctx.s("template.err.name_too_long").format(
                    config.MAX_TEMPLATE_NAME_LENGTH))
            return
        if name[0] == "-":
            await ctx.send("Template names cannot begin with hyphens.")
            return
        try:
            c = int(name)
            await ctx.send("Template names cannot be numbers.")
            return
        except ValueError:
            pass
        if sql.template_count_by_guild_id(
                ctx.guild.id) >= config.MAX_TEMPLATES_PER_GUILD:
            await ctx.send(ctx.s("template.err.max_templates"))
            return
        url = await Template.select_url(ctx, url)
        if url is None:
            await ctx.send(ctx.s("template.err.no_image"))
            return
        try:
            #cleans up x and y by removing all spaces and chars that aren't 0-9 or the minus sign using regex. Then makes em ints
            x = int(re.sub('[^0-9-]', '', x))
            y = int(re.sub('[^0-9-]', '', y))
        except ValueError:
            await ctx.send(ctx.s("template.err.invalid_coords"))
            return

        t = await Template.build_template(ctx, name, x, y, url, canvas)
        if not t:
            await ctx.send(ctx.s("template.err.template_gen_error"))
            return
        log.info("(T:{} | X:{} | Y:{} | Dim:{})".format(
            t.name, t.x, t.y, t.size))
        chk = await Template.check_for_duplicate_by_name(ctx, t)
        if chk is not None:
            if not chk or await Template.check_for_duplicates_by_md5(
                    ctx, t) is False:
                return
            sql.template_update(t)
            await ctx.send(ctx.s("template.updated").format(name))
            return
        elif await Template.check_for_duplicates_by_md5(ctx, t) is False:
            return
        sql.template_add(t)
        await ctx.send(ctx.s("template.added").format(name))
예제 #5
0
    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)
예제 #6
0
async def on_ready():
    log.info("Starting Starlight Glimmer v{}!".format(VERSION))
    if sql.version_get() is None:
        sql.version_init(VERSION)
        is_new_version = False
    else:
        old_version = sql.version_get()
        is_new_version = old_version != VERSION and old_version is not None
        if is_new_version:
            log.info("Database is a previous version. Updating...")
            sql.version_update(VERSION)
            if old_version < 1.6 <= VERSION:
                # Fix legacy templates not having a size
                for t in sql.template_get_all():
                    try:
                        t.size = await render.calculate_size(
                            await http.get_template(t.url))
                        sql.template_update(t)
                    except errors.TemplateHttpError:
                        log.error(
                            "Error retrieving template {0.name}. Skipping...".
                            format(t))

    log.info("Loading extensions...")
    for extension in extensions:
        try:
            bot.load_extension(extension)
        except Exception as e:
            log.error("Failed to load extension {}\n{}: {}".format(
                extension,
                type(e).__name__, e))

    log.info("Performing guilds check...")
    for g in bot.guilds:
        log.info("'{0.name}' (ID: {0.id})".format(g))
        db_g = sql.guild_get_by_id(g.id)
        if db_g:
            prefix = db_g.prefix if db_g.prefix else cfg.prefix
            if g.name != db_g.name:
                await ch_log.log(
                    "Guild **{1}** is now known as **{0.name}** `(ID:{0.id})`".
                    format(g, db_g.name))
                sql.guild_update(g.id, name=g.name)
            if is_new_version:
                ch = next(
                    (x for x in g.channels if x.id == db_g.alert_channel),
                    None)
                if ch:
                    data = await http.get_changelog(VERSION)
                    if data:
                        e = discord.Embed(title=data['name'], url=data['url'], color=13594340,
                                          description=data['body']) \
                            .set_author(name=data['author']['login']) \
                            .set_thumbnail(url=data['author']['avatar_url']) \
                            .set_footer(text="Released " + data['published_at'])
                        await ch.send(GlimContext.get_from_guild(
                            g, "bot.update").format(VERSION, prefix),
                                      embed=e)
                    else:
                        await ch.send(
                            GlimContext.get_from_guild(
                                g, "bot.update_no_changelog").format(
                                    VERSION, prefix))
                    log.info("- Sent update message")
                else:
                    log.info(
                        "- Could not send update message: alert channel not found."
                    )
        else:
            j = g.me.joined_at
            await ch_log.log("Joined guild **{0.name}** (ID: `{0.id}`)".format(
                g, j.isoformat(' ')))
            log.info(
                "Joined guild '{0.name}' (ID: {0.id}) between sessions at {1}".
                format(g, j.timestamp()))
            sql.guild_add(g.id, g.name, int(j.timestamp()))
            await print_welcome_message(g)

    db_guilds = sql.guild_get_all()
    if len(bot.guilds) != len(db_guilds):
        for g in db_guilds:
            if not any(x for x in bot.guilds if x.id == g.id):
                log.info("Kicked from guild '{0}' (ID: {1}) between sessions".
                         format(g.name, g.id))
                await ch_log.log(
                    "Kicked from guild **{0}** (ID: `{1}`)".format(
                        g.name, g.id))
                sql.guild_delete(g.id)

    log.info('I am ready!')
    await ch_log.log("I am ready!")
    print("I am ready!")
예제 #7
0
    async def template_info(self, ctx, *args):
        # Order Parsing
        try:
            name = args[0]
        except TypeError:
            await ctx.send("Error: no arguments were provided.")
            return

        if re.match("-\D+", name) != None:
            name = args[-1]
            args = args[:-1]
        else:
            args = args[1:]

        # Argument Parsing
        parser = GlimmerArgumentParser(ctx)
        parser.add_argument("-r", "--raw", action="store_true")
        parser.add_argument("-f",
                            "--faction",
                            default=None,
                            action=FactionAction)
        parser.add_argument("-z", "--zoom", default=1)
        try:
            args = vars(parser.parse_args(args))
        except TypeError:
            return

        image_only = args["raw"]
        f = args["faction"]
        try:
            gid, faction = f.id, f
        except AttributeError:
            gid, faction = ctx.guild.id, sql.guild_get_by_id(ctx.guild.id)
        zoom = args["zoom"]

        t = sql.template_get_by_name(gid, name)
        if not t:
            raise TemplateNotFoundError(gid, name)

        if image_only:
            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)