1111# copies of the Software, and to permit persons to whom the Software is
1212# furnished to do so, subject to the following conditions:
1313
14- # The above copyright notice and this permission notice shall be included in all
14+ # The above copyright notice and this permission notice shall be included in all
1515# copies or substantial portions of the Software.
1616
1717# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
@@ -35,52 +35,62 @@ def _maybe_sequence(doubtful) -> Sequence:
3535 else :
3636 return doubtful
3737
38+ Targets = Union [discord .User , Sequence [discord .User ]]
39+ MemberTargets = Union [discord .Member , Sequence [discord .Member ]]
40+
3841class TargetContext (_Context ):
3942 """A Context class with utilities to determine Member hierarchy.
4043
4144 Helps in checks for moderation Commands.
45+
46+ Note
47+ ====
48+ The functions of this class can only be used when the message of the context belongs to a guild
4249 """
50+ _target : Sequence [discord .User ]
4351
4452 def __init__ (self , ** kwargs ):
45- """Salt and peppa."""
4653 super ().__init__ (** kwargs )
4754 self ._target = None
4855 self .targets = self .message .mentions
4956
5057 @property
5158 def targets (self ):
52- """Sequence[:class:`discord.Member `] : A sequence of Members that were mentioned, this shall be set on invoke.
53- By default it is set to a list of mentions in the message"""
59+ """Sequence[:class:`discord.User `] : A sequence of Users that were mentioned, this should be set on invoke.
60+ By default it is set to a list of mentioned users in the message"""
5461 return self ._target
5562
5663 @targets .setter
57- def targets (self , user : Union [ discord . Member , Sequence [ discord . Member ]] ) -> None :
64+ def targets (self , user : Targets ) -> None :
5865 self ._target = _maybe_sequence (user )
5966
6067 @property
6168 def is_author_target (self ) -> bool :
62- """bool : This property is equivalent to ``ctx.is_user_target()`` or ``ctx.is_user_target(ctx.author)``"""
69+ """:class:` bool` : This property is equivalent to ``ctx.is_user_target(ctx.author)``"""
6370 return self .author in self .targets
6471
65- def is_user_target (self , user : discord .Member ) -> bool :
72+ def is_user_target (self , user : discord .User ) -> bool :
6673 """Check if a user is a target
6774
6875 Parameters
6976 ----------
70- user : :class:`discord.Member `
77+ user : :class:`discord.User `
7178 The user to verify as target
7279
7380 Returns
7481 -------
75- bool
82+ :class:` bool`
7683 True if the user is the target, else False
7784 """
78- if user == self .author :
79- return self .is_author_target
8085 return user in self .targets
8186
8287
83- def _above_check (self , user : discord .Member , users : Optional [Union [discord .Member , Sequence [discord .Member ]]] = None ) -> Tuple [bool , Union [discord .Member , None ]]:
88+ def _above_check (self , user : discord .Member ,
89+ users : Optional [MemberTargets ] = None
90+ ) -> Tuple [bool , Optional [discord .Member ]]:
91+ if self .guild is None :
92+ raise ValueError (f"Expected discord.Guild instance at { self .__class__ .__qualname__ } .guild instead got None" )
93+
8494 if user == self .guild .owner :
8595 return True , None
8696 if users is None :
@@ -89,56 +99,78 @@ def _above_check(self, user: discord.Member, users: Optional[Union[discord.Membe
8999 users = _maybe_sequence (users )
90100
91101 for member in users :
92- if member == self .guild .owner :
93- return False , member
94- if member .top_role > user .top_role :
95- return False , member
96- else :
97- pass
102+ try :
103+ if member == self .guild .owner :
104+ return False , member
105+ if member .top_role > user .top_role :
106+ return False , member
107+ else :
108+ pass
109+ except AttributeError as exc :
110+ raise TypeError (f"Expected all users to be of type discord.Member instead encountered { type (member )} " ) from exc
98111 else :
99112 return True , None
100113
101- def is_author_above (self , users : Optional [Union [discord .Member , Sequence [discord .Member ]]] = None ) -> Tuple [bool , Union [discord .Member , None ]]:
114+ def is_author_above (self ,
115+ users : Optional [MemberTargets ] = None
116+ ) -> Tuple [bool , Optional [discord .Member ]]:
102117 """Check if author is above all given users
103118
104119 Parameters
105120 ----------
106121 users : Optional[Union[:class:`discord.Member`, Sequence[:class:`discord.Member`]]]
107- The user(s) to check against, if none, then command's targets are used, by default None.
122+ The member(s) to check against, if None, then command's targets are used, by default None.
123+
124+ Raises
125+ ------
126+ :exc:`TypeError`
127+ users argument is not of specified type.
128+ :exc:`ValueError`
129+ guild attribute is None.
108130
109131 Returns
110132 -------
111- Tuple[bool, Union [:class:`discord.Member`, None ]]
133+ Tuple[:class:` bool`, Optional [:class:`discord.Member`]]
112134 A tuple of length two. If author is above targets then first element will
113135 be True and second element will be None. If author is not above target then
114136 first element will be False and second element will be the first user who is above the author.
115137 Example output: ``(True, None)``, ``(False, <discord.Member Object>)``.
116138 """
117139 return self ._above_check (self .author , users )
118140
119- def is_bot_above (self , users : Optional [Union [discord .Member , Sequence [discord .Member ]]] = None ) -> Tuple [bool , Union [discord .Member , None ]]:
141+ def is_bot_above (self ,
142+ users : Optional [MemberTargets ] = None
143+ ) -> Tuple [bool , Optional [discord .Member ]]:
120144 """Check if bot is above all given users, similar to :meth:`TargetContext.is_author_above`
121145
122146 Parameters
123147 ----------
124148 users : Optional[Union[:class:`discord.Member`, Sequence[:class:`discord.Member`]]]
125- The user(s) to check against, if none, then command's targets are used, by default None.
149+ The member(s) to check against, if None, then command's targets are used, by default None.
150+
151+ Raises
152+ ------
153+ :exc:`TypeError`
154+ users argument is not of specified type.
155+ :exc:`ValueError`
156+ guild attribute is None.
126157
127158 Returns
128159 -------
129- Tuple[bool, Union [:class:`discord.Member`, None ]]
160+ Tuple[:class:` bool`, Optional [:class:`discord.Member`]]
130161 Same as :meth:`TargetContext.is_author_above`. Only that the comparisn is with Bot.
131162 """
132- return self ._above_check (self .author , users )
163+ return self ._above_check (self .me , users )
133164
134- async def whisper (self , user : Optional [Union [discord .Member , Sequence [discord .Member ]]] = None , * args , ** kwargs ) -> None :
165+ async def whisper (self , user : Optional [Targets ] = None ,
166+ * args , ** kwargs ) -> None :
135167 """|coro|
136168 DM all targets of a command.
137169
138170 Parameters
139171 ----------
140- user : Optional(Union[:class:`discord.Member `, List[discord.Member ]])
141- The member (s) to DM. Defaults to self.targets.
172+ user : Optional(Union[:class:`discord.User `, List[:class:` discord.User` ]])
173+ The user (s) to DM. Defaults to self.targets.
142174 args
143175 The positional arguments that should be used to message the targets.
144176 kwargs
@@ -174,34 +206,3 @@ async def send_embed(self, *args, **kwargs) -> discord.Message:
174206 """
175207 return await self .send (embed = discord .Embed (* args , ** kwargs ))
176208
177- # async def send(self, content=None, **kwargs) -> discord.Message:
178- # """Convert all messages outbound from the bot to Blue Embed."""
179- # if content is not None and kwargs.pop("embed", None) is None:
180- # embed = embed = discord.Embed(description=content, colour=discord.Colour.blue())
181- # return await super().send(embed=embed, **kwargs)
182- # else:
183- # return await super().send(content=content, **kwargs)
184-
185-
186- class WebHelperContext (_Context ):
187- """Contains utilities for web requests method.
188-
189- Helps in shortening code for web requests based commands,
190- Currently only has one method."""
191- async def web_request (self , url : str ) -> aiohttp .ClientResponse :
192- """|coro|
193- Make a http rquest with aiohttp
194-
195- Parameters
196- ----------
197- url : str
198- The url to send the http request
199-
200- Returns
201- -------
202- :class:`aiohttp.ClientResponse`
203- The requests response
204- """
205- async with aiohttp .ClientSession () as session :
206- async with session .get (url ) as r :
207- return r
0 commit comments