-
Notifications
You must be signed in to change notification settings - Fork 0
/
seat_typing.py
133 lines (102 loc) · 4.31 KB
/
seat_typing.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
"""Defines data types used for typing in the rest of the project."""
from __future__ import annotations
import asyncio
import typing
import discord # type: ignore
DiscordChannel = typing.Union[discord.TextChannel,
discord.DMChannel]
class SeatException(Exception):
pass
# mypy-annotation-for-classmethod-returning-instance
# https://stackoverflow.com/questions/44640479/
GenF = typing.TypeVar('GenF', bound='Findable')
class Findable: # pylint: disable=too-few-public-methods
@classmethod
def find(cls: typing.Type[GenF],
search_key: str, **kwargs: typing.Any) -> GenF:
raise NotImplementedError('Virtual method matches.')
class PrivateNumber(int):
def __add__(self, other: typing.Any) -> PrivateNumber:
return PrivateNumber(super().__add__(other))
def __sub__(self, other: typing.Any) -> PrivateNumber:
return PrivateNumber(super().__sub__(other))
def __mod__(self, other: typing.Any) -> PrivateNumber:
return PrivateNumber(super().__mod__(other))
@classmethod
def range(cls, end: int
) -> typing.Generator[PrivateNumber, None, None]:
for i in range(end):
yield cls(i)
class Seat(int):
def __str__(self) -> str:
return chr(ord('A') + self)
def __repr__(self) -> str:
return self.__str__()
def __add__(self, other: typing.Any) -> Seat:
return Seat(super().__add__(other))
def __sub__(self, other: typing.Any) -> Seat:
return Seat(super().__sub__(other))
def __mod__(self, other: typing.Any) -> Seat:
return Seat(super().__mod__(other))
@classmethod
def range(cls, end: int
) -> typing.Generator[Seat, None, None]:
for i in range(end):
yield cls(i)
class SeatChannel:
def __init__(self,
channel: DiscordChannel):
self._channel = channel
self.is_public = isinstance(channel, discord.TextChannel)
self.is_dm = isinstance(channel, discord.DMChannel)
@classmethod
async def from_user(cls, user: discord.User) -> SeatChannel:
if user.dm_channel is None:
await user.create_dm()
return SeatChannel(user.dm_channel)
def __str__(self) -> str:
return str(self._channel)
def __hash__(self) -> int:
"""Default hash function takes the id (memory address) of the instance
and we want different instances of SeatChannel with the same channel
to have the same hash."""
return self._channel.id # type: ignore # discord untyped
def __eq__(self, other: object) -> bool:
"""And if we define __hash__ we should also define __eq__"""
if not isinstance(other, SeatChannel):
return False
# pylint: disable=protected-access # we know other is SeatChannel
# discord is untyped, so mypy also doesn't know == returns a bool.
return self._channel == other._channel # type: ignore
async def send(self,
*args: typing.Any,
sep: str = ' ',
start: str = '',
end: str = '') -> None:
try:
asyncio.create_task(
self._channel.send(
start + sep.join(str(arg) for arg in args) + end)
)
except discord.errors.Forbidden:
print('blocked by {}'.format(self._channel))
raise SeatException(
"Error: The bot needs to be able to DM you to fully "
"function.\n"
"Please allow direct messages from server "
'members, under "Privacy Settings", for this server.')
async def wait_send(self,
*args: typing.Any,
sep: str = ' ',
start: str = '',
end: str = '') -> discord.Message:
try:
return await self._channel.send(
start + sep.join(str(arg) for arg in args) + end)
except discord.errors.Forbidden:
print('blocked by {}'.format(self._channel))
raise SeatException(
"Error: The bot needs to be able to DM you to fully "
"function.\n"
"Please allow direct messages from server "
'members, under "Privacy Settings", for this server.')