示例#1
0
    def __init__(self, **kwargs):
        if ('hash' not in kwargs) or ('lines' not in kwargs) or ('chars' not in kwargs) or ('files' not in kwargs) or ('size' not in kwargs):
            libfiles = []
            lines = 0
            chars = 0
            fs = 0
            size = 0
            for subdir, dirs, files in os.walk(conf.rootDir):
                for file in files:
                    fs += 1
                    size += os.path.getsize(os.path.join(subdir, file))
                    if file.endswith(".py"):
                        libfiles.append(os.path.join(subdir, file))
                        with open(os.path.join(subdir, file), "r") as f:
                            for line in f:
                                lines += 1
                                chars += len(line)

            hash = hashlib.sha512(open(libfiles[0], 'rb').read())
            for file in libfiles[1:]:
                hash.update(open(file, 'rb').read())
            hash = hash.hexdigest()

        self.hash = kwargs['hash'] if 'hash' in kwargs else hash
        self.lines = kwargs['lines'] if 'lines' in kwargs else lines
        self.chars = kwargs['chars'] if 'chars' in kwargs else chars
        self.files = kwargs['files'] if 'files' in kwargs else fs
        self.size = kwargs['size'] if 'size' in kwargs else size
        self.number = kwargs['number'] if 'number' in kwargs else Revisioning.obtain().current.number + 1
        self.major_version = kwargs['major_version'] if 'major_version' in kwargs else conf.VERSION
        self.version_tag = kwargs['version_tag'] if 'version_tag' in kwargs else conf.VERSIONTAG
        self.timestamp = kwargs['timestamp'] if 'timestamp' in kwargs else localnow()
示例#2
0
    async def christmas(self, ctx):
        """
        Syntax: `{pre}{command_name}`

        **Aliases:** `{aliases}`
        **Node:** `{node}`
        **Grant Level:** `{grant_level}`

        __**Description**__
        Enqueue a special shuffled playlist of holiday music. This command will
        only succeed in December, so use it while you can!

        __**Arguments**__
        This command takes no arguments.

        __**Example Usage**__
        `{pre}{command_name}`
        """
        if localnow().strftime("%m") != "12":
            return await ctx.send("It's not even december.")

        player = self.get_player(ctx)

        if not player.is_connected:
            channel = await player.connect(ctx)
            if not channel:
                return
            member = Member.obtain(ctx.author.id)
            await player.set_volume(member.last_volume)

        admin = Member.obtain(conf.ownerID)
        plentries = admin.playlists["Christmas"]
        random.shuffle(plentries)
        await player.add_enqueue_job(ctx, self.wavelink, "Christmas Music",
                                     plentries)
示例#3
0
 def open(self, title, description="No description provided."):
     issue = Issue(id=self.last.id + 1,
                   title=title,
                   date=localnow(),
                   description=description)
     self.issues[str(issue.id)] = issue
     self.save()
     return issue
示例#4
0
    async def queue(self, ctx, number=10):
        """
        Syntax: `{pre}{command_name} [number]`

        **Aliases:** `{aliases}`
        **Node:** `{node}`
        **Grant Level:** `{grant_level}`

        __**Description**__
        Displays the queue, with the specified number of entries. If not
        specified, it shows the next 10 entries.

        __**Arguments**__
        `[number]` - The number of entries to show.

        __**Example Usage**__
        `{pre}{command_name}`
        `{pre}{command_name} 15`
        """
        player = self.get_player(ctx)

        try:
            status = player.queue.current_track
            status = "good"
        except QueueIsEmpty:
            status = "empty"
        except EndOfQueue:
            status = "end"

        if status == "empty":
            return await ctx.send("The queue is empty.")
        if status == "end":
            return await ctx.send("The queue has reached the end.")

        embed = discord.Embed(
            title="Queue",
            description=f"Showing up to next {number} tracks",
            colour=ctx.author.colour,
            timestamp=localnow())
        embed.set_author(name="Query Results")
        embed.set_footer(text=f"Requested by {ctx.author.display_name}",
                         icon_url=ctx.author.avatar_url)
        embed.add_field(name="Currently playing",
                        value=getattr(player.queue.current_track, "title",
                                      "No tracks currently playing."),
                        inline=False)
        upcoming = player.queue.next_tracks
        if upcoming:
            embed.add_field(name="Next up",
                            value="\n".join(t.title
                                            for t in upcoming[:number]),
                            inline=False)

        await ctx.send(embed=embed)
示例#5
0
    async def uptime(self, ctx):
        """
        Syntax: `{pre}{command_name}`

        **Aliases:** `{aliases}`
        **Node:** `{node}`
        **Grant Level:** `{grant_level}`

        __**Description**__
        Display {bot}'s current uptime statistics.

        __**Arguments**__
        This command takes no arguments.

        __**Example Usage**__
        `{pre}{command_name}`
        """
        uptimes = UptimeRecords.obtain()
        ut = uptimes.total_uptime
        dt = uptimes.total_downtime
        utpercent = uptimes.percentage_up
        dtpercent = uptimes.percentage_down
        embed = discord.Embed(title=f"__**{conf.name} Uptime Statistics**__",
                              color=discord.Colour(0xd9e0cf),
                              description="As of " +
                              localnow().strftime("%-m/%-d/%Y %H:%M:%S %Z"))
        embed.add_field(name="Total Uptime",
                        value=strfdelta(ut, "{%d} days {%H}:{%M}:{%S}\n") +
                        " (" + str(round(utpercent, 2)) + "%)")
        embed.add_field(name="Total Downtime",
                        value=strfdelta(dt, "{%d} days {%H}:{%M}:{%S}\n") +
                        " (" + str(round(dtpercent, 2)) + "%)")
        embed.add_field(
            name="Current Session",
            value=strfdelta(
                localnow() - uptimes.current_uptime.start_timestamp,
                "{%d} days {%H}:{%M}:{%S}"))
        embed.add_field(name="Initialization Instances",
                        value="{:,}".format(len(uptimes.all) + 1))
        await ctx.send(embed=embed)
示例#6
0
 def update(self):
     self.end_timestamp = localnow()
     self.save()
示例#7
0
 def __init__(self, **kwargs):
     self.start_timestamp = kwargs[
         'start_timestamp'] if 'start_timestamp' in kwargs else localnow()
     self.end_timestamp = kwargs[
         'end_timestamp'] if 'end_timestamp' in kwargs else self.start_timestamp
示例#8
0
    async def choose_track(self, ctx, tracks):
        """
        Allow for track selection.

        The vast majority of this function only fires when the command
        executor has promptOnSearch turned on. If it's off, this function
        simply returns the first result from a ytsearch, and stops cold.
        Otherwise, this handles the message asking which result should be played
        and the message response to that.
        """
        def r_check(r, u):
            return (r.emoji in OPTSR.keys() and u == ctx.author
                    and r.message.id == msg.id)

        def m_check(m):
            return (m.content in OPTSM.keys()
                    or m.content.startswith(f"{conf.prefix}play")
                    ) and m.author == ctx.author

        embed = discord.Embed(
            title="Choose a song",
            description=("\n".join(
                f"**{i+1}.** {t.title} ({t.length//60000}:{str(t.length%60).zfill(2)})"
                for i, t in enumerate(tracks[:5]))),
            colour=ctx.author.colour,
            timestamp=localnow())
        embed.set_author(name="Query Results")
        embed.set_footer(text=f"Invoked by {ctx.author.display_name}",
                         icon_url=ctx.author.avatar_url)

        msg = await ctx.send(embed=embed)
        for emoji in list(OPTSR.keys())[:min(len(tracks), len(OPTSR))]:
            await msg.add_reaction(emoji)

        try:
            tasks = [
                self.bot.wait_for("reaction_add", timeout=60.0, check=r_check),
                self.bot.wait_for("message", timeout=60.0, check=m_check)
            ]
            done, pending = await asyncio.wait(
                tasks, return_when=asyncio.FIRST_COMPLETED)
            is_reaction = True
            try:
                for task in done:
                    reaction, _ = task.result()
            except TypeError:
                for task in done:
                    message = task.result()
                    is_reaction = False

            for task in pending:
                task.cancel()
        except asyncio.TimeoutError:
            await msg.delete()
            await ctx.message.delete()
        else:
            await msg.delete()
            if is_reaction:
                return tracks[OPTSR[reaction.emoji]]
            else:
                try:
                    await message.delete()
                    await ctx.message.delete()
                except discord.errors.NotFound:
                    pass
                if message.content.startswith(f"{conf.prefix}play"):
                    return None
                return tracks[OPTSM[message.content]]
示例#9
0
async def handleOAuth(request, scope=""):
    """
    Handle OAuth2.

    This function takes the request and attempts to perform OAuth2, but only
    does so when it's necessary. It behaves differently under a few
    circumstances:

    - If the correct OAuth2 data is present, and the token has not yet expired,
    it simply returns the session object.
    - If the token has expired, it uses the refresh token to get a new one, and
    returns the new session data.
    - If the session data is not present, it checks to see if a code is attached
    to the request. If one is, it uses the code to retrieve a token, then
    returns the session data.
    - If one is not attached, it redirects the user to the OAuth2 URL, and
    obtains the code so that it can be used to retrieve a token.
    """
    session = await get_session(request)
    try:
        session['token']
        refresh_token = session['refresh_token']
        session['token_type']
        expiry = session['token_expiry']
        scope = session['scope']
        if localnow() > datetime.datetime.strptime(expiry, "%x %X %z"):
            data = {
                'client_id': request.app.bot.user.id,
                'client_secret': request.app.bot.user.id,
                'grant_type': 'refresh_token',
                'refresh_token': refresh_token,
                'redirect_uri':
                str(request.url).replace("http://", "https://"),
                'scope': scope
            }
            headers = {'Content-Type': 'application/x-www-form-urlencoded'}
            async with aiohttp.ClientSession() as session:
                async with session.post(
                        "https://discord.com/api/v6/oauth2/token",
                        data=data,
                        headers=headers) as r:
                    json = await r.json()
            session['token'] = json['access_token']
            session['refresh_token'] = json['refresh_token']
            session['token_type'] = json['token_type']
            expiry = localnow() + datetime.timedelta(
                seconds=json['expires_in'])
            session['token_expiry'] = expiry.strftime("%x %X %z")
            session['scope'] = json['scope']
        return session
    except KeyError:
        try:
            code = request.rel_url.query['code']
        except KeyError:
            query_data = {
                'client_id': request.app.bot.user.id,
                'redirect_uri':
                str(request.url).replace("http://", "https://"),
                'response_type': 'code',
                'scope': scope
            }
            query = urllib.parse.urlencode(query_data)
            raise web.HTTPFound("https://discord.com/api/oauth2/authorize?" +
                                query)
        data = {
            'client_id':
            request.app.bot.user.id,
            'client_secret':
            conf.secret,
            'grant_type':
            'authorization_code',
            'code':
            code,
            'redirect_uri':
            str(request.url).split("?")[0].replace("http://", "https://"),
            'scope':
            scope
        }
        headers = {'Content-Type': 'application/x-www-form-urlencoded'}
        async with aiohttp.ClientSession() as sesh:
            async with sesh.post("https://discord.com/api/v6/oauth2/token",
                                 data=data,
                                 headers=headers) as r:
                json = await r.json()
        session['token'] = json['access_token']
        session['refresh_token'] = json['refresh_token']
        session['token_type'] = json['token_type']
        expiry = localnow() + datetime.timedelta(seconds=json['expires_in'])
        session['token_expiry'] = expiry.strftime("%x %X %z")
        session['scope'] = json['scope']
        return session
示例#10
0
    async def issuelist(self, ctx, tag_or_id="open"):
        """
        Syntax: `{pre}{command_name} [tag_or_id]`

        **Aliases:** `{aliases}`
        **Node:** `{node}`
        **Grant Level:** `{grant_level}`

        __**Description**__
        Lists issues. A `#tag` may be specified for all issues matching that
        tag, or an issue number can be specified to list the details about
        a specific issue. If neither are specified it defaults to all open
        issues.

        __**Arguments**__
        `[tag_or_id]` - The tag or ID number. All matching tags will be shown
        whereas only the single matching issue will be shown when a number
        is specified. If not given, all open issues are displayed.

        __**Example Usage**__
        `{pre}{command_name}`
        `{pre}{command_name} #critical`
        `{pre}{command_name} 69`
        """
        if tag_or_id.isdigit():
            id = int(tag_or_id)
            try:
                issue = IssuesMaster.obtain(id=id)
            except KeyError:
                return await ctx.send(
                    "No issue with ID #{id} exists.".formaT(id=id))
            embed = discord.Embed(title="__Issue #{id}__".format(id=id),
                                  description=issue.title,
                                  color=0xc6c6c6)
            embed.add_field(
                name="__Tags__",
                value="`{tags}`".format(tags="`, `".join(issue.status_tags)),
                inline=True)
            embed.add_field(
                name="__Date Created__",
                value=issue.date.strftime("%-m/%-d/%Y %-I:%M:%S %p %Z"),
                inline=True)
            embed.add_field(name="__Description__",
                            value=issue.description,
                            inline=True)
            responses = list(
                [response.render(ctx.guild) for response in issue.responses])
            resp_title = "Responses in chronological order:" if responses else "No responses yet."
            embed.add_field(name="__Responses__",
                            value=resp_title,
                            inline=True)
            await paginate_embed(ctx, embed, responses, threshold=900)
        else:
            tag = tag_or_id.lower()
            if tag.replace("#", "") == "all":
                title = "__All Issues__"
                matches = list([
                    match
                    for id, match in IssuesMaster.obtain().issues.items()
                ])
            else:
                if tag.replace("#", "") not in conf.issues.validTags:
                    return await ctx.send(
                        "Invalid tag specified: `{tag}`. Valid tags are `{tags}`."
                        .format(tag=tag,
                                tags="`, `".join(conf.issues.validTags)))
                matches = list([
                    match
                    for id, match in IssuesMaster.obtain(tag=tag).items()
                ])
            if len(matches) == 0:
                return await ctx.send(
                    "No issues with tags matching `#{tag}` were found.".format(
                        tag=tag.replace("#", "")))
            title = "__Issues with tag {tag}__".format(
                tag=tag) if tag.startswith(
                    "#") else "__Issues with tag #{tag}__".format(tag=tag)
            description = "{matches} as of {time}".format(
                matches="{:,}".format(len(matches)),
                time=localnow().strftime("%-m/%-d/%Y %-I:%M:%S %p"))
            embed = discord.Embed(title=title,
                                  description=description,
                                  color=0xc6c6c6)
            pack = list([[
                "#{id} - {tags}".format(id=issue.id, tags=issue.rendered_tags),
                issue.title
            ] for issue in matches])
            await paginate_embed(ctx, embed, pack, threshold=900)
示例#11
0
 def add_response(self, author=None, response=None):
     self.responses.append(
         IssueResponse(timestamp=localnow(),
                       responder=author,
                       response=response))
示例#12
0
 def last(self):
     try:
         return self.issues[len(self.issues)]
     except KeyError:
         date = localnow()
         return Issue(id=0, date=date, title="none")