示例#1
0
文件: Emoji.py 项目: gearbot/GearBot
    def gen_emoji_page(self, guild: disnake.Guild, page):
        se = sorted(guild.emojis, key=lambda e: e.name)

        embed = Embed(color=0x2db1f3)
        embed.set_author(name=Translator.translate('emoji_server',
                                                   guild,
                                                   server=guild.name,
                                                   page=page + 1,
                                                   pages=len(guild.emojis) +
                                                   1),
                         url=guild.icon.url)
        if page == 0:
            for chunk in Utils.chunks(se, 18):
                embed.add_field(name="\u200b",
                                value=" ".join(str(e) for e in chunk))
            animated = set()
            static = set()
            for e in guild.emojis:
                (animated if e.animated else static).add(str(e))
            max_emoji = guild.emoji_limit
            embed.add_field(name=Translator.translate('static_emoji', guild),
                            value=f"{len(static)} / {max_emoji}")
            embed.add_field(name=Translator.translate('animated_emoji', guild),
                            value=f"{len(animated)} / {max_emoji}")
        else:
            self.add_emoji_info(guild, embed, se[page - 1])

        return embed
示例#2
0
 async def startup_greeting(self) -> None:
     """Announce presence to the devlog channel."""
     embed = Embed(description="Connected!")
     embed.set_author(
         name="Gurkbot",
         url=constants.BOT_REPO_URL,
         icon_url=self.user.display_avatar.url,
     )
     await self.get_channel(constants.Channels.devlog).send(embed=embed)
示例#3
0
 async def _send_paginated_embed(ctx: Context, lines: Iterable[str],
                                 title: str) -> None:
     """Send paginated embed."""
     embed = Embed()
     embed.set_author(name=title)
     await LinePaginator.paginate(
         [f"{i}. {line}" for i, line in enumerate(lines, start=1)],
         ctx,
         embed,
         allow_empty_lines=True,
     )
示例#4
0
    async def fider(self):
        items = []
        async with self.bot.session.get(
                'https://ideas.obsproject.com/api/v1/posts?view=recent') as r:
            if r.status == 200:
                feed = await r.json()
                for entry in feed:
                    if entry['id'] <= self.bot.state['fider_last_id']:
                        continue
                    items.append(entry)
            else:
                logger.warning(
                    f'Fetching fider posts failed with status code {r.status}')
                return

        for item in reversed(items):
            if item['id'] > self.bot.state['fider_last_id']:
                self.bot.state['fider_last_id'] = item['id']

            url = f'https://ideas.obsproject.com/posts/{item["id"]}/'
            logger.info(f'Got new Fider post: {url}')

            description = item['description']
            if len(description) > 180:
                description = description[:180] + ' [...]'

            embed = Embed(title=f'{item["id"]}: {item["title"]}',
                          colour=Colour(self._fider_colour),
                          url=url,
                          description=description,
                          timestamp=dateutil.parser.parse(item['createdAt']))

            embed.set_author(
                name='Fider',
                url='https://ideas.obsproject.com/',
                icon_url='https://cdn.rodney.io/stuff/obsbot/fider.png')
            embed.set_footer(text='New Idea on Fider')
            name = 'Anonymous' if not item['user']['name'] else item['user'][
                'name']
            embed.add_field(name='Created By', value=name, inline=True)
            await self.fider_channel.send(embed=embed)
示例#5
0
    async def get_pr_messages(self, event_body):
        pr_number = event_body['number']
        title = event_body['pull_request']['title']
        timestamp = dateutil.parser.parse(
            event_body['pull_request']['created_at'])
        embed = Embed(title=f'#{pr_number}: {title}',
                      colour=Colour(self._pull_request_colour),
                      url=event_body['pull_request']['html_url'],
                      timestamp=timestamp)

        author_name = event_body['pull_request']['user']['login']
        author = await self.get_author_info(author_name)
        if author and author['name'] and author['name'] != author['login']:
            author_name = f'{author["name"]} ({author["login"]})'

        embed.set_author(
            name=author_name,
            url=event_body['pull_request']['user']['html_url'],
            icon_url=event_body['pull_request']['user']['avatar_url'])

        embed.set_footer(text='Pull Request')
        embed.add_field(name='Repository',
                        value=event_body['repository']['full_name'],
                        inline=True)
        # create copy without description text for brief channel
        brief_embed = embed.copy()
        # filter out comments in template
        event_body['pull_request']['body'] = '\n'.join(
            l.strip() for l in event_body['pull_request']['body'].splitlines()
            if not l.startswith('<!-'))

        # trim message to discord limits
        if len(event_body['pull_request']['body']) >= 2048:
            embed.description = event_body['pull_request'][
                'body'][:2000] + ' [... message trimmed]'
        else:
            embed.description = event_body['pull_request']['body']

        return brief_embed, embed
示例#6
0
    async def get_issue_messages(self, event_body):
        issue_number = event_body['issue']['number']
        title = event_body['issue']['title']
        timestamp = dateutil.parser.parse(event_body['issue']['created_at'])
        embed = Embed(title=f'#{issue_number}: {title}',
                      colour=Colour(self._issue_colour),
                      url=event_body['issue']['html_url'],
                      timestamp=timestamp)

        author_name = event_body['issue']['user']['login']
        author = await self.get_author_info(author_name)
        if author and author['name'] and author['name'] != author['login']:
            author_name = f'{author["name"]} ({author["login"]})'

        embed.set_author(name=author_name,
                         url=event_body['issue']['user']['html_url'],
                         icon_url=event_body['issue']['user']['avatar_url'])

        embed.set_footer(text='Issue')
        embed.add_field(name='Repository',
                        value=event_body['repository']['full_name'],
                        inline=True)
        # create copy without description text for brief channel
        brief_embed = embed.copy()
        event_body['issue']['body'] = '\n'.join(
            l.strip() for l in event_body['issue']['body'].splitlines()
            if not l.startswith('<!-'))

        issue_text = event_body['issue']['body']
        # strip double-newlines from issue forms
        if '\n\n' in issue_text:
            issue_text = issue_text.replace('\n\n', '\n')

        if len(issue_text) >= 2048:
            embed.description = issue_text[:2000] + ' [... message trimmed]'
        else:
            embed.description = issue_text

        return brief_embed, embed
示例#7
0
    async def get_discussion_messages(self, event_body):
        discussion_number = event_body['discussion']['number']
        title = event_body['discussion']['title']
        category = event_body['discussion']['category']['name']
        timestamp = dateutil.parser.parse(
            event_body['discussion']['created_at'])
        embed = Embed(title=f'#{discussion_number}: {category} - {title}',
                      colour=Colour(self._discussion_colour),
                      timestamp=timestamp,
                      url=event_body['discussion']['html_url'])

        author_name = event_body['discussion']['user']['login']
        author = await self.get_author_info(author_name)
        if author and author['name'] and author['name'] != author['login']:
            author_name = f'{author["name"]} ({author["login"]})'

        embed.set_author(
            name=author_name,
            url=event_body['discussion']['user']['html_url'],
            icon_url=event_body['discussion']['user']['avatar_url'])

        embed.set_footer(text='Discussion')
        embed.add_field(name='Repository',
                        value=event_body['repository']['full_name'],
                        inline=True)
        # create copy without description text for brief channel
        brief_embed = embed.copy()
        event_body['discussion']['body'] = '\n'.join(
            l.strip() for l in event_body['discussion']['body'].splitlines()
            if not l.startswith('<!-'))

        if len(event_body['discussion']['body']) >= 1024:
            embed.description = event_body['discussion'][
                'body'][:1024] + ' [... message trimmed]'
        else:
            embed.description = event_body['discussion']['body']

        return brief_embed, embed
示例#8
0
    async def get_wiki_message(self, event_body):
        embed = Embed(colour=Colour(self._wiki_colour))
        embed.set_footer(text='GitHub Wiki Changes')
        # All edits in the response are from a single author
        author_name = event_body['sender']['login']
        author = await self.get_author_info(author_name)
        if author and author['name'] and author['name'] != author['login']:
            author_name = f'{author["name"]} ({author["login"]})'
        embed.set_author(name=author_name,
                         url=event_body['sender']['html_url'],
                         icon_url=event_body['sender']['avatar_url'])
        embed.add_field(name='Repository',
                        value=event_body['repository']['full_name'])

        body = []
        for page in event_body['pages']:
            diff_url = f'{page["html_url"]}/_compare/{page["sha"]}^...{page["sha"]}'
            page_url = f'{page["html_url"]}/{page["sha"]}'
            body.append(
                f'**{page["action"]}:** [{page["title"]}]({page_url}) [[diff]({diff_url})]'
            )
        embed.description = '\n'.join(body)
        return embed
示例#9
0
    async def get_commit_messages(self, event_body, brief=False):
        embed_commits = []
        branch = event_body['ref'].split('/', 2)[2]
        project = event_body['repository']['full_name']
        commits = event_body['commits']

        if brief and len(commits) > self.config['commit_truncation_limit']:
            first_hash = commits[0]['id']
            last_hash = commits[-2]['id']
            compare_url = f'https://github.com/{project}/compare/{first_hash}^...{last_hash}'
            embed = Embed(
                title=
                f'Skipped {len(commits) - 1} commits... (click link for diff)',
                colour=Colour(self._skipped_commit_colour),
                url=compare_url)
            embed_commits.append((embed, None))
            commits = commits[-1:]

        for commit in commits:
            author_username = commit['author'].get('username', None)
            author_name = commit['author'].get('name', None)
            timestamp = dateutil.parser.parse(commit['timestamp'])
            commit_message = commit['message'].split('\n')
            embed = Embed(title=commit_message[0],
                          colour=Colour(self._commit_colour),
                          url=commit['url'],
                          timestamp=timestamp)

            if len(commit_message) > 2 and not brief:
                commit_body = '\n'.join(commit_message[2:])
                embed.description = commit_body[:4096]

            author = await self.get_author_info(author_username)

            if author:
                if author['name'] and author['name'] != author['login']:
                    author_name = f'{author["name"]} ({author["login"]})'
                else:
                    author_name = author['login']

                embed.set_author(name=author_name,
                                 url=author['html_url'],
                                 icon_url=author['avatar_url'])
            elif author_name:
                embed.set_author(name=author_name)
            else:
                embed.set_author(name='<No Name>')

            embed.set_footer(text='Commit')
            embed.add_field(name='Repository', value=project, inline=True)
            embed.add_field(name='Branch', value=branch, inline=True)
            embed_commits.append((embed, commit['id']))

        return embed_commits
示例#10
0
async def handle_exception(exception_type,
                           bot,
                           exception,
                           event=None,
                           message=None,
                           ctx=None,
                           *args,
                           **kwargs):
    if bot is not None:
        bot.errors = bot.errors + 1
    with sentry_sdk.push_scope() as scope:
        embed = Embed(colour=Colour(0xff0000),
                      timestamp=datetime.datetime.utcfromtimestamp(
                          time.time()).replace(tzinfo=datetime.timezone.utc))

        # something went wrong and it might have been in on_command_error, make sure we log to the log file first
        lines = [
            "\n===========================================EXCEPTION CAUGHT, DUMPING ALL AVAILABLE INFO===========================================",
            f"Type: {exception_type}"
        ]

        arg_info = ""
        for arg in list(args):
            arg_info += extract_info(arg) + "\n"
        if arg_info == "":
            arg_info = "No arguments"

        kwarg_info = ""
        for name, arg in kwargs.items():
            kwarg_info += "{}: {}\n".format(name, extract_info(arg))
        if kwarg_info == "":
            kwarg_info = "No keyword arguments"

        lines.append("======================Exception======================")
        lines.append(f"{str(exception)} ({type(exception)})")

        lines.append("======================ARG INFO======================")
        lines.append(arg_info)
        sentry_sdk.add_breadcrumb(category='arg info',
                                  message=arg_info,
                                  level='info')

        lines.append("======================KWARG INFO======================")
        lines.append(kwarg_info)
        sentry_sdk.add_breadcrumb(category='kwarg info',
                                  message=kwarg_info,
                                  level='info')

        lines.append("======================STACKTRACE======================")
        tb = "".join(traceback.format_tb(exception.__traceback__))
        lines.append(tb)

        if message is None and event is not None and hasattr(event, "message"):
            message = event.message

        if message is None and ctx is not None:
            message = ctx.message

        if message is not None and hasattr(message, "content"):
            lines.append(
                "======================ORIGINAL MESSAGE======================")
            lines.append(message.content)
            if message.content is None or message.content == "":
                content = "<no content>"
            else:
                content = message.content
            scope.set_tag('message content', content)
            embed.add_field(name="Original message",
                            value=Utils.trim_message(content, 1000),
                            inline=False)

            lines.append(
                "======================ORIGINAL MESSAGE (DETAILED)======================"
            )
            lines.append(extract_info(message))

        if event is not None:
            lines.append(
                "======================EVENT NAME======================")
            lines.append(event)
            scope.set_tag('event name', event)
            embed.add_field(name="Event", value=event)

        if ctx is not None:
            lines.append(
                "======================COMMAND INFO======================")

            lines.append(f"Command: {ctx.command.name}")
            embed.add_field(name="Command", value=ctx.command.name)
            scope.set_tag('command', ctx.command.name)

            channel_name = 'Private Message' if isinstance(
                ctx.channel,
                PrivateChannel) else f"{ctx.channel.name} (`{ctx.channel.id}`)"
            lines.append(f"Channel: {channel_name}")
            embed.add_field(name="Channel", value=channel_name, inline=False)
            scope.set_tag('channel', channel_name)

            sender = f"{str(ctx.author)} (`{ctx.author.id}`)"
            scope.user = dict(id=ctx.author.id, username=str(ctx.author))
            lines.append(f"Sender: {sender}")
            embed.add_field(name="Sender", value=sender, inline=False)

        lines.append(
            "===========================================DATA DUMP COMPLETE==========================================="
        )
        GearbotLogging.error("\n".join(lines))

        for t in [ConnectionClosed, ClientOSError, ServerDisconnectedError]:
            if isinstance(exception, t):
                return
        #nice embed for info on discord

        embed.set_author(name=exception_type)
        embed.add_field(name="Exception",
                        value=f"{str(exception)} (`{type(exception)}`)",
                        inline=False)
        parts = Pages.paginate(tb, max_chars=1024)
        num = 1
        for part in parts:
            embed.add_field(name=f"Traceback {num}/{len(parts)}", value=part)
            num += 1
        sentry_sdk.capture_exception(exception)
    # try logging to botlog, wrapped in an try catch as there is no higher lvl catching to prevent taking down the bot (and if we ended here it might have even been due to trying to log to botlog
    try:
        await GearbotLogging.bot_log(embed=embed)
    except Exception as ex:
        GearbotLogging.error(
            f"Failed to log to botlog, either Discord broke or something is seriously wrong!\n{ex}"
        )
        GearbotLogging.error(traceback.format_exc())
示例#11
0
                        self.state['nightly_macos'] = self.config[
                            'artifact_service'].format(artifact['id'])
                elif 'win-x64' in artifact['name']:
                    self.state['nightly_windows'] = self.config[
                        'artifact_service'].format(artifact['id'])

            artifacts_entries.append(
                f'[{artifact["name"]}]({artifact["archive_download_url"]})')

        embed = Embed(title=f'Build {run["run_number"]} {build_result}',
                      url=web_url,
                      description='\n'.join(message),
                      timestamp=finished,
                      colour=colour)
        embed.set_author(
            name='GitHub Actions',
            icon_url='https://cdn.rodney.io/stuff/obsbot/github_actions.png')
        embed.add_field(name="Project", value=repo, inline=True)
        embed.add_field(name="Branch", value=branch, inline=True)
        # only attach artifact urls if build succeeded
        if build_success:
            embed.add_field(name='Artifacts',
                            inline=False,
                            value=', '.join(artifacts_entries))

        return build_success, embed, (commit_hash, message[0], reaction_emote,
                                      web_url)

    async def get_with_retry(self,
                             url,
                             params=None,
示例#12
0
async def updater(cog: BCVersionChecker):
    GearbotLogging.info("Started BC version checking background task")
    session: aiohttp.ClientSession = cog.bot.aiosession
    lastUpdate = 0
    while cog.running:
        try:
            # check for a newer bc version
            async with session.get(
                    'https://www.mod-buildcraft.com/build_info_full/last_change.txt'
            ) as reply:
                stamp = await reply.text()
                stamp = int(stamp[:-1])
                if stamp > lastUpdate:
                    GearbotLogging.info("New BC version somewhere!")
                    lastUpdate = stamp
                    cog.BC_VERSION_LIST = await getList(session, "BuildCraft")
                    cog.BCC_VERSION_LIST = await getList(
                        session, "BuildCraftCompat")
                    highestMC = VersionInfo.getLatest(
                        cog.BC_VERSION_LIST.keys())
                    latestBC = VersionInfo.getLatest(
                        cog.BC_VERSION_LIST[highestMC])
                    generalID = 309218657798455298
                    channel: disnake.TextChannel = cog.bot.get_channel(
                        generalID)
                    old_latest = Configuration.get_persistent_var(
                        "latest_bc", "0.0.0")
                    Configuration.set_persistent_var(
                        "latest_bc", latestBC
                    )  # save already so we don't get stuck and keep trying over and over if something goes wrong
                    if channel is not None and latestBC != old_latest:
                        GearbotLogging.info(
                            f"New BuildCraft version found: {latestBC}")
                        notify_channel = cog.bot.get_channel(
                            349517224320565258)
                        await notify_channel.send(
                            f"{Emoji.get_chat_emoji('WRENCH')} New BuildCraft version detected ({latestBC})"
                        )
                        GearbotLogging.info(
                            f"Fetching metadata for BuildCraft {latestBC}")
                        message = await notify_channel.send(
                            f"{Emoji.get_chat_emoji('REFRESH')} Fetching metadata..."
                        )
                        info = await cog.getVersionDetails(
                            "BuildCraft", latestBC)
                        GearbotLogging.info(f"Metadata acquired: {info}")
                        await message.edit(
                            content=
                            f"{Emoji.get_chat_emoji('YES')} Metadata acquired")
                        if 'blog_entry' in info:
                            message = await notify_channel.send(
                                f"{Emoji.get_chat_emoji('REFRESH')} Updating general topic..."
                            )
                            newTopic = f"General discussions about BuildCraft.\n" \
                                f"Latest version: {latestBC}\n" \
                                f"Full changelog and download: {info['blog_entry']}"
                            await channel.edit(topic=newTopic)
                            await message.edit(
                                content=
                                f"{Emoji.get_chat_emoji('YES')} Topic updated")
                        else:
                            notify_channel.send(
                                f"{Emoji.get_chat_emoji('WARNING')} No blog post data found, notifying <@180057061353193472>"
                            )

                        # message = await notify_channel.send(f"{Emoji.get_chat_emoji('REFRESH')} Uploading files to CurseForge...")
                        # code, output, errors = await Utils.execute(f'cd BuildCraft/uploader && gradle curseforge -Pnew_version="{latestBC}"')
                        # GearbotLogging.info(f"Upload to CF complete\n)------stdout------\n{output}\n------stderr------\n{errors}")
                        # if code is 0:
                        #     content = f"{Emoji.get_chat_emoji('YES')} All archives successfully uploaded"
                        #     await message.edit(content=content)
                        # else:
                        #     content = f"{Emoji.get_chat_emoji('NO')} Upload failed with code {code}, notifying <@106354106196570112>"
                        #     await notify_channel.send(content)

            # update FAQs if needed
            async with session.get(
                    'https://mod-buildcraft.com/website_src/faq.md') as reply:
                data = await reply.text()
                h = hashlib.md5(data.encode('utf-8')).hexdigest()
                old = Configuration.get_persistent_var("BCFAQ", "")
                channel = cog.bot.get_channel(361557801492938762)  # FAQs
                if channel is not None and h != old:
                    Configuration.set_persistent_var("BCFAQ", h)
                    #clean the old stuff
                    await channel.purge()

                    #send banner
                    with open("BuildCraft/FAQs.png", "rb") as file:
                        await channel.send(file=File(file, filename="FAQs.png")
                                           )
                    #send content
                    out = ""
                    parts = [
                        d.strip("#").strip() for d in data.split("##")[1:]
                    ]
                    for part in parts:
                        lines = part.splitlines()
                        content = '\n'.join(lines[1:])
                        out += f"**```{lines[0].strip()}```**{content}\n"
                    for page in Pages.paginate(out,
                                               max_chars=2048,
                                               max_lines=50):
                        embed = Embed(description=page)
                        await channel.send(embed=embed)

                pass
        except CancelledError:
            pass  # bot shutdown
        except Exception as ex:
            cog.bot.errors = cog.bot.errors + 1
            GearbotLogging.error(
                "Something went wrong in the BC version checker task")
            GearbotLogging.error(traceback.format_exc())
            embed = disnake.Embed(colour=disnake.Colour(0xff0000),
                                  timestamp=datetime.datetime.utcfromtimestamp(
                                      time.time()))
            embed.set_author(
                name="Something went wrong in the BC version checker task:")
            embed.add_field(name="Exception", value=str(ex))
            v = ""
            for line in traceback.format_exc().splitlines():
                if len(v) + len(line) >= 1024:
                    embed.add_field(name="Stacktrace", value=v)
                    v = ""
                v = f"{v}\n{line}"
            if len(v) > 0:
                embed.add_field(name="Stacktrace", value=v)
            await GearbotLogging.bot_log(embed=embed)
        for i in range(1, 60):
            if cog.force or not cog.running:
                break
            await asyncio.sleep(10)

    GearbotLogging.info("BC version checking background task terminated")