Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BC unavailable Event::GUILD_CREATE, component message non empty, mutable guild feature, deletable message, automod audit log #928

Merged
merged 13 commits into from
Sep 18, 2022
Merged
13 changes: 11 additions & 2 deletions docs/src/pages/api/03_events/04_guilds.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,17 @@ Called with a `Guild` object in one of the following situations:
3. When the Bot joins a new guild.

```php
$discord->on(Event::GUILD_CREATE, function (Guild $guild, Discord $discord) {
// ...
$discord->on(Event::GUILD_CREATE, function ($guild, Discord $discord) {
if (! ($guild instanceof Guild)) {
// the guild is unavailable due to an outage, $guild is a stdClass
// {
// "id": "",
// "unavailable": true,
// }
return;
}

// the Bot has joined the guild
});
```

Expand Down
1 change: 1 addition & 0 deletions src/Discord/Builders/MessageBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,7 @@ public function jsonSerialize(): array

if (isset($this->components)) {
$body['components'] = $this->components;
$empty = false;
}

if ($this->sticker_ids) {
Expand Down
20 changes: 10 additions & 10 deletions src/Discord/Discord.php
Original file line number Diff line number Diff line change
Expand Up @@ -473,11 +473,9 @@ protected function handleReady(object $data)
/** @var ExtendedPromiseInterface */
$promise = coroutine([$event, 'handle'], $guild);

$promise->done(null, function ($d) use (&$unavailable) {
list($status, $data) = $d;

if ($status == 'unavailable') {
$unavailable[$data] = $data;
$promise->done(function ($d) use (&$unavailable) {
if (! empty($d->unavailable)) {
$unavailable[$d->id] = $d->unavailable;
}
});
}
Expand All @@ -496,8 +494,10 @@ protected function handleReady(object $data)
$guildLoad = new Deferred();

$onGuildCreate = function ($guild) use (&$unavailable, $guildLoad) {
$this->logger->debug('guild available', ['guild' => $guild->id, 'unavailable' => count($unavailable)]);
unset($unavailable[$guild->id]);
if (empty($guild->unavailable)) {
$this->logger->debug('guild available', ['guild' => $guild->id, 'unavailable' => count($unavailable)]);
unset($unavailable[$guild->id]);
}
if (count($unavailable) < 1) {
$guildLoad->resolve();
}
Expand All @@ -508,9 +508,9 @@ protected function handleReady(object $data)
if ($guild->unavailable) {
$this->logger->debug('guild unavailable', ['guild' => $guild->id, 'unavailable' => count($unavailable)]);
unset($unavailable[$guild->id]);
if (count($unavailable) < 1) {
$guildLoad->resolve();
}
}
if (count($unavailable) < 1) {
$guildLoad->resolve();
}
};
$this->on(Event::GUILD_DELETE, $onGuildDelete);
Expand Down
2 changes: 2 additions & 0 deletions src/Discord/Parts/Channel/Channel.php
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,8 @@ protected function getGuildAttribute(): ?Guild
* Gets the last pinned message timestamp.
*
* @return Carbon|null
*
* @throws \Exception
*/
protected function getLastPinTimestampAttribute(): ?Carbon
{
Expand Down
8 changes: 4 additions & 4 deletions src/Discord/Parts/Channel/Invite.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,6 @@ protected function getChannelIdAttribute(): ?string
/**
* Returns the inviter attribute.
*
* @throws \Exception
*
* @return User|null The User that invited you.
*/
protected function getInviterAttribute(): ?User
Expand Down Expand Up @@ -230,9 +228,9 @@ protected function getTargetApplicationAttribute(): ?Application
/**
* Returns the expires at attribute.
*
* @throws \Exception
*
* @return Carbon|null The time that the invite was created.
*
* @throws \Exception
*/
protected function getExpiresAtAttribute(): ?Carbon
{
Expand Down Expand Up @@ -267,6 +265,8 @@ protected function getGuildScheduledEventAttribute(): ?ScheduledEvent
* Returns the created at attribute.
*
* @return Carbon|null The time that the invite was created.
*
* @throws \Exception
*/
protected function getCreatedAtAttribute(): ?Carbon
{
Expand Down
28 changes: 27 additions & 1 deletion src/Discord/Parts/Channel/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,8 @@ protected function getReferencedMessageAttribute(): ?Message
* Returns the timestamp attribute.
*
* @return Carbon|null The time that the message was sent.
*
* @throws \Exception
*/
protected function getTimestampAttribute(): ?Carbon
{
Expand All @@ -617,6 +619,8 @@ protected function getTimestampAttribute(): ?Carbon
* Returns the edited_timestamp attribute.
*
* @return Carbon|null The time that the message was edited.
*
* @throws \Exception
*/
protected function getEditedTimestampAttribute(): ?Carbon
{
Expand Down Expand Up @@ -800,7 +804,7 @@ public function delayedDelete(int $delay, &$timer = null): ExtendedPromiseInterf
$deferred = new Deferred();

$timer = $this->discord->getLoop()->addTimer($delay / 1000, function () use ($deferred) {
$this->delete([$deferred, 'resolve'], [$deferred, 'reject']);
$this->delete()->done([$deferred, 'resolve'], [$deferred, 'reject']);
});

return $deferred->promise();
Expand Down Expand Up @@ -901,9 +905,15 @@ private function _edit(MessageBuilder $message): ExtendedPromiseInterface
* @link https://discord.com/developers/docs/resources/channel#delete-message
*
* @return ExtendedPromiseInterface
*
* @throws \RuntimeException This type of message cannot be deleted.
*/
public function delete(): ExtendedPromiseInterface
{
if (! $this->isDeletable()) {
return reject(new \RuntimeException("Cannot delete this type of message: {$this->type}", 50021));
}

return $this->http->delete(Endpoint::bind(Endpoint::CHANNEL_MESSAGE, $this->channel_id, $this->id));
}

Expand Down Expand Up @@ -973,6 +983,22 @@ public function addEmbed(Embed $embed): ExtendedPromiseInterface
->addEmbed($embed));
}

public function isDeletable(): bool
{
return ! in_array($this->type, [
self::TYPE_RECIPIENT_ADD,
self::TYPE_RECIPIENT_REMOVE,
self::TYPE_CALL,
self::TYPE_CHANNEL_NAME_CHANGE,
self::TYPE_CHANNEL_ICON_CHANGE,
self::TYPE_GUILD_DISCOVERY_DISQUALIFIED,
self::TYPE_GUILD_DISCOVERY_REQUALIFIED,
self::TYPE_GUILD_DISCOVERY_GRACE_PERIOD_INITIAL_WARNING,
self::TYPE_GUILD_DISCOVERY_GRACE_PERIOD_FINAL_WARNING,
self::TYPE_THREAD_STARTER_MESSAGE,
]);
}

/**
* @inheritDoc
*
Expand Down
2 changes: 0 additions & 2 deletions src/Discord/Parts/Channel/Overwrite.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ class Overwrite extends Part
* Sets the allow attribute of the role.
*
* @param ChannelPermission|int $allow
* @throws \Exception
*/
protected function setAllowAttribute($allow): void
{
Expand All @@ -65,7 +64,6 @@ protected function setAllowAttribute($allow): void
* Sets the deny attribute of the role.
*
* @param ChannelPermission|int $deny
* @throws \Exception
*/
protected function setDenyAttribute($deny): void
{
Expand Down
2 changes: 2 additions & 0 deletions src/Discord/Parts/Embed/Embed.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ class Embed extends Part
* Gets the timestamp attribute.
*
* @return Carbon|null The timestamp attribute.
*
* @throws \Exception
*/
protected function getTimestampAttribute(): ?Carbon
{
Expand Down
2 changes: 2 additions & 0 deletions src/Discord/Parts/Guild/AuditLog/Entry.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ class Entry extends Part
public const AUTO_MODERATION_RULE_UPDATE = 141;
public const AUTO_MODERATION_RULE_DELETE = 142;
public const AUTO_MODERATION_BLOCK_MESSAGE = 143;
public const AUTO_MODERATION_FLAG_TO_CHANNEL = 144;
public const AUTO_MODERATION_USER_COMMUNICATION_DISABLED = 145;

// AUDIT LOG ENTRY TYPES

Expand Down
22 changes: 13 additions & 9 deletions src/Discord/Parts/Guild/AuditLog/Options.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,17 @@
*
* @since 5.1.0
*
* @property string $application_id ID of the app whose permissions were targeted.
* @property string $channel_id Channel in which the entities were targeted.
* @property string $count Number of entities that were targeted.
* @property string $delete_member_days Number of days after which inactive members were kicked.
* @property string $id Id of the overwritten entity.
* @property string $members_removed Number of members removed by the prune.
* @property string $message_id Id of the message that was targeted.
* @property string $role_name Name of the role if type is "0" (not present if type is "1").
* @property string $type Type of overwritten entity - "0" for "role" or "1" for "member".
* @property string $application_id ID of the app whose permissions were targeted.
* @property string $auto_moderation_rule_name Name of the Auto Moderation rule that was triggered.
* @property string $auto_moderation_rule_trigger_type Trigger type of the Auto Moderation rule that was triggered.
* @property string $channel_id Channel in which the entities were targeted.
* @property string $count Number of entities that were targeted.
* @property string $delete_member_days Number of days after which inactive members were kicked.
* @property string $id Id of the overwritten entity.
* @property string $members_removed Number of members removed by the prune.
* @property string $message_id Id of the message that was targeted.
* @property string $role_name Name of the role if type is "0" (not present if type is "1").
* @property string $type Type of overwritten entity - "0" for "role" or "1" for "member".
*/
class Options extends Part
{
Expand All @@ -38,6 +40,8 @@ class Options extends Part
*/
protected $fillable = [
'application_id',
'auto_moderation_rule_name',
'auto_moderation_rule_trigger_type',
'channel_id',
'count',
'delete_member_days',
Expand Down
51 changes: 48 additions & 3 deletions src/Discord/Parts/Guild/Guild.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
* @property-read User|null $owner The owner of the guild.
* @property ?string|null $region The region the guild's voice channels are hosted in.
* @property string $afk_channel_id The unique identifier of the AFK channel ID.
* @property int $afk_timeout How long you will remain in the voice channel until you are moved into the AFK channel.
* @property int $afk_timeout How long in seconds you will remain in the voice channel until you are moved into the AFK channel. Can be set to: 60, 300, 900, 1800, 3600.
* @property bool|null $widget_enabled Is server widget enabled.
* @property ?string|null $widget_channel_id Channel that the widget will create an invite to.
* @property int $verification_level The verification level used for the guild.
Expand Down Expand Up @@ -371,9 +371,9 @@ protected function getOwnerAttribute(): ?User
/**
* Returns the joined_at attribute.
*
* @throws \Exception
*
* @return Carbon|null The joined_at attribute.
*
* @throws \Exception
*/
protected function getJoinedAtAttribute(): ?Carbon
{
Expand Down Expand Up @@ -1267,6 +1267,51 @@ public function updateMFALevel(int $level, ?string $reason = null): ExtendedProm
});
}

/**
* Modify the guild feature.
*
* @link https://discord.com/developers/docs/resources/guild#modify-guild
*
* @param bool[] $features Array of features to set/unset, e.g. `['COMMUNITY' => true, 'INVITES_DISABLED' => false]`.
*
* @return ExtendedPromiseInterface<Guild> This guild.
*
* @throws \OutOfRangeException Feature is not mutable.
* @throws \RuntimeException Guild feature is already set.
*/
public function setFeatures(array $features, ?string $reason = null): ExtendedPromiseInterface
{
$setFeatures = $this->features;
foreach ($features as $feature => $set) {
if (! in_array($feature, ['COMMUNITY', 'INVITES_DISABLED', 'DISCOVERABLE'])) {
return reject(new \OutOfRangeException("Guild feature {$feature} is not mutable"));
}
$featureIdx = array_search($feature, $setFeatures);
if ($set) {
if ($featureIdx !== false) {
return reject(new \RuntimeException("Guild feature {$feature} is already set"));
}
$setFeatures[] = $feature;
} else {
if ($featureIdx === false) {
return reject(new \RuntimeException("Guild feature {$feature} is already not set"));
}
unset($setFeatures[$featureIdx]);
}
}

$headers = [];
if (isset($reason)) {
$headers['X-Audit-Log-Reason'] = $reason;
}

return $this->http->patch(Endpoint::bind(Endpoint::GUILD, $this->id), ['features' => array_values($setFeatures)], $headers)->then(function ($response) {
$this->features = $response->features;

return $this;
});
}

/**
* @inheritDoc
*
Expand Down
4 changes: 2 additions & 2 deletions src/Discord/Parts/Guild/Integration.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ protected function getUserAttribute(): ?User
/**
* Returns the synced_at attribute.
*
* @throws \Exception
*
* @return Carbon|null The synced_at attribute.
*
* @throws \Exception
*/
protected function getSyncedAtAttribute(): ?Carbon
{
Expand Down
2 changes: 0 additions & 2 deletions src/Discord/Parts/Guild/Role.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,6 @@ class Role extends Part
* Sets the permissions attribute.
*
* @param RolePermission|int $permission The permissions to set.
*
* @throws \Exception
*/
protected function setPermissionsAttribute($permission): void
{
Expand Down
8 changes: 4 additions & 4 deletions src/Discord/Parts/Guild/ScheduledEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,9 @@ protected function getImageHashAttribute(): ?string
/**
* Returns the created at attribute.
*
* @throws \Exception
*
* @return Carbon The time the scheduled event will start.
*
* @throws \Exception
*/
protected function getScheduledStartTimeAttribute(): Carbon
{
Expand All @@ -214,9 +214,9 @@ protected function getScheduledStartTimeAttribute(): Carbon
/**
* Returns the created at attribute.
*
* @throws \Exception
*
* @return Carbon|null The time the scheduled event will end, required if entity_type is EXTERNAL.
*
* @throws \Exception
*/
protected function getScheduledEndTimeAttribute(): ?Carbon
{
Expand Down
4 changes: 2 additions & 2 deletions src/Discord/Parts/Thread/Member.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ protected function getUserAttribute(): ?User
/**
* Returns the time that the member joined the thread.
*
* @throws \Exception
*
* @return Carbon
*
* @throws \Exception
*/
protected function getJoinTimestampAttribute(): Carbon
{
Expand Down
Loading