[Context] Implement LionContext
Need to append a Text to all bot replies to ask people to !vote - Implement LionContext - Implement Callback handler to enable Modules intercept cmdClient.Context.Utils() (attr calls)
This commit is contained in:
48
bot/LionContext.py
Normal file
48
bot/LionContext.py
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import datetime
|
||||||
|
|
||||||
|
import discord
|
||||||
|
from cmdClient import Context
|
||||||
|
from cmdClient.logger import log
|
||||||
|
|
||||||
|
reply_callbacks: list = [] # TODO Extend to all cmdClient.Context.Utils to give flexibility to modules
|
||||||
|
|
||||||
|
class LionContext(Context):
|
||||||
|
"""
|
||||||
|
Subclass to allow easy attachment of custom hooks and structure to contexts.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, client, **kwargs):
|
||||||
|
super().__init__(client, **kwargs)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def util(self, util_func):
|
||||||
|
"""
|
||||||
|
Decorator to make a utility function available as a Context instance method
|
||||||
|
"""
|
||||||
|
log('added util_function: ' + util_func.__name__)
|
||||||
|
|
||||||
|
def util_fun_wrapper(*args, **kwargs):
|
||||||
|
[args, kwargs] = self.util_pre(util_func, *args, **kwargs)
|
||||||
|
return util_func(*args, **kwargs)
|
||||||
|
|
||||||
|
util_fun_wrapper.__name__ = util_func.__name__ # Hack
|
||||||
|
|
||||||
|
super().util(util_fun_wrapper)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def util_pre(self, util_func, *args, **kwargs):
|
||||||
|
|
||||||
|
if util_func.__name__ == 'reply':
|
||||||
|
for cb in reply_callbacks:
|
||||||
|
[args, kwargs] = cb(util_func, *args, **kwargs) # Nesting handlers. Note: args and kwargs are mutable
|
||||||
|
|
||||||
|
return [args, kwargs]
|
||||||
|
|
||||||
|
|
||||||
|
def register_reply_callback(func):
|
||||||
|
reply_callbacks.append(func)
|
||||||
|
|
||||||
|
def unregister_reply_callback(func):
|
||||||
|
reply_callbacks.remove(func)
|
||||||
|
|
||||||
|
|
||||||
@@ -3,7 +3,7 @@ from cmdClient.cmdClient import cmdClient
|
|||||||
|
|
||||||
from .config import conf
|
from .config import conf
|
||||||
from .sharding import shard_number, shard_count
|
from .sharding import shard_number, shard_count
|
||||||
|
from LionContext import LionContext
|
||||||
|
|
||||||
# Initialise client
|
# Initialise client
|
||||||
owners = [int(owner) for owner in conf.bot.getlist('owners')]
|
owners = [int(owner) for owner in conf.bot.getlist('owners')]
|
||||||
@@ -14,6 +14,7 @@ client = cmdClient(
|
|||||||
owners=owners,
|
owners=owners,
|
||||||
intents=intents,
|
intents=intents,
|
||||||
shard_id=shard_number,
|
shard_id=shard_number,
|
||||||
shard_count=shard_count
|
shard_count=shard_count,
|
||||||
|
baseContext=LionContext
|
||||||
)
|
)
|
||||||
client.conf = conf
|
client.conf = conf
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
import discord
|
import discord
|
||||||
from cmdClient import Context
|
from LionContext import LionContext
|
||||||
from cmdClient.lib import UserCancelled, ResponseTimedOut
|
from cmdClient.lib import UserCancelled, ResponseTimedOut
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
from cmdClient import lib
|
||||||
from .lib import paginate_list
|
from .lib import paginate_list
|
||||||
|
|
||||||
# TODO: Interactive locks
|
# TODO: Interactive locks
|
||||||
@@ -19,7 +21,7 @@ async def discord_shield(coro):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@Context.util
|
@LionContext.util
|
||||||
async def cancellable(ctx, msg, add_reaction=True, cancel_message=None, timeout=300):
|
async def cancellable(ctx, msg, add_reaction=True, cancel_message=None, timeout=300):
|
||||||
"""
|
"""
|
||||||
Add a cancellation reaction to the given message.
|
Add a cancellation reaction to the given message.
|
||||||
@@ -62,7 +64,7 @@ async def cancellable(ctx, msg, add_reaction=True, cancel_message=None, timeout=
|
|||||||
return task
|
return task
|
||||||
|
|
||||||
|
|
||||||
@Context.util
|
@LionContext.util
|
||||||
async def listen_for(ctx, allowed_input=None, timeout=120, lower=True, check=None):
|
async def listen_for(ctx, allowed_input=None, timeout=120, lower=True, check=None):
|
||||||
"""
|
"""
|
||||||
Listen for a one of a particular set of input strings,
|
Listen for a one of a particular set of input strings,
|
||||||
@@ -114,7 +116,7 @@ async def listen_for(ctx, allowed_input=None, timeout=120, lower=True, check=Non
|
|||||||
return message
|
return message
|
||||||
|
|
||||||
|
|
||||||
@Context.util
|
@LionContext.util
|
||||||
async def selector(ctx, header, select_from, timeout=120, max_len=20):
|
async def selector(ctx, header, select_from, timeout=120, max_len=20):
|
||||||
"""
|
"""
|
||||||
Interactive routine to prompt the `ctx.author` to select an item from a list.
|
Interactive routine to prompt the `ctx.author` to select an item from a list.
|
||||||
@@ -214,7 +216,7 @@ async def selector(ctx, header, select_from, timeout=120, max_len=20):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
@Context.util
|
@LionContext.util
|
||||||
async def pager(ctx, pages, locked=True, start_at=0, add_cancel=False, **kwargs):
|
async def pager(ctx, pages, locked=True, start_at=0, add_cancel=False, **kwargs):
|
||||||
"""
|
"""
|
||||||
Shows the user each page from the provided list `pages` one at a time,
|
Shows the user each page from the provided list `pages` one at a time,
|
||||||
@@ -371,7 +373,7 @@ async def _pager(ctx, out_msg, pages, locked, start_at, add_cancel, **kwargs):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@Context.util
|
@LionContext.util
|
||||||
async def input(ctx, msg="", timeout=120):
|
async def input(ctx, msg="", timeout=120):
|
||||||
"""
|
"""
|
||||||
Listen for a response in the current channel, from ctx.author.
|
Listen for a response in the current channel, from ctx.author.
|
||||||
@@ -413,7 +415,7 @@ async def input(ctx, msg="", timeout=120):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
@Context.util
|
@LionContext.util
|
||||||
async def ask(ctx, msg, timeout=30, use_msg=None, del_on_timeout=False):
|
async def ask(ctx, msg, timeout=30, use_msg=None, del_on_timeout=False):
|
||||||
"""
|
"""
|
||||||
Ask ctx.author a yes/no question.
|
Ask ctx.author a yes/no question.
|
||||||
@@ -459,3 +461,41 @@ async def ask(ctx, msg, timeout=30, use_msg=None, del_on_timeout=False):
|
|||||||
if result in ["n", "no"]:
|
if result in ["n", "no"]:
|
||||||
return 0
|
return 0
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
# this reply() will be overide baseContext's reply with LionContext's, whcih can
|
||||||
|
# hook pre_execution of any util.
|
||||||
|
# Using this system, Module now have much power to change Context's utils
|
||||||
|
@LionContext.util
|
||||||
|
async def reply(ctx, content=None, allow_everyone=False, **kwargs):
|
||||||
|
"""
|
||||||
|
Helper function to reply in the current channel.
|
||||||
|
"""
|
||||||
|
if not allow_everyone:
|
||||||
|
if content:
|
||||||
|
content = lib.sterilise_content(content)
|
||||||
|
|
||||||
|
message = await ctx.ch.send(content=content, **kwargs)
|
||||||
|
ctx.sent_messages.append(message)
|
||||||
|
return message
|
||||||
|
|
||||||
|
|
||||||
|
# this reply() will be overide baseContext's reply
|
||||||
|
@LionContext.util
|
||||||
|
async def error_reply(ctx, error_str):
|
||||||
|
"""
|
||||||
|
Notify the user of a user level error.
|
||||||
|
Typically, this will occur in a red embed, posted in the command channel.
|
||||||
|
"""
|
||||||
|
embed = discord.Embed(
|
||||||
|
colour=discord.Colour.red(),
|
||||||
|
description=error_str,
|
||||||
|
timestamp=datetime.datetime.utcnow()
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
message = await ctx.ch.send(embed=embed)
|
||||||
|
ctx.sent_messages.append(message)
|
||||||
|
return message
|
||||||
|
except discord.Forbidden:
|
||||||
|
message = await ctx.reply(error_str)
|
||||||
|
ctx.sent_messages.append(message)
|
||||||
|
return message
|
||||||
Reference in New Issue
Block a user