Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 18 additions & 35 deletions discord/audit_logs.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,8 +278,8 @@ class AuditLogChanges:
"type": (None, _transform_type),
"status": (None, _enum_transformer(enums.ScheduledEventStatus)),
"entity_type": (
"location_type",
_enum_transformer(enums.ScheduledEventLocationType),
"entity_type",
_enum_transformer(enums.ScheduledEventEntityType),
),
"command_id": ("command_id", _transform_snowflake),
"image_hash": ("image", _transform_scheduled_event_image),
Expand Down Expand Up @@ -318,7 +318,11 @@ def __init__(
"$add_allow_list",
]:
self._handle_trigger_metadata(
self.before, self.after, entry, elem["new_value"], attr # type: ignore
self.before,
self.after,
entry,
elem["new_value"],
attr, # type: ignore
)
continue
elif attr in [
Expand All @@ -327,7 +331,11 @@ def __init__(
"$remove_allow_list",
]:
self._handle_trigger_metadata(
self.after, self.before, entry, elem["new_value"], attr # type: ignore
self.after,
self.before,
entry,
elem["new_value"],
attr, # type: ignore
)
continue

Expand All @@ -349,21 +357,6 @@ def __init__(
if transformer:
before = transformer(entry, before)

if attr == "location" and hasattr(self.before, "location_type"):
from .scheduled_events import ScheduledEventLocation

if (
self.before.location_type
is enums.ScheduledEventLocationType.external
):
before = ScheduledEventLocation(state=state, value=before)
elif hasattr(self.before, "channel"):
before = ScheduledEventLocation(
state=state, value=self.before.channel
)

setattr(self.before, attr, before)

try:
after = elem["new_value"]
except KeyError:
Expand All @@ -372,21 +365,6 @@ def __init__(
if transformer:
after = transformer(entry, after)

if attr == "location" and hasattr(self.after, "location_type"):
from .scheduled_events import ScheduledEventLocation

if (
self.after.location_type
is enums.ScheduledEventLocationType.external
):
after = ScheduledEventLocation(state=state, value=after)
elif hasattr(self.after, "channel"):
after = ScheduledEventLocation(
state=state, value=self.after.channel
)

setattr(self.after, attr, after)

# add an alias
if hasattr(self.after, "colour"):
self.after.color = self.after.colour
Expand Down Expand Up @@ -691,7 +669,12 @@ def _convert_target_invite(self, target_id: int) -> Invite:
"uses": changeset.uses,
}

obj = Invite(state=self._state, data=fake_payload, guild=self.guild, channel=changeset.channel) # type: ignore
obj = Invite(
state=self._state,
data=fake_payload,
guild=self.guild,
channel=changeset.channel,
) # type: ignore
try:
obj.inviter = changeset.inviter
except AttributeError:
Expand Down
72 changes: 70 additions & 2 deletions discord/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,11 @@
"EmbeddedActivity",
"ScheduledEventStatus",
"ScheduledEventPrivacyLevel",
"ScheduledEventEntityType",
"ScheduledEventLocationType",
"ScheduledEventRecurrenceFrequency",
"ScheduledEventRecurrenceWeekday",
"ScheduledEventRecurrenceMonth",
"InputTextStyle",
"SlashCommandOptionType",
"AutoModTriggerType",
Expand Down Expand Up @@ -955,13 +959,77 @@ def __int__(self):
return self.value


class ScheduledEventLocationType(Enum):
"""Scheduled event location type"""
class ScheduledEventEntityType(Enum):
"""Scheduled event entity type"""

stage_instance = 1
voice = 2
external = 3

def __int__(self):
return self.value


class ScheduledEventLocationType(ScheduledEventEntityType):
"""Scheduled event location type (deprecated alias for :class:`ScheduledEventEntityType`)"""


class ScheduledEventRecurrenceFrequency(Enum):
"""Scheduled event recurrence frequency"""

yearly = 0
monthly = 1
weekly = 2
daily = 3

def __int__(self):
return self.value


class ScheduledEventRecurrenceWeekday(Enum):
"""Scheduled event recurrence weekday"""

monday = 0
tuesday = 1
wednesday = 2
thursday = 3
friday = 4
saturday = 5
sunday = 6

def __int__(self):
return self.value


class ScheduledEventRecurrenceMonth(Enum):
"""Scheduled event recurrence month"""

january = 1
february = 2
march = 3
april = 4
may = 5
june = 6
july = 7
august = 8
september = 9
october = 10
november = 11
december = 12

def __int__(self):
return self.value


class ScheduledEventRecurrenceInterval(Enum):
"""Scheduled event recurrence interval spacing"""

single = 1
every_other = 2

def __int__(self):
return self.value


class AutoModTriggerType(Enum):
"""Automod trigger type"""
Expand Down
98 changes: 71 additions & 27 deletions discord/guild.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,21 @@
NotificationLevel,
NSFWLevel,
OnboardingMode,
ScheduledEventLocationType,
ScheduledEventEntityType,
ScheduledEventPrivacyLevel,
SortOrder,
VerificationLevel,
VideoQualityMode,
VoiceRegion,
try_enum,
)
from .errors import ClientException, HTTPException, InvalidArgument, InvalidData
from .errors import (
ClientException,
HTTPException,
InvalidArgument,
InvalidData,
ValidationError,
)
from .file import File
from .flags import SystemChannelFlags
from .incidents import IncidentsData
Expand All @@ -84,7 +90,11 @@
from .onboarding import Onboarding
from .permissions import PermissionOverwrite
from .role import Role, RoleColours
from .scheduled_events import ScheduledEvent, ScheduledEventLocation
from .scheduled_events import (
ScheduledEvent,
ScheduledEventEntityMetadata,
ScheduledEventRecurrenceRule,
)
from .soundboard import SoundboardSound
from .stage_instance import StageInstance
from .sticker import GuildSticker
Expand Down Expand Up @@ -4213,36 +4223,49 @@ async def create_scheduled_event(
*,
name: str,
description: str = MISSING,
start_time: datetime.datetime,
end_time: datetime.datetime = MISSING,
location: str | int | VoiceChannel | StageChannel | ScheduledEventLocation,
scheduled_start_time: datetime.datetime,
scheduled_end_time: datetime.datetime = MISSING,
entity_type: ScheduledEventEntityType,
entity_metadata: ScheduledEventEntityMetadata | None = MISSING,
channel_id: int = MISSING,
privacy_level: ScheduledEventPrivacyLevel = ScheduledEventPrivacyLevel.guild_only,
reason: str | None = None,
image: bytes = MISSING,
recurrence_rule: ScheduledEventRecurrenceRule | None = MISSING,
) -> ScheduledEvent | None:
"""|coro|
Creates a scheduled event.

For EXTERNAL events, ``entity_metadata`` with a location and ``end_time`` are required.
For STAGE_INSTANCE or VOICE events, ``channel_id`` is required.

Parameters
----------
name: :class:`str`
The name of the scheduled event.
description: Optional[:class:`str`]
The description of the scheduled event.
start_time: :class:`datetime.datetime`
scheduled_start_time: :class:`datetime.datetime`
A datetime object of when the scheduled event is supposed to start.
end_time: Optional[:class:`datetime.datetime`]
scheduled_end_time: Optional[:class:`datetime.datetime`]
A datetime object of when the scheduled event is supposed to end.
location: :class:`ScheduledEventLocation`
The location of where the event is happening.
Required for EXTERNAL events.
entity_type: :class:`ScheduledEventEntityType`
The type of scheduled event (STAGE_INSTANCE, VOICE, or EXTERNAL).
entity_metadata: Optional[:class:`ScheduledEventEntityMetadata`]
The entity metadata (required for EXTERNAL events with a location).
channel_id: Optional[Union[:class:`int`, :class:`VoiceChannel`, :class:`StageChannel`]]
The channel ID for STAGE_INSTANCE or VOICE events.
Can be a channel object or a snowflake ID.
privacy_level: :class:`ScheduledEventPrivacyLevel`
The privacy level of the event. Currently, the only possible value
is :attr:`ScheduledEventPrivacyLevel.guild_only`, which is default,
so there is no need to change this parameter.
is :attr:`ScheduledEventPrivacyLevel.guild_only`, which is default.
reason: Optional[:class:`str`]
The reason to show in the audit log.
image: Optional[:class:`bytes`]
The cover image of the scheduled event
recurrence_rule: Optional[Union[:class:`ScheduledEventRecurrenceRule`, :class:`dict`]]
The definition for how often this event should recur.

Returns
-------
Expand All @@ -4255,34 +4278,55 @@ async def create_scheduled_event(
You do not have the Manage Events permission.
HTTPException
The operation failed.
ValidationError
Invalid parameters for the event type.
"""
payload: dict[str, str | int] = {
"name": name,
"scheduled_start_time": start_time.isoformat(),
"scheduled_start_time": scheduled_start_time.isoformat(),
"privacy_level": int(privacy_level),
"entity_type": int(entity_type),
}

if not isinstance(location, ScheduledEventLocation):
location = ScheduledEventLocation(state=self._state, value=location)

payload["entity_type"] = location.type.value

if location.type == ScheduledEventLocationType.external:
payload["channel_id"] = None
payload["entity_metadata"] = {"location": location.value}
else:
payload["channel_id"] = location.value.id
payload["entity_metadata"] = None
if scheduled_end_time is not MISSING:
payload["scheduled_end_time"] = scheduled_end_time.isoformat()

if description is not MISSING:
payload["description"] = description

if end_time is not MISSING:
payload["scheduled_end_time"] = end_time.isoformat()

if image is not MISSING:
payload["image"] = utils._bytes_to_base64_data(image)

if recurrence_rule is not MISSING:
if recurrence_rule is None:
payload["recurrence_rule"] = None
else:
payload["recurrence_rule"] = recurrence_rule.to_payload()

if entity_type == ScheduledEventEntityType.external:
if entity_metadata is MISSING or entity_metadata is None:
raise ValidationError(
"entity_metadata with a location is required for EXTERNAL events."
)
if not entity_metadata.location:
raise ValidationError(
"entity_metadata.location cannot be empty for EXTERNAL events."
)
if scheduled_end_time is MISSING:
raise ValidationError(
"scheduled_end_time is required for EXTERNAL events."
)

payload["channel_id"] = None
payload["entity_metadata"] = entity_metadata.to_payload()
else:
if channel_id is MISSING:
raise ValidationError(
"channel_id is required for STAGE_INSTANCE and VOICE events."
)

payload["channel_id"] = channel_id

data = await self._state.http.create_scheduled_event(
guild_id=self.id, reason=reason, **payload
)
Expand Down
2 changes: 2 additions & 0 deletions discord/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -2428,6 +2428,7 @@ def create_scheduled_event(
"entity_type",
"entity_metadata",
"image",
"recurrence_rule",
)
payload = {k: v for k, v in payload.items() if k in valid_keys}

Expand Down Expand Up @@ -2467,6 +2468,7 @@ def edit_scheduled_event(
"status",
"entity_metadata",
"image",
"recurrence_rule",
)
payload = {k: v for k, v in payload.items() if k in valid_keys}

Expand Down
Loading