Skip to content
This repository was archived by the owner on Aug 29, 2021. It is now read-only.

Commit 90149fb

Browse files
committed
[v0.4@.context] Remove WebHelperContext
1 parent b5699cb commit 90149fb

3 files changed

Lines changed: 63 additions & 66 deletions

File tree

disctools/context.py

Lines changed: 60 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
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+
3841
class 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

docs/Context.rst

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,3 @@ Context
55

66
.. autoclass:: disctools.context.EmbedingContext
77
:members:
8-
9-
.. autoclass:: disctools.context.WebHelperContext
10-
:members:

tests/test_context.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
from disctools import TargetContext as TestCtx
55

6-
76
class MockUser:
87
def __init__(self, top_role: int):
98
self.top_role = top_role
@@ -23,7 +22,7 @@ def __init__(self, author: MockUser, mentions: List[MockUser], guild: MockGuild)
2322
self.guild = guild
2423
self._state = None
2524

26-
class CMDTest(unittest.TestCase):
25+
class ContextTest(unittest.TestCase):
2726
def setUp(self):
2827
self.User7 = MockUser(7) # Mentioned 1, Admin above owner (A)(U7)
2928
self.User4 = MockUser(4) # Mentioned 2 (T)(U4)
@@ -32,15 +31,15 @@ def setUp(self):
3231
self.Guild6 = MockGuild(self.User6)
3332
self.Message65 = MockMessage(self.User6, [self.User5], self.Guild6) # Ban, Kick etc. by owner
3433
self.Message56 = MockMessage(self.User5, [self.User6], self.Guild6) # Moderator trying to kick, ban Owner
35-
self.Message44 = MockMessage(self.User4, [self.User7, self.User4], self.Guild6) # trainee mod targeting admin and mentioning self
34+
self.Message44 = MockMessage(self.User4, [self.User7, self.User4], self.Guild6) # trainee mod targeting admin and mentioning self
3635
self.Message76 = MockMessage(self.User7, [self.User6], self.Guild6) # Admin kicking owner
3736
self.Message67 = MockMessage(self.User6, [self.User7], self.Guild6) # Owner kicking Admin
3837
self.Context1 = TestCtx(message=self.Message65, prefix="a") # Case 1
3938
self.Context2 = TestCtx(message=self.Message56, prefix="a") # 2 ...
4039
self.Context3 = TestCtx(message=self.Message44, prefix="a")
4140
self.Context4 = TestCtx(message=self.Message76, prefix="a")
4241
self.Context5 = TestCtx(message=self.Message67, prefix="a")
43-
42+
4443
def test_above(self):
4544
self.assertTrue(self.Context1.is_author_above()[0]) # U6(O) > U5
4645
self.assertFalse(self.Context2.is_author_above()[0])

0 commit comments

Comments
 (0)