Ejemplo n.º 1
0
    async def nowplaying(self, ctx: cmds.Context, channel: str = None):
        """See what is now playing on the radio.

        Use "!nowplaying [<channel>]" to show what is now playing on the radio.
        Short version is "!np[<channel>]".
        Leave off <channel> to auto-detect the channel you are tuned to."""

        async with ctx.typing():
            cmd = ctx.invoked_with
            chan = None

            if cmd in ['npgame', 'nprw']:
                chan = RainwaveChannel.game
            elif cmd in ['npoc', 'npocr']:
                chan = RainwaveChannel.ocr
            elif cmd in ['npcover', 'npcovers', 'npmw', 'npvw']:
                chan = RainwaveChannel.cover
            elif cmd in ['npbw', 'npch', 'npchip']:
                chan = RainwaveChannel.chip
            elif cmd in ['npall', 'npomni', 'npow']:
                chan = RainwaveChannel.all
            elif cmd in ['nowplaying', 'np']:
                if channel:
                    if channel.lower() in RainwaveChannel.__members__.keys():
                        chan = RainwaveChannel[channel.lower()]
                if chan is None:
                    listener_id = await self.get_id_for_user(ctx.author)
                    chan = await self.get_current_channel_for_id(listener_id)
                if chan is None:
                    await ctx.author.send(self.not_tuned_in)
                    return

            m = f'Now playing on the {chan.long_name}'
            d = await self.rw_info(chan.channel_id)
            event = d.get('sched_current')
            sched_id = int(event.get('id'))
            sched_type = event.get('type')
            sched_name = event.get('name')
            if sched_type == 'Election' and sched_name:
                m += f' ({sched_name})'
            elif sched_type == 'OneUp':
                m += f' ({sched_name} Power Hour)'
            song = event.get('songs')[0]
            embed = self.build_embed(song)
            m += f': {self.song_string(song)}'

            if ctx.guild:
                last = self.bot.config.get(f'rainwave:np:{chan.channel_id}', 0)
                if sched_id == last:
                    c = f'You can only use **{cmd}** in {ctx.channel.mention} once per song.'
                    await ctx.author.send(c)
                    await ctx.author.send(m, embed=embed)
                else:
                    self.bot.config.set(f'rainwave:np:{chan.channel_id}', sched_id)
                    await ctx.send(m, embed=embed)
            else:
                await ctx.send(m, embed=embed)
Ejemplo n.º 2
0
    async def _play(self, ctx: commands.Context, *, search: str):
        """Plays a song.

        If there are songs in the queue, this will be queued until the
        other songs finished playing.

        This command automatically searches from various sites if no URL is provided.
        A list of these sites can be found here: https://rg3.github.io/youtube-dl/supportedsites.html
        """
        if not ctx.voice_state.voice:
            await ctx.invoke(self._join)

        async with ctx.typing():

            # We are parsing a Spotify link
            if ("open.spotify.com" in search):
                song_info = ""

                if ("playlist" in search):
                    entries = await self.spotify.get_playlist_songs(search)
                    await ctx.send(
                        'Hai hai! :blush: Time to queue up some songs...')
                    count = 0

                    for entry in entries:
                        try:
                            time.sleep(5)
                            source = await YTDLSource.create_source(
                                ctx,
                                "%s %s" % (entry["name"], entry["artist"]),
                                loop=self.bot.loop)

                            song = Song(source)
                            await ctx.voice_state.songs.put(song)
                        except Exception as e:
                            await ctx.send("Couldn't queue up %s" %
                                           (entry['name']))
                            await ctx.send("Reason: {}".format(e))
                            continue
                        count += 1

                    await ctx.send('Queued up {} songs!'.format(count))
                else:
                    song_info = await self.spotify.get_song_info(search)
                    source = await YTDLSource.create_source(
                        ctx,
                        "%s %s" % (song_info["name"], song_info["artist"]),
                        loop=self.bot.loop)

                    song = Song(source)
                    await ctx.voice_state.songs.put(song)
                    await ctx.send('Hai hai! :blush: I shall play {} !'.format(
                        str(source)))

            # We are parsing a YouTube link
            else:
                try:
                    if ("playlist" in search):

                        # we will need to parse a playlist
                        entries = await YTDLSource.get_playlist_entries(
                            ctx, search, loop=self.bot.loop)
                        await ctx.send(
                            'Hai hai! :blush: Time to queue up some songs...')
                        count = 0

                        for entry in entries:
                            try:
                                time.sleep(5)
                                source = await YTDLSource.create_source(
                                    ctx,
                                    entry["id"],
                                    loop=self.bot.loop,
                                    using_id=True)

                                song = Song(source)
                                await ctx.voice_state.songs.put(song)
                            except Exception as e:
                                await ctx.send("Couldn't queue up %s" %
                                               (entry['title']))
                                await ctx.seed("Reason: {}".format(e))
                                continue
                            count += 1

                        await ctx.send('Queued up {} songs!'.format(count))
                    else:
                        source = await YTDLSource.create_source(
                            ctx, search, loop=self.bot.loop)
                        song = Song(source)

                        await ctx.voice_state.songs.put(song)
                        await ctx.send(
                            'Hai hai! :blush: I shall play {} !'.format(
                                str(source)))

                except Exception as e:
                    await ctx.send(
                        'Gomenasai, Traveler-dono! Something happened :cry: ... {}'
                        .format(str(e)))
Ejemplo n.º 3
0
    async def add_(self, ctx: commands.Context, member: MemberOrID, *,
                   reason: str) -> None:
        """Warn a user

        Can also be used as `warn <member> [reason]`"""
        if get_perm_level(member, await self.bot.db.get_guild_config(
                ctx.guild.id))[0] >= get_perm_level(
                    ctx.author, await self.bot.db.get_guild_config(ctx.guild.id
                                                                   ))[0]:
            await ctx.send('User has insufficient permissions')
        else:
            guild_config = await self.bot.db.get_guild_config(ctx.guild.id)
            guild_warns = guild_config.warns
            warn_punishments = guild_config.warn_punishments
            warn_punishment_limits = [i.warn_number for i in warn_punishments]
            warns = list(
                filter(lambda w: w['member_id'] == str(member.id),
                       guild_warns))

            cmd = None
            punish = False

            num_warns = len(warns) + 1
            fmt = f'You have been warned in **{ctx.guild.name}**, reason: {reason}. This is warning #{num_warns}.'

            if warn_punishments:
                punishments = list(
                    filter(lambda x: int(x) == num_warns,
                           warn_punishment_limits))
                if not punishments:
                    punish = False
                    above = list(
                        filter(lambda x: int(x) > num_warns,
                               warn_punishment_limits))
                    if above:
                        closest = min(map(int, above))
                        cmd = warn_punishments.get_kv('warn_number',
                                                      closest).punishment
                        if cmd == 'ban':
                            cmd = 'bann'
                        fmt += f' You will be {cmd}ed on warning {closest}.'
                else:
                    punish = True
                    cmd = warn_punishments.get_kv(
                        'warn_number', max(map(int, punishments))).punishment
                    if cmd == 'ban':
                        cmd = 'bann'
                    fmt += f' You have been {cmd}ed from the server.'

            try:
                await member.send(fmt)
            except discord.Forbidden:
                if ctx.author != ctx.guild.me:
                    await ctx.send(
                        'The user has PMs disabled or blocked the bot.')
            finally:
                guild_config = await self.bot.db.get_guild_config(ctx.guild.id)
                current_date = (ctx.message.created_at + timedelta(
                    hours=guild_config.time_offset)).strftime('%Y-%m-%d')
                if len(guild_warns) == 0:
                    case_number = 1
                else:
                    case_number = guild_warns[-1]['case_number'] + 1
                push = {
                    'case_number': case_number,
                    'date': current_date,
                    'member_id': str(member.id),
                    'moderator_id': str(ctx.author.id),
                    'reason': reason
                }
                await self.bot.db.update_guild_config(
                    ctx.guild.id, {'$push': {
                        'warns': push
                    }})
                if ctx.author != ctx.guild.me:
                    await ctx.send(self.bot.accept)
                await self.send_log(ctx, member, reason, case_number)

                # apply punishment
                if punish:
                    if cmd == 'bann':
                        cmd = 'ban'
                    ctx.command = self.bot.get_command(cmd)
                    ctx.author = ctx.guild.me
                    await ctx.invoke(ctx.command,
                                     member,
                                     reason=f'Hit warn limit {num_warns}')
Ejemplo n.º 4
0
    'topic': 'topic',
    'position': 1,
    'nsfw': False,
    'last_message_id': 1,
}
channel_instance = discord.TextChannel(state=unittest.mock.MagicMock(),
                                       guild=unittest.mock.MagicMock(),
                                       data=channel_data)


class MockTextChannel(unittest.mock.AsyncMock):
    """A mock subclass to mock `discord.TextChannel` objects."""
    spec_set = channel_instance


# Create a `discord.ext.commands.Context` instance
context_instance = Context(message=unittest.mock.MagicMock(),
                           prefix=unittest.mock.MagicMock())


class MockContext(unittest.mock.Mock):
    """A mock subclass to mock `discord.ext.commands.Context` objects."""
    spec_set = context_instance

    def __init__(self, **kwargs) -> None:
        super().__init__(**kwargs)
        self.bot = kwargs.get('bot', MockBot())
        self.guild = kwargs.get('guild', MockGuild())
        self.author = kwargs.get('author', MockMember())
        self.channel = kwargs.get('channel', MockTextChannel())
Ejemplo n.º 5
0
 async def cog_before_invoke(
     self, ctx: commands.Context
 ):  #Get ourselves a music context! (Only accessable throughout this cog)
     ctx.voice_state = self.get_voice_state(ctx)
Ejemplo n.º 6
0
    async def giveaway_cmd(self, ctx: Context):
        if ctx.error:
            return

        msg = ctx.message
        user = ctx.user

        # Check paused
        if await RedisDB.instance().is_paused():
            await Messages.send_error_dm(
                msg.author,
                f"Transaction activity is currently suspended. I'll be back online soon!"
            )
            return

        # Check roles
        if not await self.role_check(msg):
            return
        elif msg.channel.id in config.Config.instance().get_no_spam_channels():
            await Messages.send_error_dm(
                msg.author, f"You can't start giveaways in this channel")
            return

        if 'fee=' not in msg.content or 'duration=' not in msg.content:
            await Messages.send_usage_dm(msg.author, START_GIVEAWAY_INFO)
            await Messages.add_x_reaction(msg)
            return

        # Parse message
        split_content = msg.content.split(' ')
        cleaned_content = msg.content
        for split in split_content:
            if split.startswith('fee='):
                cleaned_content.replace(split, "")
                split = split.replace('fee=', '').strip()
                if not split:
                    continue
                try:
                    fee = float(split)
                except ValueError as e:
                    await Messages.add_x_reaction(msg)
                    await Messages.send_usage_dm(msg.author,
                                                 START_GIVEAWAY_INFO)
                    return
            elif split.startswith('duration='):
                cleaned_content.replace(split, "")
                split = split.replace('duration=', '').strip()
                if not split:
                    continue
                try:
                    duration = int(split)
                    if not ctx.god and (duration < config.Config.instance(
                    ).get_giveaway_min_duration()
                                        or duration > config.Config.instance(
                                        ).get_giveaway_max_duration()):
                        raise ValueError("Bad duration specified")
                except ValueError as e:
                    await Messages.add_x_reaction(msg)
                    await Messages.send_usage_dm(msg.author,
                                                 START_GIVEAWAY_INFO)
                    return
        # Find giveaway amount
        try:
            giveaway_amount = RegexUtil.find_float(cleaned_content)
            if Validators.too_many_decimals(giveaway_amount):
                await Messages.send_error_dm(
                    ctx.message.author,
                    f"You are only allowed to use {Env.precision_digits()} digits after the decimal for giveaway amount."
                )
                ctx.error = True
                return
            elif fee > giveaway_amount * config.Config.instance(
            ).get_giveaway_max_fee_multiplier():
                await Messages.add_x_reaction(msg)
                await Messages.send_usage_dm(msg.author, START_GIVEAWAY_INFO)
                return
            elif giveaway_amount < config.Config.instance(
            ).get_giveaway_minimum():
                await Messages.add_x_reaction(msg)
                await Messages.send_usage_dm(msg.author, START_GIVEAWAY_INFO)
                return
        except AmountMissingException:
            await Messages.add_x_reaction(msg)
            await Messages.send_usage_dm(msg.author, START_GIVEAWAY_INFO)
            return

        # See how much they need to make this tip.
        available_balance = Env.raw_to_amount(await
                                              user.get_available_balance())
        if giveaway_amount > available_balance:
            await Messages.add_x_reaction(ctx.message)
            await Messages.send_error_dm(
                msg.author,
                f"Your balance isn't high enough to start this giveaway. You have **{available_balance} {Env.currency_symbol()}**, but this tip would cost you **{giveaway_amount} {Env.currency_symbol()}**"
            )
            return

        try:
            # Lock this so concurrent giveaways can't be started/avoid race condition
            async with RedisLock(
                    await RedisDB.instance().get_redis(),
                    key=
                    f"{Env.currency_symbol().lower()}giveawaylock:{msg.guild.id}",
                    timeout=30,
                    wait_timeout=30) as lock:
                # See if giveaway already in progress
                active_giveaway = await Giveaway.get_active_giveaway(
                    server_id=msg.guild.id)
                if active_giveaway is not None:
                    await Messages.add_x_reaction(msg)
                    await Messages.send_error_dm(
                        msg.author,
                        "There's already a giveaway in progress on this server"
                    )
                    return
                # Start giveaway
                async with in_transaction() as conn:
                    gw = await Giveaway.start_giveaway_user(
                        server_id=msg.guild.id,
                        started_by=user,
                        amount=giveaway_amount,
                        entry_fee=fee,
                        duration=duration,
                        started_in_channel=msg.channel.id,
                        conn=conn)
                    # Create pending TX for this user
                    await Transaction.create_transaction_giveaway(
                        sending_user=user,
                        amount=giveaway_amount,
                        giveaway=gw,
                        conn=conn)
                # Announce giveaway
                embed = self.format_giveaway_announcement(gw)
                await msg.channel.send(embed=embed)
                for ch in config.Config.instance(
                ).get_giveaway_announce_channels():
                    if ch != msg.channel.id:
                        channel = msg.guild.get_channel(ch)
                        if channel is not None:
                            try:
                                await channel.send(embed=embed)
                            except Exception:
                                pass
                # Start the timer
                asyncio.create_task(self.start_giveaway_timer(gw))
        except LockTimeoutError:
            await Messages.add_x_reaction(msg)
            await Messages.send_error_dm(
                msg.author,
                "I couldn't start a giveaway, maybe someone else beat you to it as there can only be 1 active at a time."
            )
Ejemplo n.º 7
0
    async def movie_command(self, ctx: Context) -> None:
        """
        Gets a random snake-related movie from TMDB.

        Written by Samuel.
        Modified by gdude.
        Modified by Will Da Silva.
        """
        # Initially 8 pages are fetched. The actual number of pages is set after the first request.
        page = random.randint(1, self.num_movie_pages or 8)

        async with ctx.typing():
            response = await self.bot.http_session.get(
                "https://api.themoviedb.org/3/search/movie",
                params={
                    "query": "snake",
                    "page": page,
                    "language": "en-US",
                    "api_key": Tokens.tmdb,
                })
            data = await response.json()
            if self.num_movie_pages is None:
                self.num_movie_pages = data["total_pages"]
            movie = random.choice(data["results"])["id"]

            response = await self.bot.http_session.get(
                f"https://api.themoviedb.org/3/movie/{movie}",
                params={
                    "language": "en-US",
                    "api_key": Tokens.tmdb,
                })
            data = await response.json()

        embed = Embed(title=data["title"], color=SNAKE_COLOR)

        if data["poster_path"] is not None:
            embed.set_image(
                url=f"https://images.tmdb.org/t/p/original{data['poster_path']}"
            )

        if data["overview"]:
            embed.add_field(name="Overview", value=data["overview"])

        if data["release_date"]:
            embed.add_field(name="Release Date", value=data["release_date"])

        if data["genres"]:
            embed.add_field(name="Genres",
                            value=", ".join(
                                [x["name"] for x in data["genres"]]))

        if data["vote_count"]:
            embed.add_field(
                name="Rating",
                value=f"{data['vote_average']}/10 ({data['vote_count']} votes)",
                inline=True)

        if data["budget"] and data["revenue"]:
            embed.add_field(name="Budget", value=data["budget"], inline=True)
            embed.add_field(name="Revenue", value=data["revenue"], inline=True)

        embed.set_footer(
            text=
            "This product uses the TMDb API but is not endorsed or certified by TMDb."
        )
        embed.set_thumbnail(url="https://i.imgur.com/LtFtC8H.png")

        try:
            await ctx.send(embed=embed)
        except HTTPException as err:
            await ctx.send(
                "An error occurred while fetching a snake-related movie!")
            raise err from None
Ejemplo n.º 8
0
    async def github_repo_info(self, ctx: commands.Context, *repo: str) -> None:
        """
        Fetches a repositories' GitHub information.

        The repository should look like `user/reponame` or `user reponame`.
        """
        repo = "/".join(repo)
        if repo.count("/") != 1:
            embed = discord.Embed(
                title=random.choice(NEGATIVE_REPLIES),
                description="The repository should look like `user/reponame` or `user reponame`.",
                colour=Colours.soft_red
            )

            await ctx.send(embed=embed)
            return

        async with ctx.typing():
            repo_data = await self.fetch_data(f"{GITHUB_API_URL}/repos/{quote(repo)}")

            # There won't be a message key if this repo exists
            if "message" in repo_data:
                embed = discord.Embed(
                    title=random.choice(NEGATIVE_REPLIES),
                    description="The requested repository was not found.",
                    colour=Colours.soft_red
                )

                await ctx.send(embed=embed)
                return

        embed = discord.Embed(
            title=repo_data["name"],
            description=repo_data["description"],
            colour=discord.Colour.blurple(),
            url=repo_data["html_url"]
        )

        # If it's a fork, then it will have a parent key
        try:
            parent = repo_data["parent"]
            embed.description += f"\n\nForked from [{parent['full_name']}]({parent['html_url']})"
        except KeyError:
            log.debug("Repository is not a fork.")

        repo_owner = repo_data["owner"]

        embed.set_author(
            name=repo_owner["login"],
            url=repo_owner["html_url"],
            icon_url=repo_owner["avatar_url"]
        )

        repo_created_at = datetime.strptime(repo_data["created_at"], "%Y-%m-%dT%H:%M:%SZ").strftime("%d/%m/%Y")
        last_pushed = datetime.strptime(repo_data["pushed_at"], "%Y-%m-%dT%H:%M:%SZ").strftime("%d/%m/%Y at %H:%M")

        embed.set_footer(
            text=(
                f"{repo_data['forks_count']} ⑂ "
                f"• {repo_data['stargazers_count']} ⭐ "
                f"• Created At {repo_created_at} "
                f"• Last Commit {last_pushed}"
            )
        )

        await ctx.send(embed=embed)
Ejemplo n.º 9
0
    async def github_user_info(self, ctx: commands.Context, username: str) -> None:
        """Fetches a user's GitHub information."""
        async with ctx.typing():
            user_data = await self.fetch_data(f"{GITHUB_API_URL}/users/{quote_plus(username)}")

            # User_data will not have a message key if the user exists
            if "message" in user_data:
                embed = discord.Embed(
                    title=random.choice(NEGATIVE_REPLIES),
                    description=f"The profile for `{username}` was not found.",
                    colour=Colours.soft_red
                )

                await ctx.send(embed=embed)
                return

            org_data = await self.fetch_data(user_data["organizations_url"])
            orgs = [f"[{org['login']}](https://github.com/{org['login']})" for org in org_data]
            orgs_to_add = " | ".join(orgs)

            gists = user_data["public_gists"]

            # Forming blog link
            if user_data["blog"].startswith("http"):  # Blog link is complete
                blog = user_data["blog"]
            elif user_data["blog"]:  # Blog exists but the link is not complete
                blog = f"https://{user_data['blog']}"
            else:
                blog = "No website link available"

            embed = discord.Embed(
                title=f"`{user_data['login']}`'s GitHub profile info",
                description=f"```\n{user_data['bio']}\n```\n" if user_data["bio"] else "",
                colour=discord.Colour.blurple(),
                url=user_data["html_url"],
                timestamp=datetime.strptime(user_data["created_at"], "%Y-%m-%dT%H:%M:%SZ")
            )
            embed.set_thumbnail(url=user_data["avatar_url"])
            embed.set_footer(text="Account created at")

            if user_data["type"] == "User":

                embed.add_field(
                    name="Followers",
                    value=f"[{user_data['followers']}]({user_data['html_url']}?tab=followers)"
                )
                embed.add_field(
                    name="Following",
                    value=f"[{user_data['following']}]({user_data['html_url']}?tab=following)"
                )

            embed.add_field(
                name="Public repos",
                value=f"[{user_data['public_repos']}]({user_data['html_url']}?tab=repositories)"
            )

            if user_data["type"] == "User":
                embed.add_field(
                    name="Gists",
                    value=f"[{gists}](https://gist.github.com/{quote_plus(username, safe='')})"
                )

                embed.add_field(
                    name=f"Organization{'s' if len(orgs)!=1 else ''}",
                    value=orgs_to_add if orgs else "No organizations."
                )
            embed.add_field(name="Website", value=blog)

        await ctx.send(embed=embed)
Ejemplo n.º 10
0
 async def archiveserveremojis(self, ctx: commands.Context):
     async with ctx.typing():
         await self.partial_emoji_list_to_uploaded_zip(
             ctx, ctx.guild.emojis)
Ejemplo n.º 11
0
    async def c_add(self, ctx: Context, channel: TextChannel, *, content: str):
        perm_target: Permissions = channel.permissions_for(ctx.me)
        perm_this: Permissions = ctx.channel.permissions_for(ctx.me)
        if not perm_target.send_messages:
            return ctx.send(f"{ctx.author.mention} 채널 {channel.mention} 에 메시지를 보낼 수 없습니다. "
                            f"권한을 확인해주세요.")
        if not perm_this.add_reactions:
            return ctx.send(f"{ctx.author.mention} 이 채널에 이모지를 달 수 없습니다. 권한을 확인해주세요.")
        if not perm_this.manage_messages:
            return ctx.send(f"{ctx.author.mention} 이 채널에서 메시지를 지울 수 없습니다. 권한을 확인해주세요.")

        embed_data = Embed(title="이모지 -> 역할: 새로운 메시지", description=f"제목: {content}").to_dict()
        embed_data["fields"] = [
            {
                "name": "등록된 이모지 목록",
                "value": "<없음>",
                "inline": False,
                },
            {
                "name": "이모지 추가",
                "value": "반응할 이모지를 이 메시지에 달아주세요.\n"
                         "끝내려면 ✅ 이모지를 눌러주세요.",
                "inline": False,
                }
            ]
        print(embed_data)
        msg = await ctx.send(embed=Embed.from_dict(embed_data))
        await msg.add_reaction("✅")

        def check_same_context(r: Reaction, u: Union[User, Member]):
            print(r, u)
            return u.id == ctx.author.id and r.message.id == msg.id

        def check_same_user(m: Message):
            print(m)
            return m.author.id == ctx.author.id

        first = True
        reactions: Dict[Reaction, Role] = {}
        while True:
            try:
                if not first and reactions:
                    embed_data["fields"][0]["value"] = "\n".join(f"{k} {v}" for k, v in reactions.items())
                else:
                    embed_data["fields"][0]["value"] = "<없음>"

                embed_data["fields"][1] = {
                    "name": "이모지 추가",
                    "value": "반응할 이모지를 이 메시지에 달아주세요.\n"
                             "끝내려면 ✅ 이모지를 눌러주세요.",
                    "inline": False,
                    }
                await msg.edit(embed=Embed.from_dict(embed_data))

                reaction, user = await self.bot.wait_for("reaction_add", check=check_same_context)

                if reaction.emoji == "✅":
                    break

                if (isinstance(reaction.emoji, Emoji) and not reaction.emoji.available) or \
                        isinstance(reaction.emoji, PartialEmoji):
                    await ctx.send("봇이 이용할 수 없는 이모지입니다. 이모지 등록으로 돌아갑니다.", delete_after=5)
                    continue

                embed_data["fields"][1]["name"] = f"{reaction}의 역할 설정"
                embed_data["fields"][1]["value"] = "해당 이모지에 지급할 역할을 멘션해주세요."
                await msg.edit(embed=Embed.from_dict(embed_data))

                try:
                    role_message: Message = await self.bot.wait_for("message", check=check_same_user, timeout=60*10)
                    if not role_message.role_mentions:
                        await ctx.send("올바른 역할을 멘션하지 않았습니다. 이모지 등록으로 돌아갑니다.", delete_after=5)
                        continue

                    target_role = role_message.role_mentions[0]
                    reactions[reaction] = target_role
                    first = False
                    continue
                except asyncio.TimeoutError:
                    await ctx.send("시간 초과로 등록을 취소했습니다. 이모지 등록으로 돌아갑니다.", delete_after=5)
                    continue
            except asyncio.TimeoutError:
                embed_data["fields"][1] = {
                    "name": "이모지 추가",
                    "value": "반응할 이모지를 이 메시지에 달아주세요.\n"
                             "끝내려면 ✅ 이모지를 눌러주세요.",
                    "inline": False,
                    }
                await msg.edit(embed=Embed.from_dict(embed_data))
            except:
                await ctx.send("오류로 인해 등록을 취소했습니다.")
                return await ctx.send(traceback.format_exc())

        await msg.clear_reactions()
        del embed_data["fields"][1]
        embed_data["title"] = content
        embed_data["description"] = ""
        embed_data["fields"][0]["name"] = "・"

        g_c = f"{ctx.guild.id}, {ctx.channel.id}"
        target_msg = await channel.send(embed=Embed.from_dict(embed_data))
        for k in reactions:
            await target_msg.add_reaction(k.emoji)

        if g_c not in self.target_messages:
            self.target_messages[g_c] = {}

        self.target_messages[g_c][str(target_msg.id)] = \
            dict((k.emoji if isinstance(k.emoji, str) else str(k.emoji.id), v.id) for k, v in reactions.items())

        print(self.target_messages)
        self.save_messages()
        await ctx.send(f"{ctx.author.mention} 등록이 완료되었습니다.")
Ejemplo n.º 12
0
 async def _ore(self, ctx: commands.Context):
     hm: discord.Message = await ctx.send(embed=discord.Embed(
         colour=discord.Colour(WHITE)))
     async with ctx.typing():
         await self.ore_inventory(hm, ctx.author)
Ejemplo n.º 13
0
 async def _bal(self, ctx: commands.Context):
     hm: discord.Message = await ctx.send(embed=discord.Embed(
         colour=discord.Colour(WHITE)))
     async with ctx.typing():
         await self.detail_money(hm, ctx.author)
Ejemplo n.º 14
0
 async def on_user_error(self, ctx: commands.Context, error: Exception):
     if isinstance(error, commands.BadArgument):
         ctx.handled = True
         await self.bot.send_error(
             ctx, "ユーザーが見つかりませんでした!",
             f"`{ctx.message.content.split()[1]}`というユーザーは見つかりませんでした...")
Ejemplo n.º 15
0
 async def adminrole(self, ctx: Context, role: Role):
     async with ctx.typing():
         self._db.set_admin_role(ctx.guild.id, role.id)
         await ctx.send(':white_check_mark:  Role ' +
                        '`{}` is now set as admin role.'.format(role.name))
Ejemplo n.º 16
0
 async def reloadconfigs(self, ctx: commands.Context):
     """Reloads all server configs from disk"""
     async with ctx.typing():
         Configuration.load_master()
         await Configuration.initialize(self.bot)
     await ctx.send("Configs reloaded")
Ejemplo n.º 17
0
async def hypixel(ctx: commands.Context,
                  player: str,
                  bot: commands.Bot,
                  token,
                  key: str = None):
    with ctx.typing():
        data = await _get(player, token)
    if data["player"] is None:
        await ctx.send("That player doesn't seem to exist on hypixel.")
        return

    player = data["player"]
    player_name = player["displayname"]

    e = _mk_embed(player_name, key.split(" ")[0] if key else None)
    key = key.lower() if key else key

    if key is None:
        e.add_field(name="Previous Names",
                    value=_("\n".join(player["knownAliases"])))
        if "mcVersionRp" in player.keys():
            e.add_field(name="Minecraft Version",
                        value=_(player["mcVersionRp"]))
            # .strftime("%x %X")
        tz = pytz.timezone("America/Winnipeg")
        time = tz.localize(datetime.fromtimestamp(player["lastLogout"] / 1000))
        player_tz = bot.db.lookup_timezone(ctx.author.id)[1]
        timel = time.astimezone(
            pytz.timezone(player_tz)) if player_tz else None
        #
        e.add_field(
            name="Last Seen",
            value=
            f"{time.strftime('%x %X')} (Server)\n{timel.strftime('%x %X') if timel else 'N/A'} (Local)"
            if player["lastLogout"] > player["lastLogin"] else "Now")
        e.add_field(name="Hypixel Level",
                    value=f"{_get_level(player['networkExp'])}")

    elif key in ["bedwars", "bw"]:
        player = player["stats"]["Bedwars"]
        prefixes = {
            "2v2": "eight_two",
            "3v3v3v3": "four_three",
            "4v4v4v4": "four_four",
            "4v4": "two_four"
        }
        s = "```"
        s += f"Level {_get_level(player['Experience'])}\n"
        for _prefix in prefixes:
            w = player[f"{prefixes[_prefix]}_wins_bedwars"]
            l = player[f"{prefixes[_prefix]}_losses_bedwars"]
            fk = player[f"{prefixes[_prefix]}_final_kills_bedwars"]
            k = player[f"{prefixes[_prefix]}_kills_bedwars"]
            d = player[f"{prefixes[_prefix]}_deaths_bedwars"]
            s += _prefix.center(13, "=") + "\n"
            s += f"{w}/{w + l} Won\n"
            s += f"{k}:{d} KDR ({round(k / d, 2)}\n"
            s += f"({fk} Final Kills)\n"

        e.description = s + "```"

    elif key in ["skywars", "sw"]:
        player = player["stats"]["SkyWars"]
        prefixes = {
            "Solo": "solo",
            "Solo Normal": "solo_normal",
            "Solo Insane": "solo_insane",
            "Teams": "team",
            "Teams Normal": "teams_normal",
            "Teams Insane": "teams_insane"
        }
        results = []
        for _prefix in prefixes:
            s = [_prefix]
            vk = player.get(f'void_kills_{prefixes[_prefix]}', "-")
            w = player.get(f'wins_{prefixes[_prefix]}', "-")
            g = player.get(f'games_{prefixes[_prefix]}', "-")
            k = player.get(f'kills_{prefixes[_prefix]}', "-")
            d = player.get(f'deaths_{prefixes[_prefix]}', "-")
            s.append(f"{w}/{g} Won".ljust(21, " "))
            s.append(
                f"{k}:{d} KDR ({round(k / d, 2) if '-' not in [k, d] else ''})"
                .ljust(21, " "))
            s.append(f"{vk} Void kills".ljust(21, " "))
            results.append(s)

        e.description = ""
        for r in results:
            e.add_field(name=r[0], value="```" + "\n".join(r[1:4]) + "```")

    elif key in ["uhc"]:
        player = player["stats"]["UHC"]
        e.description = "```" \
                        f"{player['kills']} K\n" \
                        f"{player['deaths']} D" \
                        "```"

    elif key.split(" ")[0] in ["sb", "skyblock"]:
        player = player["stats"]["SkyBlock"]["profiles"]
        if len(key.split(" ")) == 1:
            e.description = f"Profiles:\n" + \
                            '\n'.join(['-' + pro['cute_name'] for pro in player.values()])
        else:
            for pro in player.values():
                if pro["cute_name"].lower() == key.split(" ")[1].lower():
                    profile_id = pro["profile_id"]
                    name = pro["cute_name"].title()
                    e.url = f"https://sky.lea.moe/stats/{player_name}/{name}"
                    e.title = "Skyblock temporarily disabled"
                    e.description = f"This is currently disabled as it is being redone. Visit " \
                                    f"[here](https://sky.lea.moe/stats/{player_name}/{name}) to view profile info"
                    await ctx.send(embed=e)
                    return
                    # break
            else:
                e.description = f"Profiles:\n" + \
                                '\n'.join(['-' + pro['cute_name'] for pro in player.values()])
                await ctx.send(embed=e)
                return
            e.title += f" ({name})"
            async with aiohttp.ClientSession() as sess:
                async with sess.get(
                        f"https://api.hypixel.net/skyblock/profile?key={token}&profile={profile_id}"
                ) as resp:
                    status = resp.status
                    data2 = await resp.json()
            profile = data2["profile"]
            player_sb_id = data["player"]["uuid"]
            player_sb = profile["members"][player_sb_id]
            if "slayer_bosses" in player_sb:
                e.add_field(
                    name="Slayers",
                    value="\n".join([
                        f"{k.title()}: {_slayer_level(v.get('xp', 0), k)}"
                        for k, v in player_sb["slayer_bosses"].items()
                    ]))
                e.add_field(
                    name="Money",
                    value=
                    f"Bank: {round(float(profile.get('banking', {'balance': 0})['balance']), 1)} Coins\n"
                    f"Purse: {round(float(player_sb['coin_purse']), 1)} Coins")
            e.add_field(
                name="Experience",
                value="\n".join([
                    k.title() + ": " +
                    str(_get_level(player_sb.get(f"experience_skill_{k}", 0)))
                    for k in
                    "alchemy,runecrafting,farming,combat,mining,enchanting,fishing,foraging,carpentry"
                    .split(",")
                ]))
            e.add_field(
                name="Misc",
                value=
                f"Fairy Souls: {player_sb.get('fairy_souls_collected', 0)}\n")
            e.set_footer(text="Click the link for more data.")
            print(player_sb)

    elif key in ["raw"]:
        e.description = await asyncio.get_event_loop().run_in_executor(
            None, _raw, data)

    await ctx.send(embed=e)
Ejemplo n.º 18
0
 async def quote(self, ctx: commands.Context, messageid: int):
     """Quotes the requested message."""
     async with ctx.typing():
         try:
             message = LoggedMessage.get(messageid=messageid)
             embed = discord.Embed(colour=discord.Color(0xd5fff),
                                   timestamp=datetime.utcfromtimestamp(
                                       message.timestamp))
             user = await ctx.bot.get_user_info(message.author)
             embed.set_author(name=user.name, icon_url=user.avatar_url)
             embed.set_footer(
                 text=
                 f"Sent in #{self.bot.get_channel(message.channel).name} | Quote requested by {ctx.author.display_name} | {messageid}"
             )
             attachmentsraw = LoggedAttachment.select().where(
                 LoggedAttachment.messageid == messageid)
             attachments = []
             for attachmentraw in attachmentsraw:
                 attachments.append(attachmentraw)
             if attachments != [] and attachments != None:
                 if len(attachments) == 1 and attachments[0].isImage:
                     embed.set_image(
                         url=self.bot.aes.decrypt(attachments[0].url))
                 else:
                     for attachment in attachments:
                         embed.add_field(name="Attachment link",
                                         value=self.bot.aes.decrypt(
                                             attachment.url))
             if message.content is not None and message.content is not "":
                 embed.description = self.bot.aes.decrypt(message.content)
             await ctx.send(embed=embed)
             await ctx.message.delete()
         except LoggedMessage.DoesNotExist:
             dmessage = None
             for server in ctx.bot.guilds:
                 for txtchannel in server.text_channels:
                     try:
                         dmessage = await txtchannel.get_message(messageid)
                         embed = discord.Embed(
                             colour=discord.Color(0xd5fff),
                             timestamp=datetime.utcfromtimestamp(
                                 dmessage.created_at.timestamp()))
                         embed.set_author(
                             name=dmessage.author.name,
                             icon_url=dmessage.author.avatar_url)
                         embed.set_footer(
                             text=
                             f"Sent in #{dmessage.channel.name} | Quote Requested by {ctx.author.display_name} | {dmessage.id}"
                         )
                         if dmessage.attachments != []:
                             if len(dmessage.attachments) == 1:
                                 embed.set_image(
                                     url=dmessage.attachments[0].url)
                             else:
                                 for attachment in dmessage.attachments:
                                     embed.add_field(name="Attachment link",
                                                     value=attachment.url)
                         if dmessage.content is not None:
                             embed.description = dmessage.content
                         await ctx.send(embed=embed)
                         await ctx.message.delete()
                         for a in dmessage.attachments:
                             LoggedAttachment.get_or_create(
                                 id=a.id,
                                 url=self.bot.aes.encrypt(a.url),
                                 isImage=(a.width is not None
                                          or a.width is 0),
                                 messageid=dmessage.id)
                         LoggedMessage.create(
                             messageid=messageid,
                             content=self.bot.aes.encrypt(dmessage.content),
                             author=dmessage.author.id,
                             timestamp=dmessage.created_at.timestamp(),
                             channel=dmessage.channel.id)
                     except discord.Forbidden:
                         pass
                     except discord.NotFound:
                         pass
             if dmessage is None:
                 await ctx.send(
                     "Sorry, I couldn't find that message anywhere")
Ejemplo n.º 19
0
    async def _pict(self, ctx: commands.Context, *args):
        if len(args) == 0:
            await ctx.send(
                content=
                f"**Insert your argument.**\nExample Command : {get_prefix(ctx.guild.id)}img Maldives"
            )
        else:
            # Connect with Google Custom Search
            async with ctx.typing():
                search_term: str = " ".join(args)
                response = self.srv.list(q=search_term,
                                         cx=CSE_ID,
                                         searchType="image",
                                         num=10,
                                         fileType='jpg,jpeg,png',
                                         safe='active').execute()
                index: int = 0
                max_index = len(response["items"])
                link_url: list = [i["link"] for i in response["items"]]

            # Initiate Embed
            menus: list = ["⏮️", "⬅️", "⏹", "➡️"]
            emb = discord.Embed(
                title=f"Search Picture | Image : {index + 1}/{max_index}",
                description=
                f"Searching for {search_term}, Result ({max_index} Entries) : ",
                colour=WHITE)
            emb.set_image(url=link_url[index])
            emb.set_footer(
                text=
                f"Image : {index + 1}/{max_index} | Searched by {ctx.author.nick if ctx.author.nick is not None else ctx.author.name}"
            )
            hm: discord.Message = await ctx.send(embed=emb)
            for i in menus:
                await hm.add_reaction(i)
            try:
                r: discord.Reaction
                u: discord.User
                while True:
                    r, u = await self.bot.wait_for(
                        event="reaction_add",
                        timeout=30.0,
                        check=lambda reaction, user: True
                        if str(reaction.emoji
                               ) in menus and user == ctx.author else False)
                    if str(r.emoji) == "⏮️":
                        if index == 0:
                            continue
                        else:
                            index = 0
                    elif str(r.emoji) == "⬅️":
                        if index > 0:
                            index -= 1
                        else:
                            continue
                    elif str(r.emoji) == "⏹":
                        emb = discord.Embed(
                            title=
                            f"Search Picture | Image : {index + 1}/{max_index}",
                            description=
                            f"Searching for {search_term}, Result ({max_index} Entries) : ",
                            colour=WHITE)
                        emb.set_image(url=link_url[index])
                        emb.set_author(name=ctx.author.name,
                                       icon_url=ctx.author.avatar_url)
                        await r.remove(u)
                        await hm.edit(embed=emb)
                        for j in menus:
                            await hm.remove_reaction(j, ctx.me)
                        return
                    else:
                        if index < max_index - 1:
                            index += 1
                        else:
                            continue
                    emb = discord.Embed(
                        title=
                        f"Search Picture | Image : {index + 1}/{max_index}",
                        description=
                        f"Searching for {search_term}, Result ({max_index} Entries) : ",
                        colour=WHITE)
                    emb.set_image(url=link_url[index])
                    emb.set_footer(
                        text=
                        f"Searched by {ctx.author.nick if ctx.author.nick is not None else ctx.author.name}"
                    )
                    await r.remove(u)
                    await hm.edit(embed=emb)
            except asyncio.TimeoutError:
                emb.set_footer(
                    text=
                    f"Searched by {ctx.author.nick if ctx.author.nick is not None else ctx.author.name} | Request Timeout"
                )
                await hm.edit(embed=emb)
                for j in menus:
                    await hm.remove_reaction(j, ctx.me)
Ejemplo n.º 20
0
 async def send(self, ctx: commands.Context, to_user=None, amount=None):
     try:
         amount = BotUtils.parseMoney(amount)
     except:
         await ctx.send(f"{ctx.author.mention} That's not a valid amount! 🤔"
                        )
         return
     if amount <= 0:
         await ctx.send(f"{ctx.author.mention} Amount must be over $1")
         return
     if to_user == None:
         ctx.send("You can't send money to no one.")
     to_user = to_user.strip("<!@>")
     try:
         to_user = self.Bot.get_user(int(to_user))
     except:
         await ctx.send(f"{ctx.author.mention} Not a valid user!")
         return
     if to_user.id == ctx.author.id:
         # Blocks people sending themselves money
         await ctx.send(
             f"{ctx.author.mention} You can't send yourself money!")
         return
     # Get users in the database
     targetQuery = self.Database.GetFromTable("Users",
                                              f"id = {to_user.id}")[0]
     userQuery = self.Database.GetFromTable("Users",
                                            f"id = {ctx.author.id}")[0]
     targetQueryMoney = BotUtils.parseMoney(targetQuery[3])
     userMoney = BotUtils.parseMoney(userQuery[3])
     if userMoney >= amount:
         confirmation = await ctx.send(
             f"Do you want to give **{to_user}** **${amount:,.2f}**?")
         conf = await self.createConfirmation(confirmation, ["✅", "❌"],
                                              ctx.author)
         if conf:
             userMoney -= amount
             targetQueryMoney += amount
             # Gives target $amount
             self.Database.GiveUserMoney(ctx.author.id, userMoney)
             self.Database.GiveUserMoney(to_user.id, targetQueryMoney)
             transactionEmbed = discord.Embed(
                 title=f"Transaction {ctx.author} => {to_user}",
                 timestamp=datetime.now(),
                 color=0xF3BF0C)
             # Sender
             transactionEmbed.add_field(name="**SENDER**",
                                        value=f"{ctx.author}",
                                        inline=True)
             transactionEmbed.add_field(name="**NEW BALANCE**",
                                        value=f"||${userMoney:,.2f}||",
                                        inline=True)
             transactionEmbed.add_field(name="**ID**",
                                        value=f"{ctx.author.id}",
                                        inline=True)
             # Receiver
             transactionEmbed.add_field(name="**RECEIVER**",
                                        value=f"{to_user}",
                                        inline=True)
             transactionEmbed.add_field(
                 name="**NEW BALANCE**",
                 value=f"||${targetQueryMoney:,.2f}||",
                 inline=True)
             transactionEmbed.add_field(name="**ID**",
                                        value=f"{to_user.id}",
                                        inline=True)
             await ctx.send(embed=transactionEmbed)
         elif conf == False:
             await confirmation.edit(content="Transaction cancelled!")
             return
     else:
         await ctx.send(
             f"{ctx.author.mention} You don't have that much money!")
Ejemplo n.º 21
0
 async def branding_refresh(self, ctx: commands.Context) -> None:
     """Sync currently available assets with branding repository."""
     async with ctx.typing():
         await self.refresh()
         await self.branding_info(ctx)
Ejemplo n.º 22
0
 async def cog_before_invoke(self, ctx: Context):
     ctx.error = False
     msg = ctx.message
     # Check paused
     if await RedisDB.instance().is_paused():
         ctx.error = True
         await Messages.send_error_dm(msg.author, f"Transaction activity is currently suspended. I'll be back online soon!")
         return
     if ctx.command.name == 'send_cmd':
         try:
             ctx.send_amount = RegexUtil.find_send_amounts(msg.content)
             if Validators.too_many_decimals(ctx.send_amount):
                 await Messages.send_error_dm(msg.author, f"You are only allowed to use {Env.precision_digits()} digits after the decimal.")
                 ctx.error = True
                 return
             elif (ctx.send_amount < 0.01 and Env.banano()) or (ctx.send_amount < 0.000001 and not Env.banano()):
                 await Messages.send_error_dm(msg.author, f"Amount too small")
                 ctx.error = True
                 return                    
         except AmountMissingException:
             await Messages.send_usage_dm(msg.author, SEND_INFO)
             ctx.error = True
             return
         except AmountAmbiguousException:
             await Messages.send_error_dm(msg.author, "You can only specify 1 amount to send")
             ctx.error = True
             return
     if ctx.command.name in ['send_cmd', 'sendmax_cmd']:
         # See if user exists in DB
         user = await User.get_user(msg.author)
         if user is None:
             await Messages.send_error_dm(msg.author, f"You should create an account with me first, send me `{config.Config.instance().command_prefix}help` to get started.")
             ctx.error = True
             return
         elif user.frozen:
             ctx.error = True
             await Messages.send_error_dm(msg.author, f"Your account is frozen. Contact an admin if you need further assistance.")
             return
         # Update name, if applicable
         await user.update_name(msg.author.name)
         ctx.user = user
         # See if they are spammin'
         withdraw_delay = await user.get_next_withdraw_s()
         if withdraw_delay > 0:
             await Messages.send_error_dm(msg.author, f"You need to wait {withdraw_delay}s before you can withdraw again")
             ctx.error = True
             return
         try:
             ctx.destination = RegexUtil.find_address_match(msg.content)
         except AddressMissingException:
             await Messages.send_usage_dm(msg.author, SEND_INFO)
             ctx.error = True
             return
         except AddressAmbiguousException:
             await Messages.send_error_dm(msg.author, "You can only specify 1 destination address")
             ctx.error = True
             return
         if not Validators.is_valid_address(ctx.destination):
             await Messages.send_error_dm(msg.author, "The destination address you specified is invalid")
             ctx.error = True
             return
Ejemplo n.º 23
0
    async def _play(self, ctx: commands.Context, *, search: str):
        """Plays a song
        
        Can either find a song via its Youtube URL or its keywords
        """

        if not ctx.voice_state.voice:
            await ctx.invoke(self._join)

        httpFlag = False

        if (search.__contains__("https://")):
            httpFlag = True
        else:
            search = "ytsearch10:" + search

        async with ctx.typing():
            try:
                if not httpFlag:
                    searchList = await YTDLSource.find_source(
                        ctx, search, loop=self.bot.loop)
                else:
                    source = await YTDLSource.create_source(ctx,
                                                            search,
                                                            loop=self.bot.loop)

            except YTDLError as e:
                await ctx.send(
                    'An error occurred while processing this request: {}'.
                    format(str(e)))
                await ctx.voice_state.stop()
                del self.voice_states[ctx.guild.id]
            else:
                if not httpFlag:
                    embed = (discord.Embed(
                        title='These are the results I found:',
                        color=discord.Color.blurple()))
                    i = 0
                    for entry in searchList:
                        if i == 5:
                            break
                        else:
                            try:
                                embed.add_field(name='Song #%d' % (i + 1),
                                                value=str(entry['title']),
                                                inline=False)
                                i += 1
                            except KeyError:
                                pass

                    sent = await ctx.send(
                        embed=embed)  #creates a message object called "sent"

                    i = 0
                    reactionEmotes = ['1️⃣', '2️⃣', '3️⃣', '4️⃣', '5️⃣', '❌']
                    for i in range(0, 6):
                        await sent.add_reaction(reactionEmotes[i])

                    def check(reaction, user):
                        if user == ctx.author:
                            if str(reaction.emoji) == '1️⃣' or str(
                                    reaction.emoji
                            ) == '2️⃣' or str(reaction.emoji) == '3️⃣' or str(
                                    reaction.emoji) == '4️⃣' or str(
                                        reaction.emoji) == '5️⃣' or str(
                                            reaction.emoji) == '❌':
                                return True
                            else:
                                return False
                        else:
                            return False

                    def convertToIdx(emote):
                        if str(emote) == '1️⃣':
                            return 0
                        elif str(emote) == '2️⃣':
                            return 1
                        elif str(emote) == '3️⃣':
                            return 2
                        elif str(emote) == '4️⃣':
                            return 3
                        elif str(emote) == '5️⃣':
                            return 4
                        elif str(emote) == '❌':
                            return -1
                        else:
                            return -2

                    try:
                        result = await self.bot.wait_for('reaction_add',
                                                         timeout=30.0,
                                                         check=check)
                        opt = convertToIdx(result[0])
                        if opt < 0:
                            await sent.delete()
                            if ctx.voice_state.current == None:
                                await ctx.voice_state.stop()
                                del self.voice_states[ctx.guild.id]
                            if (opt == -2):
                                raise commands.CommandError(
                                    'Invalid reaction!')

                    except asyncio.TimeoutError:
                        await ctx.voice_state.stop()
                        del self.voice_states[ctx.guild.id]
                    else:
                        if (opt >= 0):
                            await sent.delete()
                            urlPost = searchList[opt]['url']
                            ytURL = "https://www.youtube.com/watch?v=" + urlPost
                            source = await YTDLSource.create_source(
                                ctx, ytURL, loop=self.bot.loop)
                            song = Song(source)
                            await ctx.voice_state.songs.put(song)
                            await ctx.send('Enqueued {}'.format(str(source)))

                else:
                    song = Song(source)
                    await ctx.voice_state.songs.put(song)
                    await ctx.send('Enqueued {}'.format(str(source)))
Ejemplo n.º 24
0
 async def servers(self, ctx: commands.Context):
     async with ctx.typing():
         async with self.bot.db_engine.acquire() as conn:
             if ctx.invoked_subcommand is None:
                 servers = await BotServers.load_all(conn, ctx.guild)
                 await ctx.send(servers.printable)
Ejemplo n.º 25
0
 async def train_command(self, ctx: disextc.Context):
     async with ctx.typing():
         time = await self.train()
         await ctx.send(f'training finished in {time} seconds.')
Ejemplo n.º 26
0
    async def show(self, ctx: commands.Context, *, tank_name: str):
        """
        This command produces a gif of the specified tank. DO NOT USE SLASH COMMANDS
        """

        # Typing Indicator
        async with ctx.typing():

            # variables
            move_x = []
            min_max_y = {"Fish Bowl": (20, 50), "Small Tank": (15, 200), "Medium Tank": (20, 200)}
            min_max_x = {"Fish Bowl": (-180, 150), "Small Tank": (-180, 360), "Medium Tank": (-800, 720)}
            fish_size_speed = {'Fish Bowl': 17, 'Small Tank': 18, 'Medium Tank': 25}
            im = []
            fishes = {}
            fish_y_value = []
            files = []
            dead_alive = []
            golden_inverted_normal = 'normal'
            fish_selections = []
            gif_name = random.randint(1, 1000)
            tank_types = {"Fish Bowl": "fishbowl", "Small Tank": "Small_Tank_2D", "Medium Tank": "Medium_Tank_2D"}
            tank_slot = 0

            # gets database info for tank
            async with self.bot.database() as db:
                selected_fish = await db("""SELECT * FROM user_fish_inventory WHERE user_id = $1 AND tank_fish = $2""", ctx.author.id, tank_name)
                tank_row = await db("""SELECT * FROM user_tank_inventory WHERE user_id =$1""", ctx.author.id)

            # Check if the tank exists
            if not tank_row:
                return await ctx.send("You have no tanks! use the `firsttank` command to get one!")
            # finds the tank slot
            for tank_slot_in in tank_row[0]['tank_name']:
                if tank_slot_in == tank_name:
                    break
                else:
                    tank_slot += 1
            # finds the type of tank it is and checks if it exists
            if tank_name not in tank_row[0]['tank_name']:
                return await ctx.send(
                    f"You have no tank named **{tank_name}**!",
                    allowed_mentions=discord.AllowedMentions.none(),
                    )
            tank_info = tank_row[0]['tank_type'][tank_slot]

            # finds what type of fish it is, then adds the paths to a list, as well as finding the fish's random starting position
            for selected_fish_types in selected_fish:
                fishes[selected_fish_types['fish']] = [selected_fish_types['fish_alive']]
            for name, info in fishes.items():
                if "golden" in name:
                    fishes[name].append(name.lstrip("golden_"))
                    name = name.lstrip("golden_")
                    golden_inverted_normal = 'golden'
                if "inverted" in name:
                    fishes[name].append(name.lstrip("inverted_"))
                    name = name.lstrip("inverted_")
                    golden_inverted_normal = 'inverted'
                else:
                    fishes[name].append(name)
                for _, fish_types in self.bot.fish.items():
                    for fish_type, fish_data in fish_types.items():
                        if info[1] == fish_data['raw_name']:
                            move_x.append(random.randint(min_max_x[tank_info][0], min_max_x[tank_info][1]))
                            fish_y_value.append(random.randint(min_max_y[tank_info][0], min_max_y[tank_info][1]))
                            fish_selections.append(f"C:/Users/JT/Pictures/Aqua/assets/images/{golden_inverted_normal}_fish_size{fish_data['image'][44:]}")
                            if info[0] is True:
                                dead_alive.append(True)
                            else:
                                dead_alive.append(False)


            # gif variables
            file_prefix = "C:/Users/JT/Pictures/Aqua/assets/images"
            gif_filename = f'{file_prefix}/gifs/actual_gifs/user_tank{gif_name}.gif'

            # Open our constant images
            tank_theme = tank_row[0]['tank_theme'][tank_slot]
            background = Image.open(f"{file_prefix}/background/{tank_theme}_background_{tank_types[tank_info]}.png")
            midground = Image.open(f"{file_prefix}/background/{tank_theme}_background_{tank_types[tank_info]}_midground.png")
            foreground = Image.open(f"{file_prefix}/background/{tank_types[tank_info]}.png")
            for x in range(0, len(fish_selections)):
                im.append(Image.open(fish_selections[x]))

            # For each frame of the gif...
            for _ in range(60):

                # Add a fish to the background image
                this_background = background.copy()
                # adds multiple fish and a midground if its a fishbowl
                for x in range(0, len(im)):
                    if dead_alive[x] is False:
                        this_background.paste(im[x].rotate(180), (move_x[x], fish_y_value[x]), im[x].rotate(180))
                    else:
                        this_background.paste(im[x], (move_x[x], fish_y_value[x]), im[x])
                        move_x[x] += fish_size_speed[tank_info]
                        if move_x[x] > min_max_x[tank_info][1]:
                            move_x[x] = min_max_x[tank_info][0]
                this_background.paste(midground, (0, 0), midground)
                this_background.paste(foreground, (0, 0), foreground)

                # Save the generated image to memory
                f = io.BytesIO()
                this_background.save(f, format="PNG")
                f.seek(0)
                files.append(f)

                # Move fish

            # Save the image sequence to a gif
            image_handles = [imageio.imread(i) for i in files]
            imageio.mimsave(gif_filename, image_handles)

            # Close all our file handles because oh no
            for i in files:
                i.close()

        # Send gif to Discord
        await ctx.send(file=discord.File(gif_filename))
Ejemplo n.º 27
0
 async def cog_before_invoke(self, ctx: commands.Context):
     ctx.voice_state = self.get_voice_state(ctx)
Ejemplo n.º 28
0
 async def on_all_error(self, ctx: commands.Context, error):
     if isinstance(error, commands.CommandOnCooldown):
         ctx.handled = True
         await self.bot.send_cooldown_error(
             ctx, error, 1, 10
         )
Ejemplo n.º 29
0
    async def vote_analyze(self, ctx: commands.Context, id: str):
        '''
        投票の集計結果を表示します
        '''
        msg1 = await ctx.send(f'集計中 {self.bot.custom_emojis.loading}')
        vote = await q.Vote(self.bot, id).get()
        if vote is None:
            return await ctx.send("該当の投票は存在しません")
        with ctx.typing():
            try:
                msg: discord.Message = await ctx.fetch_message(vote.message)
            except discord.NotFound:
                return await self.bot.send_error(ctx, 'メッセージが見つかりません', '該当のメッセージは削除されているようです')
            args = [
                arg[2:]
                for arg in
                "".join(
                    msg.embeds[0]
                    .description
                    .split("\n\n")[1:]
                ).split(" ")
                if arg != ''
            ]
            if not args:
                args = ['はい', 'いいえ']
            points = {i: [k, 0, "", None] for i, k in enumerate(args)}
            for reaction in msg.reactions:
                try:
                    idx = alphabet_emojis.index(reaction.emoji)
                except ValueError:
                    continue
                points[idx][3] = reaction.emoji
                points[idx][1] = reaction.count - 1
                us = [u for u in await reaction.users().flatten() if u.id != self.bot.user.id]
                t = 5
                if len(us) == 0:
                    points[idx][2] = '-'
                elif len(us) > t:
                    points[idx][2] = ' '.join(
                        [f'{u.mention}' for u in us[:t]]) + f' ほか{len(us) - t}名'
                else:
                    points[idx][2] = ' '.join(
                        [f'{u.mention}' for u in us])
            if sum([point[1] for point in points.values()]) == 0:
                return await ctx.send("まだ誰も投票していないようです")

            def create_image(vt, pts):
                plt.style.use('dark_background')
                plt.figure(figsize=(7, 4))
                plt.axes().set_aspect('equal')
                x = [v[1] for v in pts.values()]
                l = [f"{v[0]}: {v[1]}" for v in pts.values()]
                f = io.BytesIO()
                plt.title(vote.description, fontsize=16)
                plt.rcParams["font.size"] = 14
                plt.pie(x, labels=l, startangle=90)
                plt.savefig(f, format="png")
                f.seek(0)
                return discord.File(f, filename="chart.png")
            file = await self.bot.loop.run_in_executor(None, create_image, vote, points)
            url = f"https://discord.com/channels/{vote.guild}/{vote.channel}/{vote.message}"
            embed = discord.Embed(title="投票集計", color=config.theme_color)
            embed.description = f"[{vote.description}]({url}) by <@{vote.user}>"
            for idx, point in points.items():
                if point[3]:
                    embed.add_field(
                        name=f"{point[3]}: {point[0]} ({point[1]})", value=point[2], inline=False)
            embed.set_author(name=f"投票ID: {id}",
                             icon_url=self.bot.user.avatar_url)
            await msg1.edit(content='', embed=embed)
            await ctx.send(file=file)
Ejemplo n.º 30
0
    async def eval_command(self, ctx: Context, *, code: str = None):
        """
        Run some code. get the result back. We've done our best to make this safe, but do let us know if you
        manage to find an issue with it!

        This command supports multiple lines of code, including code wrapped inside a formatted code block.
        """

        if ctx.author.id in self.jobs:
            await ctx.send(
                f"{ctx.author.mention} You've already got a job running - please wait for it to finish!"
            )
            return

        if not code:  # None or empty string
            return await ctx.invoke(self.bot.get_command("help"), "eval")

        log.info(
            f"Received code from {ctx.author.name}#{ctx.author.discriminator} for evaluation:\n{code}"
        )
        self.jobs[ctx.author.id] = datetime.datetime.now()

        # Strip whitespace and inline or block code markdown and extract the code and some formatting info
        match = FORMATTED_CODE_REGEX.fullmatch(code)
        if match:
            code, block, lang, delim = match.group("code", "block", "lang",
                                                   "delim")
            code = textwrap.dedent(code)
            if block:
                info = (f"'{lang}' highlighted"
                        if lang else "plain") + " code block"
            else:
                info = f"{delim}-enclosed inline code"
            log.trace(f"Extracted {info} for evaluation:\n{code}")
        else:
            code = textwrap.dedent(
                RAW_CODE_REGEX.fullmatch(code).group("code"))
            log.trace(
                f"Eval message contains not or badly formatted code, stripping whitespace only:\n{code}"
            )

        try:
            stripped_lines = [ln.strip() for ln in code.split('\n')]
            if all([line.startswith('#') for line in stripped_lines]):
                return await ctx.send(
                    f"{ctx.author.mention} Your eval job has completed.\n\n```[No output]```"
                )

            code = textwrap.indent(code, "    ")
            code = CODE_TEMPLATE.replace("{CODE}", code)

            await self.rmq.send_json("input",
                                     snekid=str(ctx.author.id),
                                     message=code)

            async with ctx.typing():
                message = await self.rmq.consume(str(ctx.author.id),
                                                 **RMQ_ARGS)
                paste_link = None

                if isinstance(message, str):
                    output = str.strip(" \n")
                else:
                    output = message.body.decode().strip(" \n")

                if "<@" in output:
                    output = output.replace("<@",
                                            "<@\u200B")  # Zero-width space

                if "<!@" in output:
                    output = output.replace("<!@",
                                            "<!@\u200B")  # Zero-width space

                if ESCAPE_REGEX.findall(output):
                    output = "Code block escape attempt detected; will not output result"
                else:
                    # the original output, to send to a pasting service if needed
                    full_output = output
                    truncated = False
                    if output.count("\n") > 0:
                        output = [
                            f"{i:03d} | {line}"
                            for i, line in enumerate(output.split("\n"),
                                                     start=1)
                        ]
                        output = "\n".join(output)

                    if output.count("\n") > 10:
                        output = "\n".join(output.split("\n")[:10])

                        if len(output) >= 1000:
                            output = f"{output[:1000]}\n... (truncated - too long, too many lines)"
                        else:
                            output = f"{output}\n... (truncated - too many lines)"
                        truncated = True

                    elif len(output) >= 1000:
                        output = f"{output[:1000]}\n... (truncated - too long)"
                        truncated = True

                    if truncated:
                        try:
                            response = await self.bot.http_session.post(
                                URLs.paste_service.format(key="documents"),
                                data=full_output)
                            data = await response.json()
                            if "key" in data:
                                paste_link = URLs.paste_service.format(
                                    key=data["key"])
                        except Exception:
                            log.exception(
                                "Failed to upload full output to paste service!"
                            )

                if output.strip():
                    if paste_link:
                        msg = f"{ctx.author.mention} Your eval job has completed.\n\n```py\n{output}\n```" \
                              f"\nFull output: {paste_link}"
                    else:
                        msg = f"{ctx.author.mention} Your eval job has completed.\n\n```py\n{output}\n```"

                    response = await ctx.send(msg)
                    self.bot.loop.create_task(
                        wait_for_deletion(response,
                                          user_ids=(ctx.author.id, ),
                                          client=ctx.bot))

                else:
                    await ctx.send(
                        f"{ctx.author.mention} Your eval job has completed.\n\n```[No output]```"
                    )
        finally:
            del self.jobs[ctx.author.id]
Ejemplo n.º 31
0
    async def prevplayed(self, ctx: cmds.Context, *, args: str = None):
        """Show what was previously playing on the radio.

        Use "!prevplayed [<channel>] [<index>]" to show what was previously playing on the radio.
        Short version is "!pp[<channel>] [<index>]".
        Leave off <channel> to auto-detect the channel you are tuned to.
        <index> should be a number from 0 to 4 (default 0). The higher the number, the further back in time you go."""

        async with ctx.typing():
            cmd = ctx.invoked_with
            if args is None:
                args = ''
            tokens = args.split()

            chan = None
            idx = 0

            if cmd in ['ppgame', 'pprw']:
                chan = RainwaveChannel.game
            elif cmd in ['ppoc', 'ppocr']:
                chan = RainwaveChannel.ocr
            elif cmd in ['ppcover', 'ppcovers', 'ppmw', 'ppvw']:
                chan = RainwaveChannel.cover
            elif cmd in ['ppbw', 'ppch', 'ppchip']:
                chan = RainwaveChannel.chip
            elif cmd in ['ppall', 'ppomni', 'ppow']:
                chan = RainwaveChannel.all

            if chan in RainwaveChannel and len(tokens) > 0 and tokens[0].isdigit():
                if int(tokens[0]) in range(5):
                    idx = int(tokens[0])

            if cmd in ['prevplayed', 'pp']:
                if len(tokens) > 0:
                    if tokens[0].isdigit() and int(tokens[0]) in range(5):
                        idx = int(tokens[0])
                    else:
                        if tokens[0].lower() in RainwaveChannel.__members__.keys():
                            chan = RainwaveChannel[tokens[0].lower()]
                        if len(tokens) > 1:
                            if tokens[1].isdigit() and int(tokens[1]) in range(5):
                                idx = int(tokens[1])
                if chan is None:
                    listener_id = await self.get_id_for_user(ctx.author)
                    if listener_id is None:
                        await ctx.author.send(self.nick_not_recognized)
                        return
                    chan = await self.get_current_channel_for_id(listener_id)
                if chan is None:
                    await ctx.author.send(self.not_tuned_in)
                    return

            m = f'Previously on the {chan.long_name}'
            d = await self.rw_info(chan.channel_id)
            event = d.get('sched_history')[idx]
            sched_id = int(event.get('id'))
            sched_type = event.get('type')
            sched_name = event.get('name')
            if sched_type == 'Election' and sched_name:
                m += f' ({sched_name})'
            elif sched_type == 'OneUp':
                m += f' ({sched_name} Power Hour)'
            song = event.get('songs')[0]
            embed = self.build_embed(song)
            m += f': {self.song_string(song)}'

            if ctx.guild:
                last_sched_id = f'rainwave:pp:{chan.channel_id}:{idx}'
                if sched_id == self.bot.config.get(last_sched_id, 0):
                    await ctx.author.send(f'You can only use {cmd} in {ctx.channel.mention} once per song.')
                    await ctx.author.send(m, embed=embed)
                else:
                    self.bot.config.set(last_sched_id, sched_id)
                    await ctx.send(m, embed=embed)
            else:
                await ctx.send(m, embed=embed)
Ejemplo n.º 32
0
 async def _parse_arguments(self, ctx: Context):
     interaction = ctx.interaction
     if interaction is None:
         return await self.run_parser(ctx)
     else:
         ctx.kwargs = await self.app_command._transform_arguments(interaction, interaction.namespace)