commands.Context for the future

pull/5/head
Bobloy 7 years ago
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…
Cancel
Save