Skip to content

Commit

Permalink
Entitlements part and repository
Browse files Browse the repository at this point in the history
  • Loading branch information
valzargaming committed Sep 29, 2024
1 parent e584be6 commit 93468df
Show file tree
Hide file tree
Showing 2 changed files with 282 additions and 0 deletions.
156 changes: 156 additions & 0 deletions src/Discord/Parts/Entitlements/Entitlement.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
<?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\Entitlements;

use Carbon\Carbon;
use Discord\Http\Endpoint;
use Discord\Parts\Part;
use Discord\Parts\User\User;
use Discord\Parts\Guild\Guild;
use React\Promise\ExtendedPromiseInterface;

/**
* An entitlement object represents a premium offering in the application that a user or guild has access to.
*
* @link https://discord.com/developers/docs/resources/entitlement
*
* @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 int $type Type of entitlement.
* @property bool $deleted Entitlement was deleted.
* @property Carbon|null $starts_at Start date at which the entitlement is valid.
* @property Carbon|null $ends_at Date at which the entitlement is no longer valid.
* @property string|null $guild_id ID of the guild that is granted access to the entitlement's SKU.
* @property bool|null $consumed For consumable items, whether or not the entitlement has been consumed.
* @property-read Guild|null $guild The guild that is granted access to the entitlement's SKU.
* @property-read User|null $user The user that is granted access to the entitlement's SKU.
*/
class Entitlement extends Part
{
public const OWNER_TYPE_GUILD = 1;
public const OWNER_TYPE_USER = 2;

public const TYPE_PURCHASE = 1;
public const TYPE_PREMIUM_SUBSCRIPTION = 2;
public const TYPE_DEVELOPER_GIFT = 3;
public const TYPE_TEST_MODE_PURCHASE = 4;
public const TYPE_FREE_PURCHASE = 5;
public const TYPE_USER_GIFT = 6;
public const TYPE_PREMIUM_PURCHASE = 7;
public const TYPE_APPLICATION_SUBSCRIPTION = 8;

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

// @internal
'guild',
'user',
];

/**
* Returns the guild attribute that is granted access to the entitlement's sku.
*
* @return Guild|null
*/
protected function getGuildAttribute(): ?Guild
{
return $this->discord->guilds->get('id', $this->guild_id);
}

/**
* Gets the user that is granted access to the entitlement's sku.
*
* @return User|null
*/
protected function getUserAttribute(): ?User
{
return $this->discord->users->get('id', $this->user_id);
}

/**
* {@inheritDoc}
*/
public function getRepositoryAttributes(): array
{
return [
'application_id' => $this->application_id,
'entitlement_id' => $this->id,
];
}

/**
* Returns the starts at attribute.
*
* @return Carbon|null The time that the invite was created.
*
* @throws \Exception
*/
protected function getStartsAtAttribute(): ?Carbon
{
if (! isset($this->attributes['starts_at'])) {
return null;
}

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

/**
* Returns the ends at attribute.
*
* @return Carbon|null The time that the invite was created.
*
* @throws \Exception
*/
protected function getEndsAtAttribute(): ?Carbon
{
if (! isset($this->attributes['ends_at'])) {
return null;
}

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

/**
* Consumes an entitlement.
*
* For One-Time Purchase consumable SKUs, marks a given entitlement for the user as consumed.
* The entitlement will have consumed: true when using List Entitlements.
*
* @param Entitlement $part
*
* @return ExtendedPromiseInterface A promise that resolves to an Entitlement object.
*/
public function consume(Entitlement $part): ExtendedPromiseInterface
{
return $this->http->post(Endpoint::bind(Endpoint::APPLICATION_ENTITLEMENT_CONSUME, $this->application_id, $part->id))
->then(function ($response) use ($part) { // Returns a 204 No Content on success.
$part->consumed = true;
return $part;
});
}
}
126 changes: 126 additions & 0 deletions src/Discord/Repository/Entitlements/EntitlementRepository.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\Repository;

use Discord\Discord;
use Discord\Http\Endpoint;
use Discord\Parts\Entitlements\Entitlement;
use React\Promise\ExtendedPromiseInterface;


use function React\Promise\resolve;

/**
* Contains entitlements of an application.
*
* @see Entitlement
* @see \Discord\Parts\User\Client
*
* @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 EntitlementRepository extends AbstractRepository
{
/**
* {@inheritDoc}
*/
protected $endpoints = [
'all' => Endpoint::APPLICATION_ENTITLEMENTS,
'get' => Endpoint::APPLICATION_ENTITLEMENT,
'create' => Endpoint::APPLICATION_ENTITLEMENTS,
'delete' => Endpoint::APPLICATION_ENTITLEMENT,
];

/**
* {@inheritDoc}
*/
protected $class = Entitlement::class;

/**
* {@inheritDoc}
*/
public function __construct(Discord $discord, array $vars = [])
{
$vars['application_id'] = $discord->application->id;

parent::__construct($discord, $vars);
}

/**
* @param object $response
*
* @return ExtendedPromiseInterface<static>
*/
protected function cacheFreshen($response): ExtendedPromiseInterface
{
foreach ($response as $value) foreach ($value as $value) {
$value = array_merge($this->vars, (array) $value);
$part = $this->factory->create($this->class, $value, true);
$items[$part->{$this->discrim}] = $part;
}

if (empty($items)) {
return resolve($this);
}

return $this->cache->setMultiple($items)->then(fn ($success) => $this);
}

/**
* Creates a test entitlement to a given SKU for a given guild or user.
*
* @param string $sku_id ID of the SKU to grant the entitlement to.
* @param string $owner_id ID of the guild or user to grant the entitlement to.
* @param int $owner_type 1 for a guild subscription, 2 for a user subscription.
*
* @throws \InvalidArgumentException
*
* @return ExtendedPromiseInterface<Entitlement>
*/
public function createTestEntitlement(string $sku_id, string $owner_id, int $owner_type): ExtendedPromiseInterface
{
$allowed_owner_types = [Entitlement::OWNER_TYPE_GUILD, Entitlement::OWNER_TYPE_USER];

if (! in_array($owner_type, $allowed_owner_types)) {
throw new \InvalidArgumentException("The given owner type `{$owner_type}` is not valid.");
}

$payload = [
'sku_id' => $sku_id,
'owner_id' => $owner_id,
'owner_type' => $owner_type,
];

return $this->http->post(new Endpoint(Endpoint::APPLICATION_ENTITLEMENT), $payload)
->then(fn ($response) => $this->factory->create($this->class, (array) $response, true));
}

/*
* Deletes a currently-active test entitlement.
* Discord will act as though that user or guild no longer has entitlement to your premium offering.
*
* @param Entitlement $part
*
* @return ExtendedPromiseInterface
*/
public function deleteTestEntitlement(Entitlement $part): ExtendedPromiseInterface
{
return $this->http->delete(Endpoint::bind(Endpoint::APPLICATION_ENTITLEMENT, ['application_id' => $part->application_id, 'entitlement_id' => $part->id]))
->then(fn ($response) => $this->cache->delete($part->{$this->discrim})
->then(fn ($success) => $part));
}
}

0 comments on commit 93468df

Please sign in to comment.