Skip to content

Commit 0e8f151

Browse files
committed
Add Telegram Login event
1 parent f85085a commit 0e8f151

File tree

2 files changed

+204
-2
lines changed

2 files changed

+204
-2
lines changed

src/TelegramDriver.php

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,15 @@ class TelegramDriver extends HttpDriver
2525
const DRIVER_NAME = 'Telegram';
2626
const API_URL = 'https://api.telegram.org/bot';
2727
const FILE_API_URL = 'https://api.telegram.org/file/bot';
28+
const LOGIN_EVENT = 'telegram_login';
2829

2930
protected $endpoint = 'sendMessage';
3031

3132
protected $messages = [];
3233

34+
/** @var Collection */
35+
protected $queryParameters;
36+
3337
/**
3438
* @param Request $request
3539
*/
@@ -38,6 +42,7 @@ public function buildPayload(Request $request)
3842
$this->payload = new ParameterBag((array) json_decode($request->getContent(), true));
3943
$this->event = Collection::make($this->payload->get('message'));
4044
$this->config = Collection::make($this->config->get('telegram'));
45+
$this->queryParameters = Collection::make($request->query);
4146
}
4247

4348
/**
@@ -86,6 +91,12 @@ public function matchesRequest()
8691
public function hasMatchingEvent()
8792
{
8893
$event = false;
94+
95+
if ($this->isValidLoginRequest()) {
96+
$event = new GenericEvent($this->queryParameters->except('hash'));
97+
$event->setName(self::LOGIN_EVENT);
98+
}
99+
89100
if ($this->event->has('new_chat_members')) {
90101
$event = new GenericEvent($this->event->get('new_chat_members'));
91102
$event->setName('new_chat_members');
@@ -109,6 +120,39 @@ public function hasMatchingEvent()
109120
return $event;
110121
}
111122

123+
/**
124+
* Check if the query parameters contain information about a
125+
* valid Telegram login request.
126+
*
127+
* @return bool
128+
*/
129+
protected function isValidLoginRequest()
130+
{
131+
$check_hash = $this->queryParameters->get('hash');
132+
133+
// Get sorted array of values
134+
$check = $this->queryParameters
135+
->except('hash')
136+
->map(function($value, $key) {
137+
return $key . '=' . $value;
138+
})
139+
->values()
140+
->sort();
141+
$check_string = implode("\n", $check->toArray());
142+
143+
$secret = hash('sha256', $this->config->get('token'), true);
144+
$hash = hash_hmac('sha256', $check_string, $secret);
145+
146+
if (strcmp($hash, $check_hash) !== 0) {
147+
return false;
148+
}
149+
if ((time() - $this->queryParameters->get('auth_date')) > 86400) {
150+
return false;
151+
}
152+
153+
return true;
154+
}
155+
112156
/**
113157
* This hide the inline keyboard, if is an interactive message.
114158
*/
@@ -157,8 +201,6 @@ public function getMessages()
157201

158202
/**
159203
* Load Telegram messages.
160-
*
161-
* @return array
162204
*/
163205
public function loadMessages()
164206
{
@@ -169,6 +211,10 @@ public function loadMessages()
169211
new IncomingMessage($callback->get('data'), $callback->get('from')['id'],
170212
$callback->get('message')['chat']['id'], $callback->get('message')),
171213
];
214+
} elseif ($this->isValidLoginRequest()) {
215+
$messages = [
216+
new IncomingMessage('', $this->queryParameters->get('id'), $this->queryParameters->get('id'), $this->queryParameters),
217+
];
172218
} else {
173219
$messages = [
174220
new IncomingMessage($this->event->get('text'), $this->event->get('from')['id'], $this->event->get('chat')['id'],

tests/TelegramDriverTest.php

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Tests;
44

5+
use Illuminate\Support\Collection;
56
use Mockery as m;
67
use BotMan\BotMan\Http\Curl;
78
use BotMan\BotMan\Users\User;
@@ -207,6 +208,161 @@ public function it_calls_left_chat_member_event()
207208
$this->assertSame('Marcel', $event->getPayload()['first_name']);
208209
}
209210

211+
/** @test */
212+
public function it_calls_telegram_login_event()
213+
{
214+
$token = 'randomtoken';
215+
216+
$queryParameters = [
217+
'id' => '12345',
218+
'first_name' => 'Marcel',
219+
'last_name' => 'Pociot',
220+
'username' => 'marcelpociot',
221+
'photo_url' => 'https://some/picture.jpg',
222+
'auth_date' => time()
223+
];
224+
225+
// Calculate hash
226+
$check = Collection::make($queryParameters)
227+
->except('hash')
228+
->map(function($value, $key) {
229+
return $key . '=' . $value;
230+
})
231+
->values()
232+
->sort();
233+
$check_string = implode("\n", $check->toArray());
234+
235+
$secret = hash('sha256', $token, true);
236+
$hash = hash_hmac('sha256', $check_string, $secret);
237+
238+
$queryParameters['hash'] = $hash;
239+
240+
$request = new Request($queryParameters);
241+
242+
$driver = new TelegramDriver($request, [
243+
'telegram' => [
244+
'token' => $token
245+
]
246+
], m::mock(Curl::class));
247+
248+
$event = $driver->hasMatchingEvent();
249+
$this->assertInstanceOf(GenericEvent::class, $event);
250+
$this->assertSame(TelegramDriver::LOGIN_EVENT, $event->getName());
251+
$this->assertSame('12345', $event->getPayload()['id']);
252+
$this->assertSame('Marcel', $event->getPayload()['first_name']);
253+
$this->assertSame('Pociot', $event->getPayload()['last_name']);
254+
$this->assertSame('marcelpociot', $event->getPayload()['username']);
255+
$this->assertSame('https://some/picture.jpg', $event->getPayload()['photo_url']);
256+
}
257+
258+
/** @test */
259+
public function it_does_not_call_telegram_login_event_with_outdated_auth_date()
260+
{
261+
$token = 'randomtoken';
262+
263+
$queryParameters = [
264+
'id' => '12345',
265+
'first_name' => 'Marcel',
266+
'last_name' => 'Pociot',
267+
'username' => 'marcelpociot',
268+
'photo_url' => 'https://some/picture.jpg',
269+
'auth_date' => time() - 90000
270+
];
271+
272+
// Calculate hash
273+
$check = Collection::make($queryParameters)
274+
->except('hash')
275+
->map(function($value, $key) {
276+
return $key . '=' . $value;
277+
})
278+
->values()
279+
->sort();
280+
$check_string = implode("\n", $check->toArray());
281+
282+
$secret = hash('sha256', $token, true);
283+
$hash = hash_hmac('sha256', $check_string, $secret);
284+
285+
$queryParameters['hash'] = $hash;
286+
287+
$request = new Request($queryParameters);
288+
289+
$driver = new TelegramDriver($request, [
290+
'telegram' => [
291+
'token' => $token
292+
]
293+
], m::mock(Curl::class));
294+
295+
$this->assertFalse($driver->hasMatchingEvent());
296+
}
297+
298+
/** @test */
299+
public function it_does_not_call_telegram_login_event_with_invalid_hash()
300+
{
301+
$token = 'randomtoken';
302+
303+
$queryParameters = [
304+
'id' => '12345',
305+
'first_name' => 'Marcel',
306+
'last_name' => 'Pociot',
307+
'username' => 'marcelpociot',
308+
'photo_url' => 'https://some/picture.jpg',
309+
'auth_date' => time(),
310+
'hash' => 'kajhsdkjhaskjdh'
311+
];
312+
313+
$request = new Request($queryParameters);
314+
315+
$driver = new TelegramDriver($request, [
316+
'telegram' => [
317+
'token' => $token
318+
]
319+
], m::mock(Curl::class));
320+
321+
$this->assertFalse($driver->hasMatchingEvent());
322+
}
323+
324+
/** @test */
325+
public function telegram_login_event_has_the_correct_chat_id()
326+
{
327+
$token = 'randomtoken';
328+
329+
$queryParameters = [
330+
'id' => '12345',
331+
'first_name' => 'Marcel',
332+
'last_name' => 'Pociot',
333+
'username' => 'marcelpociot',
334+
'photo_url' => 'https://some/picture.jpg',
335+
'auth_date' => time()
336+
];
337+
338+
// Calculate hash
339+
$check = Collection::make($queryParameters)
340+
->except('hash')
341+
->map(function($value, $key) {
342+
return $key . '=' . $value;
343+
})
344+
->values()
345+
->sort();
346+
$check_string = implode("\n", $check->toArray());
347+
348+
$secret = hash('sha256', $token, true);
349+
$hash = hash_hmac('sha256', $check_string, $secret);
350+
351+
$queryParameters['hash'] = $hash;
352+
353+
$request = new Request($queryParameters);
354+
355+
$driver = new TelegramDriver($request, [
356+
'telegram' => [
357+
'token' => $token
358+
]
359+
], m::mock(Curl::class));
360+
361+
$message = $driver->getMessages();
362+
363+
$this->assertSame('12345', $message[0]->getSender());
364+
}
365+
210366
/** @test */
211367
public function it_calls_new_chat_title_event()
212368
{

0 commit comments

Comments
 (0)