55
66from aiohttp import ClientResponseError , ClientResponse
77from discord import Member , DMChannel
8+ from discord .ext import commands
89
910from core .models import Bot , UserClient
1011
1112
1213class ApiClient :
14+ """
15+ This class represents the general request class for all type of clients.
16+
17+ Parameters
18+ ----------
19+ bot : Bot
20+ The Modmail bot.
21+
22+ Attributes
23+ ----------
24+ bot : Bot
25+ The Modmail bot.
26+ session : ClientSession
27+ The bot's current running `ClientSession`.
28+ headers : Dict[str, str]
29+ The HTTP headers that will be sent along with the requiest.
30+ """
31+
1332 def __init__ (self , bot : Bot ):
1433 self .bot = bot
1534 self .session = bot .session
@@ -21,6 +40,31 @@ async def request(self, url: str,
2140 return_response : bool = False ,
2241 headers : dict = None ) -> Union [ClientResponse ,
2342 dict , str ]:
43+ """
44+ Makes a HTTP request.
45+
46+ Parameters
47+ ----------
48+ url : str
49+ The destination URL of the request.
50+ method : str
51+ The HTTP method (POST, GET, PUT, DELETE, FETCH, etc.).
52+ payload : Dict[str, Any]
53+ The json payload to be sent along the request.
54+ return_response : bool
55+ Whether the `ClientResponse` object should be returned.
56+ headers : Dict[str, str]
57+ Additional headers to `headers`.
58+
59+ Returns
60+ -------
61+ ClientResponse or Dict[str, Any] or List[Any] or str
62+ `ClientResponse` if `return_response` is `True`.
63+ `dict` if the returned data is a json object.
64+ `list` if the returned data is a json list.
65+ `str` if the returned data is not a valid json data,
66+ the raw response.
67+ """
2468 if headers is not None :
2569 headers .update (self .headers )
2670 else :
@@ -35,16 +79,74 @@ async def request(self, url: str,
3579 return await resp .text ()
3680
3781 def filter_valid (self , data ):
82+ """
83+ Filters configuration keys that are accepted.
84+
85+ Parameters
86+ ----------
87+ data : Dict[str, Any]
88+ The data that needs to be cleaned.
89+
90+ Returns
91+ -------
92+ Dict[str, Any]
93+ Filtered `data` to keep only the accepted pairs.
94+ """
3895 valid_keys = self .bot .config .valid_keys .difference (
3996 self .bot .config .protected_keys
4097 )
4198 return {k : v for k , v in data .items () if k in valid_keys }
4299
43100
44- class Github (ApiClient ):
101+ class GitHub (ApiClient ):
102+ """
103+ The client for interacting with GitHub API.
104+
105+ Parameters
106+ ----------
107+ bot : Bot
108+ The Modmail bot.
109+ access_token : str, optional
110+ GitHub's access token.
111+ username : str, optional
112+ GitHub username.
113+ avatar_url : str, optional
114+ URL to the avatar in GitHub.
115+ url : str, optional
116+ URL to the GitHub profile.
117+
118+ Attributes
119+ ----------
120+ bot : Bot
121+ The Modmail bot.
122+ access_token : str
123+ GitHub's access token.
124+ username : str
125+ GitHub username.
126+ avatar_url : str
127+ URL to the avatar in GitHub.
128+ url : str
129+ URL to the GitHub profile.
130+
131+ Class Attributes
132+ ----------------
133+ BASE : str
134+ GitHub API base URL.
135+ REPO : str
136+ Modmail repo URL for GitHub API.
137+ HEAD : str
138+ Modmail HEAD URL for GitHub API.
139+ MERGE_URL : str
140+ URL for merging upstream to master.
141+ FORK_URL : str
142+ URL to fork Modmail.
143+ STAR_URL : str
144+ URL to star Modmail.
145+ """
146+
45147 BASE = 'https://api.github.com'
46148 REPO = BASE + '/repos/kyb3r/modmail'
47- head = REPO + '/git/refs/heads/master'
149+ HEAD = REPO + '/git/refs/heads/master'
48150 MERGE_URL = BASE + '/repos/{username}/modmail/merges'
49151 FORK_URL = REPO + '/forks'
50152 STAR_URL = BASE + '/user/starred/kyb3r/modmail'
@@ -56,15 +158,30 @@ def __init__(self, bot: Bot,
56158 super ().__init__ (bot )
57159 self .access_token = access_token
58160 self .username = username
59- self .id : str = kwargs .pop ('id' , '' )
60161 self .avatar_url : str = kwargs .pop ('avatar_url' , '' )
61162 self .url : str = kwargs .pop ('url' , '' )
62163 if self .access_token :
63164 self .headers = {'Authorization' : 'token ' + str (access_token )}
64165
65166 async def update_repository (self , sha : str = None ) -> Optional [dict ]:
167+ """
168+ Update the repository from Modmail main repo.
169+
170+ Parameters
171+ ----------
172+ sha : Optional[str], optional
173+ The commit SHA to update the repository.
174+
175+ Returns
176+ -------
177+ Optional[dict]
178+ If the response is a dict.
179+ """
180+ if not self .username :
181+ raise commands .CommandInvokeError ("Username not found." )
182+
66183 if sha is None :
67- resp : dict = await self .request (self .head )
184+ resp : dict = await self .request (self .HEAD )
68185 sha = resp ['object' ]['sha' ]
69186
70187 payload = {
@@ -80,25 +197,52 @@ async def update_repository(self, sha: str = None) -> Optional[dict]:
80197 return resp
81198
82199 async def fork_repository (self ) -> None :
200+ """
201+ Forks Modmail's repository.
202+ """
83203 await self .request (self .FORK_URL , method = 'POST' )
84204
85205 async def has_starred (self ) -> bool :
206+ """
207+ Checks if shared Modmail.
208+
209+ Returns
210+ -------
211+ bool
212+ `True`, if Modmail was starred.
213+ Otherwise `False`.
214+ """
86215 resp = await self .request (self .STAR_URL , return_response = True )
87216 return resp .status == 204
88217
89218 async def star_repository (self ) -> None :
219+ """
220+ Stars Modmail's repository.
221+ """
90222 await self .request (self .STAR_URL , method = 'PUT' ,
91223 headers = {'Content-Length' : '0' })
92224
93225 @classmethod
94- async def login (cls , bot ) -> 'Github' :
226+ async def login (cls , bot : Bot ) -> 'GitHub' :
227+ """
228+ Logs in to GitHub with configuration variable information.
229+
230+ Parameters
231+ ----------
232+ bot : Bot
233+ The Modmail bot.
234+
235+ Returns
236+ -------
237+ GitHub
238+ The newly created `GitHub` object.
239+ """
95240 self = cls (bot , bot .config .get ('github_access_token' ), )
96241 resp : dict = await self .request ('https://api.github.com/user' )
97242 self .username : str = resp ['login' ]
98243 self .avatar_url : str = resp ['avatar_url' ]
99244 self .url : str = resp ['html_url' ]
100- self .id : str = str (resp ['id' ])
101- print (f'Logged in to: { self .username } - { self .id } ' )
245+ print (f'Logged in to: { self .username } ' )
102246 return self
103247
104248
@@ -361,7 +505,7 @@ async def post_log(self, channel_id, data):
361505 )
362506
363507 async def update_repository (self ):
364- user = await Github .login (self .bot )
508+ user = await GitHub .login (self .bot )
365509 data = await user .update_repository ()
366510 return {
367511 'data' : data ,
@@ -373,7 +517,7 @@ async def update_repository(self):
373517 }
374518
375519 async def get_user_info (self ):
376- user = await Github .login (self .bot )
520+ user = await GitHub .login (self .bot )
377521 return {
378522 'user' : {
379523 'username' : user .username ,
0 commit comments