From 3d6b751000992164812b95048c580f9d67cb861e Mon Sep 17 00:00:00 2001 From: Roxedus Date: Mon, 28 Aug 2023 13:47:03 +0200 Subject: [PATCH 1/3] Move core functionality to functions, add dispatch --- githubcards/core.py | 79 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 61 insertions(+), 18 deletions(-) diff --git a/githubcards/core.py b/githubcards/core.py index 973af0e..bf946ee 100644 --- a/githubcards/core.py +++ b/githubcards/core.py @@ -95,6 +95,31 @@ async def _create_client(self) -> None: """Create GitHub API client.""" self.http = GitHubAPI(token=await self._get_token()) + async def _add_card(self, guild: discord.Guild, prefix: str, owner: str, repo: str) -> str: + """Adds new cards to the guild + """ + try: + await self.http.validate_repo(owner, repo) + except ApiError: + return 'The provided GitHub repository doesn\'t exist, or is unable to be accessed due to permissions.' + + async with self.config.custom("REPO", guild.id).all() as repos: + if prefix in repos.keys(): + return 'This prefix already exists in this server. Please use something else.' + + repos[prefix] = {"owner": owner, "repo": repo} + + await self.rebuild_cache_for_guild(guild.id) + return f"A GitHub repository (``{owner}/{repo}``) added with a prefix ``{prefix}``" + + async def _remove_card(self, guild: discord.Guild, prefix: str) -> str: + """Removes a card from the guild + """ + await self.config.custom("REPO", guild.id, prefix).clear() + await self.rebuild_cache_for_guild(guild.id) + + return f"A repository with the prefix ``{prefix}`` has been removed." + @commands.guild_only() @commands.command(usage=" ") async def ghsearch(self, ctx, repo_data: RepoData, *, search_query: str): @@ -128,31 +153,17 @@ async def add(self, ctx, prefix: str, github_slug: str): await ctx.send('Invalid format. Please use ``Username/Repository``.') return - try: - await self.http.validate_repo(owner, repo) - except ApiError: - await ctx.send('The provided GitHub repository doesn\'t exist, or is unable to be accessed due to permissions.') - return - - async with self.config.custom("REPO", ctx.guild.id).all() as repos: - if prefix in repos.keys(): - await ctx.send('This prefix already exists in this server. Please use something else.') - return - - repos[prefix] = {"owner": owner, "repo": repo} + msg = await self._add_card(guild=ctx.guild, prefix=prefix, owner=owner, repo=repo) - await self.rebuild_cache_for_guild(ctx.guild.id) - await ctx.send(f"A GitHub repository (``{github_slug}``) added with a prefix ``{prefix}``") + await ctx.send(msg) @ghc_group.command(name="remove", aliases=["delete"]) async def remove(self, ctx, prefix: str): """Remove a GitHub repository with its given prefix. """ - await self.config.custom("REPO", ctx.guild.id, prefix).clear() - await self.rebuild_cache_for_guild(ctx.guild.id) + msg = await self._remove_card(guild=ctx.guild, prefix=prefix) - # if that prefix doesn't exist, it will still send same message but I don't care - await ctx.send(f"A repository with the prefix ``{prefix}`` has been removed.") + await ctx.send(msg) @ghc_group.command(name="list") async def list_prefixes(self, ctx): @@ -269,6 +280,38 @@ async def on_message_without_command(self, message): async with message.channel.typing(): await self._query_and_post(message, fetchable_repos) + @commands.Cog.listener() + async def on_kowlin_ghc_add(self, *, guild: discord.Guild, owner: str, repo: str, prefix:str, **_kwargs: Any): + """Sets up listener for new repos + + Can be dispatch like + self.bot.dispatch( + "kowlin_ghc_add", + guild=ctx.guild, + owner="Kowlin" + repo="Sentinel", + prefix="Sentinel" + ) + """ + msg = await self._add_card(guild=guild, prefix=prefix, owner=owner, repo=repo) + + log.info(msg) + + @commands.Cog.listener() + async def on_kowlin_ghc_remove(self, *, guild: discord.Guild, prefix:str, **_kwargs: Any): + """Sets up listener for removal of repos + + Can be dispatch like + self.bot.dispatch( + "kowlin_ghc_remove", + guild=ctx.guild, + prefix="Sentinel" + ) + """ + msg = await self._remove_card(guild=guild, prefix=prefix) + + log.info(msg) + async def _query_and_post(self, message, fetchable_repos): # --- FETCHING --- query = Query.build_query(fetchable_repos) From a624865b1f47f3235b466bcf226db0abba9366b0 Mon Sep 17 00:00:00 2001 From: Roxedus Date: Fri, 6 Oct 2023 14:04:03 +0200 Subject: [PATCH 2/3] Pagify list --- githubcards/core.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/githubcards/core.py b/githubcards/core.py index bf946ee..c7d1692 100644 --- a/githubcards/core.py +++ b/githubcards/core.py @@ -11,6 +11,8 @@ import discord from redbot.core import Config, checks, commands +from redbot.core.utils.chat_formatting import pagify +from redbot.core.utils.views import SimpleMenu from .converters import RepoData from .exceptions import ApiError, Unauthorized @@ -174,9 +176,17 @@ async def list_prefixes(self, ctx): await ctx.send("There are no configured GitHub repositories on this server.") return msg = "\n".join( - f"``{prefix}``: ``{repo['owner']}/{repo['repo']}``" for prefix, repo in repos.items() + f"``{prefix}``: ``{repo['owner']}/{repo['repo']}``" for prefix, repo in sorted(repos.items()) ) - await ctx.send(f"List of configured prefixes on **{ctx.guild.name}** server:\n{msg}") + + pages = pagify(msg, delims=("\n")) + pages = [{"embed": discord.Embed(description=page, title=f"List of configured prefixes on **{ctx.guild.name}** server:")} for page in pages] + + if len(pages) == 1: + await ctx.send(**pages[0]) + else: + selectMenu = len(pages) >= 5 <= 25 + await SimpleMenu(pages, use_select_menu=selectMenu, use_select_only=selectMenu).start(ctx) @ghc_group.command(name="instructions") async def instructions(self, ctx): From 998baa0b1a1ac7c228962e0f4b891f1963937f27 Mon Sep 17 00:00:00 2001 From: Kowlin Date: Wed, 15 Jan 2025 04:36:40 +0100 Subject: [PATCH 3/3] Formatting & minor adjustments --- githubcards/converters.py | 4 +- githubcards/core.py | 128 +++++++++++++++++++++++++++----------- githubcards/data.py | 6 +- githubcards/formatters.py | 64 +++++++++++-------- githubcards/http.py | 61 ++++++++++-------- 5 files changed, 171 insertions(+), 92 deletions(-) diff --git a/githubcards/converters.py b/githubcards/converters.py index e7be8fc..763d772 100644 --- a/githubcards/converters.py +++ b/githubcards/converters.py @@ -12,7 +12,9 @@ class RepoData(commands.Converter): async def convert(self, ctx: commands.Context, argument: str) -> dict: cache = ctx.cog.active_prefix_matchers.get(ctx.guild.id, None) if cache is None: - raise commands.BadArgument("There are no configured repositories on this server.") + raise commands.BadArgument( + "There are no configured repositories on this server." + ) repo_data = cache["data"].get(argument, None) if repo_data is None: raise commands.BadArgument( diff --git a/githubcards/core.py b/githubcards/core.py index 3fe0217..79c76be 100644 --- a/githubcards/core.py +++ b/githubcards/core.py @@ -36,6 +36,7 @@ class GitHubCards(commands.Cog): """GitHub Cards""" + # Oh my god I'm doing it def __init__(self, bot): @@ -53,7 +54,7 @@ def __init__(self, bot): self.http: GitHubAPI = None # assigned in initialize() async def initialize(self): - """ cache preloading """ + """cache preloading""" await self.rebuild_cache_for_guild() await self._create_client() self._ready.set() @@ -69,7 +70,10 @@ async def rebuild_cache_for_guild(self, *guild_ids): for guild_id, guild_data in data.items(): partial = "|".join(re.escape(prefix) for prefix in guild_data.keys()) pattern = re.compile(rf"^({partial})#([0-9]+)$", re.IGNORECASE) - self.active_prefix_matchers[int(guild_id)] = {"pattern": pattern, "data": guild_data} + self.active_prefix_matchers[int(guild_id)] = { + "pattern": pattern, + "data": guild_data, + } finally: self._ready.set() @@ -99,26 +103,28 @@ async def _create_client(self) -> None: """Create GitHub API client.""" self.http = GitHubAPI(token=await self._get_token()) - async def _add_card(self, guild: discord.Guild, prefix: str, owner: str, repo: str) -> str: - """Adds new cards to the guild - """ + async def _add_card( + self, guild: discord.Guild, prefix: str, owner: str, repo: str + ) -> str: + """Adds new cards to the guild""" try: await self.http.validate_repo(owner, repo) except ApiError: - return 'The provided GitHub repository doesn\'t exist, or is unable to be accessed due to permissions.' + return "The provided GitHub repository doesn't exist, or is unable to be accessed due to permissions." async with self.config.custom("REPO", guild.id).all() as repos: if prefix in repos.keys(): - return 'This prefix already exists in this server. Please use something else.' + return "This prefix already exists in this server. Please use something else." repos[prefix] = {"owner": owner, "repo": repo} await self.rebuild_cache_for_guild(guild.id) - return f"A GitHub repository (``{owner}/{repo}``) added with a prefix ``{prefix}``" + return ( + f"A GitHub repository (``{owner}/{repo}``) added with a prefix ``{prefix}``" + ) async def _remove_card(self, guild: discord.Guild, prefix: str) -> str: - """Removes a card from the guild - """ + """Removes a card from the guild""" await self.config.custom("REPO", guild.id, prefix).clear() await self.rebuild_cache_for_guild(guild.id) @@ -150,45 +156,61 @@ async def add(self, ctx, prefix: str, github_slug: str): Format for adding a new GitHub repo is "Username/Repository" """ - prefix = prefix.lower() # Ensure lowering of prefixes, since fuck anything else. + prefix = ( + prefix.lower() + ) # Ensure lowering of prefixes, since fuck anything else. try: owner, repo = github_slug.split("/") except ValueError: - await ctx.send('Invalid format. Please use ``Username/Repository``.') + await ctx.send("Invalid format. Please use ``Username/Repository``.") return - msg = await self._add_card(guild=ctx.guild, prefix=prefix, owner=owner, repo=repo) + msg = await self._add_card( + guild=ctx.guild, prefix=prefix, owner=owner, repo=repo + ) await ctx.send(msg) @ghc_group.command(name="remove", aliases=["delete"]) async def remove(self, ctx, prefix: str): - """Remove a GitHub repository with its given prefix. - """ + """Remove a GitHub repository with its given prefix.""" msg = await self._remove_card(guild=ctx.guild, prefix=prefix) await ctx.send(msg) @ghc_group.command(name="list") - async def list_prefixes(self, ctx): - """List all prefixes for GitHub Cards in this server. - """ + async def list_prefixes(self, ctx: commands.Context): + """List all prefixes for GitHub Cards in this server.""" repos = await self.config.custom("REPO", ctx.guild.id).all() if not repos: - await ctx.send("There are no configured GitHub repositories on this server.") + await ctx.send( + "There are no configured GitHub repositories on this server." + ) return msg = "\n".join( - f"``{prefix}``: ``{repo['owner']}/{repo['repo']}``" for prefix, repo in sorted(repos.items()) + f"``{prefix}``: ``{repo['owner']}/{repo['repo']}``" + for prefix, repo in sorted(repos.items()) ) pages = pagify(msg, delims=("\n")) - pages = [{"embed": discord.Embed(description=page, title=f"List of configured prefixes on **{ctx.guild.name}** server:")} for page in pages] + pages = [ + { + "embed": discord.Embed( + description=page, + title=f"List of configured prefixes on **{ctx.guild.name}** server:", + color=await self.bot.get_embed_colour(ctx.message), + ) + } + for page in pages + ] if len(pages) == 1: await ctx.send(**pages[0]) else: selectMenu = len(pages) >= 5 <= 25 - await SimpleMenu(pages, use_select_menu=selectMenu, use_select_only=selectMenu).start(ctx) + await SimpleMenu( + pages, use_select_menu=selectMenu, use_select_only=selectMenu + ).start(ctx) @ghc_group.command(name="instructions") async def instructions(self, ctx): @@ -219,7 +241,9 @@ async def is_eligible_as_command(self, message: discord.Message) -> bool: and not await self.bot.cog_disabled_in_guild(self, message.guild) ) - def get_matcher_by_message(self, message: discord.Message) -> Optional[Dict[str, Any]]: + def get_matcher_by_message( + self, message: discord.Message + ) -> Optional[Dict[str, Any]]: """Get matcher from message object. This also checks if the message is eligible as command and returns None otherwise. @@ -250,24 +274,44 @@ async def on_message_without_command(self, message): if message.content.startswith(f"{prefix}#s "): async with message.channel.typing(): search_query = message.content.replace(f"{prefix}#s ", "") - if all(issue_type not in search_query for issue_type in ["is:issue", "is:pr", "is:pull-request", "is:pull_request"]): + if all( + issue_type not in search_query + for issue_type in [ + "is:issue", + "is:pr", + "is:pull-request", + "is:pull_request", + ] + ): search_data_issues = await self.http.search_issues( - data["owner"], data["repo"], search_query, type=IssueType.ISSUE + data["owner"], + data["repo"], + search_query, + type=IssueType.ISSUE, ) search_data_prs = await self.http.search_issues( - data["owner"], data["repo"], search_query, type=IssueType.PULL_REQUEST + data["owner"], + data["repo"], + search_query, + type=IssueType.PULL_REQUEST, ) # truncate the results to 15 based on date - combined_results = search_data_issues.results + search_data_prs.results + combined_results = ( + search_data_issues.results + search_data_prs.results + ) for result in combined_results: - result["createdAt"] = datetime.strptime(result['createdAt'], '%Y-%m-%dT%H:%M:%SZ') - combined_results.sort(key=lambda x: x["createdAt"], reverse=True) + result["createdAt"] = datetime.strptime( + result["createdAt"], "%Y-%m-%dT%H:%M:%SZ" + ) + combined_results.sort( + key=lambda x: x["createdAt"], reverse=True + ) combined_results = combined_results[:15] search_data = SearchData( total=search_data_issues.total + search_data_prs.total, results=combined_results, - query=search_query + query=search_query, ) else: search_data = await self.http.search_issues( @@ -290,7 +334,7 @@ async def on_message_without_command(self, message): number = int(match.group(2)) prefix_data = matcher["data"][prefix] - name_with_owner = (prefix_data['owner'], prefix_data['repo']) + name_with_owner = (prefix_data["owner"], prefix_data["repo"]) # Magical fetching aquesition done. # Ensure that the repo exists as a key @@ -302,9 +346,9 @@ async def on_message_without_command(self, message): "fetchable_issues": {}, # using dict instead of a set since it's ordered } # No need to post card for same issue number from the same repo in one message twice - if number in fetchable_repos[name_with_owner]['fetchable_issues']: + if number in fetchable_repos[name_with_owner]["fetchable_issues"]: continue - fetchable_repos[name_with_owner]['fetchable_issues'][number] = None + fetchable_repos[name_with_owner]["fetchable_issues"][number] = None if len(fetchable_repos) == 0: return # End if no repos are found to query over. @@ -313,7 +357,15 @@ async def on_message_without_command(self, message): await self._query_and_post(message, fetchable_repos) @commands.Cog.listener() - async def on_kowlin_ghc_add(self, *, guild: discord.Guild, owner: str, repo: str, prefix:str, **_kwargs: Any): + async def on_kowlin_ghc_add( + self, + *, + guild: discord.Guild, + owner: str, + repo: str, + prefix: str, + **_kwargs: Any, + ): """Sets up listener for new repos Can be dispatch like @@ -330,7 +382,9 @@ async def on_kowlin_ghc_add(self, *, guild: discord.Guild, owner: str, repo: str log.info(msg) @commands.Cog.listener() - async def on_kowlin_ghc_remove(self, *, guild: discord.Guild, prefix:str, **_kwargs: Any): + async def on_kowlin_ghc_remove( + self, *, guild: discord.Guild, prefix: str, **_kwargs: Any + ): """Sets up listener for removal of repos Can be dispatch like @@ -374,7 +428,9 @@ async def _query_and_post(self, message, fetchable_repos): issue_embeds.append(e) continue else: - overflow.append(f"[{issue.name_with_owner}#{issue.number}]({issue.url})") + overflow.append( + f"[{issue.name_with_owner}#{issue.number}]({issue.url})" + ) for embed in issue_embeds: await message.channel.send(embed=embed) diff --git a/githubcards/data.py b/githubcards/data.py index e2936d0..ec96198 100644 --- a/githubcards/data.py +++ b/githubcards/data.py @@ -43,9 +43,9 @@ class IssueData(object): @dataclass(init=True) class IssueStateColour(object): - OPEN: int = 0x6cc644 - CLOSED: int = 0xbd2c00 - MERGED: int = 0x6e5494 + OPEN: int = 0x6CC644 + CLOSED: int = 0xBD2C00 + MERGED: int = 0x6E5494 class IssueType(Enum): diff --git a/githubcards/formatters.py b/githubcards/formatters.py index 6c039ef..5903fc8 100644 --- a/githubcards/formatters.py +++ b/githubcards/formatters.py @@ -25,30 +25,30 @@ def format_issue_class(issue: dict) -> IssueData: else: milestone_title = None - if issue['author'] is None: - issue['author'] = { + if issue["author"] is None: + issue["author"] = { "login": "Ghost", "url": "https://github.com/ghost", - "avatarUrl": "https://avatars.githubusercontent.com/u/10137?v=4" + "avatarUrl": "https://avatars.githubusercontent.com/u/10137?v=4", } labels = tuple(label["name"] for label in issue["labels"]["nodes"]) data = IssueData( - name_with_owner=issue['repository']['nameWithOwner'], - author_name=issue['author']['login'], - author_url=issue['author']['url'], - author_avatar_url=issue['author']['avatarUrl'], - issue_type=issue['__typename'], - number=issue['number'], - title=issue['title'], - body_text=issue['body'], - url=issue['url'], - state=issue['state'], + name_with_owner=issue["repository"]["nameWithOwner"], + author_name=issue["author"]["login"], + author_url=issue["author"]["url"], + author_avatar_url=issue["author"]["avatarUrl"], + issue_type=issue["__typename"], + number=issue["number"], + title=issue["title"], + body_text=issue["body"], + url=issue["url"], + state=issue["state"], is_draft=is_draft, mergeable_state=mergeable_state, milestone=milestone_title, labels=labels, - created_at=datetime.strptime(issue['createdAt'], '%Y-%m-%dT%H:%M:%SZ') + created_at=datetime.strptime(issue["createdAt"], "%Y-%m-%dT%H:%M:%SZ"), ) return data @@ -59,7 +59,7 @@ def format_issue(issue_data: IssueData) -> discord.Embed: embed.set_author( name=issue_data.author_name, url=issue_data.author_url, - icon_url=issue_data.author_avatar_url + icon_url=issue_data.author_avatar_url, ) number_suffix = f" #{issue_data.number}" max_len = 256 - len(number_suffix) @@ -69,12 +69,24 @@ def format_issue(issue_data: IssueData) -> discord.Embed: embed.title = f"{issue_data.title}{number_suffix}" embed.url = issue_data.url if len(issue_data.body_text) > 300: - embed.description = next(pagify(issue_data.body_text, delims=[" ", "\n"], page_length=300, shorten_by=0)) + "..." + embed.description = ( + next( + pagify( + issue_data.body_text, + delims=[" ", "\n"], + page_length=300, + shorten_by=0, + ) + ) + + "..." + ) else: embed.description = issue_data.body_text embed.colour = getattr(IssueStateColour, issue_data.state) - formatted_datetime = issue_data.created_at.strftime('%d %b %Y, %H:%M') - embed.set_footer(text=f"{issue_data.name_with_owner} • Created on {formatted_datetime}") + formatted_datetime = issue_data.created_at.strftime("%d %b %Y, %H:%M") + embed.set_footer( + text=f"{issue_data.name_with_owner} • Created on {formatted_datetime}" + ) if issue_data.labels: embed.add_field( name=f"Labels [{len(issue_data.labels)}]", @@ -105,11 +117,7 @@ def format_search(search_data: SearchData) -> discord.Embed: else: state = "\N{LARGE PURPLE CIRCLE}" - issue_type = ( - "Issue" - if entry["__typename"] == "Issue" - else "Pull Request" - ) + issue_type = "Issue" if entry["__typename"] == "Issue" else "Pull Request" mergeable_state = entry.get("mergeable", None) is_draft = entry.get("isDraft", None) if entry["state"] == "OPEN": @@ -124,7 +132,9 @@ def format_search(search_data: SearchData) -> discord.Embed: f"{entry['title']}" ) if search_data.total > 10: - embed.set_footer(text=f"Showing the first 10 results, {search_data.total} results in total.") + embed.set_footer( + text=f"Showing the first 10 results, {search_data.total} results in total." + ) embed_body += ( "\n\n[Click here for all the results]" f"(https://github.com/search?type=Issues&q={search_data.escaped_query})" @@ -151,7 +161,7 @@ def build_query(cls, fetchable_repos: Dict[str, FetchableReposDict]) -> str: repos = list(fetchable_repos.values()) for idx, repo_data in enumerate(repos): issue_queries = [] - for issue in repo_data['fetchable_issues']: + for issue in repo_data["fetchable_issues"]: issue_queries.append(Queries.findIssueFullData % {"number": issue}) repo_queries.append( Queries.findIssueRepository @@ -163,6 +173,8 @@ def build_query(cls, fetchable_repos: Dict[str, FetchableReposDict]) -> str: } ) - query_string = Queries.findIssueQuery % {"repositories": "\n".join(repo_queries)} + query_string = Queries.findIssueQuery % { + "repositories": "\n".join(repo_queries) + } return cls(query_string, repos) diff --git a/githubcards/http.py b/githubcards/http.py index 3dc16fd..01081d7 100644 --- a/githubcards/http.py +++ b/githubcards/http.py @@ -27,7 +27,9 @@ class RateLimit: We really should just use that lib already... """ - def __init__(self, *, limit: int, remaining: int, reset: float, cost: Optional[int]) -> None: + def __init__( + self, *, limit: int, remaining: int, reset: float, cost: Optional[int] + ) -> None: self.limit = limit self.remaining = remaining self.reset = reset @@ -47,7 +49,9 @@ def from_http( try: limit = ratelimit_data["limit"] remaining = ratelimit_data["remaining"] - reset = datetime.strptime(ratelimit_data["resetAt"], '%Y-%m-%dT%H:%M:%SZ') + reset = datetime.strptime( + ratelimit_data["resetAt"], "%Y-%m-%dT%H:%M:%SZ" + ) except KeyError: return None else: @@ -70,20 +74,24 @@ def _create_session(self, token: str) -> None: "Authorization": f"bearer {token}", "Content-Type": "application/json", "Accept": "application/vnd.github+json", - "User-Agent": "Py aiohttp - GitHubCards (github.com/Kowlin/sentinel)" + "User-Agent": "Py aiohttp - GitHubCards (github.com/Kowlin/sentinel)", } self._token = token self.session = aiohttp.ClientSession(headers=headers) async def validate_user(self): - async with self.session.post(baseUrl, json={"query": Queries.validateUser}) as call: + async with self.session.post( + baseUrl, json={"query": Queries.validateUser} + ) as call: json = await call.json() if call.status == 401: raise Unauthorized(json["message"]) if "errors" in json.keys(): - raise ApiError(json['errors']) + raise ApiError(json["errors"]) self._log_ratelimit( - self.validate_user, call.headers, ratelimit_data=json['data']['rateLimit'] + self.validate_user, + call.headers, + ratelimit_data=json["data"]["rateLimit"], ) return json @@ -99,47 +107,48 @@ async def validate_repo(self, repoOwner: str, repoName: str): if call.status == 401: raise Unauthorized(json["message"]) if "errors" in json.keys(): - raise ApiError(json['errors']) + raise ApiError(json["errors"]) self._log_ratelimit( - self.validate_repo, call.headers, ratelimit_data=json['data']['rateLimit'] + self.validate_repo, + call.headers, + ratelimit_data=json["data"]["rateLimit"], ) return json - async def search_issues(self, repoOwner: str, repoName: str, searchParam: str, type: Optional[Literal[IssueType.ISSUE, IssueType.PULL_REQUEST]]): + async def search_issues( + self, + repoOwner: str, + repoName: str, + searchParam: str, + type: Optional[Literal[IssueType.ISSUE, IssueType.PULL_REQUEST]], + ): if type is IssueType.ISSUE: searchParam = f"{searchParam} is:issue" elif type is IssueType.PULL_REQUEST: searchParam = f"{searchParam} is:pr" query = f"repo:{repoOwner}/{repoName} {searchParam}" async with self.session.post( - baseUrl, - json={ - "query": Queries.searchIssues, - "variables": {"query": query} - } + baseUrl, json={"query": Queries.searchIssues, "variables": {"query": query}} ) as call: json = await call.json() if "errors" in json.keys(): - raise ApiError(json['errors']) + raise ApiError(json["errors"]) self._log_ratelimit( - self.search_issues, call.headers, ratelimit_data=json['data']['rateLimit'] + self.search_issues, + call.headers, + ratelimit_data=json["data"]["rateLimit"], ) - search_results = json['data']['search'] + search_results = json["data"]["search"] data = SearchData( - total=search_results['issueCount'], - results=search_results['nodes'], - query=query + total=search_results["issueCount"], + results=search_results["nodes"], + query=query, ) return data async def send_query(self, query: str): - async with self.session.post( - baseUrl, - json={ - "query": query - } - ) as call: + async with self.session.post(baseUrl, json={"query": query}) as call: json = await call.json() if call.status == 401: raise Unauthorized(json["message"])