|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/** |
|
4
|
|
|
* Client class for Telegram Bot-API. Can be used for running bots in two supported modes: |
|
5
|
|
|
* daemon listener mode and webhook mode. Can easily be instantiated in any place of your application. |
|
6
|
|
|
* |
|
7
|
|
|
* @package Teebot (Telegram bot framework) |
|
8
|
|
|
* |
|
9
|
|
|
* @author Stanislav Drozdov <[email protected]> |
|
10
|
|
|
*/ |
|
11
|
|
|
|
|
12
|
|
|
namespace Teebot; |
|
13
|
|
|
|
|
14
|
|
|
use Teebot\Method\GetUpdates; |
|
15
|
|
|
use Teebot\Command\Executor; |
|
16
|
|
|
use Teebot\Exception\Fatal; |
|
17
|
|
|
use Teebot\Exception\Output; |
|
18
|
|
|
|
|
19
|
|
|
class Client |
|
20
|
|
|
{ |
|
21
|
|
|
/** |
|
22
|
|
|
* @var Executor $executor Executor object |
|
23
|
|
|
*/ |
|
24
|
|
|
protected $executor; |
|
25
|
|
|
|
|
26
|
|
|
/** @var int $timeout getUpdates timeout and sleep timer for the listener */ |
|
27
|
|
|
protected $timeout; |
|
28
|
|
|
|
|
29
|
|
|
protected $cliOptions = [ |
|
30
|
|
|
'short' => 'n:c:', |
|
31
|
|
|
'long' => ['name:', 'config'] |
|
32
|
|
|
]; |
|
33
|
|
|
|
|
34
|
|
|
/** |
|
35
|
|
|
* Constructs Client instance and initialises configuration and default values. |
|
36
|
|
|
* |
|
37
|
|
|
* @param array $args Array of arguments to create the client, otherwise arguments from command line |
|
38
|
|
|
* will be used. |
|
39
|
|
|
*/ |
|
40
|
|
|
public function __construct($args = []) |
|
41
|
|
|
{ |
|
42
|
|
|
if (empty($args)) { |
|
43
|
|
|
$args = getopt($this->cliOptions['short'], $this->cliOptions['long']); |
|
44
|
|
|
} |
|
45
|
|
|
|
|
46
|
|
|
$this->init($args); |
|
47
|
|
|
} |
|
48
|
|
|
|
|
49
|
|
|
/** |
|
50
|
|
|
* Initialises the client and loads Configuration. |
|
51
|
|
|
* |
|
52
|
|
|
* @param array $args Array of initialisation arguments |
|
53
|
|
|
*/ |
|
54
|
|
|
protected function init($args) { |
|
55
|
|
|
$botName = $this->getBotName($args); |
|
56
|
|
|
$botConfig = $this->getBotConfig($args); |
|
57
|
|
|
|
|
58
|
|
|
if (!$botName && !$botConfig) { |
|
59
|
|
|
Output::log(new Fatal("Bot name or config should be specified!")); |
|
60
|
|
|
} |
|
61
|
|
|
|
|
62
|
|
|
$config = new Config($botName, $botConfig); |
|
63
|
|
|
$this->timeout = $config->getTimeout(); |
|
64
|
|
|
|
|
65
|
|
|
$this->executor = Executor::getInstance(); |
|
66
|
|
|
$this->executor->initWithConfig($config); |
|
67
|
|
|
} |
|
68
|
|
|
|
|
69
|
|
|
/** |
|
70
|
|
|
* Returns bot name from initialisation arguments |
|
71
|
|
|
* |
|
72
|
|
|
* @param array $args Array with initialisation values |
|
73
|
|
|
* |
|
74
|
|
|
* @return string |
|
75
|
|
|
*/ |
|
76
|
|
|
protected function getBotName($args) |
|
77
|
|
|
{ |
|
78
|
|
|
return $args['n'] ?? $args['name'] ?? ''; |
|
79
|
|
|
} |
|
80
|
|
|
|
|
81
|
|
|
/** |
|
82
|
|
|
* Returns configuration file path from initialisation arguments |
|
83
|
|
|
* |
|
84
|
|
|
* @param array $args Array with initialisation values |
|
85
|
|
|
* |
|
86
|
|
|
* @return string |
|
87
|
|
|
*/ |
|
88
|
|
|
protected function getBotConfig($args) |
|
89
|
|
|
{ |
|
90
|
|
|
return $args['c'] ?? $args['config'] ?? ''; |
|
91
|
|
|
} |
|
92
|
|
|
|
|
93
|
|
|
/** |
|
94
|
|
|
* Requests and returns the latest updates from Telegram's API server |
|
95
|
|
|
* |
|
96
|
|
|
* @param int $offset Offset for the updates list |
|
97
|
|
|
* @param int $limit Limit of the updates to get |
|
98
|
|
|
* @param bool $silentMode If set to true then the events, mapped (in config or by default) to |
|
99
|
|
|
* the entities in the result will not be triggered |
|
100
|
|
|
* @return Response |
|
101
|
|
|
*/ |
|
102
|
|
|
public function getUpdates($offset = Config::DEFAULT_LIMIT, $limit = Config::DEFAULT_OFFSET, $silentMode = false) |
|
103
|
|
|
{ |
|
104
|
|
|
$method = (new GetUpdates()) |
|
105
|
|
|
->setOffset($offset) |
|
106
|
|
|
->setLimit($limit) |
|
107
|
|
|
->setTimeout($this->timeout); |
|
108
|
|
|
|
|
109
|
|
|
return $this->executor->callRemoteMethod($method, $silentMode); |
|
110
|
|
|
} |
|
111
|
|
|
|
|
112
|
|
|
/** |
|
113
|
|
|
* Flushes the results and resets the offset pointer to the latest updates. Returns last offset. |
|
114
|
|
|
* Should be used to skip previous results from dialogs during first listener's start, should not |
|
115
|
|
|
* be used for webhook. |
|
116
|
|
|
* |
|
117
|
|
|
* @return int |
|
118
|
|
|
*/ |
|
119
|
|
|
public function flush() |
|
120
|
|
|
{ |
|
121
|
|
|
$response = $this->getUpdates(Config::DEFAULT_OFFSET, Config::DEFAULT_LIMIT, true); |
|
122
|
|
|
|
|
123
|
|
|
return $response instanceof Response ? $response->getOffset() : -1; |
|
124
|
|
|
} |
|
125
|
|
|
|
|
126
|
|
|
/** |
|
127
|
|
|
* Starts listener daemon for getting the updates from the chats. Should be used if webhook is not set. |
|
128
|
|
|
*/ |
|
129
|
|
|
public function listen() |
|
130
|
|
|
{ |
|
131
|
|
|
$offset = $this->flush(); |
|
132
|
|
|
|
|
133
|
|
|
while (1) { |
|
134
|
|
|
$response = $this->getUpdates($offset); |
|
135
|
|
|
|
|
136
|
|
|
if ($response instanceof Response) { |
|
137
|
|
|
$offset = $response->getOffset(); |
|
138
|
|
|
} |
|
139
|
|
|
|
|
140
|
|
|
sleep($this->timeout); |
|
141
|
|
|
} |
|
142
|
|
|
} |
|
143
|
|
|
|
|
144
|
|
|
/** |
|
145
|
|
|
* Returns Response object built from received data. Method should be used if |
|
146
|
|
|
* bot is running in webhook mode. |
|
147
|
|
|
* |
|
148
|
|
|
* @param array $receivedData Received data from Telegram's webhook call. Not required, but could |
|
149
|
|
|
* be passed manually. If not passed - php input will be used to get the data. |
|
150
|
|
|
* @param bool $silentMode If set to true then the events, mapped to |
|
151
|
|
|
* the entities in the result will not be triggered |
|
152
|
|
|
* @return Response |
|
153
|
|
|
*/ |
|
154
|
|
|
public function webhook($receivedData = [], $silentMode = false) |
|
155
|
|
|
{ |
|
156
|
|
|
if (empty($receivedData)) { |
|
157
|
|
|
$receivedData = file_get_contents("php://input"); |
|
158
|
|
|
} |
|
159
|
|
|
|
|
160
|
|
|
if (empty($receivedData)) { |
|
161
|
|
|
return null; |
|
162
|
|
|
} |
|
163
|
|
|
|
|
164
|
|
|
return $this->executor->getWebhookResponse($receivedData, $silentMode); |
|
|
|
|
|
|
165
|
|
|
} |
|
166
|
|
|
} |
|
167
|
|
|
|
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.