commands.Context for the future
This commit is contained in:
parent
03bd13309e
commit
2cd594c36a
@ -3,13 +3,13 @@ from collections import defaultdict
|
|||||||
from random import choice
|
from random import choice
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
from redbot.core import RedContext
|
from discord.ext import commands
|
||||||
|
|
||||||
# Import all roles here
|
# Import all roles here
|
||||||
from werewolf.roles.seer import Seer
|
from werewolf.roles.seer import Seer
|
||||||
from werewolf.roles.vanillawerewolf import VanillaWerewolf
|
from werewolf.roles.vanillawerewolf import VanillaWerewolf
|
||||||
from werewolf.roles.villager import Villager
|
from werewolf.roles.villager import Villager
|
||||||
from werewolf.utils.menus import menu, prev_page, next_page, close_menu
|
from redbot.core.utils.menus import menu, prev_page, next_page, close_menu
|
||||||
|
|
||||||
# All roles in this list for iterating
|
# All roles in this list for iterating
|
||||||
|
|
||||||
@ -181,7 +181,7 @@ async def encode(roles, rand_roles):
|
|||||||
return out_code
|
return out_code
|
||||||
|
|
||||||
|
|
||||||
async def next_group(ctx: RedContext, pages: list,
|
async def next_group(ctx: commands.Context, pages: list,
|
||||||
controls: dict, message: discord.Message, page: int,
|
controls: dict, message: discord.Message, page: int,
|
||||||
timeout: float, emoji: str):
|
timeout: float, emoji: str):
|
||||||
perms = message.channel.permissions_for(ctx.guild.me)
|
perms = message.channel.permissions_for(ctx.guild.me)
|
||||||
@ -201,7 +201,7 @@ async def next_group(ctx: RedContext, pages: list,
|
|||||||
page=page, timeout=timeout)
|
page=page, timeout=timeout)
|
||||||
|
|
||||||
|
|
||||||
async def prev_group(ctx: RedContext, pages: list,
|
async def prev_group(ctx: commands.Context, pages: list,
|
||||||
controls: dict, message: discord.Message, page: int,
|
controls: dict, message: discord.Message, page: int,
|
||||||
timeout: float, emoji: str):
|
timeout: float, emoji: str):
|
||||||
perms = message.channel.permissions_for(ctx.guild.me)
|
perms = message.channel.permissions_for(ctx.guild.me)
|
||||||
@ -268,7 +268,7 @@ class GameBuilder:
|
|||||||
self.rand_roles = []
|
self.rand_roles = []
|
||||||
setup()
|
setup()
|
||||||
|
|
||||||
async def build_game(self, ctx: RedContext):
|
async def build_game(self, ctx: commands.Context):
|
||||||
new_controls = {
|
new_controls = {
|
||||||
'⏪': prev_group,
|
'⏪': prev_group,
|
||||||
"⬅": prev_page,
|
"⬅": prev_page,
|
||||||
@ -286,7 +286,7 @@ class GameBuilder:
|
|||||||
out = await encode(self.code, self.rand_roles)
|
out = await encode(self.code, self.rand_roles)
|
||||||
return out
|
return out
|
||||||
|
|
||||||
async def list_roles(self, ctx: RedContext, pages: list,
|
async def list_roles(self, ctx: commands.Context, pages: list,
|
||||||
controls: dict, message: discord.Message, page: int,
|
controls: dict, message: discord.Message, page: int,
|
||||||
timeout: float, emoji: str):
|
timeout: float, emoji: str):
|
||||||
perms = message.channel.permissions_for(ctx.guild.me)
|
perms = message.channel.permissions_for(ctx.guild.me)
|
||||||
@ -301,7 +301,7 @@ class GameBuilder:
|
|||||||
return await menu(ctx, pages, controls, message=message,
|
return await menu(ctx, pages, controls, message=message,
|
||||||
page=page, timeout=timeout)
|
page=page, timeout=timeout)
|
||||||
|
|
||||||
async def select_page(self, ctx: RedContext, pages: list,
|
async def select_page(self, ctx: commands.Context, pages: list,
|
||||||
controls: dict, message: discord.Message, page: int,
|
controls: dict, message: discord.Message, page: int,
|
||||||
timeout: float, emoji: str):
|
timeout: float, emoji: str):
|
||||||
perms = message.channel.permissions_for(ctx.guild.me)
|
perms = message.channel.permissions_for(ctx.guild.me)
|
||||||
|
@ -2,7 +2,7 @@ import asyncio
|
|||||||
import random
|
import random
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
from redbot.core import RedContext
|
from discord.ext import commands
|
||||||
|
|
||||||
from werewolf.builder import parse_code
|
from werewolf.builder import parse_code
|
||||||
from werewolf.player import Player
|
from werewolf.player import Player
|
||||||
@ -77,7 +77,7 @@ class Game:
|
|||||||
# for c_data in self.p_channels.values():
|
# for c_data in self.p_channels.values():
|
||||||
# asyncio.ensure_future(c_data["channel"].delete("Werewolf game-over"))
|
# asyncio.ensure_future(c_data["channel"].delete("Werewolf game-over"))
|
||||||
|
|
||||||
async def setup(self, ctx: RedContext):
|
async def setup(self, ctx: commands.Context):
|
||||||
"""
|
"""
|
||||||
Runs the initial setup
|
Runs the initial setup
|
||||||
|
|
||||||
@ -673,7 +673,7 @@ class Game:
|
|||||||
async def get_day_target(self, target_id, source=None):
|
async def get_day_target(self, target_id, source=None):
|
||||||
return self.players[target_id] # ToDo check source
|
return self.players[target_id] # ToDo check source
|
||||||
|
|
||||||
async def set_code(self, ctx: RedContext, game_code):
|
async def set_code(self, ctx: commands.Context, game_code):
|
||||||
if game_code is not None:
|
if game_code is not None:
|
||||||
self.game_code = game_code
|
self.game_code = game_code
|
||||||
await ctx.send("Code has been set")
|
await ctx.send("Code has been set")
|
||||||
|
@ -1,134 +0,0 @@
|
|||||||
import asyncio
|
|
||||||
|
|
||||||
import discord
|
|
||||||
from redbot.core import RedContext
|
|
||||||
|
|
||||||
|
|
||||||
async def menu(ctx: RedContext, pages: list,
|
|
||||||
controls: dict,
|
|
||||||
message: discord.Message = None, page: int = 0,
|
|
||||||
timeout: float = 30.0):
|
|
||||||
"""
|
|
||||||
An emoji-based menu
|
|
||||||
|
|
||||||
.. note:: All pages should be of the same type
|
|
||||||
|
|
||||||
.. note:: All functions for handling what a particular emoji does
|
|
||||||
should be coroutines (i.e. :code:`async def`). Additionally,
|
|
||||||
they must take all of the parameters of this function, in
|
|
||||||
addition to a string representing the emoji reacted with.
|
|
||||||
This parameter should be the last one, and none of the
|
|
||||||
parameters in the handling functions are optional
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
ctx: RedContext
|
|
||||||
The command context
|
|
||||||
pages: `list` of `str` or `discord.Embed`
|
|
||||||
The pages of the menu.
|
|
||||||
controls: dict
|
|
||||||
A mapping of emoji to the function which handles the action for the
|
|
||||||
emoji.
|
|
||||||
message: discord.Message
|
|
||||||
The message representing the menu. Usually :code:`None` when first opening
|
|
||||||
the menu
|
|
||||||
page: int
|
|
||||||
The current page number of the menu
|
|
||||||
timeout: float
|
|
||||||
The time (in seconds) to wait for a reaction
|
|
||||||
|
|
||||||
Raises
|
|
||||||
------
|
|
||||||
RuntimeError
|
|
||||||
If either of the notes above are violated
|
|
||||||
"""
|
|
||||||
if not all(isinstance(x, discord.Embed) for x in pages) and \
|
|
||||||
not all(isinstance(x, str) for x in pages):
|
|
||||||
raise RuntimeError("All pages must be of the same type")
|
|
||||||
for key, value in controls.items():
|
|
||||||
if not asyncio.iscoroutinefunction(value):
|
|
||||||
raise RuntimeError("Function must be a coroutine")
|
|
||||||
current_page = pages[page]
|
|
||||||
|
|
||||||
if not message:
|
|
||||||
if isinstance(current_page, discord.Embed):
|
|
||||||
message = await ctx.send(embed=current_page)
|
|
||||||
else:
|
|
||||||
message = await ctx.send(current_page)
|
|
||||||
for key in controls.keys():
|
|
||||||
await message.add_reaction(key)
|
|
||||||
else:
|
|
||||||
if isinstance(current_page, discord.Embed):
|
|
||||||
await message.edit(embed=current_page)
|
|
||||||
else:
|
|
||||||
await message.edit(content=current_page)
|
|
||||||
|
|
||||||
def react_check(r, u):
|
|
||||||
return u == ctx.author and str(r.emoji) in controls.keys()
|
|
||||||
|
|
||||||
try:
|
|
||||||
react, user = await ctx.bot.wait_for(
|
|
||||||
"reaction_add",
|
|
||||||
check=react_check,
|
|
||||||
timeout=timeout
|
|
||||||
)
|
|
||||||
except asyncio.TimeoutError:
|
|
||||||
try:
|
|
||||||
await message.clear_reactions()
|
|
||||||
except discord.Forbidden: # cannot remove all reactions
|
|
||||||
for key in controls.keys():
|
|
||||||
await message.remove_reaction(key, ctx.bot.user)
|
|
||||||
return None
|
|
||||||
|
|
||||||
return await controls[react.emoji](ctx, pages, controls,
|
|
||||||
message, page,
|
|
||||||
timeout, react.emoji)
|
|
||||||
|
|
||||||
|
|
||||||
async def next_page(ctx: RedContext, pages: list,
|
|
||||||
controls: dict, message: discord.Message, page: int,
|
|
||||||
timeout: float, emoji: str):
|
|
||||||
perms = message.channel.permissions_for(ctx.guild.me)
|
|
||||||
if perms.manage_messages: # Can manage messages, so remove react
|
|
||||||
try:
|
|
||||||
await message.remove_reaction(emoji, ctx.author)
|
|
||||||
except discord.NotFound:
|
|
||||||
pass
|
|
||||||
if page == len(pages) - 1:
|
|
||||||
next_page = 0 # Loop around to the first item
|
|
||||||
else:
|
|
||||||
next_page = page + 1
|
|
||||||
return await menu(ctx, pages, controls, message=message,
|
|
||||||
page=next_page, timeout=timeout)
|
|
||||||
|
|
||||||
|
|
||||||
async def prev_page(ctx: RedContext, pages: list,
|
|
||||||
controls: dict, message: discord.Message, page: int,
|
|
||||||
timeout: float, emoji: str):
|
|
||||||
perms = message.channel.permissions_for(ctx.guild.me)
|
|
||||||
if perms.manage_messages: # Can manage messages, so remove react
|
|
||||||
try:
|
|
||||||
await message.remove_reaction(emoji, ctx.author)
|
|
||||||
except discord.NotFound:
|
|
||||||
pass
|
|
||||||
if page == 0:
|
|
||||||
page = len(pages) - 1 # Loop around to the last item
|
|
||||||
else:
|
|
||||||
page = page - 1
|
|
||||||
return await menu(ctx, pages, controls, message=message,
|
|
||||||
page=page, timeout=timeout)
|
|
||||||
|
|
||||||
|
|
||||||
async def close_menu(ctx: RedContext, pages: list,
|
|
||||||
controls: dict, message: discord.Message, page: int,
|
|
||||||
timeout: float, emoji: str):
|
|
||||||
if message:
|
|
||||||
await message.delete()
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_CONTROLS = {
|
|
||||||
"➡": next_page,
|
|
||||||
"⬅": prev_page,
|
|
||||||
"❌": close_menu,
|
|
||||||
}
|
|
@ -1,12 +1,12 @@
|
|||||||
import discord
|
import discord
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from redbot.core import Config, checks
|
from redbot.core import Config, checks
|
||||||
from redbot.core import RedContext
|
|
||||||
from redbot.core.bot import Red
|
from redbot.core.bot import Red
|
||||||
|
|
||||||
from werewolf.builder import GameBuilder, role_from_name, role_from_alignment, role_from_category, role_from_id
|
from werewolf.builder import GameBuilder, role_from_name, role_from_alignment, role_from_category, role_from_id
|
||||||
from werewolf.game import Game
|
from werewolf.game import Game
|
||||||
from werewolf.utils.menus import menu, DEFAULT_CONTROLS
|
from redbot.core.utils.menus import menu, DEFAULT_CONTROLS
|
||||||
|
|
||||||
|
|
||||||
class Werewolf:
|
class Werewolf:
|
||||||
@ -36,7 +36,7 @@ class Werewolf:
|
|||||||
del game
|
del game
|
||||||
|
|
||||||
@commands.command()
|
@commands.command()
|
||||||
async def buildgame(self, ctx: RedContext):
|
async def buildgame(self, ctx: commands.Context):
|
||||||
gb = GameBuilder()
|
gb = GameBuilder()
|
||||||
code = await gb.build_game(ctx)
|
code = await gb.build_game(ctx)
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ class Werewolf:
|
|||||||
|
|
||||||
@checks.guildowner()
|
@checks.guildowner()
|
||||||
@commands.group()
|
@commands.group()
|
||||||
async def wwset(self, ctx: RedContext):
|
async def wwset(self, ctx: commands.Context):
|
||||||
"""
|
"""
|
||||||
Base command to adjust settings. Check help for command list.
|
Base command to adjust settings. Check help for command list.
|
||||||
"""
|
"""
|
||||||
@ -56,7 +56,7 @@ class Werewolf:
|
|||||||
|
|
||||||
@commands.guild_only()
|
@commands.guild_only()
|
||||||
@wwset.command(name="list")
|
@wwset.command(name="list")
|
||||||
async def wwset_list(self, ctx: RedContext):
|
async def wwset_list(self, ctx: commands.Context):
|
||||||
"""
|
"""
|
||||||
Lists current guild settings
|
Lists current guild settings
|
||||||
"""
|
"""
|
||||||
@ -74,7 +74,7 @@ class Werewolf:
|
|||||||
|
|
||||||
@commands.guild_only()
|
@commands.guild_only()
|
||||||
@wwset.command(name="role")
|
@wwset.command(name="role")
|
||||||
async def wwset_role(self, ctx: RedContext, role: discord.Role=None):
|
async def wwset_role(self, ctx: commands.Context, role: discord.Role=None):
|
||||||
"""
|
"""
|
||||||
Assign the game role
|
Assign the game role
|
||||||
This role should not be manually assigned
|
This role should not be manually assigned
|
||||||
@ -88,7 +88,7 @@ class Werewolf:
|
|||||||
|
|
||||||
@commands.guild_only()
|
@commands.guild_only()
|
||||||
@wwset.command(name="category")
|
@wwset.command(name="category")
|
||||||
async def wwset_category(self, ctx: RedContext, category_id=None):
|
async def wwset_category(self, ctx: commands.Context, category_id=None):
|
||||||
"""
|
"""
|
||||||
Assign the channel category
|
Assign the channel category
|
||||||
"""
|
"""
|
||||||
@ -105,7 +105,7 @@ class Werewolf:
|
|||||||
|
|
||||||
@commands.guild_only()
|
@commands.guild_only()
|
||||||
@wwset.command(name="channel")
|
@wwset.command(name="channel")
|
||||||
async def wwset_channel(self, ctx: RedContext, channel: discord.TextChannel=None):
|
async def wwset_channel(self, ctx: commands.Context, channel: discord.TextChannel=None):
|
||||||
"""
|
"""
|
||||||
Assign the village channel
|
Assign the village channel
|
||||||
"""
|
"""
|
||||||
@ -118,7 +118,7 @@ class Werewolf:
|
|||||||
|
|
||||||
@commands.guild_only()
|
@commands.guild_only()
|
||||||
@wwset.command(name="logchannel")
|
@wwset.command(name="logchannel")
|
||||||
async def wwset_log_channel(self, ctx: RedContext, channel: discord.TextChannel=None):
|
async def wwset_log_channel(self, ctx: commands.Context, channel: discord.TextChannel=None):
|
||||||
"""
|
"""
|
||||||
Assign the log channel
|
Assign the log channel
|
||||||
"""
|
"""
|
||||||
@ -130,7 +130,7 @@ class Werewolf:
|
|||||||
await ctx.send("Game Log Channel has been set to **{}**".format(channel.mention))
|
await ctx.send("Game Log Channel has been set to **{}**".format(channel.mention))
|
||||||
|
|
||||||
@commands.group()
|
@commands.group()
|
||||||
async def ww(self, ctx: RedContext):
|
async def ww(self, ctx: commands.Context):
|
||||||
"""
|
"""
|
||||||
Base command for this cog. Check help for the commands list.
|
Base command for this cog. Check help for the commands list.
|
||||||
"""
|
"""
|
||||||
@ -139,7 +139,7 @@ class Werewolf:
|
|||||||
|
|
||||||
@commands.guild_only()
|
@commands.guild_only()
|
||||||
@ww.command(name="new")
|
@ww.command(name="new")
|
||||||
async def ww_new(self, ctx: RedContext, game_code=None):
|
async def ww_new(self, ctx: commands.Context, game_code=None):
|
||||||
"""
|
"""
|
||||||
Create and join a new game of Werewolf
|
Create and join a new game of Werewolf
|
||||||
"""
|
"""
|
||||||
@ -151,7 +151,7 @@ class Werewolf:
|
|||||||
|
|
||||||
@commands.guild_only()
|
@commands.guild_only()
|
||||||
@ww.command(name="join")
|
@ww.command(name="join")
|
||||||
async def ww_join(self, ctx: RedContext):
|
async def ww_join(self, ctx: commands.Context):
|
||||||
"""
|
"""
|
||||||
Joins a game of Werewolf
|
Joins a game of Werewolf
|
||||||
"""
|
"""
|
||||||
@ -166,7 +166,7 @@ class Werewolf:
|
|||||||
|
|
||||||
@commands.guild_only()
|
@commands.guild_only()
|
||||||
@ww.command(name="code")
|
@ww.command(name="code")
|
||||||
async def ww_code(self, ctx: RedContext, code):
|
async def ww_code(self, ctx: commands.Context, code):
|
||||||
"""
|
"""
|
||||||
Adjust game code
|
Adjust game code
|
||||||
"""
|
"""
|
||||||
@ -181,7 +181,7 @@ class Werewolf:
|
|||||||
|
|
||||||
@commands.guild_only()
|
@commands.guild_only()
|
||||||
@ww.command(name="quit")
|
@ww.command(name="quit")
|
||||||
async def ww_quit(self, ctx: RedContext):
|
async def ww_quit(self, ctx: commands.Context):
|
||||||
"""
|
"""
|
||||||
Quit a game of Werewolf
|
Quit a game of Werewolf
|
||||||
"""
|
"""
|
||||||
@ -192,7 +192,7 @@ class Werewolf:
|
|||||||
|
|
||||||
@commands.guild_only()
|
@commands.guild_only()
|
||||||
@ww.command(name="start")
|
@ww.command(name="start")
|
||||||
async def ww_start(self, ctx: RedContext):
|
async def ww_start(self, ctx: commands.Context):
|
||||||
"""
|
"""
|
||||||
Checks number of players and attempts to start the game
|
Checks number of players and attempts to start the game
|
||||||
"""
|
"""
|
||||||
@ -205,7 +205,7 @@ class Werewolf:
|
|||||||
|
|
||||||
@commands.guild_only()
|
@commands.guild_only()
|
||||||
@ww.command(name="stop")
|
@ww.command(name="stop")
|
||||||
async def ww_stop(self, ctx: RedContext):
|
async def ww_stop(self, ctx: commands.Context):
|
||||||
"""
|
"""
|
||||||
Stops the current game
|
Stops the current game
|
||||||
"""
|
"""
|
||||||
@ -223,7 +223,7 @@ class Werewolf:
|
|||||||
|
|
||||||
@commands.guild_only()
|
@commands.guild_only()
|
||||||
@ww.command(name="vote")
|
@ww.command(name="vote")
|
||||||
async def ww_vote(self, ctx: RedContext, target_id: int):
|
async def ww_vote(self, ctx: commands.Context, target_id: int):
|
||||||
"""
|
"""
|
||||||
Vote for a player by ID
|
Vote for a player by ID
|
||||||
"""
|
"""
|
||||||
@ -263,7 +263,7 @@ class Werewolf:
|
|||||||
await ctx.send("Nothing to vote for in this channel")
|
await ctx.send("Nothing to vote for in this channel")
|
||||||
|
|
||||||
@ww.command(name="choose")
|
@ww.command(name="choose")
|
||||||
async def ww_choose(self, ctx: RedContext, data):
|
async def ww_choose(self, ctx: commands.Context, data):
|
||||||
"""
|
"""
|
||||||
Arbitrary decision making
|
Arbitrary decision making
|
||||||
Handled by game+role
|
Handled by game+role
|
||||||
@ -285,7 +285,7 @@ class Werewolf:
|
|||||||
await game.choose(ctx, data)
|
await game.choose(ctx, data)
|
||||||
|
|
||||||
@ww.group(name="search")
|
@ww.group(name="search")
|
||||||
async def ww_search(self, ctx: RedContext):
|
async def ww_search(self, ctx: commands.Context):
|
||||||
"""
|
"""
|
||||||
Find custom roles by name, alignment, category, or ID
|
Find custom roles by name, alignment, category, or ID
|
||||||
"""
|
"""
|
||||||
@ -293,7 +293,7 @@ class Werewolf:
|
|||||||
await ctx.send_help()
|
await ctx.send_help()
|
||||||
|
|
||||||
@ww_search.command(name="name")
|
@ww_search.command(name="name")
|
||||||
async def ww_search_name(self, ctx: RedContext, *, name):
|
async def ww_search_name(self, ctx: commands.Context, *, name):
|
||||||
"""Search for a role by name"""
|
"""Search for a role by name"""
|
||||||
if name is not None:
|
if name is not None:
|
||||||
from_name = role_from_name(name)
|
from_name = role_from_name(name)
|
||||||
@ -303,7 +303,7 @@ class Werewolf:
|
|||||||
await ctx.send("No roles containing that name were found")
|
await ctx.send("No roles containing that name were found")
|
||||||
|
|
||||||
@ww_search.command(name="alignment")
|
@ww_search.command(name="alignment")
|
||||||
async def ww_search_alignment(self, ctx: RedContext, alignment: int):
|
async def ww_search_alignment(self, ctx: commands.Context, alignment: int):
|
||||||
"""Search for a role by alignment"""
|
"""Search for a role by alignment"""
|
||||||
if alignment is not None:
|
if alignment is not None:
|
||||||
from_alignment = role_from_alignment(alignment)
|
from_alignment = role_from_alignment(alignment)
|
||||||
@ -313,7 +313,7 @@ class Werewolf:
|
|||||||
await ctx.send("No roles with that alignment were found")
|
await ctx.send("No roles with that alignment were found")
|
||||||
|
|
||||||
@ww_search.command(name="category")
|
@ww_search.command(name="category")
|
||||||
async def ww_search_category(self, ctx: RedContext, category: int):
|
async def ww_search_category(self, ctx: commands.Context, category: int):
|
||||||
"""Search for a role by category"""
|
"""Search for a role by category"""
|
||||||
if category is not None:
|
if category is not None:
|
||||||
pages = role_from_category(category)
|
pages = role_from_category(category)
|
||||||
@ -323,7 +323,7 @@ class Werewolf:
|
|||||||
await ctx.send("No roles in that category were found")
|
await ctx.send("No roles in that category were found")
|
||||||
|
|
||||||
@ww_search.command(name="index")
|
@ww_search.command(name="index")
|
||||||
async def ww_search_index(self, ctx: RedContext, idx: int):
|
async def ww_search_index(self, ctx: commands.Context, idx: int):
|
||||||
"""Search for a role by ID"""
|
"""Search for a role by ID"""
|
||||||
if idx is not None:
|
if idx is not None:
|
||||||
idx_embed = role_from_id(idx)
|
idx_embed = role_from_id(idx)
|
||||||
@ -332,7 +332,7 @@ class Werewolf:
|
|||||||
else:
|
else:
|
||||||
await ctx.send("Role ID not found")
|
await ctx.send("Role ID not found")
|
||||||
|
|
||||||
async def _get_game(self, ctx: RedContext, game_code=None):
|
async def _get_game(self, ctx: commands.Context, game_code=None):
|
||||||
guild: discord.Guild = ctx.guild
|
guild: discord.Guild = ctx.guild
|
||||||
|
|
||||||
if guild is None:
|
if guild is None:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user