Skip to content
Merged
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
21 changes: 18 additions & 3 deletions src/Rest/Helpers/Emoji/EmojiBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,25 @@ public function get(): array
return $this->data;
}

/**
* The emoji as a reaction endpoint takes it.
*
* A custom emoji is "name:id". A standard one is the character itself,
* percent encoded, and may be held under either key: fromPart() puts it in
* name, because that is where Discord sends it in a reaction event, while
* setId() has long been the documented way to write one by hand.
*
* @see https://discord.com/developers/docs/resources/channel#create-reaction
*/
public function __toString(): string
{
return isset($this->data['name'])
? $this->data['name'] . ':' . $this->data['id']
: urlencode($this->data['id']);
$id = $this->data['id'] ?? null;
$name = $this->data['name'] ?? null;

if ($id !== null && $name !== null) {
return $name . ':' . $id;
}

return rawurlencode((string) ($name ?? $id));
}
}
32 changes: 32 additions & 0 deletions tests/Rest/Helpers/Emoji/EmojiBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,38 @@ public function testCreateEmojiFromIdAndName(): void
$this->assertEquals('name:12345', (string) $emojiBuilder);
}

/**
* A reaction event carries a standard emoji as its name with no id, which
* is what fromPart() copies across. Rendering that as "✅:" — with the id
* missing entirely — made every reaction on a standard emoji a malformed
* request, and warned about an undefined key on the way out.
*/
public function testCreateEmojiFromNameAlone(): void
{
$emojiBuilder = new EmojiBuilder();
$emojiBuilder->setName('✅');

$this->assertEquals(rawurlencode('✅'), (string) $emojiBuilder);
}

public function testAStandardEmojiFromAReactionEventIsRenderedForTheEndpoint(): void
{
$emoji = new Emoji();
$emoji->name = '❌';
$emoji->id = null;

$this->assertEquals(rawurlencode('❌'), (string) EmojiBuilder::fromPart($emoji));
}

public function testACustomEmojiFromAReactionEventKeepsBothHalves(): void
{
$emoji = new Emoji();
$emoji->name = 'apex';
$emoji->id = '12345';

$this->assertEquals('apex:12345', (string) EmojiBuilder::fromPart($emoji));
}

#[DataProvider('getFromPartProvider')]
public function testGetFromPart(Emoji $emoji, array $result): void
{
Expand Down