Message::subEntities()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 40
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 38
dl 0
loc 40
c 0
b 0
f 0
rs 9.312
cc 1
nc 1
nop 0
1
<?php
2
3
4
namespace TelegramBot\Entities;
5
6
use TelegramBot\Entities\Games\Game;
7
use TelegramBot\Entities\Payments\Invoice;
8
use TelegramBot\Entities\Payments\SuccessfulPayment;
9
use TelegramBot\Entities\TelegramPassport\PassportData;
10
use TelegramBot\Entity;
11
12
/**
13
 * Class Message
14
 *
15
 * Represents a message
16
 *
17
 * @link https://core.telegram.org/bots/api#message
18
 *
19
 * @method int                           getMessageId()                         Unique message identifier
20
 * @method User                          getFrom()                              Optional. Sender, can be empty for messages sent to channels
21
 * @method Chat                          getSenderChat()                        Optional. Sender of the message, sent on behalf of a chat. The channel itself for channel messages. The supergroup itself for messages from anonymous group administrators. The linked channel for messages automatically forwarded to the discussion group
22
 * @method int                           getDate()                              Date the message was sent in Unix time
23
 * @method Chat                          getChat()                              Conversation the message belongs to
24
 * @method User                          getForwardFrom()                       Optional. For forwarded messages, sender of the original message
25
 * @method Chat                          getForwardFromChat()                   Optional. For messages forwarded from a channel, information about the original channel
26
 * @method int                           getForwardFromMessageId()              Optional. For forwarded channel posts, identifier of the original message in the channel
27
 * @method string                        getForwardSignature()                  Optional. For messages forwarded from channels, signature of the post author if present
28
 * @method string                        getForwardSenderName()                 Optional. Sender's name for messages forwarded from users who disallow adding a link to their account in forwarded messages
29
 * @method int                           getForwardDate()                       Optional. For forwarded messages, date the original message was sent in Unix time
30
 * @method bool                          getIsAutomaticForward()                Optional. True, if the message is a channel post that was automatically forwarded to the connected discussion group
31
 * @method ReplyToMessage                getReplyToMessage()                    Optional. For replies, the original message. Note that the Message object in this field will not contain further reply_to_message fields even if it itself is a reply.
32
 * @method User                          getViaBot()                            Optional. Bot through which the message was sent
33
 * @method int                           getEditDate()                          Optional. Date the message was last edited in Unix time
34
 * @method bool                          getHasProtectedContent()               Optional. True, if the message can't be forwarded
35
 * @method string                        getMediaGroupId()                      Optional. The unique identifier of a media message group this message belongs to
36
 * @method string                        getAuthorSignature()                   Optional. Signature of the post author for messages in channels
37
 * @method MessageEntity[]               getEntities()                          Optional. For text messages, special entities like usernames, URLs, bot commands, etc. that appear in the text
38
 * @method Animation                     getAnimation()                         Optional. Message is an animation, information about the animation. For backward compatibility, when this field is set, the document field will also be set
39
 * @method Audio                         getAudio()                             Optional. Message is an audio file, information about the file
40
 * @method Document                      getDocument()                          Optional. Message is a general file, information about the file
41
 * @method PhotoSize[]                   getPhoto()                             Optional. Message is a photo, available sizes of the photo
42
 * @method Sticker                       getSticker()                           Optional. Message is a sticker, information about the sticker
43
 * @method Video                         getVideo()                             Optional. Message is a video, information about the video
44
 * @method VideoNote                     getVideoNote()                         Optional. Message is a video note message, information about the video
45
 * @method Voice                         getVoice()                             Optional. Message is a voice message, information about the file
46
 * @method string                        getCaption()                           Optional. Caption for the document, photo or video, 0-200 characters
47
 * @method MessageEntity[]               getCaptionEntities()                   Optional. For messages with a caption, special entities like usernames, URLs, bot commands, etc. that appear in the caption
48
 * @method Contact                       getContact()                           Optional. Message is a shared contact, information about the contact
49
 * @method Dice                          getDice()                              Optional. Message is a dice with random value, 1-6 for “🎲” and “🎯” base emoji, 1-5 for “🏀” and “⚽” base emoji, 1-64 for “🎰” base emoji
50
 * @method Game                          getGame()                              Optional. Message is a game, information about the game.
51
 * @method Poll                          getPoll()                              Optional. Message is a native poll, information about the poll
52
 * @method Venue                         getVenue()                             Optional. Message is a venue, information about the venue
53
 * @method Location                      getLocation()                          Optional. Message is a shared location, information about the location
54
 * @method User[]                        getNewChatMembers()                    Optional. A new member(s) was added to the group, information about them (one of this members may be the bot itself)
55
 * @method User                          getLeftChatMember()                    Optional. A member was removed from the group, information about them (this member may be the bot itself)
56
 * @method string                        getNewChatTitle()                      Optional. A chat title was changed to this value
57
 * @method PhotoSize[]                   getNewChatPhoto()                      Optional. A chat photo was changed to this value
58
 * @method bool                          getDeleteChatPhoto()                   Optional. Service message: the chat photo was deleted
59
 * @method bool                          getGroupChatCreated()                  Optional. Service message: the group has been created
60
 * @method bool                          getSupergroupChatCreated()             Optional. Service message: the supergroup has been created. This field can't be received in a message coming through updates, because bot can’t be a member of a supergroup when it is created. It can only be found in reply_to_message if someone replies to a very first message in a directly created supergroup.
61
 * @method MessageAutoDeleteTimerChanged getMessageAutoDeleteTimerChanged()     Optional. Service message: auto-delete timer settings changed in the chat
62
 * @method int                           getMigrateToChatId()                   Optional. The group has been migrated to a supergroup with the specified identifier. This number may be greater than 32 bits and some programming languages may have difficulty/silent defects in interpreting it. But it smaller than 52 bits, so a signed 64 bit integer or double-precision float type are safe for storing this identifier.
63
 * @method int                           getMigrateFromChatId()                 Optional. The supergroup has been migrated from a group with the specified identifier. This number may be greater than 32 bits and some programming languages may have difficulty/silent defects in interpreting it. But it smaller than 52 bits, so a signed 64 bit integer or double-precision float type are safe for storing this identifier.
64
 * @method Message                       getPinnedMessage()                     Optional. Specified message was pinned. Note that the Message object in this field will not contain further reply_to_message fields even if it is itself a reply.
65
 * @method SuccessfulPayment             getSuccessfulPayment()                 Optional. Message is a service message about a successful payment, information about the payment.
66
 * @method Invoice                       getInvoice()                           Optional. Message is an invoice for a payment, information about the invoice.
67
 * @method string                        getConnectedWebsite()                  Optional. The domain name of the website on which the user has logged in.
68
 * @method PassportData                  getPassportData()                      Optional. Telegram Passport data
69
 * @method ProximityAlertTriggered       getProximityAlertTriggered()           Optional. Service message. A user in the chat triggered another user's proximity alert while sharing Live Location.
70
 * @method bool                          getChannelChatCreated()                Optional. Service message: the channel has been created. This field can't be received in a message coming through updates, because bot can’t be a member of a channel when it is created. It can only be found in reply_to_message if someone replies to a very first message in a channel.
71
 * @method VoiceChatScheduled            getVoiceChatScheduled()                Optional. Service message: voice chat scheduled
72
 * @method VoiceChatStarted              getVoiceChatStarted()                  Optional. Service message: voice chat started
73
 * @method VoiceChatEnded                getVoiceChatEnded()                    Optional. Service message: voice chat ended
74
 * @method VoiceChatParticipantsInvited  getVoiceChatParticipantsInvited()      Optional. Service message: new participants invited to a voice chat
75
 * @method WebAppData                    getWebAppData()                        Optional. Service message: data sent by a Web App
76
 * @method InlineKeyboard                getReplyMarkup()                       Optional. Inline keyboard attached to the message. login_url buttons are represented as ordinary url buttons.
77
 */
78
class Message extends Entity
79
{
80
81
    /**
82
     * For text messages, the actual UTF-8 text of the message, 0-4096 characters.
83
     *
84
     * @param bool $without_cmd
85
     *
86
     * @return string|null
87
     */
88
    public function getText(bool $without_cmd = false): ?string
89
    {
90
        $text = $this->getProperty('text');
91
92
        if ($without_cmd && $command = $this->getFullCommand()) {
93
            if (strlen($command) + 1 < strlen($text)) {
94
                return substr($text, strlen($command) + 1);
95
            }
96
97
            return '';
98
        }
99
100
        return $text;
101
    }
102
103
    /**
104
     * return the entire command like /echo or /echo@bot1 if specified
105
     *
106
     * @return string|null
107
     */
108
    public function getFullCommand(): ?string
109
    {
110
        $text = $this->getProperty('text');
111
        if (!str_starts_with($text, '/')) {
112
            return null;
113
        }
114
115
        $no_EOL = strtok($text, PHP_EOL);
116
        $no_space = strtok($text, ' ');
117
118
        //try to understand which separator \n or space divide /command from text
119
        return strlen($no_space) < strlen($no_EOL) ? $no_space : $no_EOL;
120
    }
121
122
    /**
123
     * Bot added in chat
124
     *
125
     * @return bool
126
     */
127
    public function botAddedInChat(): bool
128
    {
129
        foreach ($this->getNewChatMembers() as $member) {
0 ignored issues
show
Bug introduced by
The method getNewChatMembers() does not exist on TelegramBot\Entities\Message. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

129
        foreach ($this->/** @scrutinizer ignore-call */ getNewChatMembers() as $member) {
Loading history...
130
            if ($member instanceof User && $member->getUsername() === $this->getBotUsername()) {
0 ignored issues
show
Bug introduced by
The method getBotUsername() does not exist on TelegramBot\Entities\Message. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

130
            if ($member instanceof User && $member->getUsername() === $this->/** @scrutinizer ignore-call */ getBotUsername()) {
Loading history...
131
                return true;
132
            }
133
        }
134
135
        return false;
136
    }
137
138
    /**
139
     * Detect type based on properties.
140
     *
141
     * @return string
142
     */
143
    public function getType(): string
144
    {
145
        $types = [
146
            'text',
147
            'audio',
148
            'animation',
149
            'document',
150
            'game',
151
            'photo',
152
            'sticker',
153
            'video',
154
            'voice',
155
            'video_note',
156
            'contact',
157
            'location',
158
            'venue',
159
            'poll',
160
            'new_chat_members',
161
            'left_chat_member',
162
            'new_chat_title',
163
            'new_chat_photo',
164
            'delete_chat_photo',
165
            'group_chat_created',
166
            'supergroup_chat_created',
167
            'channel_chat_created',
168
            'message_auto_delete_timer_changed',
169
            'migrate_to_chat_id',
170
            'migrate_from_chat_id',
171
            'pinned_message',
172
            'invoice',
173
            'successful_payment',
174
            'passport_data',
175
            'proximity_alert_triggered',
176
            'voice_chat_scheduled',
177
            'voice_chat_started',
178
            'voice_chat_ended',
179
            'voice_chat_participants_invited',
180
            'reply_markup',
181
        ];
182
183
        $is_command = $this->getCommand() !== null;
184
        foreach ($types as $type) {
185
            if ($this->getProperty($type) !== null) {
186
                if ($is_command && $type === 'text') {
187
                    return 'command';
188
                }
189
190
                return $type;
191
            }
192
        }
193
194
        return 'message';
195
    }
196
197
    /**
198
     * Get command
199
     *
200
     * @return string|null
201
     */
202
    public function getCommand(): ?string
203
    {
204
        if ($command = $this->getProperty('command')) {
205
            return $command;
206
        }
207
208
        $full_command = $this->getFullCommand() ?? '';
209
        if (strpos($full_command, '/') !== 0) {
210
            return null;
211
        }
212
        $full_command = substr($full_command, 1);
213
214
        //check if command is followed by bot username
215
        $split_cmd = explode('@', $full_command);
216
        if (!isset($split_cmd[1])) {
217
            //command is not followed by name
218
            return $full_command;
219
        }
220
221
        if (strtolower($split_cmd[1]) === strtolower($this->getBotUsername())) {
222
            //command is addressed to me
223
            return $split_cmd[0];
224
        }
225
226
        return null;
227
    }
228
229
    /**
230
     * {@inheritdoc}
231
     */
232
    protected function subEntities(): array
233
    {
234
        return [
235
            'from' => User::class,
236
            'sender_chat' => Chat::class,
237
            'chat' => Chat::class,
238
            'forward_from' => User::class,
239
            'forward_from_chat' => Chat::class,
240
            'reply_to_message' => ReplyToMessage::class,
241
            'via_bot' => User::class,
242
            'entities' => [MessageEntity::class],
243
            'caption_entities' => [MessageEntity::class],
244
            'audio' => Audio::class,
245
            'document' => Document::class,
246
            'animation' => Animation::class,
247
            'game' => Game::class,
248
            'photo' => [PhotoSize::class],
249
            'sticker' => Sticker::class,
250
            'video' => Video::class,
251
            'voice' => Voice::class,
252
            'video_note' => VideoNote::class,
253
            'contact' => Contact::class,
254
            'location' => Location::class,
255
            'venue' => Venue::class,
256
            'poll' => Poll::class,
257
            'dice' => Dice::class,
258
            'new_chat_members' => [User::class],
259
            'left_chat_member' => User::class,
260
            'new_chat_photo' => [PhotoSize::class],
261
            'message_auto_delete_timer_changed' => MessageAutoDeleteTimerChanged::class,
262
            'pinned_message' => __CLASS__,
263
            'invoice' => Invoice::class,
264
            'successful_payment' => SuccessfulPayment::class,
265
            'passport_data' => PassportData::class,
266
            'proximity_alert_triggered' => ProximityAlertTriggered::class,
267
            'voice_chat_scheduled' => VoiceChatScheduled::class,
268
            'voice_chat_started' => VoiceChatStarted::class,
269
            'voice_chat_ended' => VoiceChatEnded::class,
270
            'voice_chat_participants_invited' => VoiceChatParticipantsInvited::class,
271
            'reply_markup' => InlineKeyboard::class,
272
        ];
273
    }
274
275
}
276