@@ -31,16 +31,28 @@ class InvalidPluginError(commands.BadArgument):
31
31
32
32
33
33
class Plugin :
34
- def __init__ (self , user , repo , name , branch = None ):
35
- self .user = user
36
- self .repo = repo
37
- self .name = name
38
- self .branch = branch if branch is not None else "master"
39
- self .url = f"https://github.com/{ user } /{ repo } /archive/{ self .branch } .zip"
40
- self .link = f"https://github.com/{ user } /{ repo } /tree/{ self .branch } /{ name } "
34
+ def __init__ (self , user , repo = None , name = None , branch = None ):
35
+ if repo is None :
36
+ self .user = "@local"
37
+ self .repo = "@local"
38
+ self .name = user
39
+ self .local = True
40
+ self .branch = "@local"
41
+ self .url = f"@local/{ user } "
42
+ self .link = f"@local/{ user } "
43
+ else :
44
+ self .user = user
45
+ self .repo = repo
46
+ self .name = name
47
+ self .local = False
48
+ self .branch = branch if branch is not None else "master"
49
+ self .url = f"https://github.com/{ user } /{ repo } /archive/{ self .branch } .zip"
50
+ self .link = f"https://github.com/{ user } /{ repo } /tree/{ self .branch } /{ name } "
41
51
42
52
@property
43
53
def path (self ):
54
+ if self .local :
55
+ return PurePath ("plugins" ) / "@local" / self .name
44
56
return PurePath ("plugins" ) / self .user / self .repo / f"{ self .name } -{ self .branch } "
45
57
46
58
@property
@@ -49,6 +61,8 @@ def abs_path(self):
49
61
50
62
@property
51
63
def cache_path (self ):
64
+ if self .local :
65
+ raise ValueError ("No cache path for local plugins!" )
52
66
return (
53
67
Path (__file__ ).absolute ().parent .parent
54
68
/ "temp"
@@ -58,20 +72,27 @@ def cache_path(self):
58
72
59
73
@property
60
74
def ext_string (self ):
75
+ if self .local :
76
+ return f"plugins.@local.{ self .name } .{ self .name } "
61
77
return f"plugins.{ self .user } .{ self .repo } .{ self .name } -{ self .branch } .{ self .name } "
62
78
63
79
def __str__ (self ):
80
+ if self .local :
81
+ return f"@local/{ self .name } "
64
82
return f"{ self .user } /{ self .repo } /{ self .name } @{ self .branch } "
65
83
66
84
def __lt__ (self , other ):
67
85
return self .name .lower () < other .name .lower ()
68
86
69
87
@classmethod
70
88
def from_string (cls , s , strict = False ):
71
- if not strict :
72
- m = match (r"^(.+?)/(.+?)/(.+?)(?:@(.+?))?$" , s )
73
- else :
74
- m = match (r"^(.+?)/(.+?)/(.+?)@(.+?)$" , s )
89
+ m = match (r"^@local/(.+)$" , s )
90
+ if m is None :
91
+ if not strict :
92
+ m = match (r"^(.+?)/(.+?)/(.+?)(?:@(.+?))?$" , s )
93
+ else :
94
+ m = match (r"^(.+?)/(.+?)/(.+?)@(.+?)$" , s )
95
+
75
96
if m is not None :
76
97
return Plugin (* m .groups ())
77
98
raise InvalidPluginError ("Cannot decipher %s." , s ) # pylint: disable=raising-format-tuple
@@ -155,6 +176,9 @@ async def download_plugin(self, plugin, force=False):
155
176
if plugin .abs_path .exists () and not force :
156
177
return
157
178
179
+ if plugin .local :
180
+ raise InvalidPluginError (f"Local plugin { plugin } not found!" )
181
+
158
182
plugin .abs_path .mkdir (parents = True , exist_ok = True )
159
183
160
184
if plugin .cache_path .exists () and not force :
@@ -290,7 +314,7 @@ async def parse_user_input(self, ctx, plugin_name, check_version=False):
290
314
embed = discord .Embed (
291
315
description = "Invalid plugin name, double check the plugin name "
292
316
"or use one of the following formats: "
293
- "username/repo/plugin, username/repo/plugin@branch." ,
317
+ "username/repo/plugin, username/repo/plugin@branch, @local/plugin ." ,
294
318
color = self .bot .error_color ,
295
319
)
296
320
await ctx .send (embed = embed )
@@ -314,7 +338,8 @@ async def plugins_add(self, ctx, *, plugin_name: str):
314
338
Install a new plugin for the bot.
315
339
316
340
`plugin_name` can be the name of the plugin found in `{prefix}plugin registry`,
317
- or a direct reference to a GitHub hosted plugin (in the format `user/repo/name[@branch]`).
341
+ or a direct reference to a GitHub hosted plugin (in the format `user/repo/name[@branch]`)
342
+ or `@local/name` for local plugins.
318
343
"""
319
344
320
345
plugin = await self .parse_user_input (ctx , plugin_name , check_version = True )
@@ -395,7 +420,7 @@ async def plugins_remove(self, ctx, *, plugin_name: str):
395
420
Remove an installed plugin of the bot.
396
421
397
422
`plugin_name` can be the name of the plugin found in `{prefix}plugin registry`, or a direct reference
398
- to a GitHub hosted plugin (in the format `user/repo/name[@branch]`).
423
+ to a GitHub hosted plugin (in the format `user/repo/name[@branch]`) or `@local/name` for local plugins .
399
424
"""
400
425
plugin = await self .parse_user_input (ctx , plugin_name )
401
426
if plugin is None :
@@ -416,17 +441,18 @@ async def plugins_remove(self, ctx, *, plugin_name: str):
416
441
417
442
self .bot .config ["plugins" ].remove (str (plugin ))
418
443
await self .bot .config .update ()
419
- shutil .rmtree (
420
- plugin .abs_path ,
421
- onerror = lambda * args : logger .warning (
422
- "Failed to remove plugin files %s: %s" , plugin , str (args [2 ])
423
- ),
424
- )
425
- try :
426
- plugin .abs_path .parent .rmdir ()
427
- plugin .abs_path .parent .parent .rmdir ()
428
- except OSError :
429
- pass # dir not empty
444
+ if not plugin .local :
445
+ shutil .rmtree (
446
+ plugin .abs_path ,
447
+ onerror = lambda * args : logger .warning (
448
+ "Failed to remove plugin files %s: %s" , plugin , str (args [2 ])
449
+ ),
450
+ )
451
+ try :
452
+ plugin .abs_path .parent .rmdir ()
453
+ plugin .abs_path .parent .parent .rmdir ()
454
+ except OSError :
455
+ pass # dir not empty
430
456
431
457
embed = discord .Embed (
432
458
description = "The plugin is successfully uninstalled." , color = self .bot .main_color
@@ -477,7 +503,7 @@ async def plugins_update(self, ctx, *, plugin_name: str = None):
477
503
Update a plugin for the bot.
478
504
479
505
`plugin_name` can be the name of the plugin found in `{prefix}plugin registry`, or a direct reference
480
- to a GitHub hosted plugin (in the format `user/repo/name[@branch]`).
506
+ to a GitHub hosted plugin (in the format `user/repo/name[@branch]`) or `@local/name` for local plugins .
481
507
482
508
To update all plugins, do `{prefix}plugins update`.
483
509
"""
@@ -514,7 +540,7 @@ async def plugins_reset(self, ctx):
514
540
shutil .rmtree (cache_path )
515
541
516
542
for entry in os .scandir (Path (__file__ ).absolute ().parent .parent / "plugins" ):
517
- if entry .is_dir ():
543
+ if entry .is_dir () and entry . name != "@local" :
518
544
shutil .rmtree (entry .path )
519
545
logger .warning ("Removing %s." , entry .name )
520
546
0 commit comments