Skip to content

Entitlements updates #1186

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

Open
wants to merge 30 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
f5d77f7
Entitlements updates
key2peace Oct 20, 2023
d265ea6
typo fix
key2peace Oct 20, 2023
a856129
Link them better
key2peace Oct 20, 2023
ff95829
Update EntitlementDelete.php
key2peace Oct 20, 2023
ee253f6
Update EntitlementUpdate.php
key2peace Oct 20, 2023
426940e
Update EntitlementUpdate.php
key2peace Oct 20, 2023
7256ee4
Update EntitlementCreate.php
key2peace Oct 20, 2023
a162632
Update InteractionCreate.php
key2peace Oct 20, 2023
b532a79
Update EntitlementsRepository.php
key2peace Oct 21, 2023
7a1f429
change pushItem to set
key2peace Oct 21, 2023
c5036ba
Update src/Discord/Parts/Interactions/Entitlement.php
key2peace Oct 22, 2023
173a0ee
Update src/Discord/Parts/Interactions/Entitlement.php
key2peace Oct 22, 2023
8d0979c
Update src/Discord/Parts/Interactions/Entitlement.php
key2peace Oct 22, 2023
d6dae87
Update src/Discord/Parts/Interactions/Entitlement.php
key2peace Oct 22, 2023
d2f5d5f
Update src/Discord/Parts/Interactions/Entitlement.php
key2peace Oct 22, 2023
c0d894c
Apply suggestions from code review
key2peace Oct 22, 2023
d7d9fa8
Update EntitlementsRepository.php
key2peace Oct 22, 2023
dc1b478
Update Guild.php
key2peace Oct 22, 2023
629e65f
move and rename
key2peace Oct 22, 2023
79290e7
Update Guild.php
key2peace Oct 22, 2023
157b2af
Update User.php
key2peace Oct 22, 2023
7f4e39e
Update Interaction.php
key2peace Oct 22, 2023
1587873
Update EntitlementCreate.php
key2peace Oct 22, 2023
a927566
Update EntitlementDelete.php
key2peace Oct 22, 2023
5cab513
Update EntitlementDelete.php
key2peace Oct 22, 2023
8ff0f90
Update EntitlementUpdate.php
key2peace Oct 22, 2023
147e8b3
Update InteractionCreate.php
key2peace Oct 22, 2023
6a58513
Update Guild.php
key2peace Nov 6, 2023
971039a
Update User.php
key2peace Nov 6, 2023
544bd52
Update Guild.php
key2peace Nov 6, 2023
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
14 changes: 14 additions & 0 deletions src/Discord/Parts/Guild/Guild.php
Original file line number Diff line number Diff line change
Expand Up @@ -1590,6 +1590,20 @@ public function setFeatures(array $features, ?string $reason = null): ExtendedPr
});
}

/**
* Returns the guilds entitlements for this application.
*
* @link https://discord.com/developers/docs/monetization/entitlements#list-entitlements
*
* @return Collection
*/
public function getMyApplicationEntitlement(): Collection
{
return $this->discord->application->entitlements->filter(function ($entitlement) {
return $entitlement->guild_id == $this->id;
});
}

/**
* {@inheritDoc}
*
Expand Down
126 changes: 126 additions & 0 deletions src/Discord/Parts/Interactions/Entitlement.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<?php

/*
* This file is a part of the DiscordPHP project.
*
* Copyright (c) 2015-present David Cole <[email protected]>
*
* This file is subject to the MIT license that is bundled
* with this source code in the LICENSE.md file.
*/

namespace Discord\Parts\Interactions;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.


use Discord\Http\Endpoint;
use Discord\Parts\Guild\Guild;
use Discord\Parts\User\User;
use Discord\WebSockets\Event;


/**
* Represents an entitlement from Discord.
*
* @link https://discord.com/developers/docs/monetization/entitlements#entitlement-object
*
* @since 10.0.0
*
* @property string $id ID of the entitlement.
* @property string $sku_id ID of the SKU.
* @property string $application_id ID of the parent application.
* @property string|null $user_id ID of the user that is granted access to the entitlement's sku.
* @property string|null $promotion_id ID of the promotion that applies to the entitlement.
* @property-read User|null $user User that is granted access to the entitlement's sku.
* @property int $type Type of entitlement.
* @property bool $deleted Entitlement was deleted.
* @property int|null $gift_code_flags Gift code flags that apply to this entitlement.
* @property bool|null $consumed Entitlement has been consumed.
* @property Carbon|null $starts_at Start date at which the entitlement is valid. Not present when using test entitlements.
* @property Carbon|null $ends_at Date at which the entitlement is no longer valid. Not present when using test entitlements.
* @property string|null $guild_id ID of the guild that is granted access to the entitlement's sku.
* @property-read Guild|null $guild Guild that is granted access to the entitlement's sku.
* @property string|null $subscription_id ID of the subscription.
*/
class Entitlement extends Part
{
public const TYPE_APPLICATION_SUBSCRIPTION = 8;


/**
* {@inheritDoc}
*/
protected $fillable = [
'id',
'sku_id',
'application_id',
'user_id',
'promotion_id',
'type',
'deleted',
'gift_code_flags',
'consumed',
'guild_id',
'subscription_id',
'starts_at',
'ends_at',
];

/**
* Returns the guild that is granted access to the entitlement's sku.
*
* @return Guild|null
*/
protected function getGuildAttribute(): ?Guild
{
if (! isset($this->attributes['guild_id'])) {
return null;
}

return $this->discord->guilds->get('id', $this->guild_id);
}

/**
* Returns the user that is granted access to the entitlement's sku.
*
* @return User|null
*/
protected function getUserAttribute(): ?User
{
if (! isset($this->attributes['user_id'])) {
return null;
}

return $this->discord->users->get('id', $this->user_id);
}

/**
* Returns the start date at which the entitlement is valid. Not present when using test entitlements.
*
* @return Carbon|null The start date at which the entitlement is valid. Not present when using test entitlements.
*
* @throws \Exception
*/
protected function getStartsAtAttribute(): ?Carbon
{
if (! isset($this->attributes['starts_at']) {
return null;
}

return new Carbon($this->attributes['starts_at']);
}

/**
* Returns the date at which the entitlement is no longer valid. Not present when using test entitlements.
*
* @return Carbon|null The date at which the entitlement is no longer valid. Not present when using test entitlements.
*
* @throws \Exception
*/
protected function getEndsAtAttribute(): ?Carbon
{
if (! isset($this->attributes['ends_at']) {
return null;
}

return new Carbon($this->attributes['ends_at']);
}
}
23 changes: 23 additions & 0 deletions src/Discord/Parts/Interactions/Interaction.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
* @property-read ChannelPermission|null $app_permissions Bitwise set of permissions the app or bot has within the channel the interaction was sent from.
* @property string|null $locale The selected language of the invoking user.
* @property string|null $guild_locale The guild's preferred locale, if invoked in a guild.
* @property Entitlement|null $entitlements The user's and guild's entitlements for this application.
*/
class Interaction extends Part
{
Expand All @@ -80,6 +81,7 @@ class Interaction extends Part
'app_permissions',
'locale',
'guild_locale',
'entitlements',
];

/**
Expand Down Expand Up @@ -402,6 +404,27 @@ public function sendFollowUpMessage(MessageBuilder $builder, bool $ephemeral = f
});
}

/**
* Responds to the interaction with PREMIUM_REQUIRED.
*
* @link https://discord.com/developers/docs/monetization/app-subscriptions#gating-premium-interactions
*
* @throws \LogicException Interaction is not Application Command, Message Component, or Modal Submit.
*
* @return ExtendedPromiseInterface
*/
public function respondWithPremiumRequired(): ExtendedPromiseInterface
{
if (! in_array($this->type, [InteractionType::APPLICATION_COMMAND, InteractionType::MESSAGE_COMPONENT, InteractionType::MODAL_SUBMIT])) {
return reject(new \LogicException('You can only acknowledge application command, message component, or modal submit interactions.'));
}

return $this->respond([
'type' => InteractionResponseType::PREMIUM_REQUIRED,
'data' => [],
]);
}

/**
* Responds to the interaction with a message.
*
Expand Down
5 changes: 4 additions & 1 deletion src/Discord/Parts/OAuth/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Discord\Parts\Part;
use Discord\Parts\Permissions\Permission;
use Discord\Parts\User\User;
use Discord\Repository\Interaction\EntitlementsRepository;
use Discord\Repository\Interaction\GlobalCommandRepository;

/**
Expand Down Expand Up @@ -50,7 +51,8 @@
*
* @property string $invite_url The invite URL to invite the bot to a guild.
*
* @property GlobalCommandRepository $commands The application global commands.
* @property EntitlementsRepository $entitlements The application entitlements.
* @property GlobalCommandRepository $commands The application global commands.
*/
class Application extends Part
{
Expand Down Expand Up @@ -99,6 +101,7 @@ class Application extends Part
*/
protected $repositories = [
'commands' => GlobalCommandRepository::class,
'entitlements' => EntitlementsRepository::class,
];

/**
Expand Down
14 changes: 14 additions & 0 deletions src/Discord/Parts/User/User.php
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this belongs here, Entitlement should be part of applications not users

Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,20 @@ protected function getBannerHashAttribute(): ?string
return $this->attributes['banner'] ?? null;
}

/**
* Returns the users entitlements for this application.
*
* @link https://discord.com/developers/docs/monetization/entitlements#list-entitlements
*
* @return Collection
*/
public function getMyApplicationEntitlement(): Collection
{
return $this->discord->application->entitlements->filter(function ($entitlement) {
return $entitlement->user_id == $this->id;
});
}

/**
* Returns a timestamp for when a user's account was created.
*
Expand Down
47 changes: 47 additions & 0 deletions src/Discord/Repository/Interaction/EntitlementsRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

/*
* This file is a part of the DiscordPHP project.
*
* Copyright (c) 2015-present David Cole <[email protected]>
*
* This file is subject to the MIT license that is bundled
* with this source code in the LICENSE.md file.
*/

namespace Discord\Repository\Interaction;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.


use Discord\Http\Endpoint;
use Discord\Parts\Interaction\Entitlement;
use Discord\Repository\AbstractRepository;

/**
* Guild/User entitlements.
*
* @see \Discord\Parts\Guild\Guild
* @see \Discord\Parts\User\User
*
* @since 10.0.0
*
* @method Entitlement|null get(string $discrim, $key)
* @method Entitlement|null pull(string|int $key, $default = null)
* @method Entitlement|null first()
* @method Entitlement|null last()
* @method Entitlement|null find(callable $callback)
*/
class EntitlementsRepository extends AbstractRepository
{
/**
* {@inheritDoc}
*/
protected $endpoints = [
'all' => Endpoint::APPLICATION_ENTITLEMENTS,
'create' => Endpoint::APPLICATION_ENTITLEMENTS,
'delete' => Endpoint::APPLICATION_ENTITLEMENT,
];

/**
* {@inheritDoc}
*/
protected $class = Entitlement::class;
}
5 changes: 5 additions & 0 deletions src/Discord/WebSockets/Event.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ abstract class Event
public const MESSAGE_REACTION_REMOVE_ALL = 'MESSAGE_REACTION_REMOVE_ALL';
public const MESSAGE_REACTION_REMOVE_EMOJI = 'MESSAGE_REACTION_REMOVE_EMOJI';

// Entitlements
public const ENTITLEMENT_CREATE = 'ENTITLEMENT_CREATE';
public const ENTITLEMENT_UPDATE = 'ENTITLEMENT_UPDATE';
public const ENTITLEMENT_DELETE = 'ENTITLEMENT_DELETE';

/**
* The Discord client instance.
*
Expand Down
36 changes: 36 additions & 0 deletions src/Discord/WebSockets/Events/EntitlementCreate.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

/*
* This file is a part of the DiscordPHP project.
*
* Copyright (c) 2015-present David Cole <[email protected]>
*
* This file is subject to the MIT license that is bundled
* with this source code in the LICENSE.md file.
*/

namespace Discord\WebSockets\Events;

use Discord\WebSockets\Event;
use Discord\Parts\Interaction\Entitlement;

/**
* @link https://discord.com/developers/docs/topics/gateway-events#entitlement-create
*
* @since 10.0.0
*/
class EntitlementCreate extends Event
{
/**
* {@inheritDoc}
*/
public function handle($data)
{
/** @var Entitlement */
$entitlementPart = $this->factory->part(Entitlement::class, (array) $data, true);

$this->discord->application->entitlements->set($data->id, $entitlementPart);

return $entitlementPart;
}
}
36 changes: 36 additions & 0 deletions src/Discord/WebSockets/Events/EntitlementDelete.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

/*
* This file is a part of the DiscordPHP project.
*
* Copyright (c) 2015-present David Cole <[email protected]>
*
* This file is subject to the MIT license that is bundled
* with this source code in the LICENSE.md file.
*/

namespace Discord\WebSockets\Events;

use Discord\Parts\Interaction\Entitlement;
use Discord\WebSockets\Event;

/**
* @link https://discord.com/developers/docs/topics/gateway-events#entitlement-delete
*
* @since 10.0.0
*/
class EntitlementDelete extends Event
{
/**
* {@inheritDoc}
*/
public function handle($data)
{
if ($entitlementPart = yield $this->discord->application->entitlements->cachePull($data->id)) {
$entitlementPart->fill((array) $data);
$entitlementPart->created = false;
}

return $entitlementPart ?? $this->factory->part(Entitlement::class, (array) $data);
}
}
Loading