示例#1
0
async def help_command(command: str, message: discord.Message):

    if command.lower() == "help":
        # basic help route
        embed = discord.Embed(
            title=f"Help for {client.bot_name}",
            description=
            f"For help on a specific command, run `{client.default_prefix}help <command>`",
            colour=0x06b206)

        for cmd, desc in client._basic_help.items():
            embed = embed.add_field(name=f"{cmd}", value=desc, inline=False)
        embed.set_footer(text=__common__.get_timestamp())
        await message.channel.send(embed=embed)

    if command.lower().startswith(
            "help "
    ):  # a trailing space means there's text after it (Discord strips whitespace)

        sub_help = command.lower()[5:]
        sub_help = client._long_help.get(
            sub_help,
            client._long_help.get(client.alias_lookup.get(sub_help, None)))

        if sub_help is None:
            # unknown command branch
            embed = discord.Embed(
                title=f"Help for command `{command.lower()[5:]}`",
                description=f"Unknown command",
                colour=0xa20303)
            embed = embed.set_footer(text=__common__.get_timestamp())
            await message.channel.send(embed=embed)

        elif type(sub_help) == dict:
            embed = discord.Embed(
                title=f"Help for command `{command.lower()[5:]}`",
                description=sub_help.get("_description", discord.Embed.Empty),
                colour=0x06b206)
            for title, text in sub_help.items():
                embed = embed.add_field(name=title, value=text, inline=False)
            if client.cmd_aliases.get(command.lower()[5:], []):
                embed = embed.add_field(name="Aliases",
                                        value="\n".join(
                                            client.cmd_aliases.get(
                                                command.lower()[5:], [])))
            embed = embed.set_footer(text=__common__.get_timestamp())
            await message.channel.send(embed=embed)
示例#2
0
文件: about.py 项目: ntoskrnl4/arbys
async def return_bot_info(command: str, message: discord.Message):
    owner = client.get_user(288438228959363073)
    
    python_version = f"Python {sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
    if sys.version_info[3] == "alpha":
        python_version += f"a{sys.version_info.serial}"
    if sys.version_info[3] == "beta":
        python_version += f"b{sys.version_info.serial}"
    if sys.version_info[3] == "candidate":
        python_version += f"rc{sys.version_info.serial}"
    
    embed = discord.Embed(title=f"{client.bot_name} info", description=discord.Embed.Empty, color=0x404040)
    embed = embed.add_field(name="Version", value=f"Framework version {client.__version__}")
    embed = embed.add_field(name="Creator", value=f"{owner.name}#{owner.discriminator}\nID {owner.id}\n{owner.mention}")
    embed = embed.add_field(name="Github", value="`ntoskrnl4/arbys`\nhttps://www.github.com/ntoskrnl4/arbys", inline=False)
    embed = embed.add_field(name="Built with", value=f"Running on {python_version}\ndiscord.py library version {discord.__version__}\nntoskrnl-bot framework (`ntoskrnl4/ntoskrnl-bot`)")
    embed = embed.add_field(name="Invite Link", value=discord.utils.oauth_url(client.user.id), inline=False)
    embed = embed.add_field(name="Usage Notice", value="This bot may log messages to disk as part of moderation duties, development debugging, and command usage. Logs will never be used maliciously, are not stored in the cloud, and will not be given to any third party. For comments, questions, concerns, deletion orders, or retrieval requests, please contact ntoskrnl.")
    embed = embed.set_footer(text=__common__.get_timestamp())
    await message.channel.send(embed=embed)
    return
示例#3
0
文件: ntp.py 项目: ntoskrnl4/arbys
async def get_ntp_stats(command: str, message: discord.Message):
    embed = discord.Embed(
        title="NTP Statistics",
        description="NTP synchronization info for Arbys' local machine")
    try:
        sub = subprocess.Popen(["ntpq", "-c", "rv"],
                               stdout=subprocess.PIPE,
                               stderr=subprocess.DEVNULL)
        await asyncio.sleep(0.1)
        stdout, stderr = sub.communicate(timeout=0.1)
    except subprocess.TimeoutExpired:
        sub.kill()
        embed.description = embed.description + "\n\nsubprocess.TimeoutExpired error while getting statistics."
    except:
        embed.description = embed.description + "\n\nUnknown error while getting statistics."
    else:
        # make this into a decently easily parsed list
        parts = stdout.decode().replace("\n", "").replace(" ", "").split(",")

        sync_status = [x for x in parts if x.startswith("sync_")][0]
        stratum = int([x for x in parts if x.startswith("stratum=")][0][8:])
        refid = [x for x in parts if x.startswith("refid=")
                 ][0][6:]  # this mess just gets the refid
        offset = float([x for x in parts if x.startswith("offset=")
                        ][0][7:]) * 1000
        freq = float([x for x in parts if x.startswith("frequency=")][0][10:])
        jitter = float([x for x in parts if x.startswith("sys_jitter=")
                        ][0][11:]) * 1000

        embed = embed.add_field(name="Sync Status", value=sync_status)
        embed = embed.add_field(name="System Peer RefID", value=refid)
        embed = embed.add_field(name="System Stratum", value=stratum)
        embed = embed.add_field(name="Offset", value=f"{round(offset, 3)} us")
        embed = embed.add_field(name="Jitter", value=f"{jitter} us")
        embed = embed.add_field(name="Frequency Drift", value=f"{freq} ppm")

    embed = embed.set_footer(text=__common__.get_timestamp())
    await message.channel.send(embed=embed)
示例#4
0
async def command(parts: str, message: discord.Message):
    parts = parts.split(" ")
    
    response = discord.Embed()
    
    try:
        parts, arguments = __common__.parse_arguments(parts, {
            "charlimit": 1500,
            "attempts": 50,
            "size": -1
        })
    except RuntimeError as e:
        response.colour = 0xb81209
        response.title = "Markov function error"
        response.description = str(e) + "\n\nFor help on using this command, run `cqdx help markov`"
        response.set_footer(text=__common__.get_timestamp())
        await message.channel.send(embed=response)
        return
    
    size = arguments["size"]
    charlimit = arguments["charlimit"]
    attempts = arguments["attempts"]
    
    # determine our target.
    target = None
    target_type = "unknown"
    # check for nothing
    if len(parts) is 1:
        target = message.channel
        target_type = "channel"
    
    if len(parts) > 1:
        
        # get channel if it is one
        if parts[1].startswith("<#"):
            target = message.channel_mentions[0]
            target_type = "channel"
        
        if parts[1].startswith("<@") or parts[1].startswith("<!@"):
            target = message.mentions[0]
            target_type = "user"
    
    if target_type == "unknown":
        try:
            user = message.guild.get_member(__common__.strip_to_id(parts[1]))
        except TypeError:
            await message.channel.send("Argument error: Invalid object or user/channel mention")
            return
        channel = message.guild.get_channel(__common__.strip_to_id(parts[1]))
        if user is not None:
            target_type = "user"
            target = user
        if channel is not None:
            target_type = "channel"
            target = channel
    
    if target_type == "unknown":
        await message.channel.send("Argument error: Invalid object or user/channel mention")
    
    # run different outputs for different input types
    async with message.channel.typing():

        if target_type == "user":
            target_member = message.guild.get_member(target.id)
            if target_member is not None:
                display_target = f"{target_member.display_name}"
            else:
                display_target = f"{target.name}#{target.discriminator}"

            response.set_author(name=display_target, icon_url=target.avatar_url_as(format="png", size=128))
            
            try:
                input_messages = await get_user_markov(target.id, message)
            except KeyError:
                await message.channel.send(f"{message.author.mention} The user you have specified has had no recent messages. This function only works on users who have been active recently.")
                return

        if target_type == "channel":
            if target.guild.id != message.guild.id:
                await message.channel.send("Argument error: Channel provided is not in current server")
                return
            input_messages = await get_channel_markov(target)

            if input_messages is None:  # permissions error
                response.colour = 0xb81209
                response.title = "Markov chain failed"
                response.description = "Unable to run markov chain: Insufficient permissions to read channel history"
                response.set_footer(text=f"{__common__.get_timestamp()}")
                response.set_author(name=f"#{target.name}")
                # if we can't read the channel we should check if we can write to it also
                try:
                    await message.channel.send(embed=response)
                except discord.Forbidden:
                    pass

            response.set_author(name=f"#{target.name}")

        if size == -1:
            if len(input_messages) < 500:
                size = 2
            elif 500 < len(input_messages) < 1000:
                size = 3
            elif 1000 < len(input_messages):
                size = 4

        src_string = "\n".join([x.content for x in input_messages])
        model = markovify.NewlineText(src_string, state_size=size)
        await asyncio.sleep(0.1)
        result = model.make_short_sentence(max_chars=charlimit, tries=attempts)

        if result is None:
            response.colour = 0xb81209
            response.title = "Markov function failed"
            response.description = "Unable to run markov chain - try running the command again"
        else:
            response.colour = 0x243b61
            response.description = result

        response.set_footer(text=f"{__common__.get_timestamp()} | "
                                 f"{len(input_messages)} messages in input | "
                                 f"Size: {size}")
        await message.channel.send(embed=response)
        return
示例#5
0
async def command(command: str, message: discord.Message):
    parts = command.split(" ")
    if len(parts) == 1:
        parts.append(str(message.author.id))
    try:
        u = await client.fetch_user(__common__.strip_to_id(parts[1]))
    except TypeError:
        await message.channel.send(
            "Invalid argument: integer ID or mentions are acceptable")
        return
    except:
        isUser = False
    else:
        isUser = True

    s = client.get_guild(__common__.strip_to_id(parts[1]))
    if s is None:
        isServer = False
    else:
        isServer = True

    c = client.get_channel(__common__.strip_to_id(parts[1]))
    if c is None:
        isTextChannel = False
        isVoiceChannel = False
    else:
        if isinstance(c, discord.TextChannel):
            isTextChannel = True
            isVoiceChannel = False
        elif isinstance(c, discord.VoiceChannel):
            isTextChannel = False
            isVoiceChannel = True
        else:
            await message.channel.send(
                "Invalid channel type - handling for this is not implemented. Sorry."
            )
            return

    if isUser and not "--status" in command:
        user_embed = discord.Embed(
            title="User Information",
            description=f"Information about {u.mention}",
            color=0x3127b3)
        user_embed = user_embed.set_thumbnail(url=u.avatar_url)
        user_embed = user_embed.add_field(name="Tag",
                                          value=u.name + "#" + u.discriminator)
        # user_embed = user_embed.add_field(name="Avatar URL", value=u.avatar_url_as(static_format="png", size=1024))
        if message.guild.get_member(u.id) is not None:
            m = message.guild.get_member(u.id)
            user_embed = user_embed.add_field(name="Nickname",
                                              value=m.display_name)
        user_embed = user_embed.add_field(name="Raw ID", value=u.id)
        # user_embed = user_embed.add_field(name="Is Bot", value=u.bot)
        ctime_str = f"{str(u.created_at)}\n({str(datetime.datetime.utcnow()-u.created_at)})"
        user_embed = user_embed.add_field(name="Account Creation Time",
                                          value=ctime_str)
        if get_any_member(u.id) is not None:
            m = get_any_member(u.id)
            user_embed = user_embed.add_field(
                name="Current Status",
                value=f"Apparent Status: {status_emoji(m.status)}\n"
                f"Desktop: {status_emoji(m.desktop_status)}\n"
                f"Web: {status_emoji(m.web_status)}\n"
                f"Mobile: {status_emoji(m.mobile_status)}\n",
                inline=True)
        if message.guild.get_member(u.id) is not None:
            m = message.guild.get_member(u.id)
            jtime_str = f"{str(m.joined_at)}\n({str(datetime.datetime.utcnow()-m.joined_at)})"
            user_embed = user_embed.add_field(name="Joined this server",
                                              value=jtime_str)
            roles = "\n".join([f"{x.name} ({x.id})" for x in m.roles][::-1])
            user_embed = user_embed.add_field(name="Roles in this server",
                                              value=roles,
                                              inline=False)
        user_embed = user_embed.set_footer(text=__common__.get_timestamp())

    if isUser and "--status" in command:
        if get_any_member(u.id) is not None:
            m = get_any_member(u.id)
        else:
            return await message.channel.send(
                "Cannot get status: I do not share any servers with this user (in order to get a user's status I must share a server with them)"
            )
        user_embed = discord.Embed(
            description=f"Apparent Status: {status_emoji(m.status)}\n"
            f"Desktop: {status_emoji(m.desktop_status)}\n"
            f"Web: {status_emoji(m.web_status)}\n"
            f"Mobile: {status_emoji(m.mobile_status)}\n"
            f"Is on mobile? {m.is_on_mobile()}", )
        user_embed = user_embed.set_author(icon_url=m.avatar_url_as(
            format="png", size=128),
                                           name=f"{m.name}#{m.discriminator}")
        user_embed = user_embed.set_footer(text=__common__.get_timestamp())

    if isServer:
        server_embed = discord.Embed(title="Server Information",
                                     color=0xb368a2)
        server_embed = server_embed.add_field(name="Name", value=s.name)
        server_embed = server_embed.add_field(name="Raw ID", value=s.id)
        icon = s.icon_url_as(format="png", size=1024)
        if not icon:  # Used to be != "" before icon was a discord.Asset, credit to eyyyyyy for finding/fixing this
            icon = "[no custom icon]"
            server_embed = server_embed.set_thumbnail(url=s.icon_url)
        server_embed = server_embed.add_field(name="Icon URL", value=icon)
        server_embed = server_embed.add_field(
            name="Owner",
            value=f"{s.owner.name}#{s.owner.discriminator}\nID {s.owner.id}")
        server_embed = server_embed.add_field(name="Member Count",
                                              value=s.member_count)
        server_embed = server_embed.add_field(name="Role Count",
                                              value=len(s.roles))
        server_embed = server_embed.add_field(name="Emoji Count",
                                              value=len(s.emojis))
        server_embed = server_embed.add_field(name="Creation Time",
                                              value=s.created_at)
        server_embed = server_embed.add_field(name="Region", value=s.region)
        server_embed = server_embed.add_field(name="Is offline?",
                                              value=s.unavailable)
        server_embed = server_embed.add_field(name="Admin 2FA required?",
                                              value=bool(s.mfa_level))
        server_embed = server_embed.add_field(name="Verification Level",
                                              value=s.verification_level)
        server_embed = server_embed.set_footer(text=__common__.get_timestamp())

    if isTextChannel:
        channel_embed = discord.Embed(
            title="Channel Information",
            description=f"Information about the text channel {c.mention}",
            color=0x8f44a2)
        channel_embed = channel_embed.add_field(name="Name", value=c.name)
        channel_embed = channel_embed.add_field(name="ID", value=c.id)
        channel_embed = channel_embed.add_field(
            name="Server", value=f"{c.guild.name} ({c.guild.id})")
        t = c.topic
        if t == "":
            t = "[none]"
        channel_embed = channel_embed.add_field(name="Topic",
                                                value=t,
                                                inline=False)
        channel_embed = channel_embed.add_field(name="Creation Time",
                                                value=c.created_at)

    if isVoiceChannel:
        channel_embed = discord.Embed(
            title="Channel Information",
            description=f"Information about the voice channel {c.name}",
            color=0x8f44a2)
        channel_embed = channel_embed.add_field(name="Name", value=c.name)
        channel_embed = channel_embed.add_field(name="ID", value=c.id)
        channel_embed = channel_embed.add_field(
            name="Server", value=f"{c.guild.name} ({c.guild.id})")
        channel_embed = channel_embed.add_field(name="Bitrate",
                                                value=c.bitrate)
        channel_embed = channel_embed.add_field(name="User Limit",
                                                value=c.user_limit)
        channel_embed = channel_embed.add_field(name="Creation Time",
                                                value=c.created_at)
        in_vc = "\n".join([
            f"{x.display_name} ({x.name}#{x.discriminator} - {x.id})"
            for x in c.members
        ])
        if in_vc == "":
            in_vc = "[none]"
        channel_embed = channel_embed.add_field(
            name="Members Currently In Channel", value=in_vc)

    if isUser:
        await message.channel.send(embed=user_embed)
        await asyncio.sleep(0.05)

    if isServer:
        await message.channel.send(embed=server_embed)
        await asyncio.sleep(0.05)

    if isTextChannel or isVoiceChannel:
        channel_embed = channel_embed.set_footer(
            text=__common__.get_timestamp())
        await message.channel.send(embed=channel_embed)
        await asyncio.sleep(0.05)

    if not (isUser or isServer or
            (isTextChannel
             or isVoiceChannel)):  # if not a user, server, or channel:
        await message.channel.send(
            f"Unknown user, server, or channel with ID {parts[1]}. I might not be able to 'see' that object."
        )
    return
示例#6
0
async def statistics(command: str, message: discord.Message):
    if "--uptime" in command:
        up = time.perf_counter() - client.first_execution
        await message.channel.send(f"Uptime:\n`{up:.3f}` seconds\n`{up/86400:.4f}` days")
        return
    
    async with message.channel.typing():
        
        embed = discord.Embed(title=f"Running statistics for {client.bot_name}", description=discord.Embed.Empty, color=0x404040)
        
        up = time.perf_counter() - client.first_execution
        embed = embed.add_field(name="Uptime", value=f"{up:.3f} seconds\n{up/86400:.4f} days")
        embed = embed.add_field(name="Servers", value=len(client.guilds))
        embed = embed.add_field(name="Commands since boot", value=client.command_count)
        embed = embed.add_field(name="Messages since boot", value=client.message_count)
        embed = embed.add_field(name="Messages in cache", value=len(client._connection._messages))
        n_connected = len(client.voice_clients)
        n_playing = len([x for x in client.voice_clients if x.is_playing()])
        embed = embed.add_field(name="Connected voice chats", value=f"{n_connected} ({n_playing} playing)")
        embed = embed.add_field(name="Bot Process ID", value=os.getpid())
        embed = embed.add_field(name="Host Machine Name", value=socket.gethostname())
        
        if has_psutil:
            try:
                temp = psutil.sensors_temperatures()['cpu-thermal'][0].current
            except (AttributeError, KeyError):
                temp = None
            self = psutil.Process()
            cpu_self = self.cpu_percent(interval=1)
            self_m_used = self.memory_info().rss
            m_raw = psutil.virtual_memory()
            m_total = m_raw.total
            m_available = m_raw.available
            m_used = m_total - m_available
            cpu = psutil.cpu_percent(percpu=True)
            index = 0
            cpu_text = ""
            for v in cpu:
                cpu_text += f"**CPU {index}:** {v}%\n"
                index += 1
            
            embed = embed.add_field(name="Host CPU temp", value=f"{int(temp) if temp is not None else 'Unknown'}°C")
            embed = embed.add_field(name="Process Memory", value=f"{self_m_used/(1024*1024):.3f} MiB")
            embed = embed.add_field(name="Process CPU", value=f"{cpu_self:.1f}%")
            embed = embed.add_field(name="System RAM Usage", value=f"{m_used/(1024*1024):.1f}/{m_total/(1024*1024):.1f} MiB ({(m_used/m_total)*100:.2f}%)")
            embed = embed.add_field(name="System CPU", value=cpu_text)
        
        if client.__version__ == "0.7":
            # todo: v0.7 - update references
            raise RuntimeError("TODO: Update references")
        
        bg_count = len(client._background_tasks)
        cmd_count = len(set(client._command_lookup.values()))
        ready_count = len(client._ready_handlers)
        shutdown_count = len(client._shutdown_handlers)
        msg_count = len(client._message_handlers)
        mj_count = len(client._member_join_handlers)
        ml_count = len(client._member_remove_handlers)
        readd_count = len(client._reaction_add_handlers)
        redel_count = len(client._reaction_remove_handlers)
        
        embed = embed.add_field(name="Registered Event Handlers",
                                value=f"Registered commands: {cmd_count}\n"
                                      f"Background tasks: {bg_count}\n"
                                      f"Ready handlers: {ready_count}\n"
                                      f"Shutdown handlers: {shutdown_count}\n"
                                      f"Message handlers: {msg_count}\n"
                                      f"Member join handlers: {mj_count}\n"
                                      f"Member leave handlers: {ml_count}\n"
                                      f"Reaction add handlers: {readd_count}\n"
                                      f"Reaction remove handlers: {redel_count}\n")
        
        embed = embed.set_footer(text=__common__.get_timestamp())
    await message.channel.send(embed=embed)
示例#7
0
文件: n2yo.py 项目: ntoskrnl4/arbys
async def process_command(command: str, message: discord.Message):
    global last_pass_req
    
    parts = command.split(" ")
    
    try:
        parts, args = __common__.parse_arguments(parts, {
            "debug": False,
            "apicount": False,
            "alt": 100.0,
            "dx": False,
            "days": 3,
        })
    except RuntimeError as e:
        pass
        return
    
    if args["debug"]: await message.channel.send(f"debug: running command with arguments `{parts}`")
    
    if len(parts) is 1:
        # no arguments, print help
        embed = discord.Embed(title="Command usage", description=cmd_desc, colour=0x42bf92)
        embed = embed.add_field(name="Get current satellite position", value=get_sat_pos)
        embed = embed.add_field(name="Get upcoming passes", value=get_passes)
        embed = embed.set_footer(text=__common__.get_timestamp())
        await message.channel.send(embed=embed)
        return
    
    if parts[1] == "sats":
        if args["debug"]: await message.channel.send("debug: returning satellite info embed")
        await message.channel.send(embed=sat_id_embed)
        return
    
    if parts[1] in ["passinfo"]:
        if not last_pass_req:
            await message.channel.send("State error: `passes` command has not been run; no passes available to get details on")
            return
        try:
            num = int(parts[2])
        except ValueError:
            await message.channel.send(f"Argument error: Invalid integer provided (got: {parts[2]})")
            return
        except IndexError:
            # no second number
            await message.channel.send("Argument error: No pass specified")
            return
        
        try:
            target_pass = last_pass_req["passes"][num]
        except IndexError:
            await message.channel.send("State error: Index out of bounds")
            return
        
        embed = discord.Embed(title="Satellite pass details", description=f"Information about satellite pass of {last_pass_req['info']['satname']} (id {last_pass_req['info']['satid']})")
        embed = embed.add_field(name="Pass Start",
                                value=f"`Timestamp: {datetime.datetime.utcfromtimestamp(target_pass['startUTC']).__str__()} UTC`\n"
                                      f"`Azimuth: {target_pass['startAz']} degrees`\n",
                                inline=False)
        embed = embed.add_field(name="Pass Climax",
                                value=f"`Timestamp: {datetime.datetime.utcfromtimestamp(target_pass['maxUTC']).__str__()} UTC`\n"
                                      f"`Azimuth: {target_pass['maxAz']} degrees`\n"
                                      f"`Elevation: {target_pass['maxEl']} degrees`\n",
                                inline=False)
        embed = embed.add_field(name="Pass End",
                                value=f"`Timestamp: {datetime.datetime.utcfromtimestamp(target_pass['endUTC']).__str__()} UTC`\n"
                                      f"`Azimuth: {target_pass['endAz']} degrees`\n",
                                inline=False)
        await message.channel.send(embed=embed)
        return
    
    if not check_cooldowns():
        await message.channel.send("Sorry, but the API limit has been reached. Please try again later, or go to the n2yo.com website.")
        return
    
    if parts[1] in ["get_pos", "pos", "position"]:
        if len(parts) < 4:
            await message.channel.send("Argument error: Not enough arguments provided for specified operation. Run `n2yo` without arguments for command help.")
            return
        
        # get our targeted satellite
        target_sat = parts[2]
        try: target_sat = int(target_sat)  # Literally only doing this so the folded code will look neat in PyCharm (it doesn't fold single lines >:( )
        except ValueError:
            await message.channel.send(f"Argument error: Target satellite could not be converted to integer. Run `n2yo` without arguments for command help. (got: {target_sat})")
            return
        
        # get our targeted grid
        target_grid = parts[3]
        if len(target_grid) is not 6:
            await message.channel.send(f"Argument error: Provided grid not 6 characters long. Please use your 6 digit Maidenhead grid locator only. Run `n2yo` without arguments for command help. (got: {target_grid})")
            return
        if not (target_grid[:2].isalpha() and target_grid[2:4].isdigit() and target_grid[4:6].isalpha()):
            await message.channel.send(f"Argument error: Provided grid not formatted correctly. Format must be 6 digit Maidenhead grid locator. (got: {target_grid})")
            return
        target_lat, target_long = get_lat_long(target_grid)
        if args["debug"]: await message.channel.send(f"debug: target coordinates {target_lat} {target_long}")
        
        async with message.channel.typing():
            async with aiohttp.ClientSession() as connection:
                
                target_url = f"{base}/positions/{target_sat}/{target_lat}/{target_long}/{args['alt']}/{2 if args['dx'] else 1}/"
                if args["debug"]: await message.channel.send(f"debug: calling api url `{target_url}`")
                async with connection.get(target_url+api_key) as response:
                    info = await response.json()
            
            satname = info['info']['satname']
            satid = info['info']['satid']
            ts = datetime.datetime.utcfromtimestamp(info['positions'][0]['timestamp'])
            gr_lat = info['positions'][0]['satlatitude']
            gr_lon = info['positions'][0]['satlongitude']
            sat_alt = info['positions'][0]['sataltitude']
            azimuth = info['positions'][0]['azimuth']
            elevation = info['positions'][0]['elevation']
            ra = info['positions'][0]['ra']
            dec = info['positions'][0]['dec']
            ra_h, ra_m, ra_s = deg2hms(ra)
            
            gr_loc = f"`Latitude: {str(gr_lat)[:8]}°`\n`Longitude: {str(gr_lon)[:7]}°`\n`Altitude: {sat_alt:.2f} km`"
            sky_loc = f"`Azimuth: {azimuth}°`\n`Elevation: {elevation}°`"
            cel_loc = f"`RA: {ra_h}h {ra_m}m {ra_s:.3f}s`\n`Dec: {dec:.2f} degrees`"
            
            if args["dx"]:
                d_gr_lat = info['positions'][1]['satlatitude'] - gr_lat
                d_gr_lon = info['positions'][1]['satlongitude'] - gr_lon
                d_sat_alt = info['positions'][1]['sataltitude'] - sat_alt
                d_azimuth = info['positions'][1]['azimuth'] - azimuth
                d_elevation = info['positions'][1]['elevation'] - elevation
                d_ra = info['positions'][1]['ra'] - ra
                d_dec = info['positions'][1]['dec'] - dec
                d_ra_h, d_ra_m, d_ra_s = deg2hms(d_ra)
                
                d_gr_loc = f"`Latitude: {d_gr_lat:.2f}°/sec`\n`Longitude: {d_gr_lon:.2f}°/sec`\n`Altitude: {d_sat_alt:.2f} km/s`"
                d_sky_loc = f"`Azimuth: {d_azimuth:.2f}°/sec`\n`Elevation: {d_elevation:.2f}°/sec`"
                d_cel_loc = f"`RA: {d_ra_s+(d_ra_m*60)+(d_ra_h*3600):.2f}s /second`\n`Dec: {d_dec:.4f} degrees/sec`"
            
            embed = discord.Embed(title=f"Current satellite position for \"{satname}\" (ID {satid})",
                                  description=f"This information calculated for {ts.__str__()} UTC")
            embed = embed.add_field(name="Ground Location", value=gr_loc)
            embed = embed.add_field(name="Sky Location", value=sky_loc)
            embed = embed.add_field(name="Celestial Sphere Location", value=cel_loc)
            
            if args["dx"]:
                embed = embed.add_field(name="Ground Movement", value=d_gr_loc)
                embed = embed.add_field(name="Sky Movement", value=d_sky_loc)
                embed = embed.add_field(name="Celestial Sphere Movement", value=d_cel_loc)
            
            if '--apicount' in parts:
                embed = embed.set_footer(text=f"Information provided thanks to the N2YO.com API - API Usage for past hour: {info['info']['transactionscount']}")
            else:
                embed = embed.set_footer(text=f"Information provided thanks to the N2YO.com API")
        
        await message.channel.send(embed=embed)
        return
    
    if parts[1] in ["passes"]:
        # params: n2yo passes satid grid min_elevation --alt val --days x --apicount --debug
        if len(parts) < 4:
            await message.channel.send("Argument error: Not enough arguments provided for specified operation. Run `n2yo` without arguments for command help.")
            return
        
        target_sat = parts[2]
        try:
            target_sat = int(target_sat)
        except ValueError:
            await message.channel.send(f"Argument error: Target satellite could not be converted to integer. Run `n2yo` without arguments for command help. (got: {target_sat})")
            return
        
        target_grid = parts[3]
        if len(target_grid) is not 6:
            await message.channel.send(f"Argument error: Provided grid not 6 characters long. Please use your 6 digit Maidenhead grid locator only. Run `n2yo` without arguments for command help. (got: {target_grid})")
            return
        if not target_grid[:2].isalpha() or not target_grid[2:4].isdigit() or not target_grid[4:6].isalpha():
            await message.channel.send(f"Argument error: Provided grid not formatted correctly. Format must be 6 digit Maidenhead grid locator. (got: {target_grid})")
            return
        target_lat, target_long = get_lat_long(target_grid)
        
        if args["debug"]: await message.channel.send(f"debug: successfully got target coordinates {target_lat} {target_long}")
        
        target_elevation = parts[4]
        try:
            target_elevation = int(target_elevation)
        except ValueError:
            await message.channel.send(f"Argument error: Target elevation could not be converted to integer. Run `n2yo` without arguments for command help. (got: {target_elevation})")
            return
            
        async with message.channel.typing():
            async with aiohttp.ClientSession() as connection:
                
                target_url = f"{base}/radiopasses/{target_sat}/{target_lat}/{target_long}/{args['alt']}/{args['days']}/{target_elevation}/"
                if args["debug"]: await message.channel.send(f"debug: calling api url `{target_url}`")
                async with connection.get(target_url+api_key) as response:
                    info = await response.json()
            
            satname = info["info"]["satname"]
            satid = info["info"]["satid"]
            passcount = info["info"]["passescount"]
            
            last_pass_req = info
            
            embed = discord.Embed(title=f"Upcoming passes of satellite {satname} (id {satid})",
                                  description=passinfo(40, info["passes"]))
            embed = embed.add_field(name="To see more details about a specific pass run the following command:",
                                    value="`n2yo passinfo <number>`")
            if args['apicount']:
                embed = embed.set_footer(text=f"Information provided thanks to the N2YO.com API - API Usage for past hour: {info['info']['transactionscount']}")
            else:
                embed = embed.set_footer(text=f"Information provided thanks to the N2YO.com API")
        
        await message.channel.send(embed=embed)