Skip to content

Commit 9d635ea

Browse files
committed
✨ Excessive changes including gears and make all this more or less work
1 parent 2a48cf2 commit 9d635ea

37 files changed

+880
-307
lines changed

discord/app/cache.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ async def store_private_channel(self, channel: "PrivateChannel") -> None: ...
143143

144144
async def store_message(self, message: MessagePayload, channel: "MessageableChannel") -> Message: ...
145145

146+
async def store_built_message(self, message: Message) -> None: ...
147+
146148
async def upsert_message(self, message: Message) -> None: ...
147149

148150
async def delete_message(self, message_id: int) -> None: ...
@@ -175,6 +177,7 @@ async def get_all_sounds(self) -> list[SoundboardSound]: ...
175177

176178
async def delete_sound(self, sound_id: int) -> None: ...
177179

180+
178181
class MemoryCache(Cache):
179182
def __init__(self, max_messages: int | None = None) -> None:
180183
self.__state: ConnectionState | None = None
@@ -195,8 +198,6 @@ def __init__(self, max_messages: int | None = None) -> None:
195198

196199
self._guild_members: dict[int, dict[int, Member]] = defaultdict(dict)
197200

198-
199-
200201
def _flatten(self, matrix: list[list[T]]) -> list[T]:
201202
return [item for row in matrix for item in row]
202203

@@ -373,9 +374,12 @@ async def upsert_message(self, message: Message) -> None:
373374

374375
async def store_message(self, message: MessagePayload, channel: "MessageableChannel") -> Message:
375376
msg = await Message._from_data(state=self._state, channel=channel, data=message)
376-
self._messages.append(msg)
377+
self.store_built_message(msg)
377378
return msg
378379

380+
async def store_built_message(self, message: Message) -> None:
381+
self._messages.append(message)
382+
379383
async def delete_message(self, message_id: int) -> None:
380384
self._messages.remove(utils.find(lambda m: m.id == message_id, reversed(self._messages)))
381385

discord/app/event_emitter.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,7 @@ def __init__(self, state: "ConnectionState") -> None:
9191
self._events: dict[str, list[type[Event]]] = defaultdict(list)
9292
self._state: ConnectionState = state
9393

94-
# Auto-register all Event classes
95-
from ..events import ALL_EVENTS
94+
from ..events import ALL_EVENTS # noqa: PLC0415
9695

9796
for event_cls in ALL_EVENTS:
9897
self.add_event(event_cls)

discord/app/state.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ async def _get_guild_channel(
451451
# guild_id is in data
452452
guild = await self._get_guild(int(guild_id or data["guild_id"])) # type: ignore
453453
except KeyError:
454-
channel = DMChannel._from_message(self, channel_id)
454+
channel = DMChannel(id=channel_id, state=self)
455455
guild = None
456456
else:
457457
channel = guild and guild._resolve_channel(channel_id)

discord/bot.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@
4646
)
4747

4848
from .client import Client
49-
from .cog import CogMixin
5049
from .commands import (
5150
ApplicationCommand,
5251
ApplicationContext,
@@ -59,6 +58,7 @@
5958
)
6059
from .enums import IntegrationType, InteractionContextType, InteractionType
6160
from .errors import CheckFailure, DiscordException
61+
from .events import InteractionCreate
6262
from .interactions import Interaction
6363
from .shard import AutoShardedClient
6464
from .types import interactions
@@ -1082,7 +1082,7 @@ async def invoke_application_command(self, ctx: ApplicationContext) -> None:
10821082
ctx: :class:`.ApplicationCommand`
10831083
The invocation context to invoke.
10841084
"""
1085-
self._bot.dispatch("application_command", ctx)
1085+
# self._bot.dispatch("application_command", ctx) # TODO: Remove when moving away from ApplicationContext
10861086
try:
10871087
if await self._bot.can_run(ctx, call_once=True):
10881088
await ctx.command.invoke(ctx)
@@ -1091,14 +1091,15 @@ async def invoke_application_command(self, ctx: ApplicationContext) -> None:
10911091
except DiscordException as exc:
10921092
await ctx.command.dispatch_error(ctx, exc)
10931093
else:
1094-
self._bot.dispatch("application_command_completion", ctx)
1094+
# self._bot.dispatch("application_command_completion", ctx) # TODO: Remove when moving away from ApplicationContext
1095+
pass
10951096

10961097
@property
10971098
@abstractmethod
10981099
def _bot(self) -> Bot | AutoShardedBot: ...
10991100

11001101

1101-
class BotBase(ApplicationCommandMixin, CogMixin, ABC):
1102+
class BotBase(ApplicationCommandMixin, ABC):
11021103
_supports_prefixed_commands = False
11031104

11041105
def __init__(self, description=None, *args, **options):
@@ -1152,11 +1153,13 @@ def __init__(self, description=None, *args, **options):
11521153
self._before_invoke = None
11531154
self._after_invoke = None
11541155

1156+
self._bot.add_listener(self.on_interaction, event=InteractionCreate)
1157+
11551158
async def on_connect(self):
11561159
if self.auto_sync_commands:
11571160
await self.sync_commands()
11581161

1159-
async def on_interaction(self, interaction):
1162+
async def on_interaction(self, interaction: InteractionCreate):
11601163
await self.process_application_commands(interaction)
11611164

11621165
async def on_application_command_error(self, context: ApplicationContext, exception: DiscordException) -> None:

discord/channel/__init__.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
from ..enums import ChannelType, try_enum
2+
from ..threads import Thread
3+
from .channel import *
4+
from .dm import DMChannel, GroupDMChannel
5+
6+
7+
def _guild_channel_factory(channel_type: int):
8+
value = try_enum(ChannelType, channel_type)
9+
if value is ChannelType.text:
10+
return TextChannel, value
11+
elif value is ChannelType.voice:
12+
return VoiceChannel, value
13+
elif value is ChannelType.category:
14+
return CategoryChannel, value
15+
elif value is ChannelType.news:
16+
return TextChannel, value
17+
elif value is ChannelType.stage_voice:
18+
return StageChannel, value
19+
elif value is ChannelType.directory:
20+
return None, value # todo: Add DirectoryChannel when applicable
21+
elif value is ChannelType.forum:
22+
return ForumChannel, value
23+
elif value is ChannelType.media:
24+
return MediaChannel, value
25+
else:
26+
return None, value
27+
28+
29+
def _channel_factory(channel_type: int):
30+
cls, value = _guild_channel_factory(channel_type)
31+
if value is ChannelType.private:
32+
return DMChannel, value
33+
elif value is ChannelType.group:
34+
return GroupDMChannel, value
35+
else:
36+
return cls, value
37+
38+
39+
def _threaded_channel_factory(channel_type: int):
40+
cls, value = _channel_factory(channel_type)
41+
if value in (
42+
ChannelType.private_thread,
43+
ChannelType.public_thread,
44+
ChannelType.news_thread,
45+
):
46+
return Thread, value
47+
return cls, value
48+
49+
50+
def _threaded_guild_channel_factory(channel_type: int):
51+
cls, value = _guild_channel_factory(channel_type)
52+
if value in (
53+
ChannelType.private_thread,
54+
ChannelType.public_thread,
55+
ChannelType.news_thread,
56+
):
57+
return Thread, value
58+
return cls, value

discord/channel/base.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
"""
2+
The MIT License (MIT)
3+
4+
Copyright (c) 2021-present Pycord Development
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a
7+
copy of this software and associated documentation files (the "Software"),
8+
to deal in the Software without restriction, including without limitation
9+
the rights to use, copy, modify, merge, publish, distribute, sublicense,
10+
and/or sell copies of the Software, and to permit persons to whom the
11+
Software is furnished to do so, subject to the following conditions:
12+
13+
The above copyright notice and this permission notice shall be included in
14+
all copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17+
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22+
DEALINGS IN THE SOFTWARE.
23+
"""
24+
25+
import datetime
26+
import logging
27+
from abc import ABC, abstractmethod
28+
from typing import TYPE_CHECKING, Generic
29+
30+
from typing_extensions import Self, TypeVar, override
31+
32+
from ..abc import Snowflake
33+
from ..enums import ChannelType, try_enum
34+
from ..permissions import Permissions
35+
from ..types.channel import Channel as ChannelPayload
36+
from ..utils import snowflake_time
37+
38+
_log = logging.getLogger(__name__)
39+
40+
if TYPE_CHECKING:
41+
from ..app.state import ConnectionState
42+
43+
44+
P = TypeVar("P", bound="ChannelPayload")
45+
46+
47+
class BaseChannel(ABC, Generic[P]):
48+
__slots__: tuple[str, ...] = ("id", "_type", "_state", "_data") # pyright: ignore [reportIncompatibleUnannotatedOverride]
49+
50+
def __init__(self, id: int, state: "ConnectionState"):
51+
self.id: int = id
52+
self._state: ConnectionState = state
53+
self._data: P = {} # type: ignore
54+
55+
async def _update(self, data: P) -> None:
56+
self._type: int = data["type"]
57+
self._data = self._data | data # type: ignore
58+
59+
@classmethod
60+
async def _from_data(cls, *, data: P, state: "ConnectionState", **kwargs) -> Self:
61+
if kwargs:
62+
_log.warning("Unexpected keyword arguments passed to %s._from_data: %r", cls.__name__, kwargs)
63+
self = cls(int(data["id"]), state)
64+
await self._update(data)
65+
return self
66+
67+
@property
68+
def type(self) -> ChannelType:
69+
"""The channel's Discord channel type."""
70+
return try_enum(ChannelType, self._type)
71+
72+
async def _get_channel(self) -> Self:
73+
return self
74+
75+
@property
76+
def created_at(self) -> datetime.datetime:
77+
"""The channel's creation time in UTC."""
78+
return snowflake_time(self.id)
79+
80+
@abstractmethod
81+
@override
82+
def __repr__(self) -> str: ...
83+
84+
@property
85+
@abstractmethod
86+
def jump_url(self) -> str: ...
87+
88+
@abstractmethod
89+
def permissions_for(self, obj: Snowflake, /) -> Permissions: ...

0 commit comments

Comments
 (0)