From 463c53aecd6a3e13ada3141d4a09acdbb0ffe76a Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Fri, 18 Oct 2019 21:02:59 +0300 Subject: [PATCH] top --- github/api/__init__.py | 1 + github/api/client.py | 35 +++++++---------------------------- github/api/queries.py | 34 ++++++++++++++++++++++++++++++++++ github/bot.py | 26 ++++++++++++-------------- 4 files changed, 54 insertions(+), 42 deletions(-) create mode 100644 github/api/queries.py diff --git a/github/api/__init__.py b/github/api/__init__.py index 6c2eeeb..99b8b49 100644 --- a/github/api/__init__.py +++ b/github/api/__init__.py @@ -1,2 +1,3 @@ from .client import GitHubClient from .webhook import GitHubWebhookReceiver +from .queries import GET_REPO_INFO, CREATE_ISSUE diff --git a/github/api/client.py b/github/api/client.py index 4df8669..129c252 100644 --- a/github/api/client.py +++ b/github/api/client.py @@ -13,13 +13,15 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -from typing import Optional, Dict, Union, Tuple, Any, Awaitable +from typing import Optional, Dict, Union, Any import random import string from aiohttp import ClientSession from yarl import URL +from mautrix.util.config import RecursiveDict + class GitHubClient: api_url: URL = URL("https://api.github.com/graphql") @@ -63,39 +65,16 @@ async def finish_login(self, code: str, state: str) -> None: data = await resp.json() self.token = data["access_token"] - @staticmethod - def _parse_key(key: str) -> Tuple[str, Optional[str]]: - if '.' not in key: - return key, None - key, next_key = key.split('.', 1) - if len(key) > 0 and key[0] == "[": - end_index = next_key.index("]") - key = key[1:] + "." + next_key[:end_index] - next_key = next_key[end_index + 2:] if len(next_key) > end_index + 1 else None - return key, next_key - @classmethod def _recursive_get(cls, data: Dict, key: str) -> Any: - key, next_key = cls._parse_key(key) + key, next_key = RecursiveDict.parse_key(key) if next_key is not None: return cls._recursive_get(data[key], next_key) return data[key] - def query(self, query: str, args: str = "", variables: Optional[Dict] = None, - path: Optional[str] = None) -> Awaitable[Any]: - return self.call("query", query, args, variables, path) - - def mutate(self, query: str, args: str = "", variables: Optional[Dict] = None, - path: Optional[str] = None) -> Awaitable[Any]: - return self.call("mutation", query, args, variables, path) - - async def call(self, query_type: str, query: str, args: str, variables: Optional[Dict] = None, - path: Optional[str] = None) -> Any: - full_query = query_type - if args: - full_query += f" ({args})" - full_query += " {%s}" % query - resp = await self.call_raw(full_query, variables) + async def call(self, query: str, variables: Optional[Dict] = None, path: Optional[str] = None + ) -> Any: + resp = await self.call_raw(query, variables) print(resp) if path: return self._recursive_get(resp["data"], path) diff --git a/github/api/queries.py b/github/api/queries.py new file mode 100644 index 0000000..19b975c --- /dev/null +++ b/github/api/queries.py @@ -0,0 +1,34 @@ +# github - A maubot plugin to act as a GitHub client and webhook receiver. +# Copyright (C) 2019 Tulir Asokan +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +GET_REPO_INFO = """ +query ($owner: String!, $name: String!) { + repository(name: $name, owner: $owner) { + id + } +} +""" + +CREATE_ISSUE = """ +mutation ($input: CreateIssueInput!) { + createIssue(input: $input) { + issue { + number + url + } + } +} +""" diff --git a/github/bot.py b/github/bot.py index 9100e46..fc32ec4 100644 --- a/github/bot.py +++ b/github/bot.py @@ -13,7 +13,7 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -from typing import Type, Dict, Tuple, Awaitable, Callable +from typing import Type, Dict, Tuple import string import json @@ -27,7 +27,7 @@ from maubot.handlers import command from .client_manager import ClientManager -from .api import GitHubWebhookReceiver, GitHubClient +from .api import GitHubWebhookReceiver, GitHubClient, GET_REPO_INFO, CREATE_ISSUE secret_charset = string.ascii_letters + string.digits @@ -131,18 +131,16 @@ async def raw_query(self, evt: MessageEvent, query: str, client: GitHubClient) - async def create_issue(self, evt: MessageEvent, repo: Tuple[str, str], data: str, client: GitHubClient) -> None: title, body = data.split("\n", 1) if "\n" in data else (data, "") - repo_id = await client.query(query="repository (name: $name, owner: $owner) { id }", - args="$owner: String!, $name: String!", - variables={"owner": repo[0], "name": repo[1]}, - path="repository.id") - issue = await client.mutate(query="createIssue(input: $input) { issue { number url } }", - args="$input: CreateIssueInput!", - variables={"input": { - "repositoryId": repo_id, - "title": title, - "body": body, - }}, - path="createIssue.issue") + repo_id = await client.call(query=GET_REPO_INFO, + variables={"owner": repo[0], "name": repo[1]}, + path="repository.id") + issue = await client.call(query=CREATE_ISSUE, + variables={"input": { + "repositoryId": repo_id, + "title": title, + "body": body, + }}, + path="createIssue.issue") await evt.reply(f"Created [issue #{issue['number']}]({issue['url']})") @classmethod