Passed
Push — master ( 7ecda6...2093cf )
by Armando
04:22 queued 02:31
created

Message   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 184
Duplicated Lines 0 %

Test Coverage

Coverage 83.72%

Importance

Changes 8
Bugs 0 Features 0
Metric Value
eloc 100
c 8
b 0
f 0
dl 0
loc 184
rs 10
ccs 36
cts 43
cp 0.8372
wmc 22

6 Methods

Rating   Name   Duplication   Size   Complexity  
A botAddedInChat() 0 9 4
A getFullCommand() 0 12 3
A subEntities() 0 35 1
A getType() 0 47 5
A getCommand() 0 25 5
A getText() 0 13 4
1
<?php
2
3
/**
4
 * This file is part of the TelegramBot package.
5
 *
6
 * (c) Avtandil Kikabidze aka LONGMAN <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Longman\TelegramBot\Entities;
13
14
use Longman\TelegramBot\Entities\Games\Game;
15
use Longman\TelegramBot\Entities\Payments\Invoice;
16
use Longman\TelegramBot\Entities\Payments\SuccessfulPayment;
17
use Longman\TelegramBot\Entities\TelegramPassport\PassportData;
18
19
/**
20
 * Class Message
21
 *
22
 * @link https://core.telegram.org/bots/api#message
23
 *
24
 * @method int                     getMessageId()               Unique message identifier
25
 * @method User                    getFrom()                    Optional. Sender, can be empty for messages sent to channels
26
 * @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
27
 * @method int                     getDate()                    Date the message was sent in Unix time
28
 * @method Chat                    getChat()                    Conversation the message belongs to
29
 * @method User                    getForwardFrom()             Optional. For forwarded messages, sender of the original message
30
 * @method Chat                    getForwardFromChat()         Optional. For messages forwarded from a channel, information about the original channel
31
 * @method int                     getForwardFromMessageId()    Optional. For forwarded channel posts, identifier of the original message in the channel
32
 * @method string                  getForwardSignature()        Optional. For messages forwarded from channels, signature of the post author if present
33
 * @method string                  getForwardSenderName()       Optional. Sender's name for messages forwarded from users who disallow adding a link to their account in forwarded messages
34
 * @method int                     getForwardDate()             Optional. For forwarded messages, date the original message was sent in Unix time
35
 * @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.
36
 * @method User                    getViaBot()                  Optional. Bot through which the message was sent
37
 * @method int                     getEditDate()                Optional. Date the message was last edited in Unix time
38
 * @method string                  getMediaGroupId()            Optional. The unique identifier of a media message group this message belongs to
39
 * @method string                  getAuthorSignature()         Optional. Signature of the post author for messages in channels
40
 * @method MessageEntity[]         getEntities()                Optional. For text messages, special entities like usernames, URLs, bot commands, etc. that appear in the text
41
 * @method MessageEntity[]         getCaptionEntities()         Optional. For messages with a caption, special entities like usernames, URLs, bot commands, etc. that appear in the caption
42
 * @method Audio                   getAudio()                   Optional. Message is an audio file, information about the file
43
 * @method Document                getDocument()                Optional. Message is a general file, information about the file
44
 * @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
45
 * @method Game                    getGame()                    Optional. Message is a game, information about the game.
46
 * @method PhotoSize[]             getPhoto()                   Optional. Message is a photo, available sizes of the photo
47
 * @method Sticker                 getSticker()                 Optional. Message is a sticker, information about the sticker
48
 * @method Video                   getVideo()                   Optional. Message is a video, information about the video
49
 * @method Voice                   getVoice()                   Optional. Message is a voice message, information about the file
50
 * @method VideoNote               getVideoNote()               Optional. Message is a video note message, information about the video
51
 * @method string                  getCaption()                 Optional. Caption for the document, photo or video, 0-200 characters
52
 * @method Contact                 getContact()                 Optional. Message is a shared contact, information about the contact
53
 * @method Location                getLocation()                Optional. Message is a shared location, information about the location
54
 * @method Venue                   getVenue()                   Optional. Message is a venue, information about the venue
55
 * @method Poll                    getPoll()                    Optional. Message is a native poll, information about the poll
56
 * @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
57
 * @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)
58
 * @method User                    getLeftChatMember()          Optional. A member was removed from the group, information about them (this member may be the bot itself)
59
 * @method string                  getNewChatTitle()            Optional. A chat title was changed to this value
60
 * @method PhotoSize[]             getNewChatPhoto()            Optional. A chat photo was changed to this value
61
 * @method bool                    getDeleteChatPhoto()         Optional. Service message: the chat photo was deleted
62
 * @method bool                    getGroupChatCreated()        Optional. Service message: the group has been created
63
 * @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.
64
 * @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.
65
 * @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.
66
 * @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.
67
 * @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.
68
 * @method Invoice                 getInvoice()                 Optional. Message is an invoice for a payment, information about the invoice.
69
 * @method SuccessfulPayment       getSuccessfulPayment()       Optional. Message is a service message about a successful payment, information about the payment.
70
 * @method string                  getConnectedWebsite()        Optional. The domain name of the website on which the user has logged in.
71
 * @method PassportData            getPassportData()            Optional. Telegram Passport data
72
 * @method ProximityAlertTriggered getProximityAlertTriggered() Optional. Service message. A user in the chat triggered another user's proximity alert while sharing Live Location.
73
 * @method InlineKeyboard          getReplyMarkup()             Optional. Inline keyboard attached to the message. login_url buttons are represented as ordinary url buttons.
74
 */
75
class Message extends Entity
76
{
77
    /**
78
     * {@inheritdoc}
79
     */
80 11
    protected function subEntities(): array
81
    {
82
        return [
83 11
            'from'                      => User::class,
84
            'sender_chat'               => Chat::class,
85
            'chat'                      => Chat::class,
86
            'forward_from'              => User::class,
87
            'forward_from_chat'         => Chat::class,
88
            'reply_to_message'          => ReplyToMessage::class,
89
            'via_bot'                   => User::class,
90
            'entities'                  => [MessageEntity::class],
91
            'caption_entities'          => [MessageEntity::class],
92
            'audio'                     => Audio::class,
93
            'document'                  => Document::class,
94
            'animation'                 => Animation::class,
95
            'game'                      => Game::class,
96
            'photo'                     => [PhotoSize::class],
97
            'sticker'                   => Sticker::class,
98
            'video'                     => Video::class,
99
            'voice'                     => Voice::class,
100
            'video_note'                => VideoNote::class,
101
            'contact'                   => Contact::class,
102
            'location'                  => Location::class,
103
            'venue'                     => Venue::class,
104
            'poll'                      => Poll::class,
105
            'dice'                      => Dice::class,
106
            'new_chat_members'          => [User::class],
107
            'left_chat_member'          => User::class,
108
            'new_chat_photo'            => [PhotoSize::class],
109
            'pinned_message'            => Message::class,
110
            'invoice'                   => Invoice::class,
111
            'successful_payment'        => SuccessfulPayment::class,
112
            'passport_data'             => PassportData::class,
113
            'proximity_alert_triggered' => ProximityAlertTriggered::class,
114
            'reply_markup'              => InlineKeyboard::class,
115
        ];
116
    }
117
118
    /**
119
     * return the entire command like /echo or /echo@bot1 if specified
120
     *
121
     * @return string|null
122
     */
123 2
    public function getFullCommand(): ?string
124
    {
125 2
        $text = $this->getProperty('text');
126 2
        if (strpos($text, '/') !== 0) {
127 2
            return null;
128
        }
129
130 2
        $no_EOL   = strtok($text, PHP_EOL);
131 2
        $no_space = strtok($text, ' ');
132
133
        //try to understand which separator \n or space divide /command from text
134 2
        return strlen($no_space) < strlen($no_EOL) ? $no_space : $no_EOL;
135
    }
136
137
    /**
138
     * Get command
139
     *
140
     * @return string|null
141
     */
142 2
    public function getCommand(): ?string
143
    {
144 2
        if ($command = $this->getProperty('command')) {
145
            return $command;
146
        }
147
148 2
        $full_command = $this->getFullCommand();
149 2
        if (strpos($full_command, '/') !== 0) {
150 2
            return null;
151
        }
152 2
        $full_command = substr($full_command, 1);
153
154
        //check if command is followed by bot username
155 2
        $split_cmd = explode('@', $full_command);
156 2
        if (!isset($split_cmd[1])) {
157
            //command is not followed by name
158 2
            return $full_command;
159
        }
160
161 1
        if (strtolower($split_cmd[1]) === strtolower($this->getBotUsername())) {
162
            //command is addressed to me
163 1
            return $split_cmd[0];
164
        }
165
166
        return null;
167
    }
168
169
    /**
170
     * For text messages, the actual UTF-8 text of the message, 0-4096 characters.
171
     *
172
     * @param bool $without_cmd
173
     *
174
     * @return string|null
175
     */
176 9
    public function getText($without_cmd = false): ?string
177
    {
178 9
        $text = $this->getProperty('text');
179
180 9
        if ($without_cmd && $command = $this->getFullCommand()) {
181 1
            if (strlen($command) + 1 < strlen($text)) {
182 1
                return substr($text, strlen($command) + 1);
183
            }
184
185 1
            return '';
186
        }
187
188 9
        return $text;
189
    }
190
191
    /**
192
     * Bot added in chat
193
     *
194
     * @return bool
195
     */
196
    public function botAddedInChat(): bool
197
    {
198
        foreach ($this->getNewChatMembers() as $member) {
0 ignored issues
show
Bug introduced by
The method getNewChatMembers() does not exist on Longman\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

198
        foreach ($this->/** @scrutinizer ignore-call */ getNewChatMembers() as $member) {
Loading history...
199
            if ($member instanceof User && $member->getUsername() === $this->getBotUsername()) {
200
                return true;
201
            }
202
        }
203
204
        return false;
205
    }
206
207
    /**
208
     * Detect type based on properties.
209
     *
210
     * @return string
211
     */
212 1
    public function getType(): string
213
    {
214
        $types = [
215 1
            'text',
216
            'audio',
217
            'animation',
218
            'document',
219
            'game',
220
            'photo',
221
            'sticker',
222
            'video',
223
            'voice',
224
            'video_note',
225
            'contact',
226
            'location',
227
            'venue',
228
            'poll',
229
            'new_chat_members',
230
            'left_chat_member',
231
            'new_chat_title',
232
            'new_chat_photo',
233
            'delete_chat_photo',
234
            'group_chat_created',
235
            'supergroup_chat_created',
236
            'channel_chat_created',
237
            'migrate_to_chat_id',
238
            'migrate_from_chat_id',
239
            'pinned_message',
240
            'invoice',
241
            'successful_payment',
242
            'passport_data',
243
            'proximity_alert_triggered',
244
            'reply_markup',
245
        ];
246
247 1
        $is_command = strlen($this->getCommand()) > 0;
248 1
        foreach ($types as $type) {
249 1
            if ($this->getProperty($type) !== null) {
250 1
                if ($is_command && $type === 'text') {
251 1
                    return 'command';
252
                }
253
254 1
                return $type;
255
            }
256
        }
257
258 1
        return 'message';
259
    }
260
}
261