@@ -49,8 +49,7 @@ async def populate_registry(self):
49
49
50
50
@staticmethod
51
51
def _asubprocess_run (cmd ):
52
- return subprocess .run (cmd , shell = True , check = True ,
53
- capture_output = True )
52
+ return subprocess .run (cmd , shell = True , check = True , capture_output = True )
54
53
55
54
@staticmethod
56
55
def parse_plugin (name ):
@@ -60,10 +59,12 @@ def parse_plugin(name):
60
59
result [2 ] = '/' .join (result [2 :])
61
60
except IndexError :
62
61
return None
62
+
63
63
return tuple (result )
64
64
65
65
async def download_initial_plugins (self ):
66
66
await self .bot ._connected .wait ()
67
+
67
68
for i in self .bot .config .plugins :
68
69
parsed_plugin = self .parse_plugin (i )
69
70
@@ -78,29 +79,29 @@ async def download_initial_plugins(self):
78
79
except DownloadError as exc :
79
80
msg = f'{ parsed_plugin [0 ]} /{ parsed_plugin [1 ]} - { exc } '
80
81
logger .error (error (msg ))
82
+
81
83
await async_all (env () for env in self .bot .extra_events .get ('on_plugin_ready' , []))
84
+
82
85
logger .debug (info ('on_plugin_ready called.' ))
83
86
84
87
async def download_plugin_repo (self , username , repo ):
85
88
try :
86
89
cmd = f'git clone https://github.com/{ username } /{ repo } '
87
90
cmd += f'plugins/{ username } -{ repo } -q'
88
- await self .bot .loop .run_in_executor (
89
- None ,
90
- self ._asubprocess_run ,
91
- cmd
92
- )
91
+
92
+ await self .bot .loop .run_in_executor (None , self ._asubprocess_run , cmd )
93
93
# -q (quiet) so there's no terminal output unless there's an error
94
94
except subprocess .CalledProcessError as exc :
95
95
err = exc .stderr .decode ('utf-8' ).strip ()
96
- if not err . endswith ( 'already exists and is '
97
- ' not an empty directory.' ):
96
+
97
+ if not err . endswith ( 'already exists and is not an empty directory.' ):
98
98
# don't raise error if the plugin folder exists
99
99
raise DownloadError (error ) from exc
100
100
101
101
async def load_plugin (self , username , repo , plugin_name ):
102
102
ext = f'plugins.{ username } -{ repo } .{ plugin_name } .{ plugin_name } '
103
103
dirname = f'plugins/{ username } -{ repo } /{ plugin_name } '
104
+
104
105
if 'requirements.txt' in os .listdir (dirname ):
105
106
# Install PIP requirements
106
107
try :
@@ -113,6 +114,7 @@ async def load_plugin(self, username, repo, plugin_name):
113
114
# so there's no terminal output unless there's an error
114
115
except subprocess .CalledProcessError as exc :
115
116
err = exc .stderr .decode ('utf8' ).strip ()
117
+
116
118
if err :
117
119
raise DownloadError (
118
120
f'Unable to download requirements: ```\n { error } \n ```'
@@ -135,28 +137,33 @@ async def load_plugin(self, username, repo, plugin_name):
135
137
@checks .has_permissions (PermissionLevel .OWNER )
136
138
async def plugin (self , ctx ):
137
139
"""Plugin handler. Controls the plugins in the bot."""
140
+
138
141
await ctx .send_help (ctx .command )
139
142
140
143
@plugin .command (name = 'add' , aliases = ['install' ])
141
144
@checks .has_permissions (PermissionLevel .OWNER )
142
145
async def plugin_add (self , ctx , * , plugin_name : str ):
143
146
"""Add a plugin."""
147
+
144
148
if plugin_name in self .registry :
145
149
info = self .registry [plugin_name ]
146
150
plugin_name = info ['repository' ] + '/' + plugin_name
147
151
required_version = info ['bot_version' ]
152
+
148
153
if parse_version (self .bot .version ) < parse_version (required_version ):
149
154
em = discord .Embed (
150
155
description = f'Your bot\' s version is too low. This plugin requires version `{ required_version } `.' ,
151
156
color = self .bot .main_color
152
157
)
153
158
return await ctx .send (embed = em )
159
+
154
160
if plugin_name in self .bot .config .plugins :
155
161
em = discord .Embed (
156
162
description = 'This plugin is already installed.' ,
157
163
color = self .bot .main_color
158
164
)
159
165
return await ctx .send (embed = em )
166
+
160
167
if plugin_name in self .bot .cogs .keys ():
161
168
# another class with the same name
162
169
em = discord .Embed (
@@ -170,6 +177,7 @@ async def plugin_add(self, ctx, *, plugin_name: str):
170
177
color = self .bot .main_color
171
178
)
172
179
message = await ctx .send (embed = em )
180
+
173
181
async with ctx .typing ():
174
182
if len (plugin_name .split ('/' )) >= 3 :
175
183
parsed_plugin = self .parse_plugin (plugin_name )
@@ -184,6 +192,7 @@ async def plugin_add(self, ctx, *, plugin_name: str):
184
192
return await ctx .send (embed = em )
185
193
186
194
importlib .invalidate_caches ()
195
+
187
196
try :
188
197
await self .load_plugin (* parsed_plugin )
189
198
except DownloadError as exc :
@@ -216,15 +225,16 @@ async def plugin_add(self, ctx, *, plugin_name: str):
216
225
@checks .has_permissions (PermissionLevel .OWNER )
217
226
async def plugin_remove (self , ctx , * , plugin_name : str ):
218
227
"""Remove a plugin."""
228
+
219
229
if plugin_name in self .registry :
220
230
info = self .registry [plugin_name ]
221
231
plugin_name = info ['repository' ] + '/' + plugin_name
232
+
222
233
if plugin_name in self .bot .config .plugins :
223
234
try :
224
235
username , repo , name = self .parse_plugin (plugin_name )
225
- self .bot .unload_extension (
226
- f'plugins.{ username } -{ repo } .{ name } .{ name } '
227
- )
236
+
237
+ self .bot .unload_extension (f'plugins.{ username } -{ repo } .{ name } .{ name } ' )
228
238
except Exception :
229
239
pass
230
240
@@ -240,14 +250,14 @@ def onerror(func, path, exc_info): # pylint: disable=W0613
240
250
os .chmod (path , stat .S_IWUSR )
241
251
func (path )
242
252
243
- shutil .rmtree (f'plugins/{ username } -{ repo } ' ,
244
- onerror = onerror )
253
+ shutil .rmtree (f'plugins/{ username } -{ repo } ' , onerror = onerror )
245
254
except Exception as exc :
246
255
logger .error (str (exc ))
247
256
self .bot .config .plugins .append (plugin_name )
248
257
raise exc
249
258
250
259
await self .bot .config .update ()
260
+
251
261
em = discord .Embed (
252
262
description = 'The plugin is uninstalled and all it\' s data is erased.' ,
253
263
color = self .bot .main_color
@@ -264,9 +274,11 @@ def onerror(func, path, exc_info): # pylint: disable=W0613
264
274
@checks .has_permissions (PermissionLevel .OWNER )
265
275
async def plugin_update (self , ctx , * , plugin_name : str ):
266
276
"""Update a plugin."""
277
+
267
278
if plugin_name in self .registry :
268
279
info = self .registry [plugin_name ]
269
280
plugin_name = info ['repository' ] + '/' + plugin_name
281
+
270
282
if plugin_name not in self .bot .config .plugins :
271
283
em = discord .Embed (
272
284
description = 'That plugin is not installed.' ,
@@ -276,22 +288,22 @@ async def plugin_update(self, ctx, *, plugin_name: str):
276
288
277
289
async with ctx .typing ():
278
290
username , repo , name = self .parse_plugin (plugin_name )
291
+
279
292
try :
280
293
cmd = f'cd plugins/{ username } -{ repo } && git pull'
281
- cmd = await self .bot .loop .run_in_executor (
282
- None ,
283
- self ._asubprocess_run ,
284
- cmd
285
- )
294
+ cmd = await self .bot .loop .run_in_executor (None , self ._asubprocess_run , cmd )
286
295
except subprocess .CalledProcessError as exc :
287
296
err = exc .stderr .decode ('utf8' ).strip ()
297
+
288
298
em = discord .Embed (
289
299
description = f'An error occured while updating: { err } .' ,
290
300
color = self .bot .main_color
291
301
)
292
302
await ctx .send (embed = em )
303
+
293
304
else :
294
305
output = cmd .stdout .decode ('utf8' ).strip ()
306
+
295
307
em = discord .Embed (
296
308
description = '```\n {output}\n ```' ,
297
309
color = self .bot .main_color
@@ -302,6 +314,7 @@ async def plugin_update(self, ctx, *, plugin_name: str):
302
314
# repo was updated locally, now perform the cog reload
303
315
ext = f'plugins.{ username } -{ repo } .{ name } .{ name } '
304
316
self .bot .unload_extension (ext )
317
+
305
318
try :
306
319
await self .load_plugin (username , repo , name )
307
320
except DownloadError as exc :
@@ -315,6 +328,7 @@ async def plugin_update(self, ctx, *, plugin_name: str):
315
328
@checks .has_permissions (PermissionLevel .OWNER )
316
329
async def plugin_enabled (self , ctx ):
317
330
"""Shows a list of currently enabled plugins."""
331
+
318
332
if self .bot .config .plugins :
319
333
msg = '```\n ' + '\n ' .join (self .bot .config .plugins ) + '\n ```'
320
334
em = discord .Embed (
@@ -358,8 +372,10 @@ def find_index(name):
358
372
)
359
373
360
374
matches = get_close_matches (plugin_name , self .registry .keys ())
375
+
361
376
if matches :
362
377
em .add_field (name = 'Perhaps you meant' , value = '\n ' .join (f'`{ m } `' for m in matches ))
378
+
363
379
return await ctx .send (embed = em )
364
380
365
381
for name , info in registry :
0 commit comments