def wrap(func: t.Callable) -> t.Union[t.Callable, None]: func.__locks = WeakValueDictionary() @wraps(func) async def inner(self: t.Callable, ctx: Context, *args, **kwargs) -> t.Union[t.Callable, None]: lock = func.__locks.setdefault(ctx.author.id, Lock()) if lock.locked(): embed = Embed() embed.colour = Colour.red() log.debug("User tried to invoke a locked command.") embed.description = ( "You're already using this command. Please wait until " "it is done before you use it again." ) embed.title = random.choice(ERROR_REPLIES) await ctx.send(embed=embed) return async with func.__locks.setdefault(ctx.author.id, Lock()): return await func(self, ctx, *args, **kwargs) return inner