Example #1
0
    async def cleanup_old_messages(self) -> None:
        """This will periodically iterate through old messages
        and prune them based on age to help keep data relatively easy to work
        through
        """
        purge_time = await self.config.purge_time()

        if not purge_time:
            return
        purge = timedelta(seconds=purge_time)
        while True:
            total_pruned = 0
            guilds_ignored = 0
            to_purge = datetime.utcnow() - purge
            # Prune only the last 30 days worth of data
            for guild_id, starboards in self.starboards.items():
                guild = self.bot.get_guild(guild_id)
                if not guild:
                    guilds_ignored += 1
                    continue
                # log.debug(f"Cleaning starboard data for {guild.name} ({guild.id})")
                for name, starboard in starboards.items():
                    async with starboard.lock:
                        to_rem = []
                        to_rem_index = []
                        try:
                            async for message_ids, message in AsyncIter(
                                    starboard.messages.items(), steps=500):
                                if message.new_message:
                                    if snowflake_time(
                                            message.new_message) < to_purge:
                                        to_rem.append(message_ids)
                                        index_key = f"{message.new_channel}-{message.new_message}"
                                        to_rem_index.append(index_key)
                                else:
                                    if snowflake_time(message.original_message
                                                      ) < to_purge:
                                        to_rem.append(message_ids)
                            for m in to_rem:
                                log.debug(f"Removing {m}")
                                del starboard.messages[m]
                                total_pruned += 1
                            for m in to_rem_index:
                                del starboard.starboarded_messages[m]
                            if len(to_rem) > 0:
                                log.info(
                                    f"Starboard pruned {len(to_rem)} messages that are "
                                    f"{humanize_timedelta(timedelta=purge)} old from "
                                    f"{guild.name} ({guild.id})")
                        except Exception:
                            log.exception(
                                "Error trying to clenaup old starboard messages."
                            )
                await self._save_starboards(guild)
            if total_pruned:
                log.info(
                    f"Starboard has pruned {total_pruned} messages and ignored {guilds_ignored} guilds."
                )
            # Sleep 1 day but also run on cog reload
            await asyncio.sleep(60 * 60 * 24)
Example #2
0
async def copy_warn(user_id: int, warn: models.Warn):
    await add_dbmember_if_not_exist(user_id)
    warn.id = utils.time_snowflake(
        utils.snowflake_time(warn.id) + datetime.timedelta(milliseconds=1))
    while await get_warn(warn.id):
        warn.id = utils.time_snowflake(
            utils.snowflake_time(warn.id) + datetime.timedelta(milliseconds=1))
    warn.user = user_id
    await warn.create()
Example #3
0
    async def censor_detector(self):
        # reciever taks for someone gets censored
        while self.running:
            try:
                message = None
                message = await self.bot.wait_for("user_censored")
                # make sure our cog is still running so we don't handle it twice
                if not self.running:
                    return

                # make sure anti-spam is enabled
                cfg = Configuration.get_var(message.guild.id, "ANTI_SPAM")
                if not cfg.get("ENABLED", False) or message.id in self.censor_processed:
                    continue
                buckets = Configuration.get_var(message.guild.id, "ANTI_SPAM", "BUCKETS", [])
                count = 0
                for b in buckets:
                    t = b["TYPE"]
                    if t == "censored":
                        msg_time = int(snowflake_time(message.id).timestamp())
                        bucket = self.get_bucket(message.guild.id, f"censored:{count}", b, message.author.id)
                        if bucket is not None and await bucket.check(message.author.id, msg_time, 1, f"{message.channel.id}-{message.id}"):
                            count = await bucket.count(message.author.id, msg_time, expire=False)
                            period = await bucket.size(message.author.id, msg_time, expire=False)
                            self.bot.loop.create_task(
                                self.violate(Violation("max_censored", message.guild, f"{Translator.translate('spam_max_censored', message)} ({count}/{period}s)",
                                                       message.author,
                                                       message.channel,
                                                       await bucket.get(message.author.id, msg_time, expire=False),
                                                       b, count)))

            except CancelledError:
                pass
            except Exception as e:
                await TheRealGearBot.handle_exception("censor detector", self.bot, e)
Example #4
0
    async def snowflake(self, ctx: Context, *snowflakes: Snowflake) -> None:
        """Get Discord snowflake creation time."""
        if len(snowflakes) > 1 and await has_no_roles_check(ctx, *STAFF_ROLES):
            raise BadArgument(
                "Cannot process more than one snowflake in one invocation.")

        if not snowflakes:
            raise BadArgument("At least one snowflake must be provided.")

        embed = Embed(colour=Colour.blue())
        embed.set_author(
            name=
            f"Snowflake{'s'[:len(snowflakes)^1]}",  # Deals with pluralisation
            icon_url=
            "https://github.com/twitter/twemoji/blob/master/assets/72x72/2744.png?raw=true"
        )

        lines = []
        for snowflake in snowflakes:
            created_at = snowflake_time(snowflake)
            lines.append(
                f"**{snowflake}**\nCreated at {created_at} ({time_since(created_at, max_units=3)})."
            )

        await LinePaginator.paginate(lines,
                                     ctx=ctx,
                                     embed=embed,
                                     max_lines=5,
                                     max_size=1000)
Example #5
0
    async def _before_first_ping(self) -> None:
        """
        Sleep until `REMINDER_MESSAGE` should be sent again.

        If latest reminder is not cached, exit instantly. Otherwise, wait wait until the
        configured `REMINDER_FREQUENCY` has passed.
        """
        last_reminder: t.Optional[int] = await self.task_cache.get(
            "last_reminder")

        if last_reminder is None:
            log.trace(
                "Latest verification reminder message not cached, task will not wait"
            )
            return

        # Convert cached message id into a timestamp
        time_since = datetime.utcnow() - snowflake_time(last_reminder)
        log.trace(f"Time since latest verification reminder: {time_since}")

        to_sleep = timedelta(
            hours=constants.Verification.reminder_frequency) - time_since
        log.trace(f"Time to sleep until next ping: {to_sleep}")

        # Delta can be negative if `REMINDER_FREQUENCY` has already passed
        secs = max(to_sleep.total_seconds(), 0)
        await asyncio.sleep(secs)
Example #6
0
async def send_exception(client: discord.Client, exception: Exception, source_name: str, mention_role: Optional[int] = 820974562770550816, pin: bool = True, timestamp: bool = True):
    """
    sends the exception into a channel if `DATA.debug` ist disabled
    """
    if not DATA.debug:
        super_log: discord.TextChannel = client.get_channel(DATA.IDs.Channels.Super_Log)

        file = discord.File(BytesIO(format_exc().encode()), "exception.log")
        embed: discord.Embed = discord.Embed(title=source_name,
                                             description=f"{exception.__class__.__name__}: {exception.__str__()}\n",
                                             color=discord.Color.magenta())

        message: discord.Message = await super_log.send(embed=embed, file=file)

        if timestamp:
            from discord.utils import snowflake_time
            embed.add_field(name="datetime.datetime",
                            value=snowflake_time(message.id).__str__())
            await message.edit(embed=embed)
        if pin:
            await message.pin()
        if mention_role:
            await super_log.send(f"<@&{mention_role}>")
    else:
        raise exception
Example #7
0
    async def userinfobyid(self, ctx, uid: str):
        """Shows users's information"""
        server = ctx.message.server
        user = server.get_member(uid)
        user_created = snowflake_time(uid).strftime("%d %b %Y %H:%M")
        if user is not None:
            desc = "Is a member of this server"
            col = user.color
            name = "{0.name} #{0.discriminator}".format(user)
            if user.nick is not None:
                name += " AKA: {0.nick}".format(user)
        else:
            user = await self.bot.get_user_info(uid)
            if user is None:
                return await self.bot.say("No such user")
            col = discord.Color.purple()
            desc = "Not a member of this server"
            name = "{0.name} #{0.discriminator}".format(user)

        data = discord.Embed(description=desc, colour=col)
        if user.avatar_url:
            data.set_author(name=name, url=user.avatar_url)
            data.set_thumbnail(url=user.avatar_url)
        else:
            data.set_author(name=name)

        try:
            await self.bot.say(embed=data)
        except Exception:
            pass
Example #8
0
    async def convert(self, ctx: Context, arg: str) -> int:
        """
        Ensure `arg` matches the ID pattern and its timestamp is in range.

        Return `arg` as an int if it's a valid snowflake.
        """
        error = f"Invalid snowflake {arg!r}"

        if not self._get_id_match(arg):
            raise BadArgument(error)

        snowflake = int(arg)

        try:
            time = snowflake_time(snowflake)
        except (OverflowError, OSError) as e:
            # Not sure if this can ever even happen, but let's be safe.
            raise BadArgument(f"{error}: {e}")

        if time < DISCORD_EPOCH_DT:
            raise BadArgument(f"{error}: timestamp is before the Discord epoch.")
        elif (datetime.utcnow() - time).days < -1:
            raise BadArgument(f"{error}: timestamp is too far into the future.")

        return snowflake
Example #9
0
 async def on_reaction_add(self, reaction, user):
     if isinstance(reaction.message.channel, discord.DMChannel):
         return
     try:
         emoji = reaction.emoji.id
         db.update_emoji(
             {
                 "e_id": emoji,
                 "g_id": reaction.message.guild.id,
                 "name": reaction.emoji.name,
                 "animated": reaction.emoji.animated,
                 "created_time": utils.snowflake_time(reaction.emoji.id),
             }
         )
     except AttributeError:
         emoji = reaction.emoji
         db.update_emoji(
             {
                 "e_id": emoji,
                 "g_id": reaction.message.guild.id,
                 "name": emoji,
                 "animated": False,
                 "created_time": END_TIME,
             }
         )
     db.update_reaction(
         data={
             "m_id": reaction.message.id,
             "e_id": emoji,
             "count": reaction.count,
         }
     )
 async def cleaner(self):
     now = datetime.datetime.utcnow()
     for errorlog in self.errorlog.iterdir():
         if not errorlog.name.startswith('.') and errorlog.suffix == '.log':
             messageid = base64.urlsafe_b64decode(errorlog.stem.encode())
             time = snowflake_time(int.from_bytes(messageid, 'big'))
             if (now - time).total_seconds() > self.maxage:
                 errorlog.unlink()
Example #11
0
    async def snowflake(self, ctx: Context, arg: int):
        if arg < 0:
            raise CommandError(t.invalid_snowflake)

        try:
            await reply(ctx, format_dt(snowflake_time(arg), style="F"))
        except (OverflowError, ValueError, OSError):
            raise CommandError(t.invalid_snowflake)
Example #12
0
 def to_json(self):
     return {
         "id": str(self.mid),
         "channel": str(self.channel),
         "member": self.hid,
         "system": self.system_hid,
         "message_sender": str(self.sender),
         "timestamp": snowflake_time(self.mid).isoformat()
     }
Example #13
0
def test_snowflake_conversion():
    from discord import utils

    now = datetime.datetime.utcnow()

    snowflake = utils.time_snowflake(now)
    time = utils.snowflake_time(snowflake)

    # Accept a millisecond or less of error
    assert abs((time - now).total_seconds()) <= 0.001
Example #14
0
    def is_valid_timestamp(b64_content: str) -> bool:
        b64_content += '=' * (-len(b64_content) % 4)

        try:
            content = base64.urlsafe_b64decode(b64_content)
            snowflake = struct.unpack('i', content)[0]
        except (binascii.Error, struct.error):
            return False
        return snowflake_time(snowflake +
                              TOKEN_EPOCH) < DISCORD_EPOCH_TIMESTAMP
Example #15
0
def test_snowflake_time(snowflake: int,
                        time_tuple: typing.Tuple[int, int, int, int, int,
                                                 int]):
    dt = utils.snowflake_time(snowflake)

    assert (dt.year, dt.month, dt.day, dt.hour, dt.minute,
            dt.second) == time_tuple

    assert utils.time_snowflake(
        dt, high=False) <= snowflake <= utils.time_snowflake(dt, high=True)
Example #16
0
 async def snowflake(self, ctx: Context, snowflake: Snowflake) -> None:
     """Get Discord snowflake creation time."""
     created_at = snowflake_time(snowflake)
     embed = Embed(
         description=f"**Created at {created_at}** ({time_since(created_at, max_units=3)}).",
         colour=Colour.blue()
     )
     embed.set_author(
         name=f"Snowflake: {snowflake}",
         icon_url="https://github.com/twitter/twemoji/blob/master/assets/72x72/2744.png?raw=true"
     )
     await ctx.send(embed=embed)
Example #17
0
def home():
	if request.method == "POST":
		try:
			snowflake_id = request.form["id"]
			tz = pytz.timezone("America/Los_Angeles")
			tz2 = tz.localize(datetime.datetime.now())
			snow_pst = snowflake_time(int(snowflake_id)).astimezone(tz)
			created_at = f'{datetime.datetime.strftime(snow_pst, "%A, %B %-d, %Y, %-I:%M:%S %p")} {tz2.tzname()}'
			timestamp = round(time.mktime(snowflake_time(int(snowflake_id)).timetuple()))
			iso = snowflake_time(int(snowflake_id))
			return redirect(f"https://www.snowflake-time.tk/?id={request.form['id']}") 
		except:
			return redirect("https://www.snowflake-time.tk/")
	
	if request.args.get("id"):
		try:
			snowflake_id = request.args.get("id")
			tz = pytz.timezone("America/Los_Angeles")
			tz2 = tz.localize(datetime.datetime.now())
			snow_pst = snowflake_time(int(snowflake_id)).astimezone(tz)
			created_at = f'{datetime.datetime.strftime(snow_pst, "%A, %B %-d, %Y, %-I:%M:%S %p")} {tz2.tzname()}'
			timestamp = round(time.mktime(snowflake_time(int(snowflake_id)).timetuple()))
			iso = snowflake_time(int(snowflake_id))
			return render_template("index.html", created_at=created_at, timestamp=timestamp, iso=iso, share_url=f"https://www.snowflake-time.tk/?id={snowflake_id}")
		except:
			return redirect("https://www.snowflake-time.tk/")
	
	return render_template("index.html")
Example #18
0
    async def task(self):
        try:
            log.spam("Running delete task...")

            for guild in self.bot.guilds:
                # get guild data and determine if this server is using auto delete
                guild_data = await self.bot.get_guild_data(guild.id)
                if guild_data:
                    auto_del_data = guild_data.auto_delete_data
                    if not auto_del_data:
                        continue

                    for channel_data in auto_del_data:
                        channel: discord.TextChannel = self.bot.get_channel(
                            int(channel_data["channel_id"]))
                        if channel:
                            messages_to_delete = {}
                            async for message in channel.history(
                                    limit=None,
                                    after=datetime.utcnow() -
                                    timedelta(days=14)):
                                message_age = datetime.utcnow(
                                ) - snowflake_time(message.id)
                                # message is younger than 14 days, but older than specified time
                                if message_age.total_seconds() >= int(
                                        channel_data["delete_after"]) * 60:
                                    messages_to_delete[message.id] = message
                                    if len(messages_to_delete) >= 200:
                                        # to avoid api spamming, i only want to delete in batches of 200 at most
                                        break
                            if len(messages_to_delete) != 0:
                                messages_to_delete = list(
                                    messages_to_delete.values())
                                # bulk delete can only take 100 messages at a time,
                                # so we chunk the deletions into batches of 100 or less
                                message_chunk = []
                                for i, msg in enumerate(messages_to_delete):
                                    message_chunk.append(msg)
                                    if len(message_chunk) == 100 or i == len(
                                            messages_to_delete) - 1:
                                        await channel.delete_messages(
                                            message_chunk)
                                        message_chunk = []
                                log.spam(
                                    f"Deleted {len(messages_to_delete)} messages"
                                )

                await asyncio.sleep(0)
        except Exception as e:
            log.error("".join(
                traceback.format_exception(type(e), e, e.__traceback__)))
Example #19
0
    def is_valid_timestamp(b64_content: str) -> bool:
        """
        Check potential token to see if it contains a valid timestamp.

        See: https://discordapp.com/developers/docs/reference#snowflakes
        """
        b64_content += '=' * (-len(b64_content) % 4)

        try:
            content = base64.urlsafe_b64decode(b64_content)
            snowflake = struct.unpack('i', content)[0]
        except (binascii.Error, struct.error):
            return False
        return snowflake_time(snowflake + TOKEN_EPOCH) < DISCORD_EPOCH_TIMESTAMP
Example #20
0
    async def snowflake(self, ctx: Context, *snowflakes: Snowflake) -> None:
        """Get Discord snowflake creation time."""
        if len(snowflakes) > 1 and await has_no_roles_check(ctx, *STAFF_ROLES):
            raise BadArgument("Cannot process more than one snowflake in one invocation.")

        for snowflake in snowflakes:
            created_at = snowflake_time(snowflake)
            embed = Embed(
                description=f"**Created at {created_at}** ({time_since(created_at, max_units=3)}).",
                colour=Colour.blue()
            )
            embed.set_author(
                name=f"Snowflake: {snowflake}",
                icon_url="https://github.com/twitter/twemoji/blob/master/assets/72x72/2744.png?raw=true"
            )
            await ctx.send(embed=embed)
Example #21
0
 def should_remove(self, seconds: int) -> bool:
     """
     Returns True if we should end the event
     Returns False if the event should stay open
     """
     now = datetime.now(timezone.utc).timestamp()
     if self.message is None:
         # If we don't even have a message linked to this event delete it
         # although in practice this should never happen
         return True
     if self.start:
         future = (self.start + timedelta(seconds=seconds)).timestamp()
         log.debug(f"{humanize_timedelta(seconds = future-now)}")
         return now > future
     else:
         future = (
             snowflake_time(self.message).replace(tzinfo=timezone.utc) +
             timedelta(seconds=seconds)).timestamp()
         log.debug(f"{humanize_timedelta(seconds = future-now)}")
         return now > future
Example #22
0
 def remaining(self, seconds: int) -> str:
     """
     Returns the time remaining on an event
     """
     now = datetime.now(timezone.utc).timestamp()
     if self.message is None:
         # If we don't even have a message linked to this event delete it
         # although in practice this should never happen
         return _("0 seconds")
     if self.start:
         future = (self.start + timedelta(seconds=seconds)).timestamp()
         diff = future - now
         log.debug(f"Set time {future=} {now=} {diff=}")
         return humanize_timedelta(seconds=future - now)
     else:
         future = (
             snowflake_time(self.message).replace(tzinfo=timezone.utc) +
             timedelta(seconds=seconds)).timestamp()
         diff = future - now
         log.debug(f"Message Time {future=} {now=} {diff=}")
         return humanize_timedelta(seconds=future - now)
Example #23
0
    async def userlogs(self,
                       ctx: Context,
                       user: Optional[Union[User, int]] = None):
        """
        show moderation log of a user
        """

        user, user_id, arg_passed = await self.get_stats_user(ctx, user)
        await update_join_date(self.bot.guilds[0], user_id)

        out: List[Tuple[datetime, str]] = [(snowflake_time(user_id),
                                            translations.ulog_created)]
        for join in await db_thread(db.all, Join, member=user_id):
            out.append((join.timestamp, translations.ulog_joined))
        for leave in await db_thread(db.all, Leave, member=user_id):
            out.append((leave.timestamp, translations.ulog_left))
        for username_update in await db_thread(db.all,
                                               UsernameUpdate,
                                               member=user_id):
            if not username_update.nick:
                msg = translations.f_ulog_username_updated(
                    username_update.member_name, username_update.new_name)
            elif username_update.member_name is None:
                msg = translations.f_ulog_nick_set(username_update.new_name)
            elif username_update.new_name is None:
                msg = translations.f_ulog_nick_cleared(
                    username_update.member_name)
            else:
                msg = translations.f_ulog_nick_updated(
                    username_update.member_name, username_update.new_name)
            out.append((username_update.timestamp, msg))
        for report in await db_thread(db.all, Report, member=user_id):
            out.append((report.timestamp,
                        translations.f_ulog_reported(f"<@{report.reporter}>",
                                                     report.reason)))
        for warn in await db_thread(db.all, Warn, member=user_id):
            out.append((warn.timestamp,
                        translations.f_ulog_warned(f"<@{warn.mod}>",
                                                   warn.reason)))
        for mute in await db_thread(db.all, Mute, member=user_id):
            text = [translations.ulog_muted, translations.ulog_muted_inf
                    ][mute.days == -1][mute.is_upgrade].format
            if mute.days == -1:
                out.append((mute.timestamp, text(f"<@{mute.mod}>",
                                                 mute.reason)))
            else:
                out.append((mute.timestamp,
                            text(f"<@{mute.mod}>", mute.days, mute.reason)))
            if not mute.active and not mute.upgraded:
                if mute.unmute_mod is None:
                    out.append((mute.deactivation_timestamp,
                                translations.ulog_unmuted_expired))
                else:
                    out.append((
                        mute.deactivation_timestamp,
                        translations.f_ulog_unmuted(f"<@{mute.unmute_mod}>",
                                                    mute.unmute_reason),
                    ))
        for kick in await db_thread(db.all, Kick, member=user_id):
            if kick.mod is not None:
                out.append((kick.timestamp,
                            translations.f_ulog_kicked(f"<@{kick.mod}>",
                                                       kick.reason)))
            else:
                out.append((kick.timestamp, translations.ulog_autokicked))
        for ban in await db_thread(db.all, Ban, member=user_id):
            text = [translations.ulog_banned, translations.ulog_banned_inf
                    ][ban.days == -1][ban.is_upgrade].format
            if ban.days == -1:
                out.append((ban.timestamp, text(f"<@{ban.mod}>", ban.reason)))
            else:
                out.append(
                    (ban.timestamp, text(f"<@{ban.mod}>", ban.days,
                                         ban.reason)))
            if not ban.active and not ban.upgraded:
                if ban.unban_mod is None:
                    out.append((ban.deactivation_timestamp,
                                translations.ulog_unbanned_expired))
                else:
                    out.append((
                        ban.deactivation_timestamp,
                        translations.f_ulog_unbanned(f"<@{ban.unban_mod}>",
                                                     ban.unban_reason),
                    ))
        for log in await db_thread(db.all, InviteLog,
                                   applicant=user_id):  # type: InviteLog
            if log.approved:
                out.append((log.timestamp,
                            translations.f_ulog_invite_approved(
                                f"<@{log.mod}>", log.guild_name)))
            else:
                out.append((log.timestamp,
                            translations.f_ulog_invite_removed(
                                f"<@{log.mod}>", log.guild_name)))

        out.sort()
        embed = Embed(title=translations.userlogs, color=Colours.userlog)
        if isinstance(user, int):
            embed.set_author(name=str(user))
        else:
            embed.set_author(name=f"{user} ({user_id})",
                             icon_url=user.avatar_url)
        for row in out:
            name = row[0].strftime("%d.%m.%Y %H:%M:%S")
            value = row[1]
            embed.add_field(name=name, value=value, inline=False)

        embed.set_footer(text=translations.utc_note)

        if arg_passed:
            await send_long_embed(ctx, embed)
        else:
            try:
                await send_long_embed(ctx.author, embed)
            except (Forbidden, HTTPException):
                raise CommandError(translations.could_not_send_dm)
            await ctx.message.add_reaction(name_to_emoji["white_check_mark"])
Example #24
0
 def get_time(self):
     return pendulum.parse(str(snowflake_time(self.msg_id))).utc()
Example #25
0
async def whois(client, message, *args):
    if len(message.mentions) == 0:
        await message.channel.send(f"Usage: {PREFIX}whois <@user mention>")
        return
    user = message.mentions[0]
    embed = discord.Embed(title=f"{user.name}#{user.discriminator}",
                          color=user.colour)
    tdelta = datetime.datetime.now() - user.joined_at
    embed.add_field(name="User ID", value=user.id)
    if user.nick:
        embed.add_field(name="Nickname", value=user.nick)
    if user.top_role:
        embed.add_field(name="Top Role", value=user.top_role)
    embed.add_field(name="Status", value=user.status)
    embed.add_field(name="Is Bot", value=user.bot)
    _perms = user.guild_permissions
    embed.add_field(name="Is Administrator", value=_perms.administrator)
    roles = user.roles[1:]
    if len(roles) > 0:
        role_str = ", ".join([i.name for i in roles])
    else:
        role_str = "No roles set."
    embed.add_field(name="Roles", inline=False, value=role_str)
    embed.add_field(
        name="Account Created On",
        inline=False,
        value=snowflake_time(user.id).strftime("%A, %d %B, %Y. %I:%M:%S %p"),
    )
    embed.add_field(
        name="In Server For",
        inline=False,
        value=f"{tdelta.days} days, {tdelta.seconds//3600} hours",
    )
    perms_list = [
        "kick_members",
        "ban_members",
        "manage_channels",
        "manage_guild",
        "add_reactions",
        "view_audit_log",
        "priority_speaker",
        "send_messages",
        "send_tts_messages",
        "manage_messages",
        "attach_files",
        "read_message_history",
        "mention_everyone",
        "embed_links",
        "external_emojis",
        "connect",
        "speak",
        "mute_members",
        "deafen_members",
        "move_members",
        "use_voice_activation",
        "change_nickname",
        "manage_nicknames",
        "manage_roles",
        "manage_webhooks",
        "manage_emojis",
    ]
    perms = []
    for i in perms_list:
        if getattr(_perms, i):
            perms += [i.replace("_", " ").capitalize()]
    if perms == []:
        perms = ["No special permissions."]
    perms_str = ", ".join(perms)
    embed.add_field(name="Permissions", value=perms_str, inline=False)
    embed.set_thumbnail(url=user.avatar_url)
    await message.channel.send(embed=embed)
 def created_at(self) -> int:
     return snowflake_time(self.id).timestamp()
Example #27
0
 def created_at(self):
     """:class:`datetime.datetime`: Returns the webhook's creation time in UTC."""
     return utils.snowflake_time(self.id)
Example #28
0
async def __main__(client: Client, _event: int, *args: Union[Message, Member, VoiceState, User, Member, Role]):
    try:
        super_log: TextChannel = client.get_channel(DATA.IDs.Channels.Super_Log)
        attachments = None

        if _event == EVENT.on_message:
            datetime_edit = False

            if args[0].channel.id != super_log.id:
                embed: Embed = Embed(title=f"on_message | "
                                           f"<{args[0].jump_url}> |" +
                                           (f" {args[0].channel.category} |"
                                            f" {args[0].channel.mention}" if hasattr(args[0].channel, "category") else " DM"),
                                     description=args[0].content+(" | EMBED" if args[0].embeds else "")+(" | ATTACHMENT" if args[0].attachments else ""),
                                     color=Color.gold())
                embed.set_author(name=args[0].author, url=args[0].author.avatar_url)
                embed.add_field(name="datetime.datetime",
                                value=args[0].created_at)

                from io import BytesIO
                if args[0].attachments:
                    attachments = []
                    for attachment in args[0].attachments:
                        fp = BytesIO()
                        await attachment.save(fp)
                        attachments.append(File(fp, attachment.filename))

                from json import dump
                if args[0].embeds:
                    attachments = []
                    for i, attachment in enumerate(args[0].embeds):
                        with open("_.log", "w") as fp:
                            dump(attachment.to_dict(), fp, indent=2)
                        with open("_.log", "rb") as fp:
                            attachments.append(File(fp, f"EMBED-{i}.json"))

            else:
                return

        elif _event == EVENT.on_message_delete:
            datetime_edit = False
            embed: Embed = Embed(title=f"on_message_delete | "
                                       f"<{args[0].jump_url}> |" +
                                       (f" {args[0].channel.category} |"
                                        f" {args[0].channel.mention}" if hasattr(args[0].channel, "category") else " DM"),
                                 description=args[0].content+(" | EMBED" if args[0].embeds else "")+(" | ATTACHMENT" if args[0].attachments else ""),
                                 color=Color.gold())
            embed.set_author(name=args[0].author, url=args[0].author.avatar_url)
            embed.add_field(name="datetime.datetime",
                            value=args[0].created_at)

            from io import BytesIO
            if args[0].attachments:
                attachments = []
                for attachment in args[0].attachments:
                    fp = BytesIO()
                    await attachment.save(fp)
                    attachments.append(File(fp, attachment.filename))

            from json import dump
            if args[0].embeds:
                attachments = []
                for i, attachment in enumerate(args[0].embeds):
                    with open("_.log", "w") as fp:
                        dump(attachment.to_dict(), fp, indent=2)
                    with open("_.log", "rb") as fp:
                        attachments.append(File(fp, f"EMBED-{i}.json"))

        elif _event == EVENT.on_message_edit:
            datetime_edit = False
            if args[0].author.id != client.user.id:
                embed: Embed = Embed(title=f"on_message_edit | "
                                           f"<{args[0].jump_url}> |" +
                                           (f" {args[0].channel.category} |"
                                            f" {args[0].channel.mention}" if hasattr(args[0].channel, "category") else " DM"),
                                     color=Color.gold())
                embed.set_author(name=args[0].author, url=args[0].author.avatar_url)
                embed.add_field(name=f"before ({args[0].created_at})",
                                value=args[0].content+(" | EMBED" if args[0].embeds else "")+(" | ATTACHMENT" if args[0].attachments else ""))
                embed.add_field(name=f"after ({args[0].edited_at})",
                                value=args[1].content+(" | EMBED" if args[0].embeds else "")+(" | ATTACHMENT" if args[0].attachments else ""))

                from io import BytesIO
                if args[0].attachments:
                    attachments = []
                    for attachment in args[0].attachments:
                        fp = BytesIO()
                        await attachment.save(fp)
                        attachments.append(File(fp, attachment.filename))

                from json import dump
                if args[0].embeds:
                    attachments = []
                    for i, attachment in enumerate(args[0].embeds):
                        with open("_.log", "w") as fp:
                            dump(attachment.to_dict(), fp, indent=2)
                        with open("_.log", "rb") as fp:
                            attachments.append(File(fp, f"EMBED-OLD-{i}.json"))

                if args[1].attachments:
                    attachments = []
                    for attachment in args[1].attachments:
                        fp = BytesIO()
                        await attachment.save(fp)
                        attachments.append(File(fp, attachment.filename))

                if args[1].embeds:
                    attachments = []
                    for i, attachment in enumerate(args[1].embeds):
                        with open("_.log", "w") as fp:
                            dump(attachment.to_dict(), fp, indent=2)
                        with open("_.log", "rb") as fp:
                            attachments.append(File(fp, f"EMBED-NEW-{i}.json"))
            else:
                return

        elif _event == EVENT.on_ready:
            datetime_edit = True
            embed: Embed = Embed(title=f"on_ready",
                                 color=Color.green())

        elif _event == EVENT.on_voice_state_update:
            datetime_edit = True
            embed: Embed = Embed(title=f"on_voice_state_update",
                                 color=Color.greyple())
            embed.set_author(name=args[0].__str__(), url=args[0].avatar_url)

            if args[1].channel is None:
                embed.description = f"joined {args[2].channel}"
            if args[2].channel is None:
                embed.description = f"leaved {args[1].channel}"
            if args[1].channel is not None and args[2].channel is not None and args[1].channel != args[2].channel:
                embed.add_field(name="moved", value=f"{args[1].channel} -> {args[2].channel}")
            if args[1].deaf != args[2].deaf:
                embed.add_field(name="server deafen", value=f"{args[1].deaf} -> {args[2].deaf}")
            if args[1].mute != args[2].mute:
                embed.add_field(name="server mute", value=f"{args[1].mute} -> {args[2].mute}")
            if args[1].self_deaf != args[2].self_deaf:
                embed.add_field(name="self self_deafen", value=f"{args[1].self_deaf} -> {args[2].self_deaf}")
            if args[1].self_mute != args[2].self_mute:
                embed.add_field(name="self mute", value=f"{args[1].self_mute} -> {args[2].self_mute}")
            if args[1].self_stream != args[2].self_stream:
                embed.add_field(name="self stream", value=f"{args[1].self_stream} -> {args[2].self_stream}")
            if args[1].self_video != args[2].self_video:
                embed.add_field(name="self video", value=f"{args[1].self_video} -> {args[2].self_video}")
            if args[1].afk != args[2].afk:
                embed.add_field(name="afk", value=f"{args[1].afk} -> {args[2].afk}")

        elif _event == EVENT.on_user_update:
            datetime_edit = True
            embed: Embed = Embed(title=f"on_user_update",
                                 color=Color.blurple())
            embed.set_author(name=args[0].__str__(), url=args[0].avatar_url)
            if args[0].avatar != args[1].avatar:
                embed.add_field(name="avatar", value=f"[IMG]({args[0].avatar_url}) -> [IMG]({args[1].avatar_url})")
            if args[0].name != args[1].name:
                embed.add_field(name="name", value=f"{args[0].name} -> {args[1].name}")
            if args[0].discriminator != args[1].discriminator:
                embed.add_field(name="discriminator", value=f"{args[0].discriminator} -> {args[1].discriminator}")

        elif _event == EVENT.on_member_update:
            datetime_edit = True
            embed: Embed = Embed(title=f"on_member_update",
                                 color=Color.blue())
            embed.set_author(name=args[0].__str__(), url=args[0].avatar_url)
            if args[0].nick != args[1].nick:
                embed.add_field(name="nickname", value=f"{args[0].nick} -> {args[1].nick}")
            if args[0].roles != args[1].roles:
                if len(args[0].roles) < len(args[1].roles):
                    meta = list()
                    for role in args[1].roles:
                        if role not in args[0].roles:
                            meta.append(f"**+** `{role.name}` `{role.id}`")
                    embed.add_field(name="role", value="\n".join(meta))
                if len(args[0].roles) > len(args[1].roles):
                    meta = list()
                    for role in args[0].roles:
                        if role not in args[1].roles:
                            meta.append(f"**-** `{role.name}` `{role.id}`")
                    embed.add_field(name="role", value="\n".join(meta))
                if len(args[0].roles) == len(args[1].roles):
                    embed.add_field(name="role", value="***__PLEASE CONTACT A <@820974562770550816>!!!__***")

            if len(embed.fields) == 0:
                return

        else:
            datetime_edit = True
            embed = Embed()

        message: Message = await super_log.send(embed=embed, files=attachments)

        if datetime_edit:
            from discord.utils import snowflake_time
            embed.add_field(name="datetime.datetime",
                            value=snowflake_time(message.id).__str__(),
                            inline=False)
            await message.edit(embed=embed)

    except Exception as e:
        await send_exception(client=client, exception=e, source_name=__name__)
Example #29
0
 def created_at(self):
     """Returns the user's creation time in UTC.
     This is when the user's discord account was created."""
     return snowflake_time(self.id)
Example #30
0
    async def background_loop(self):
        """
        Check for age of the last message sent in the channel.
        If it's too old, consider the channel inactive and close the ticket.
        """
        category = await self.get_forwarding_category()
        now = datetime.datetime.now()
        one_day_ago = now - datetime.timedelta(days=1)
        for ticket_channel in category.text_channels:
            last_message_id = ticket_channel.last_message_id
            if last_message_id:
                # We have the ID of the last message, there is no need to fetch the API, since we can just extract the
                # datetime from it.
                last_message_time = snowflake_time(last_message_id)
            else:
                # For some reason, we couldn't get the last message, so we'll have to go the expensive route.
                # In my testing, I didn't see it happen, but better safe than sorry.
                try:
                    last_message = (await
                                    ticket_channel.history(limit=1
                                                           ).flatten())[0]
                except IndexError:
                    # No messages at all.
                    last_message_time = now
                else:
                    last_message_time = last_message.created_at

            inactive_for = last_message_time - now
            inactive_for_str = format_timedelta(inactive_for,
                                                granularity='minute',
                                                locale='en',
                                                threshold=1.1)
            self.bot.logger.debug(
                f"[SUPPORT GARBAGE COLLECTOR] "
                f"#{ticket_channel.name} has been inactive for {inactive_for_str}."
            )

            if last_message_time <= one_day_ago:
                self.bot.logger.debug(f"[SUPPORT GARBAGE COLLECTOR] "
                                      f"Deleting #{ticket_channel.name}...")
                # The last message was sent a day ago, or more.
                # It's time to close the channel.
                async with ticket_channel.typing():
                    user = await self.get_user(ticket_channel.name)
                    db_user = await get_from_db(user, as_user=True)

                    ticket = await db_user.get_or_create_support_ticket()
                    ticket.close(
                        await get_from_db(self.bot.user, as_user=True),
                        "Automatic closing for inactivity.")

                    await ticket.save()

                    language = db_user.language

                    _ = get_translate_function(self.bot, language)

                    inactivity_embed = discord.Embed(
                        color=discord.Color.orange(),
                        title=_("DM Timed Out"),
                        description=
                        _("It seems like nothing has been said here for a long time, "
                          "so I've gone ahead and closed your ticket, deleting its history. "
                          "Thanks for using DuckHunt DM support. "
                          "If you need anything else, feel free to open a new ticket by sending a message "
                          "here."),
                    )

                    inactivity_embed.add_field(
                        name=_("Support server"),
                        value=
                        _("For all your questions, there is a support server. "
                          "Click [here](https://duckhunt.me/support) to join."
                          ))

                    try:
                        await user.send(embed=inactivity_embed)
                    except:
                        pass

                    await self.clear_caches(ticket_channel)

                    await ticket_channel.delete(
                        reason=f"Automatic deletion for inactivity.")