Beispiel #1
0
    async def set_presense(self):
        try:
            # https://stackoverflow.com/a/3155023
            def millify(n):
                millnames = ['', 'K', 'M', 'B', 'T']
                n = float(n)
                millidx = max(
                    0,
                    min(
                        len(millnames) - 1,
                        int(math.floor(0 if n == 0 else math.log10(abs(n)) /
                                       3))))

                return '{:.0f}{}'.format(n / 10**(3 * millidx),
                                         millnames[millidx])

            with session_scope() as session:
                pixels = session.query(func.sum(
                    Template.size)).filter(Template.alert_id != None).scalar()

            if not pixels:
                pixels = "Pixels!"
            else:
                pixels = f"{millify(pixels)} Pixels!"

            await self.change_presence(status=discord.Status.online,
                                       activity=discord.Activity(
                                           name=pixels,
                                           type=discord.ActivityType.watching))
        except Exception:
            log.exception("Error during status update task.")
Beispiel #2
0
    def process(self, pixels, alert_template, days):
        # We need to begin a new session for this thread and migrate all
        # the pixel objects over to it so we can use them safely!
        with session_scope() as session:
            ps = [session.merge(p) for p in pixels]

            x_data = []
            # Uses up wayyy more space than it's gonna need, maybe I should aim low and expand?
            y_data = np.zeros((len(ps), 2), dtype=np.int16)
            for i, (_, pixels) in enumerate(
                    groupby(ps,
                            key=lambda p: f"{p.placed.day} {p.placed.hour}")):
                counter = {"ally": 0, "enemy": 0}
                for pixel in pixels:
                    color = alert_template.color_at(pixel.x, pixel.y)
                    if color == -1:
                        continue
                    elif color == pixel.color:
                        counter["ally"] += 1
                    else:
                        counter["enemy"] += 1

                x_data.append(
                    datetime.datetime(pixel.placed.year,
                                      pixel.placed.month,
                                      pixel.placed.day,
                                      hour=pixel.placed.hour))
                y_data[i, 0] = counter["ally"]
                y_data[i, 1] = counter["enemy"]

            y_data = y_data[0:i + 1, :]
            return x_data, y_data
Beispiel #3
0
def process_check(templates, chunks):
    # We need to begin a new session for this thread and migrate all
    # the template objects over to it so we can use them safely!

    with session_scope() as session:
        ts = [session.merge(t) for t in templates]

        example_chunk = next(iter(chunks))
        for t in ts:
            empty_bcs, shape = example_chunk.get_intersecting(
                t.x, t.y, t.width, t.height)
            tmp = Image.new("RGBA", (example_chunk.width * shape[0],
                                     example_chunk.height * shape[1]))
            for i, ch in enumerate(empty_bcs):
                ch = next((x for x in chunks if x == ch))
                if ch.is_in_bounds():
                    tmp.paste(ch.image, ((i % shape[0]) * ch.width,
                                         (i // shape[0]) * ch.height))

            x, y = t.x - empty_bcs[0].p_x, t.y - empty_bcs[0].p_y
            tmp = tmp.crop((x, y, x + t.width, y + t.height))
            template = Image.open(http.get_template_blocking(
                t.url, t.name)).convert('RGBA')
            alpha = Image.new('RGBA', template.size, (255, 255, 255, 0))
            template = Image.composite(template, alpha, template)
            tmp = Image.composite(tmp, alpha, template)
            tmp = ImageChops.difference(tmp.convert('RGB'),
                                        template.convert('RGB'))
            t.errors = np.array(tmp).any(axis=-1).sum()

        return [{"tid": t.id, "errors": t.errors} for t in ts]
Beispiel #4
0
    def get_guild_language(self, guild):
        with session_scope() as session:
            if isinstance(guild, discord.Guild):
                guild = session.query(Guild).get(guild.id)
            else:
                guild = session.query(Guild).get(guild)

            return guild.language.lower()
Beispiel #5
0
    async def update_placements(x, y, color, canvas_name):
        with session_scope() as session:
            canvas = session.query(Canvas).filter_by(nick=canvas_name).first()
            if not canvas:
                log.exception(f"No row found for canvas {canvas_name}, placement stats were not updated.")
                return

            session.add(Pixel(x=x, y=y, color=color, canvas=canvas))
Beispiel #6
0
 async def on_message(self, message):
     with session_scope() as session:
         if not message.author.bot and session.query(AnimoteUser).get(
                 message.author.id):
             channel = message.channel
             content = emote_corrector(message)
             if content:
                 await message.delete()
                 await channel.send(content=content)
Beispiel #7
0
 async def on_guild_role_delete(self, role):
     with session_scope() as session:
         guild = session.query(Guild).get(role.guild.id)
         if guild.template_admin == role.id:
             guild.template_admin = None
         if guild.template_adder == role.id:
             guild.template_adder = None
         if guild.bot_admin == role.id:
             guild.bot_admin = None
Beispiel #8
0
    def canvas_check(self):
        with session_scope() as session:
            for nick, url in canvases.pretty_print.items():
                canvas = session.query(Canvas).filter_by(nick=nick).first()
                if canvas:
                    continue

                log.info(f"Canvas {nick} not found in database, creating...")
                session.add(Canvas(nick=nick, url=url))
Beispiel #9
0
    async def on_message(self, message):
        # Ignore channels that can't be posted in
        if message.guild and not message.channel.permissions_for(
                message.guild.me).send_messages:
            return

        # Ignore other bots
        if message.author.bot:
            return

        # Ignore messages from users currently making a menu choice
        with session_scope() as session:
            lock = session.query(MenuLock).filter(
                message.author.id == MenuLock.user_id,
                message.channel.id == MenuLock.channel_id).first()

            if lock:
                return

        # Ignore messages with spoilered images
        for attachment in message.attachments:
            if attachment.is_spoiler():
                return

        # Ignore messages with any spoilered text
        if re.match(r".*\|\|.*\|\|.*", message.content):
            return

        with session_scope() as session:
            # Create context from message, and assign a db session to it
            # we do that here because before_invoke doesn't happen
            # before checks
            ctx = await self.get_context(message, cls=GlimContext)
            ctx.session = session

            # Attempt to invoke a command from the context
            await self.invoke(ctx)

            # A command was recognised, so autoscan doesn't need to occur
            if ctx.invoked_with:
                return

            # Autoscan, since the message contained no command
            await utils.autoscan(ctx)
Beispiel #10
0
def get_prefix(bot_, msg: discord.Message):
    prefix_list = [config.PREFIX, bot_.user.mention + " "]

    if msg.guild:
        with session_scope() as session:
            guild = session.query(Guild).get(msg.guild.id)
            if guild and guild.prefix is not None:
                prefix_list[0] = guild.prefix

    return prefix_list
Beispiel #11
0
    async def on_guild_remove(self, guild):
        log.info("Kicked from guild '{0.name}' (ID: {0.id})".format(guild))
        if utils.config.CHANNEL_LOG_GUILD_KICKS:
            await utils.channel_log(
                self.bot,
                "Kicked from guild **{0.name}** (ID: `{0.id}`)".format(guild))

        with session_scope() as session:
            db_guild = session.query(Guild).get(guild.id)
            session.delete(db_guild)
Beispiel #12
0
 async def clear_old_stats(self):
     try:
         now = datetime.datetime.now(datetime.timezone.utc)
         seven_days_ago = now - datetime.timedelta(days=7)
         with session_scope() as session:
             session.query(Pixel).filter(
                 Pixel.placed < seven_days_ago).delete()
             session.query(Online).filter(
                 Online.time < seven_days_ago).delete()
     except Exception:
         log.exception("Error during old stats clearing task.")
Beispiel #13
0
    def update_online(self, time, count):
        with session_scope() as session:
            canvas_query = session.query(Canvas).filter_by(nick=self.canvas)
            canvas = canvas_query.first()
            if not canvas:
                log.exception(f"No row found for canvas {self.canvas}, online stats were not updated.")
                return

            session.add(Online(
                time=datetime.datetime.fromtimestamp(time, tz=datetime.timezone.utc),
                count=count,
                canvas=canvas))
Beispiel #14
0
    async def on_guild_update(self, before, after):
        if before.name != after.name:
            log.info("Guild {0.name} is now known as {1.name} (ID: {1.id})")
            if utils.config.CHANNEL_LOG_GUILD_RENAMES:
                await utils.channel_log(
                    self.bot,
                    "Guild **{0.name}** is now known as **{1.name}** (ID: `{1.id}`)"
                    .format(before, after))

            with session_scope() as session:
                db_guild = session.query(Guild).get(after.id)
                db_guild.name = after.name
Beispiel #15
0
    async def on_guild_join(self, guild):
        log.info("Joined new guild '{0.name}' (ID: {0.id})".format(guild))
        if utils.config.CHANNEL_LOG_GUILD_JOINS:
            await utils.channel_log(
                self.bot,
                "Joined new guild **{0.name}** (ID: `{0.id}`)".format(guild))

        with session_scope() as session:
            db_guild = Guild(id=guild.id,
                             name=guild.name,
                             join_date=int(guild.me.joined_at.timestamp()))
            session.add(db_guild)
Beispiel #16
0
    async def unmute(self):
        try:
            with session_scope() as session:
                mutes = session.query(MutedTemplate).filter(
                    MutedTemplate.expires < time.time()).all()

                for mute in mutes:
                    mute.template.alert_channel = mute.alert_id
                    session.delete(mute)

        except Exception:
            log.exception("Error during unmute task.")
Beispiel #17
0
    async def on_guild_channel_delete(self, channel):
        with session_scope() as session:
            guild = session.query(Guild).get(channel.guild.id)

            if guild.alert_channel == channel.id:
                guild.alert_channel = None

            session.query(Template).filter_by(guild_id=channel.guild.id,
                                              alert_id=channel.id).update(
                                                  {Template.alert_id: None})

            session.query(MutedTemplate).filter(
                MutedTemplate.template.guild_id == channel.guild.id,
                MutedTemplate.alert_id == channel.id).delete()
Beispiel #18
0
    async def update(self):
        try:
            with session_scope() as session:
                # Get the templates currently in the db
                templates = session.query(TemplateDb).filter(
                    TemplateDb.alert_id != None).all()

                # Remove any templates from self.templates that are no longer in db
                db_t_ids = [t.id for t in templates]
                for t in self.templates:
                    if t.id not in db_t_ids:
                        log.debug(
                            f"Template {t} no longer in the database, removed."
                        )
                        self.templates.remove(t)

                # Update any templates already in self.templates that have changed
                for old_t in self.templates:
                    for t in templates:
                        if old_t.id != t.id:
                            continue
                        if not old_t.changed(t):
                            continue

                        tp = await Template.new(t)
                        if tp is not None:
                            self.templates.remove(old_t)
                            self.templates.append(tp)

                # Add any new templates from db to self.templates
                template_ids = [template.id for template in self.templates]
                for t in templates:
                    if t.id in template_ids:
                        continue
                    tp = await Template.new(t)
                    if tp is None:
                        continue

                    self.templates.append(tp)

        except Exception as e:
            log.exception(f'Failed to update. {e}')
Beispiel #19
0
    async def database_check(self):
        with session_scope() as session:
            is_new_version = False

            old_version = session.query(Version).first()
            if not old_version:
                print("version initialized to {}".format(VERSION))
                version = Version(version=VERSION)
                session.add(version)
                return is_new_version

            is_new_version = old_version.version != VERSION

            if not is_new_version:
                return is_new_version

            log.info("Database is a previous version. Updating...")

            print("updated to {}".format(VERSION))
            old_version.version = VERSION

            return is_new_version
Beispiel #20
0
                            channel.send(f"```{message}```"))
                except discord.errors.Forbidden:
                    log.warning("Forbidden from logging channel!")


# Use a handler to try to send error level logs to my discord logging channel
global_logger = logging.getLogger()

error_log = DiscordLogger(bot)
error_log.setLevel(logging.ERROR)
error_log.setFormatter(config.formatter)

global_logger.addHandler(error_log)

# Delete all old menu locks
with session_scope() as session:
    session.query(MenuLock).delete()


@bot.before_invoke
async def on_command_preprocess(ctx):
    if ctx.guild:
        log.info(
            "[uuid:{0}] {1.name}#{1.discriminator} used '{2}' in {3.name} (UID:{1.id} GID:{3.id})"
            .format(ctx.uuid, ctx.author, ctx.command.qualified_name,
                    ctx.guild))
    else:
        log.info(
            "[uuid:{0}] {1.name}#{1.discriminator} used '{2}' in DM (UID:{1.id})"
            .format(ctx.uuid, ctx.author, ctx.command.qualified_name))
    log.info("[uuid:{0}] {1}".format(ctx.uuid, ctx.message.content))
Beispiel #21
0
    async def guilds_check(self, is_new_version):
        with session_scope() as session:
            for g in bot.guilds:
                log.info("'{0.name}' (ID: {0.id})".format(g))

                db_g = session.query(Guild).get(g.id)
                if db_g:
                    prefix = db_g.prefix if db_g.prefix else config.PREFIX
                    if g.name != db_g.name:
                        if config.CHANNEL_LOG_GUILD_RENAMES:
                            await utils.channel_log(
                                bot,
                                "Guild **{1}** is now known as **{0.name}** `(ID:{0.id})`"
                                .format(g, db_g.name))
                        db_g.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(
                                    self, g,
                                    "bot.update").format(VERSION, prefix),
                                              embed=e)
                            else:
                                await ch.send(
                                    GlimContext.get_from_guild(
                                        self, 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
                    if config.CHANNEL_LOG_GUILD_JOINS:
                        await utils.channel_log(
                            bot,
                            "Joined guild **{0.name}** (ID: `{0.id}`)".format(
                                g))
                    log.info(
                        "Joined guild '{0.name}' (ID: {0.id}) between sessions at {1}"
                        .format(g, j.timestamp()))
                    session.add(
                        Guild(id=g.id,
                              name=g.name,
                              join_date=int(j.timestamp())))
                    # await utils.print_welcome_message(g)

            db_guilds = session.query(Guild).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))
                        if config.CHANNEL_LOG_GUILD_KICKS:
                            await utils.channel_log(
                                bot,
                                "Kicked from guild **{0}** (ID: `{1}`)".format(
                                    g.name, g.id))
                        session.delete(g)