Skip to content

Commit 0c2e79b

Browse files
authored
📝 add docs and change to async
1 parent 290d82a commit 0c2e79b

File tree

2 files changed

+150
-48
lines changed

2 files changed

+150
-48
lines changed

README.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,92 @@ _✨ GitHub 协议适配 ✨_
4141
<img src="https://discordapp.com/api/guilds/847819937858584596/widget.png?style=shield" alt="Discord Server">
4242
</a>
4343
</p>
44+
45+
## 安装
46+
47+
```bash
48+
poetry add nonebot-adapter-github
49+
# 或者
50+
pip install nonebot-adapter-github
51+
```
52+
53+
## 加载适配器
54+
55+
```python
56+
import nonebot
57+
from nonebot.adapters.github import Adapter
58+
59+
nonebot.init()
60+
61+
driver = nonebot.get_driver()
62+
driver.register_adapter(Adapter)
63+
```
64+
65+
## 配置
66+
67+
### 配置 APP
68+
69+
```dotenv
70+
GITHUB_APPS='
71+
[
72+
{
73+
"app_id": "123456", # GitHub App ID 必填
74+
"private_key": [
75+
"-----BEGIN RSA PRIVATE KEY-----"
76+
"...",
77+
"-----END RSA PRIVATE KEY-----"
78+
], # GitHub App 私钥必填
79+
"client_id": "123456", # OAuth App Client ID 必填,GitHub App 可选
80+
"client_secret": "xxxxxx", # OAuth App Client Secret 必填,GitHub App 可选
81+
"webhook_secret": "xxxxxx" # 可选
82+
}
83+
]'
84+
```
85+
86+
### 其他配置
87+
88+
```dotenv
89+
GITHUB_BASE_URL=https://api.github.com
90+
GITHUB_ACCEPR_FORMAT=full+json
91+
GITHUB_PREVIEWS=["starfox"]
92+
```
93+
94+
## 使用
95+
96+
### WebHook
97+
98+
URL: `/github/webhooks/<app_id>` (GitHub APP) / `/github/webhooks/<client_id>` (OAuth APP)
99+
100+
事件格式:
101+
102+
```python
103+
class Event(BaseModel):
104+
id: str # 事件 ID
105+
name: str # 事件名称
106+
payload: Dict[str, Any] # 事件内容
107+
108+
to_me: bool = False # 是否 @ 了机器人或机器人昵称
109+
```
110+
111+
具体事件类型及内容请参考 [GitHub Developer](https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads)
112+
113+
### 调用 API
114+
115+
可以直接通过 bot 调用 API,但是请注意 **只能使用异步接口,参数必须是 keyword args**。具体使用方法参考 [githubkit](https://github.com/yanyongyu/githubkit)
116+
117+
```python
118+
async with bot.as_installation(installation_id=1):
119+
resp = await bot.rest.issues.async_get(owner="owner", repo="repo", issue_number=1)
120+
issue = resp.parsed_data
121+
122+
resp = await bot.async_graphql(query=query)
123+
124+
async for issue in bot.github.paginate(bot.rest.issues.async_list_for_repo, owner="owner", repo="repo"):
125+
print(issue)
126+
```
127+
128+
也可以直接使用 `githubkit`,但是将绕过 NoneBot 的 `call api hook`
129+
130+
```python
131+
github = bot.github
132+
```

nonebot/adapters/github/bot.py

Lines changed: 61 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
11
import re
22
from typing_extensions import Self
3-
from contextlib import contextmanager
4-
from typing import TYPE_CHECKING, Any, Dict, List, Union, Callable, Optional, Generator
3+
from contextlib import asynccontextmanager
4+
from typing import (
5+
TYPE_CHECKING,
6+
Any,
7+
Dict,
8+
List,
9+
Union,
10+
Callable,
11+
Optional,
12+
AsyncGenerator,
13+
)
514

615
from nonebot.typing import overrides
716
from githubkit.utils import UNSET, Unset
@@ -59,11 +68,9 @@ def _check_nickname(bot: "Bot", event: Event) -> None:
5968
if message[0].type != "markdown":
6069
return
6170

62-
seg = message[0]
63-
text = str(seg).lstrip()
64-
6571
if nicknames := {nickname for nickname in bot.config.nickname if nickname}:
6672
# check if the user is calling me with my nickname
73+
text = str(message[0]).lstrip()
6774
nickname_regex = "|".join(nicknames)
6875
if m := re.match(rf"^({nickname_regex})([\s,,]*|$)", text, re.IGNORECASE):
6976
event.to_me = True
@@ -156,29 +163,31 @@ def __init__(self, adapter: "Adapter", app: OAuthApp):
156163
timeout=self.config.api_timeout,
157164
)
158165

159-
@contextmanager
160-
def as_web_user(
166+
@asynccontextmanager
167+
async def as_web_user(
161168
self, code: str, redirect_uri: Optional[str] = None
162-
) -> Generator[Self, None, None]:
169+
) -> AsyncGenerator[Self, None]:
163170
if self._ctx_github is not None:
164171
raise RuntimeError("Can not enter context twice.")
165172
self._ctx_github = self._github.with_auth(
166173
self._github.auth.as_web_user(code, redirect_uri)
167174
)
168-
try:
169-
yield self
170-
finally:
171-
self._ctx_github = None
172-
173-
@contextmanager
174-
def as_user(self, token: str) -> Generator[Self, None, None]:
175+
async with self._ctx_github:
176+
try:
177+
yield self
178+
finally:
179+
self._ctx_github = None
180+
181+
@asynccontextmanager
182+
async def as_user(self, token: str) -> AsyncGenerator[Self, None]:
175183
if self._ctx_github is not None:
176184
raise RuntimeError("Can not enter context twice.")
177185
self._ctx_github = GitHub(TokenAuthStrategy(token))
178-
try:
179-
yield self
180-
finally:
181-
self._ctx_github = None
186+
async with self._ctx_github:
187+
try:
188+
yield self
189+
finally:
190+
self._ctx_github = None
182191

183192
@overrides(Bot)
184193
async def handle_event(self, event: Event) -> None:
@@ -207,59 +216,63 @@ async def _get_self_info(self):
207216
slug if isinstance((slug := res.parsed_data.slug), str) else None
208217
)
209218

210-
@contextmanager
211-
def as_oauth_app(self) -> Generator[Self, None, None]:
219+
@asynccontextmanager
220+
async def as_oauth_app(self) -> AsyncGenerator[Self, None]:
212221
if self._ctx_github is not None:
213222
raise RuntimeError("Can not enter context twice.")
214223
self._ctx_github = self._github.with_auth(self._github.auth.as_oauth_app())
215-
try:
216-
yield self
217-
finally:
218-
self._ctx_github = None
219-
220-
@contextmanager
221-
def as_installation(
224+
async with self._ctx_github:
225+
try:
226+
yield self
227+
finally:
228+
self._ctx_github = None
229+
230+
@asynccontextmanager
231+
async def as_installation(
222232
self,
223233
installation_id: int,
224234
repositories: Union[Unset, List[str]] = UNSET,
225235
repository_ids: Union[Unset, List[int]] = UNSET,
226236
permissions: Union[Unset, "AppPermissionsType"] = UNSET,
227-
) -> Generator[Self, None, None]:
237+
) -> AsyncGenerator[Self, None]:
228238
if self._ctx_github is not None:
229239
raise RuntimeError("Can not enter context twice.")
230240
self._ctx_github = self._github.with_auth(
231241
self._github.auth.as_installation(
232242
installation_id, repositories, repository_ids, permissions
233243
)
234244
)
235-
try:
236-
yield self
237-
finally:
238-
self._ctx_github = None
239-
240-
@contextmanager
241-
def as_web_user(
245+
async with self._ctx_github:
246+
try:
247+
yield self
248+
finally:
249+
self._ctx_github = None
250+
251+
@asynccontextmanager
252+
async def as_web_user(
242253
self, code: str, redirect_uri: Optional[str] = None
243-
) -> Generator[Self, None, None]:
254+
) -> AsyncGenerator[Self, None]:
244255
if self._ctx_github is not None:
245256
raise RuntimeError("Can not enter context twice.")
246257
self._ctx_github = self._github.with_auth(
247258
self._github.auth.as_oauth_app().as_web_user(code, redirect_uri)
248259
)
249-
try:
250-
yield self
251-
finally:
252-
self._ctx_github = None
253-
254-
@contextmanager
255-
def as_user(self, token: str) -> Generator[Self, None, None]:
260+
async with self._ctx_github:
261+
try:
262+
yield self
263+
finally:
264+
self._ctx_github = None
265+
266+
@asynccontextmanager
267+
async def as_user(self, token: str) -> AsyncGenerator[Self, None]:
256268
if self._ctx_github is not None:
257269
raise RuntimeError("Can not enter context twice.")
258270
self._ctx_github = GitHub(TokenAuthStrategy(token))
259-
try:
260-
yield self
261-
finally:
262-
self._ctx_github = None
271+
async with self._ctx_github:
272+
try:
273+
yield self
274+
finally:
275+
self._ctx_github = None
263276

264277
@overrides(Bot)
265278
async def handle_event(self, event: Event) -> None:

0 commit comments

Comments
 (0)