1
0
mirror of https://github.com/danog/MadelineProto.git synced 2024-11-26 17:04:39 +01:00

Entity refactoring

This commit is contained in:
Daniil Gentili 2024-04-21 13:51:07 +02:00
parent a3d9007337
commit fd9b0af1b4
25 changed files with 221 additions and 70 deletions

2
docs

@ -1 +1 @@
Subproject commit 422f5aa4f6c2cec63663d5b82f383113b4fab80f
Subproject commit c39c48b1b164b5ea6bd95a9e6660f50b361f9ec8

View File

@ -11,4 +11,8 @@ final class BankCard extends MessageEntity
{
return ['type' => 'bank_card', 'offset' => $this->offset, 'length' => $this->length];
}
public function toMTProto(): array
{
return ['_' => 'messageEntityBankCard', 'offset' => $this->offset, 'length' => $this->length];
}
}

View File

@ -11,4 +11,8 @@ final class Blockquote extends MessageEntity
{
return ['type' => 'block_quote', 'offset' => $this->offset, 'length' => $this->length];
}
public function toMTProto(): array
{
return ['_' => 'messageEntityBlockquote', 'offset' => $this->offset, 'length' => $this->length];
}
}

View File

@ -11,4 +11,8 @@ final class Bold extends MessageEntity
{
return ['type' => 'bold', 'offset' => $this->offset, 'length' => $this->length];
}
public function toMTProto(): array
{
return ['_' => 'messageEntityBold', 'offset' => $this->offset, 'length' => $this->length];
}
}

View File

@ -11,4 +11,8 @@ final class BotCommand extends MessageEntity
{
return ['type' => 'bot_command', 'offset' => $this->offset, 'length' => $this->length];
}
public function toMTProto(): array
{
return ['_' => 'messageEntityBotCommand', 'offset' => $this->offset, 'length' => $this->length];
}
}

View File

@ -11,4 +11,8 @@ final class Cashtag extends MessageEntity
{
return ['type' => 'cashtag', 'offset' => $this->offset, 'length' => $this->length];
}
public function toMTProto(): array
{
return ['_' => 'messageEntityCashtag', 'offset' => $this->offset, 'length' => $this->length];
}
}

View File

@ -11,4 +11,8 @@ final class Code extends MessageEntity
{
return ['type' => 'code', 'offset' => $this->offset, 'length' => $this->length];
}
public function toMTProto(): array
{
return ['_' => 'messageEntityCode', 'offset' => $this->offset, 'length' => $this->length];
}
}

View File

@ -7,17 +7,24 @@ namespace danog\MadelineProto\EventHandler\Message\Entities;
*/
final class CustomEmoji extends MessageEntity
{
/** Document ID of the [custom emoji](https://core.telegram.org/api/custom-emoji). */
public readonly int $documentId;
public function __construct(
/** Offset of message entity within message (in UTF-16 code units) */
public readonly int $offset,
/** @internal */
protected function __construct(array $rawEntities)
{
parent::__construct($rawEntities);
$this->documentId = $rawEntities['document_id'] ?? $rawEntities['custom_emoji_id'];
/** Length of message entity within message (in UTF-16 code units) */
public readonly int $length,
/** Document ID of the [custom emoji](https://core.telegram.org/api/custom-emoji). */
public readonly int $documentId
) {
}
public function toBotAPI(): array
{
return ['type' => 'custom_emoji', 'offset' => $this->offset, 'length' => $this->length, 'custom_emoji_id' => $this->documentId];
}
public function toMTProto(): array
{
return ['_' => 'messageEntityCustomEmoji', 'offset' => $this->offset, 'length' => $this->length, 'document_id' => $this->documentId];
}
}

View File

@ -11,4 +11,8 @@ final class Email extends MessageEntity
{
return ['type' => 'email', 'offset' => $this->offset, 'length' => $this->length];
}
public function toMTProto(): array
{
return ['_' => 'messageEntityEmail', 'offset' => $this->offset, 'length' => $this->length];
}
}

View File

@ -11,4 +11,8 @@ final class Hashtag extends MessageEntity
{
return ['type' => 'hashtag', 'offset' => $this->offset, 'length' => $this->length];
}
public function toMTProto(): array
{
return ['_' => 'messageEntityHashtag', 'offset' => $this->offset, 'length' => $this->length];
}
}

View File

@ -7,17 +7,24 @@ namespace danog\MadelineProto\EventHandler\Message\Entities;
*/
final class InputMentionName extends MessageEntity
{
/** Identifier of the user that was mentioned */
public readonly int|string $userId;
public function __construct(
/** Offset of message entity within message (in UTF-16 code units) */
public readonly int $offset,
/** @internal */
protected function __construct(array $rawEntities)
{
parent::__construct($rawEntities);
$this->userId = $rawEntities['user_id'];
/** Length of message entity within message (in UTF-16 code units) */
public readonly int $length,
/** Identifier of the user that was mentioned */
public readonly int|string $userId
) {
}
public function toBotAPI(): array
{
return ['type' => 'text_mention', 'offset' => $this->offset, 'length' => $this->length, 'user' => ['id' => $this->userId]];
}
public function toMTProto(): array
{
return ['_' => 'inputMessageEntityMentionName', 'offset' => $this->offset, 'length' => $this->length, 'user_id' => $this->userId];
}
}

View File

@ -11,4 +11,8 @@ final class Italic extends MessageEntity
{
return ['type' => 'italic', 'offset' => $this->offset, 'length' => $this->length];
}
public function toMTProto(): array
{
return ['_' => 'messageEntityItalic', 'offset' => $this->offset, 'length' => $this->length];
}
}

View File

@ -11,4 +11,8 @@ final class Mention extends MessageEntity
{
return ['type' => 'mention', 'offset' => $this->offset, 'length' => $this->length];
}
public function toMTProto(): array
{
return ['_' => 'messageEntityMention', 'offset' => $this->offset, 'length' => $this->length];
}
}

View File

@ -7,17 +7,25 @@ namespace danog\MadelineProto\EventHandler\Message\Entities;
*/
final class MentionName extends MessageEntity
{
/** Identifier of the user that was mentioned */
public readonly int $userId;
/** @internal */
protected function __construct(array $rawEntities)
{
parent::__construct($rawEntities);
$this->userId = $rawEntities['user_id'] ?? $rawEntities['user']['id'];
public function __construct(
/** Offset of message entity within message (in UTF-16 code units) */
public readonly int $offset,
/** Length of message entity within message (in UTF-16 code units) */
public readonly int $length,
/** Identifier of the user that was mentioned */
public readonly int $userId
) {
}
public function toBotAPI(): array
{
return ['type' => 'text_mention', 'offset' => $this->offset, 'length' => $this->length, 'user' => ['id' => $this->userId]];
}
public function toMTProto(): array
{
return ['_' => 'messageEntityMentionName', 'offset' => $this->offset, 'length' => $this->length, 'user_id' => $this->userId];
}
}

View File

@ -12,17 +12,13 @@ use ReflectionProperty;
*/
abstract class MessageEntity implements JsonSerializable
{
/** Offset of message entity within message (in UTF-16 code units) */
public readonly int $offset;
public function __construct(
/** Offset of message entity within message (in UTF-16 code units) */
public readonly int $offset,
/** Length of message entity within message (in UTF-16 code units) */
public readonly int $length;
/** @internal */
protected function __construct(array $rawEntities)
{
$this->offset = $rawEntities['offset'];
$this->length = $rawEntities['length'];
/** Length of message entity within message (in UTF-16 code units) */
public readonly int $length
) {
}
/**
@ -37,26 +33,26 @@ abstract class MessageEntity implements JsonSerializable
public static function fromRawEntity(array $entity): self
{
return match ($entity['_'] ?? $entity['type']) {
'mention', 'messageEntityMention' => new Mention($entity),
'hashtag', 'messageEntityHashtag' => new Hashtag($entity),
'bot_command', 'messageEntityBotCommand' => new BotCommand($entity),
'email', 'messageEntityEmail' => new Email($entity),
'bold', 'messageEntityBold' => new Bold($entity),
'italic', 'messageEntityItalic' => new Italic($entity),
'url', 'messageEntityUrl' => new Url($entity),
'code', 'messageEntityCode' => new Code($entity),
'pre', 'messageEntityPre' => new Pre($entity),
'text_link', 'messageEntityTextUrl' => new TextUrl($entity),
'text_mention', 'messageEntityMentionName' => new MentionName($entity),
'inputMessageEntityMentionName' => new InputMentionName($entity),
'phone_number', 'messageEntityPhone' => new Phone($entity),
'cashtag', 'messageEntityCashtag' => new Cashtag($entity),
'underline', 'messageEntityUnderline' => new Underline($entity),
'strikethrough', 'messageEntityStrike' => new Strike($entity),
'block_quote', 'messageEntityBlockquote' => new Blockquote($entity),
'messageEntityBankCard' => new BankCard($entity),
'spoiler', 'messageEntitySpoiler' => new Spoiler($entity),
'custom_emoji', 'messageEntityCustomEmoji' => new CustomEmoji($entity),
'mention', 'messageEntityMention' => new Mention($entity['offset'], $entity['length']),
'hashtag', 'messageEntityHashtag' => new Hashtag($entity['offset'], $entity['length']),
'bot_command', 'messageEntityBotCommand' => new BotCommand($entity['offset'], $entity['length']),
'email', 'messageEntityEmail' => new Email($entity['offset'], $entity['length']),
'bold', 'messageEntityBold' => new Bold($entity['offset'], $entity['length']),
'italic', 'messageEntityItalic' => new Italic($entity['offset'], $entity['length']),
'url', 'messageEntityUrl' => new Url($entity['offset'], $entity['length']),
'code', 'messageEntityCode' => new Code($entity['offset'], $entity['length']),
'pre', 'messageEntityPre' => new Pre($entity['offset'], $entity['length'], $entity['language']),
'text_link', 'messageEntityTextUrl' => new TextUrl($entity['offset'], $entity['length'], $entity['url']),
'text_mention', 'messageEntityMentionName' => new MentionName($entity['offset'], $entity['length'], $entity['user_id'] ?? $entity['user']['id']),
'inputMessageEntityMentionName' => new InputMentionName($entity['offset'], $entity['length'], $entity['user_id']),
'phone_number', 'messageEntityPhone' => new Phone($entity['offset'], $entity['length']),
'cashtag', 'messageEntityCashtag' => new Cashtag($entity['offset'], $entity['length']),
'underline', 'messageEntityUnderline' => new Underline($entity['offset'], $entity['length']),
'strikethrough', 'messageEntityStrike' => new Strike($entity['offset'], $entity['length']),
'block_quote', 'messageEntityBlockquote' => new Blockquote($entity['offset'], $entity['length']),
'bank_card', 'messageEntityBankCard' => new BankCard($entity['offset'], $entity['length']),
'spoiler', 'messageEntitySpoiler' => new Spoiler($entity['offset'], $entity['length']),
'custom_emoji', 'messageEntityCustomEmoji' => new CustomEmoji($entity['offset'], $entity['length'], $entity['document_id'] ?? $entity['custom_emoji_id']),
default => throw new AssertionError("Unknown entity type: ".($entity['_'] ?? $entity['type']))
};
}
@ -65,6 +61,10 @@ abstract class MessageEntity implements JsonSerializable
* Convert entity to bot API entity.
*/
abstract public function toBotAPI(): array;
/**
* Convert entity to MTProto entity.
*/
abstract public function toMTProto(): array;
/** @internal */
public function jsonSerialize(): mixed

View File

@ -9,6 +9,10 @@ final class Phone extends MessageEntity
{
public function toBotAPI(): array
{
return ['type' => 'phone', 'offset' => $this->offset, 'length' => $this->length];
return ['type' => 'phone_number', 'offset' => $this->offset, 'length' => $this->length];
}
public function toMTProto(): array
{
return ['_' => 'messageEntityPhone', 'offset' => $this->offset, 'length' => $this->length];
}
}

View File

@ -7,15 +7,18 @@ namespace danog\MadelineProto\EventHandler\Message\Entities;
*/
final class Pre extends MessageEntity
{
/** Programming language of the code */
public readonly string $language;
public function __construct(
/** Offset of message entity within message (in UTF-16 code units) */
public readonly int $offset,
/** @internal */
protected function __construct(array $rawEntities)
{
parent::__construct($rawEntities);
$this->language = $rawEntities['language'];
/** Length of message entity within message (in UTF-16 code units) */
public readonly int $length,
/** Programming language of the code */
public readonly string $language
) {
}
public function toBotAPI(): array
{
$res = ['type' => 'pre', 'offset' => $this->offset, 'length' => $this->length];
@ -24,4 +27,8 @@ final class Pre extends MessageEntity
}
return $res;
}
public function toMTProto(): array
{
return ['_' => 'messageEntityPre', 'offset' => $this->offset, 'length' => $this->length, 'language' => $this->language];
}
}

View File

@ -11,4 +11,8 @@ final class Spoiler extends MessageEntity
{
return ['type' => 'spoiler', 'offset' => $this->offset, 'length' => $this->length];
}
public function toMTProto(): array
{
return ['_' => 'messageEntitySpoiler', 'offset' => $this->offset, 'length' => $this->length];
}
}

View File

@ -11,4 +11,8 @@ final class Strike extends MessageEntity
{
return ['type' => 'strikethrough', 'offset' => $this->offset, 'length' => $this->length];
}
public function toMTProto(): array
{
return ['_' => 'messageEntityStrike', 'offset' => $this->offset, 'length' => $this->length];
}
}

View File

@ -7,17 +7,24 @@ namespace danog\MadelineProto\EventHandler\Message\Entities;
*/
final class TextUrl extends MessageEntity
{
/** The actual URL */
public readonly string $url;
public function __construct(
/** Offset of message entity within message (in UTF-16 code units) */
public readonly int $offset,
/** @internal */
protected function __construct(array $rawEntities)
{
parent::__construct($rawEntities);
$this->url = $rawEntities['url'];
/** Length of message entity within message (in UTF-16 code units) */
public readonly int $length,
/** The actual URL */
public readonly string $url
) {
}
public function toBotAPI(): array
{
return ['type' => 'text_link', 'offset' => $this->offset, 'length' => $this->length, 'url' => $this->url];
}
public function toMTProto(): array
{
return ['_' => 'messageEntityTextUrl', 'offset' => $this->offset, 'length' => $this->length, 'url' => $this->url];
}
}

View File

@ -11,4 +11,8 @@ final class Underline extends MessageEntity
{
return ['type' => 'underline', 'offset' => $this->offset, 'length' => $this->length];
}
public function toMTProto(): array
{
return ['_' => 'messageEntityUnderline', 'offset' => $this->offset, 'length' => $this->length];
}
}

View File

@ -11,4 +11,8 @@ final class Url extends MessageEntity
{
return ['type' => 'url', 'offset' => $this->offset, 'length' => $this->length];
}
public function toMTProto(): array
{
return ['_' => 'messageEntityUrl', 'offset' => $this->offset, 'length' => $this->length];
}
}

View File

@ -27,7 +27,6 @@ use danog\MadelineProto\Logger;
use danog\MadelineProto\MTProto;
use danog\MadelineProto\StrTools;
use danog\MadelineProto\Tools;
use danog\TelegramEntities\Entities;
use Throwable;
/**
@ -407,12 +406,12 @@ trait BotAPI
$arguments['parse_mode'] = str_replace('textParseMode', '', $arguments['parse_mode']['_']);
}
if (stripos($arguments['parse_mode'], 'markdown') !== false) {
$entities = Entities::fromMarkdown($arguments[$key]);
$entities = StrTools::markdownToMessageEntities($arguments[$key]);
$arguments[$key] = $entities->message;
$arguments['entities'] = array_merge($arguments['entities'] ?? [], $entities->entities);
unset($arguments['parse_mode']);
} elseif (stripos($arguments['parse_mode'], 'html') !== false) {
$entities = Entities::fromHtml($arguments[$key]);
$entities = StrTools::htmlToMessageEntities($arguments[$key]);
$arguments[$key] = $entities->message;
$arguments['entities'] = array_merge($arguments['entities'] ?? [], $entities->entities);
unset($arguments['parse_mode']);

View File

@ -20,6 +20,7 @@ declare(strict_types=1);
namespace danog\MadelineProto\TL;
use danog\MadelineProto\EventHandler\Message\Entities\MessageEntity;
use danog\MadelineProto\Lang;
use danog\MadelineProto\Logger;
use danog\MadelineProto\Magic;
@ -579,6 +580,9 @@ final class TL implements TLInterface
return $object;
}
}
if ($object instanceof MessageEntity) {
$object = $object->toMTProto();
}
if ($type['type'] === 'InputMessage' && !\is_array($object)) {
$object = ['_' => 'inputMessageID', 'id' => $object];
} elseif (isset($this->typeMismatch[$type['type']]) && (!\is_array($object) || isset($object['_']) && $this->constructors->findByPredicate($object['_'])['type'] !== $type['type'])) {

View File

@ -4,6 +4,26 @@ declare(strict_types=1);
namespace danog\MadelineProto\Test;
use danog\MadelineProto\EventHandler\Message\Entities\BankCard;
use danog\MadelineProto\EventHandler\Message\Entities\Blockquote;
use danog\MadelineProto\EventHandler\Message\Entities\Bold;
use danog\MadelineProto\EventHandler\Message\Entities\BotCommand;
use danog\MadelineProto\EventHandler\Message\Entities\Cashtag;
use danog\MadelineProto\EventHandler\Message\Entities\Code;
use danog\MadelineProto\EventHandler\Message\Entities\CustomEmoji;
use danog\MadelineProto\EventHandler\Message\Entities\Email;
use danog\MadelineProto\EventHandler\Message\Entities\Hashtag;
use danog\MadelineProto\EventHandler\Message\Entities\Italic;
use danog\MadelineProto\EventHandler\Message\Entities\Mention;
use danog\MadelineProto\EventHandler\Message\Entities\MentionName;
use danog\MadelineProto\EventHandler\Message\Entities\MessageEntity;
use danog\MadelineProto\EventHandler\Message\Entities\Phone;
use danog\MadelineProto\EventHandler\Message\Entities\Pre;
use danog\MadelineProto\EventHandler\Message\Entities\Spoiler;
use danog\MadelineProto\EventHandler\Message\Entities\Strike;
use danog\MadelineProto\EventHandler\Message\Entities\TextUrl;
use danog\MadelineProto\EventHandler\Message\Entities\Underline;
use danog\MadelineProto\EventHandler\Message\Entities\Url;
use danog\MadelineProto\StrTools;
use danog\MadelineProto\TextEntities;
use danog\MadelineProto\Tools;
@ -29,6 +49,38 @@ class EntitiesTest extends TestCase
$this->assertEquals(['a👍', 'a👍'], StrTools::mbStrSplit('a👍a👍', 3));
$this->assertEquals(['🇺🇦', '🇺🇦'], StrTools::mbStrSplit('🇺🇦🇺🇦', 4));
}
/**
* @dataProvider provideEntityObjects
*/
public function testAllEntities(MessageEntity $message): void
{
$this->assertTrue(MessageEntity::fromRawEntity($message->toBotAPI()) == $message);
$this->assertTrue(MessageEntity::fromRawEntity($message->toMTProto()) == $message);
}
public static function provideEntityObjects(): array
{
return [
[new BankCard(1, 2)],
[new Blockquote(1, 2)],
[new Bold(1, 2)],
[new BotCommand(1, 2)],
[new Cashtag(1, 2)],
[new Code(1, 2)],
[new CustomEmoji(1, 2, 12345)],
[new Email(1, 2)],
[new Hashtag(1, 2)],
[new Italic(1, 2)],
[new MentionName(1, 2, 12345)],
[new Mention(1, 2)],
[new Phone(1, 2)],
[new Pre(1, 2, "language")],
[new Spoiler(1, 2)],
[new Strike(1, 2)],
[new TextUrl(1, 2, "https://google.com")],
[new Underline(1, 2)],
[new Url(1, 2)],
];
}
private static function sendMessage(string $message, string $parse_mode): TextEntities
{
return match ($parse_mode) {