Skip to content

Commit f9b1ce4

Browse files
authored
Merge pull request #237 from papiersnipper/master
Update the plugins cog
2 parents 7e12199 + 1afaef6 commit f9b1ce4

File tree

1 file changed

+126
-54
lines changed

1 file changed

+126
-54
lines changed

cogs/plugins.py

Lines changed: 126 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,15 @@ def __init__(self, bot):
4141
self.registry = {}
4242
self.bot.loop.create_task(self.download_initial_plugins())
4343
self.bot.loop.create_task(self.populate_registry())
44-
44+
4545
async def populate_registry(self):
4646
url = 'https://raw.githubusercontent.com/kyb3r/modmail/master/plugins/registry.json'
4747
async with self.bot.session.get(url) as resp:
4848
self.registry = json.loads(await resp.text())
4949

5050
@staticmethod
5151
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)
5453

5554
@staticmethod
5655
def parse_plugin(name):
@@ -60,10 +59,12 @@ def parse_plugin(name):
6059
result[2] = '/'.join(result[2:])
6160
except IndexError:
6261
return None
62+
6363
return tuple(result)
6464

6565
async def download_initial_plugins(self):
6666
await self.bot._connected.wait()
67+
6768
for i in self.bot.config.plugins:
6869
parsed_plugin = self.parse_plugin(i)
6970

@@ -78,29 +79,29 @@ async def download_initial_plugins(self):
7879
except DownloadError as exc:
7980
msg = f'{parsed_plugin[0]}/{parsed_plugin[1]} - {exc}'
8081
logger.error(error(msg))
82+
8183
await async_all(env() for env in self.bot.extra_events.get('on_plugin_ready', []))
84+
8285
logger.debug(info('on_plugin_ready called.'))
8386

8487
async def download_plugin_repo(self, username, repo):
8588
try:
8689
cmd = f'git clone https://github.com/{username}/{repo} '
8790
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)
9393
# -q (quiet) so there's no terminal output unless there's an error
9494
except subprocess.CalledProcessError as exc:
9595
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.'):
9898
# don't raise error if the plugin folder exists
9999
raise DownloadError(error) from exc
100100

101101
async def load_plugin(self, username, repo, plugin_name):
102102
ext = f'plugins.{username}-{repo}.{plugin_name}.{plugin_name}'
103103
dirname = f'plugins/{username}-{repo}/{plugin_name}'
104+
104105
if 'requirements.txt' in os.listdir(dirname):
105106
# Install PIP requirements
106107
try:
@@ -113,6 +114,7 @@ async def load_plugin(self, username, repo, plugin_name):
113114
# so there's no terminal output unless there's an error
114115
except subprocess.CalledProcessError as exc:
115116
err = exc.stderr.decode('utf8').strip()
117+
116118
if err:
117119
raise DownloadError(
118120
f'Unable to download requirements: ```\n{error}\n```'
@@ -135,68 +137,105 @@ async def load_plugin(self, username, repo, plugin_name):
135137
@checks.has_permissions(PermissionLevel.OWNER)
136138
async def plugin(self, ctx):
137139
"""Plugin handler. Controls the plugins in the bot."""
140+
138141
await ctx.send_help(ctx.command)
139142

140143
@plugin.command(name='add', aliases=['install'])
141144
@checks.has_permissions(PermissionLevel.OWNER)
142145
async def plugin_add(self, ctx, *, plugin_name: str):
143146
"""Add a plugin."""
147+
144148
if plugin_name in self.registry:
145149
info = self.registry[plugin_name]
146150
plugin_name = info['repository'] + '/' + plugin_name
147151
required_version = info['bot_version']
152+
148153
if parse_version(self.bot.version) < parse_version(required_version):
149-
return await ctx.send(f"Bot version too low, plugin requires version `{required_version}`")
154+
em = discord.Embed(
155+
description=f'Your bot\'s version is too low. This plugin requires version `{required_version}`.',
156+
color=self.bot.main_color
157+
)
158+
return await ctx.send(embed=em)
159+
150160
if plugin_name in self.bot.config.plugins:
151-
return await ctx.send('Plugin already installed.')
161+
em = discord.Embed(
162+
description='This plugin is already installed.',
163+
color=self.bot.main_color
164+
)
165+
return await ctx.send(embed=em)
166+
152167
if plugin_name in self.bot.cogs.keys():
153168
# another class with the same name
154-
return await ctx.send('Another cog exists with the same name.')
169+
em = discord.Embed(
170+
description='There\'s another cog installed with the same name.',
171+
color=self.bot.main_color
172+
)
173+
return await ctx.send(embed=em)
174+
175+
em = discord.Embed(
176+
description='Downloading this plugin...',
177+
color=self.bot.main_color
178+
)
179+
message = await ctx.send(embed=em)
155180

156-
message = await ctx.send('Downloading plugin...')
157181
async with ctx.typing():
158182
if len(plugin_name.split('/')) >= 3:
159183
parsed_plugin = self.parse_plugin(plugin_name)
160184

161185
try:
162186
await self.download_plugin_repo(*parsed_plugin[:-1])
163187
except DownloadError as exc:
164-
return await ctx.send(
165-
f'Unable to fetch plugin from Github: {exc}.'
188+
em = discord.Embed(
189+
description=f'Unable to fetch this plugin from Github: {exc}.',
190+
color=self.bot.main_color
166191
)
192+
return await ctx.send(embed=em)
167193

168194
importlib.invalidate_caches()
195+
169196
try:
170197
await self.load_plugin(*parsed_plugin)
171198
except DownloadError as exc:
172-
return await ctx.send(f'Unable to load plugin: `{exc}`.')
199+
em = discord.Embed(
200+
description=f'Unable to load this plugin: {exc}.',
201+
color=self.bot.main_color
202+
)
203+
return await ctx.send(embed=em)
173204

174205
# if it makes it here, it has passed all checks and should
175206
# be entered into the config
176207

177208
self.bot.config.plugins.append(plugin_name)
178209
await self.bot.config.update()
179210

180-
await message.edit(content='Plugin installed. Any plugin that '
181-
'you install is of your OWN RISK.')
211+
em = discord.Embed(
212+
description='The plugin is installed.\n'
213+
'*Please note: any plugin that you install is of your OWN RISK*',
214+
color=self.bot.main_color
215+
)
216+
await message.edit(embed=em)
182217
else:
183-
await message.edit(content='Invalid plugin name format. '
184-
'Use username/repo/plugin.')
218+
em = discord.Embed(
219+
description='Invalid plugin name format: use username/repo/plugin.',
220+
color=self.bot.main_color
221+
)
222+
await message.edit(embed=em)
185223

186224
@plugin.command(name='remove', aliases=['del', 'delete', 'rm'])
187225
@checks.has_permissions(PermissionLevel.OWNER)
188226
async def plugin_remove(self, ctx, *, plugin_name: str):
189227
"""Remove a plugin."""
228+
190229
if plugin_name in self.registry:
191230
info = self.registry[plugin_name]
192231
plugin_name = info['repository'] + '/' + plugin_name
232+
193233
if plugin_name in self.bot.config.plugins:
194234
try:
195235
username, repo, name = self.parse_plugin(plugin_name)
196-
self.bot.unload_extension(
197-
f'plugins.{username}-{repo}.{name}.{name}'
198-
)
199-
except:
236+
237+
self.bot.unload_extension(f'plugins.{username}-{repo}.{name}.{name}')
238+
except Exception:
200239
pass
201240

202241
self.bot.config.plugins.remove(plugin_name)
@@ -211,67 +250,102 @@ def onerror(func, path, exc_info): # pylint: disable=W0613
211250
os.chmod(path, stat.S_IWUSR)
212251
func(path)
213252

214-
shutil.rmtree(f'plugins/{username}-{repo}',
215-
onerror=onerror)
253+
shutil.rmtree(f'plugins/{username}-{repo}', onerror=onerror)
216254
except Exception as exc:
217255
logger.error(str(exc))
218256
self.bot.config.plugins.append(plugin_name)
219257
raise exc
220258

221259
await self.bot.config.update()
222-
await ctx.send('Plugin uninstalled and '
223-
'all related data is erased.')
260+
261+
em = discord.Embed(
262+
description='The plugin is uninstalled and all its data is erased.',
263+
color=self.bot.main_color
264+
)
265+
await ctx.send(embed=em)
224266
else:
225-
await ctx.send('Plugin not installed.')
267+
em = discord.Embed(
268+
description='That plugin is not installed.',
269+
color=self.bot.main_color
270+
)
271+
await ctx.send(embed=em)
226272

227273
@plugin.command(name='update')
228274
@checks.has_permissions(PermissionLevel.OWNER)
229275
async def plugin_update(self, ctx, *, plugin_name: str):
230276
"""Update a plugin."""
277+
231278
if plugin_name in self.registry:
232279
info = self.registry[plugin_name]
233280
plugin_name = info['repository'] + '/' + plugin_name
281+
234282
if plugin_name not in self.bot.config.plugins:
235-
return await ctx.send('Plugin not installed.')
283+
em = discord.Embed(
284+
description='That plugin is not installed.',
285+
color=self.bot.main_color
286+
)
287+
return await ctx.send(embed=em)
236288

237289
async with ctx.typing():
238290
username, repo, name = self.parse_plugin(plugin_name)
291+
239292
try:
240293
cmd = f'cd plugins/{username}-{repo} && git pull'
241-
cmd = await self.bot.loop.run_in_executor(
242-
None,
243-
self._asubprocess_run,
244-
cmd
245-
)
294+
cmd = await self.bot.loop.run_in_executor(None, self._asubprocess_run, cmd)
246295
except subprocess.CalledProcessError as exc:
247296
err = exc.stderr.decode('utf8').strip()
248-
await ctx.send(f'Error while updating: {err}.')
297+
298+
em = discord.Embed(
299+
description=f'An error occured while updating: {err}.',
300+
color=self.bot.main_color
301+
)
302+
await ctx.send(embed=em)
303+
249304
else:
250305
output = cmd.stdout.decode('utf8').strip()
251-
await ctx.send(f'```\n{output}\n```')
306+
307+
em = discord.Embed(
308+
description=f'```\n{output}\n```',
309+
color=self.bot.main_color
310+
)
311+
await ctx.send(embed=em)
252312

253313
if output != 'Already up to date.':
254314
# repo was updated locally, now perform the cog reload
255315
ext = f'plugins.{username}-{repo}.{name}.{name}'
256316
self.bot.unload_extension(ext)
317+
257318
try:
258319
await self.load_plugin(username, repo, name)
259320
except DownloadError as exc:
260-
await ctx.send(f'Unable to start plugin: `{exc}`.')
321+
em = discord.Embed(
322+
description=f'Unable to start the plugin: `{exc}`.',
323+
color=self.bot.main_color
324+
)
325+
await ctx.send(embed=em)
261326

262327
@plugin.command(name='enabled', aliases=['installed'])
263328
@checks.has_permissions(PermissionLevel.OWNER)
264329
async def plugin_enabled(self, ctx):
265330
"""Shows a list of currently enabled plugins."""
331+
266332
if self.bot.config.plugins:
267333
msg = '```\n' + '\n'.join(self.bot.config.plugins) + '\n```'
268-
await ctx.send(msg)
334+
em = discord.Embed(
335+
description=msg,
336+
color=self.bot.main_color
337+
)
338+
await ctx.send(embed=em)
269339
else:
270-
await ctx.send('No plugins installed.')
340+
em = discord.Embed(
341+
description='There are no plugins installed.',
342+
color=self.bot.main_color
343+
)
344+
await ctx.send(embed=em)
271345

272346
@plugin.group(invoke_without_command=True, name='registry', aliases=['list'])
273347
@checks.has_permissions(PermissionLevel.OWNER)
274-
async def plugin_registry(self, ctx, *, plugin_name:str=None):
348+
async def plugin_registry(self, ctx, *, plugin_name: str = None):
275349
"""Shows a list of all approved plugins."""
276350

277351
await self.populate_registry()
@@ -293,13 +367,15 @@ def find_index(name):
293367
index = find_index(plugin_name)
294368
elif plugin_name is not None:
295369
em = discord.Embed(
296-
color=discord.Color.red(),
297-
description=f'Could not find a plugin with name "{plugin_name}" within the registry.'
298-
)
370+
color=discord.Color.red(),
371+
description=f'Could not find a plugin with name "{plugin_name}" within the registry.'
372+
)
299373

300374
matches = get_close_matches(plugin_name, self.registry.keys())
375+
301376
if matches:
302377
em.add_field(name='Perhaps you meant', value='\n'.join(f'`{m}`' for m in matches))
378+
303379
return await ctx.send(embed=em)
304380

305381
for name, info in registry:
@@ -312,11 +388,11 @@ def find_index(name):
312388
url=repo,
313389
title=info['repository']
314390
)
315-
391+
316392
em.add_field(
317-
name='Installation',
393+
name='Installation',
318394
value=f'```{self.bot.prefix}plugins add {name}```')
319-
395+
320396
em.set_author(name=info['title'], icon_url=info.get('icon_url'), url=url)
321397
if info.get('thumbnail_url'):
322398
em.set_thumbnail(url=info.get('thumbnail_url'))
@@ -351,12 +427,12 @@ async def plugin_registry_compact(self, ctx):
351427
pages.append(fmt+'\n')
352428
else:
353429
pages[-1] += fmt + '\n'
354-
430+
355431
embeds = []
356432

357433
for page in pages:
358434
em = discord.Embed(
359-
color=self.bot.main_color,
435+
color=self.bot.main_color,
360436
description=page,
361437
)
362438
em.set_author(name='Plugin Registry', icon_url=self.bot.user.avatar_url)
@@ -366,9 +442,5 @@ async def plugin_registry_compact(self, ctx):
366442
await paginator.run()
367443

368444

369-
370-
371-
372-
373445
def setup(bot):
374446
bot.add_cog(Plugins(bot))

0 commit comments

Comments
 (0)