1- from typing import TYPE_CHECKING , Union , Optional
1+ import re
2+ from typing_extensions import Self
3+ from contextlib import contextmanager
4+ from typing import TYPE_CHECKING , Any , Dict , List , Union , Optional , Generator
25
36from nonebot .typing import overrides
7+ from githubkit .utils import UNSET , Unset
48from nonebot .message import handle_event
5- from githubkit import GitHub , AppAuthStrategy , OAuthAppAuthStrategy
9+ from githubkit import GitHub , AppAuthStrategy , TokenAuthStrategy , OAuthAppAuthStrategy
610
711from nonebot .adapters import Bot as BaseBot
812
913from .event import Event
14+ from .utils import APIContext
15+ from .message import MessageSegment
1016from .config import OAuthApp , GitHubApp
1117
1218if TYPE_CHECKING :
19+ from githubkit .rest import RestNamespace
20+ from githubkit .rest .types import AppPermissionsType
21+
1322 from .adapter import Adapter
1423
1524
25+ def _check_at_me (bot : "GitHubBot" , event : Event ) -> None :
26+ try :
27+ message = event .get_message ()
28+ except Exception :
29+ return
30+
31+ # ensure message not empty
32+ if not message :
33+ message .append (MessageSegment .markdown ("" ))
34+ return
35+
36+ if message [0 ].type != "markdown" :
37+ return
38+ if not bot ._app_slug :
39+ return
40+
41+ seg = message [0 ]
42+ text = str (seg ).lstrip ()
43+ if text .startswith (f"@{ bot ._app_slug } " ):
44+ message [0 ] = MessageSegment .markdown (text [len (bot ._app_slug ) + 1 :].lstrip ())
45+ event .to_me = True
46+
47+
48+ def _check_nickname (bot : "Bot" , event : Event ) -> None :
49+ try :
50+ message = event .get_message ()
51+ except Exception :
52+ return
53+
54+ # ensure message not empty
55+ if not message :
56+ message .append (MessageSegment .markdown ("" ))
57+ return
58+
59+ if message [0 ].type != "markdown" :
60+ return
61+
62+ seg = message [0 ]
63+ text = str (seg ).lstrip ()
64+
65+ if nicknames := {nickname for nickname in bot .config .nickname if nickname }:
66+ # check if the user is calling me with my nickname
67+ nickname_regex = "|" .join (nicknames )
68+ if m := re .match (rf"^({ nickname_regex } )([\s,,]*|$)" , text , re .IGNORECASE ):
69+ event .to_me = True
70+ message [0 ] = MessageSegment .markdown (text [m .end () :])
71+
72+
1673class Bot (BaseBot ):
17- github : GitHub
74+
75+ if TYPE_CHECKING :
76+ rest : RestNamespace
77+
78+ async def async_graphql (
79+ self , query : str , variables : Optional [Dict [str , Any ]] = None
80+ ) -> Dict [str , Any ]:
81+ ...
1882
1983 @overrides (BaseBot )
2084 def __init__ (self , adapter : "Adapter" , app : Union [GitHubApp , OAuthApp ]):
2185 super ().__init__ (adapter , app .id )
2286 self .app = app
87+ self ._github : GitHub
88+ self ._ctx_github : Optional [GitHub ] = None
89+
90+ def __getattr__ (self , name : str ) -> APIContext :
91+ return APIContext (self , (name ,))
92+
93+ @property
94+ def github (self ) -> GitHub :
95+ return self ._ctx_github or self ._github
2396
2497 async def handle_event (self , event : Event ) -> None :
2598 await handle_event (self , event )
@@ -33,14 +106,45 @@ class OAuthBot(Bot):
33106 @overrides (Bot )
34107 def __init__ (self , adapter : "Adapter" , app : OAuthApp ):
35108 super ().__init__ (adapter , app )
36- self ._github = GitHub (OAuthAppAuthStrategy (app .client_id , app .client_secret ))
109+ self ._github : GitHub [OAuthAppAuthStrategy ] = GitHub (
110+ OAuthAppAuthStrategy (app .client_id , app .client_secret )
111+ )
112+
113+ @contextmanager
114+ def as_web_user (
115+ self , code : str , redirect_uri : Optional [str ] = None
116+ ) -> Generator [Self , None , None ]:
117+ if self ._ctx_github is not None :
118+ raise RuntimeError ("Can not enter context twice." )
119+ self ._ctx_github = self ._github .with_auth (
120+ self ._github .auth .as_web_user (code , redirect_uri )
121+ )
122+ try :
123+ yield self
124+ finally :
125+ self ._ctx_github = None
126+
127+ @contextmanager
128+ def as_user (self , token : str ) -> Generator [Self , None , None ]:
129+ if self ._ctx_github is not None :
130+ raise RuntimeError ("Can not enter context twice." )
131+ self ._ctx_github = GitHub (TokenAuthStrategy (token ))
132+ try :
133+ yield self
134+ finally :
135+ self ._ctx_github = None
136+
137+ @overrides (Bot )
138+ async def handle_event (self , event : Event ) -> None :
139+ _check_nickname (self , event )
140+ await super ().handle_event (event )
37141
38142
39143class GitHubBot (Bot ):
40144 @overrides (Bot )
41145 def __init__ (self , adapter : "Adapter" , app : GitHubApp ):
42146 super ().__init__ (adapter , app )
43- self ._github = GitHub (
147+ self ._github : GitHub [ AppAuthStrategy ] = GitHub (
44148 AppAuthStrategy (
45149 app .app_id , app .private_key , app .client_id , app .client_secret
46150 )
@@ -52,3 +156,63 @@ async def _get_self_info(self):
52156 self ._app_slug = (
53157 slug if isinstance ((slug := res .parsed_data .slug ), str ) else None
54158 )
159+
160+ @contextmanager
161+ def as_oauth_app (self ) -> Generator [Self , None , None ]:
162+ if self ._ctx_github is not None :
163+ raise RuntimeError ("Can not enter context twice." )
164+ self ._ctx_github = self ._github .with_auth (self ._github .auth .as_oauth_app ())
165+ try :
166+ yield self
167+ finally :
168+ self ._ctx_github = None
169+
170+ @contextmanager
171+ def as_installation (
172+ self ,
173+ installation_id : int ,
174+ repositories : Union [Unset , List [str ]] = UNSET ,
175+ repository_ids : Union [Unset , List [int ]] = UNSET ,
176+ permissions : Union [Unset , "AppPermissionsType" ] = UNSET ,
177+ ) -> Generator [Self , None , None ]:
178+ if self ._ctx_github is not None :
179+ raise RuntimeError ("Can not enter context twice." )
180+ self ._ctx_github = self ._github .with_auth (
181+ self ._github .auth .as_installation (
182+ installation_id , repositories , repository_ids , permissions
183+ )
184+ )
185+ try :
186+ yield self
187+ finally :
188+ self ._ctx_github = None
189+
190+ @contextmanager
191+ def as_web_user (
192+ self , code : str , redirect_uri : Optional [str ] = None
193+ ) -> Generator [Self , None , None ]:
194+ if self ._ctx_github is not None :
195+ raise RuntimeError ("Can not enter context twice." )
196+ self ._ctx_github = self ._github .with_auth (
197+ self ._github .auth .as_oauth_app ().as_web_user (code , redirect_uri )
198+ )
199+ try :
200+ yield self
201+ finally :
202+ self ._ctx_github = None
203+
204+ @contextmanager
205+ def as_user (self , token : str ) -> Generator [Self , None , None ]:
206+ if self ._ctx_github is not None :
207+ raise RuntimeError ("Can not enter context twice." )
208+ self ._ctx_github = GitHub (TokenAuthStrategy (token ))
209+ try :
210+ yield self
211+ finally :
212+ self ._ctx_github = None
213+
214+ @overrides (Bot )
215+ async def handle_event (self , event : Event ) -> None :
216+ _check_at_me (self , event )
217+ _check_nickname (self , event )
218+ await super ().handle_event (event )
0 commit comments