Skip to content

Commit

Permalink
Add Telegram Login event
Browse files Browse the repository at this point in the history
  • Loading branch information
mpociot committed Feb 9, 2018
1 parent f85085a commit 0e8f151
Show file tree
Hide file tree
Showing 2 changed files with 204 additions and 2 deletions.
50 changes: 48 additions & 2 deletions src/TelegramDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,15 @@ class TelegramDriver extends HttpDriver
const DRIVER_NAME = 'Telegram';
const API_URL = 'https://api.telegram.org/bot';
const FILE_API_URL = 'https://api.telegram.org/file/bot';
const LOGIN_EVENT = 'telegram_login';

protected $endpoint = 'sendMessage';

protected $messages = [];

/** @var Collection */
protected $queryParameters;

/**
* @param Request $request
*/
Expand All @@ -38,6 +42,7 @@ public function buildPayload(Request $request)
$this->payload = new ParameterBag((array) json_decode($request->getContent(), true));
$this->event = Collection::make($this->payload->get('message'));
$this->config = Collection::make($this->config->get('telegram'));
$this->queryParameters = Collection::make($request->query);
}

/**
Expand Down Expand Up @@ -86,6 +91,12 @@ public function matchesRequest()
public function hasMatchingEvent()
{
$event = false;

if ($this->isValidLoginRequest()) {
$event = new GenericEvent($this->queryParameters->except('hash'));
$event->setName(self::LOGIN_EVENT);
}

if ($this->event->has('new_chat_members')) {
$event = new GenericEvent($this->event->get('new_chat_members'));
$event->setName('new_chat_members');
Expand All @@ -109,6 +120,39 @@ public function hasMatchingEvent()
return $event;
}

/**
* Check if the query parameters contain information about a
* valid Telegram login request.
*
* @return bool
*/
protected function isValidLoginRequest()
{
$check_hash = $this->queryParameters->get('hash');

// Get sorted array of values
$check = $this->queryParameters
->except('hash')
->map(function($value, $key) {
return $key . '=' . $value;
})
->values()
->sort();
$check_string = implode("\n", $check->toArray());

$secret = hash('sha256', $this->config->get('token'), true);
$hash = hash_hmac('sha256', $check_string, $secret);

if (strcmp($hash, $check_hash) !== 0) {
return false;
}
if ((time() - $this->queryParameters->get('auth_date')) > 86400) {
return false;
}

return true;
}

/**
* This hide the inline keyboard, if is an interactive message.
*/
Expand Down Expand Up @@ -157,8 +201,6 @@ public function getMessages()

/**
* Load Telegram messages.
*
* @return array
*/
public function loadMessages()
{
Expand All @@ -169,6 +211,10 @@ public function loadMessages()
new IncomingMessage($callback->get('data'), $callback->get('from')['id'],
$callback->get('message')['chat']['id'], $callback->get('message')),
];
} elseif ($this->isValidLoginRequest()) {
$messages = [
new IncomingMessage('', $this->queryParameters->get('id'), $this->queryParameters->get('id'), $this->queryParameters),
];
} else {
$messages = [
new IncomingMessage($this->event->get('text'), $this->event->get('from')['id'], $this->event->get('chat')['id'],
Expand Down
156 changes: 156 additions & 0 deletions tests/TelegramDriverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Tests;

use Illuminate\Support\Collection;
use Mockery as m;
use BotMan\BotMan\Http\Curl;
use BotMan\BotMan\Users\User;
Expand Down Expand Up @@ -207,6 +208,161 @@ public function it_calls_left_chat_member_event()
$this->assertSame('Marcel', $event->getPayload()['first_name']);
}

/** @test */
public function it_calls_telegram_login_event()
{
$token = 'randomtoken';

$queryParameters = [
'id' => '12345',
'first_name' => 'Marcel',
'last_name' => 'Pociot',
'username' => 'marcelpociot',
'photo_url' => 'https://some/picture.jpg',
'auth_date' => time()
];

// Calculate hash
$check = Collection::make($queryParameters)
->except('hash')
->map(function($value, $key) {
return $key . '=' . $value;
})
->values()
->sort();
$check_string = implode("\n", $check->toArray());

$secret = hash('sha256', $token, true);
$hash = hash_hmac('sha256', $check_string, $secret);

$queryParameters['hash'] = $hash;

$request = new Request($queryParameters);

$driver = new TelegramDriver($request, [
'telegram' => [
'token' => $token
]
], m::mock(Curl::class));

$event = $driver->hasMatchingEvent();
$this->assertInstanceOf(GenericEvent::class, $event);
$this->assertSame(TelegramDriver::LOGIN_EVENT, $event->getName());
$this->assertSame('12345', $event->getPayload()['id']);
$this->assertSame('Marcel', $event->getPayload()['first_name']);
$this->assertSame('Pociot', $event->getPayload()['last_name']);
$this->assertSame('marcelpociot', $event->getPayload()['username']);
$this->assertSame('https://some/picture.jpg', $event->getPayload()['photo_url']);
}

/** @test */
public function it_does_not_call_telegram_login_event_with_outdated_auth_date()
{
$token = 'randomtoken';

$queryParameters = [
'id' => '12345',
'first_name' => 'Marcel',
'last_name' => 'Pociot',
'username' => 'marcelpociot',
'photo_url' => 'https://some/picture.jpg',
'auth_date' => time() - 90000
];

// Calculate hash
$check = Collection::make($queryParameters)
->except('hash')
->map(function($value, $key) {
return $key . '=' . $value;
})
->values()
->sort();
$check_string = implode("\n", $check->toArray());

$secret = hash('sha256', $token, true);
$hash = hash_hmac('sha256', $check_string, $secret);

$queryParameters['hash'] = $hash;

$request = new Request($queryParameters);

$driver = new TelegramDriver($request, [
'telegram' => [
'token' => $token
]
], m::mock(Curl::class));

$this->assertFalse($driver->hasMatchingEvent());
}

/** @test */
public function it_does_not_call_telegram_login_event_with_invalid_hash()
{
$token = 'randomtoken';

$queryParameters = [
'id' => '12345',
'first_name' => 'Marcel',
'last_name' => 'Pociot',
'username' => 'marcelpociot',
'photo_url' => 'https://some/picture.jpg',
'auth_date' => time(),
'hash' => 'kajhsdkjhaskjdh'
];

$request = new Request($queryParameters);

$driver = new TelegramDriver($request, [
'telegram' => [
'token' => $token
]
], m::mock(Curl::class));

$this->assertFalse($driver->hasMatchingEvent());
}

/** @test */
public function telegram_login_event_has_the_correct_chat_id()
{
$token = 'randomtoken';

$queryParameters = [
'id' => '12345',
'first_name' => 'Marcel',
'last_name' => 'Pociot',
'username' => 'marcelpociot',
'photo_url' => 'https://some/picture.jpg',
'auth_date' => time()
];

// Calculate hash
$check = Collection::make($queryParameters)
->except('hash')
->map(function($value, $key) {
return $key . '=' . $value;
})
->values()
->sort();
$check_string = implode("\n", $check->toArray());

$secret = hash('sha256', $token, true);
$hash = hash_hmac('sha256', $check_string, $secret);

$queryParameters['hash'] = $hash;

$request = new Request($queryParameters);

$driver = new TelegramDriver($request, [
'telegram' => [
'token' => $token
]
], m::mock(Curl::class));

$message = $driver->getMessages();

$this->assertSame('12345', $message[0]->getSender());
}

/** @test */
public function it_calls_new_chat_title_event()
{
Expand Down

0 comments on commit 0e8f151

Please sign in to comment.