Skip to content

Instantly share code, notes, and snippets.

@chuv1
Last active May 1, 2017 22:26
Show Gist options
  • Save chuv1/5eb2a7c7849d225b1e230a1ad0fd704d to your computer and use it in GitHub Desktop.
Save chuv1/5eb2a7c7849d225b1e230a1ad0fd704d to your computer and use it in GitHub Desktop.
Authorise you website users with Telegram bot.

Using https://github.com/php-telegram-bot

First.

Create some script that will issue tokens for users and will check if user logged in when asked.

auth.php

<?php

date_default_timezone_set('Asia/Bangkok');
define('users_db',__DIR__'/users.db3');

function getAuth($seed){

    try{

      $db = new PDO('sqlite:'.users_db);
      $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

      $query = "SELECT * FROM logins WHERE seed = '".$seed."' AND loginTime != '' AND tid != ''";

      $result = $db->query($query)->fetchAll(PDO::FETCH_ASSOC);

    }
    catch (PDOException $e){

      $result = $e->getMessage();

    }

    return $result[0];
}

function setAuth($seed){

    try{

      $db = new PDO('sqlite:'.users_db);
      $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

      $query = "INSERT INTO logins (seed, tid, tun, loginTime) VALUES (:seed, :tid, :tun, :loginTime)";

      $query = $db->prepare($query);

      $query->bindValue(':seed', $seed, PDO::PARAM_STR);
      $query->bindValue(':tid', null);
      $query->bindValue(':tun', null);
      $query->bindValue(':loginTime', null);

      $result = $query->execute();

    }
    catch (PDOException $e){

      $result = $e->getMessage();

    }

    return $result;
  }


if(isset($_GET['auth']) && empty($_GET['auth'])){

    $seed = md5(rand()*rand()/rand());

    setcookie('auth',$seed,(time()+86400*7),'/');
    $auth = setAuth($seed);

    die($auth?json_encode(['auth'=>$seed]):json_encode(['error'=>'Set Auth Error']));

  }
  elseif(isset($_GET['auth']) && $_GET['auth'] == 'check' && !empty($_COOKIE['auth'])){

    $auth = getAuth($_COOKIE['auth']);
    if(!empty($auth)) die(json_encode($auth));
    else              die(json_encode(['error'=>'Not Authorised']));

  }
  elseif(isset($_GET['auth']) && $_GET['auth'] == 'check' && empty($_COOKIE['auth'])){
    die(json_encode(['error'=>'cookie error']));
  }
  elseif(isset($_GET['logout'])){
    setcookie('auth',null,(time()-86400*7),'/');
    die(json_encode(['logout'=>true]));
  }

?>

Second

Add JS code to handle logins on website

login.js

document.onreadystatechange = function() {

	if(document.readyState !== "interactive") return false;
	$("#auth").on('click',function(){

	wd.authButton = typeof wd.authButton === 'undefined' ? $(this) : wd.authButton;

	function iframeDataURITest(src) {
		var support,
		    iframe = document.createElement('iframe');

		iframe.style.display = 'none';
		iframe.setAttribute('src', src);

		document.body.appendChild(iframe);

		try {
			support = !!iframe.contentDocument;
		} catch (e) {
			support = false;
		}

		document.body.removeChild(iframe);

		return support;
	}

	if(!wd.user){

			// This timer starts as soon as user clicks login button and checks each second if user pushed start in the bot
		var checkTimer = setInterval(function(){
			if(wd.user == false){
				wd.checkStatus();
			}else{

				typeof wd.loginPopup !== 'undefined' && wd.loginPopup.close() ;

				wd.authButton.find('span').text(wd.user.tun != '' ? wd.user.tun.replace('@',''):'%username%');
				wd.authButton.find('img').attr('src','img/icons/user.svg');
				wd.authButton.addClass('phoogleGreen').removeClass('blue');

				clearInterval(checkTimer);
			}
		}, 1000);
			$.getJSON('/auth.php?auth', function (data) {

				if(typeof data.auth !== 'undefined'){
					if(iframeDataURITest('tg://resolve?domain=PhoogleBot&start='+data.auth)){
						console.log('Telegram found');
					}else{
						wd.loginPopup = window.open('https://telegram.me/PhoogleBot?start='+data.auth, '_blank', 'location=no,height=600,width=520,scrollbars=no,status=no');
					}
				}

			});
		}
		else{
			wd.authButton.next().toggleClass('hidden');
		}

	});
	
	$("#logout").on('click',function(e){
	
		e.stopPropagation();
		wd.authButton = typeof wd.authButton === 'undefined' ? $("#auth") : wd.authButton;

		$.getJSON('/auth.php?logout', function (data) {

		if(typeof data.logout !== 'undefined'){
			if(wd.user){

				wd.user = false;
				wd.authButton.find('span').text('Авторизоваться');
				wd.authButton.find('img').attr('src','img/icons/telegram.svg');
				wd.authButton.addClass('blue').removeClass('green');

			}
		}

		});

		wd.authButton.next().toggleClass('hidden');
	});

};

Third

Now catch /start with token payload in your bot and add this user to DB. I do it like this in my StartCommand.php in execute() section

if(preg_match('/^[a-f0-9]{32}$/i', $message_text)){

    try{

      $db = new PDO('sqlite:'.$this->users_db);
      $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

      $query = "UPDATE logins SET tid = :tid, tun = :tun, loginTime = :loginTime WHERE seed = :seed";

      $query = $db->prepare($query);

      $query->bindValue(':seed', $message_text, PDO::PARAM_STR);
      $query->bindValue(':tid', $message->getFrom()->getId(), PDO::PARAM_INT);
      $query->bindValue(':tun', $message->getFrom()->tryMention(), PDO::PARAM_STR);
      $query->bindValue(':loginTime', time(), PDO::PARAM_INT);

      $result = $query->execute();

    }
    catch (PDOException $e){

      $result = false;

    }

    if($result){
      // Sending "You are logged in" message
      $text = "Привет, ".$message->getFrom()->tryMention(true)."! Живи долго и процветай!".PHP_EOL."Можешь вернуться на сайт. Он тебя уже должен был опознать.";
    }
    else{
      // Sending Error message
      $text = "Привет, ".$message->getFrom()->tryMention(true)."! Ой, облом!".PHP_EOL."Ну в смысле что-то не сработало. Хозяин оповещён.";
    }

    $data = [
        'chat_id'             => $chat_id,
        'parse_mode'          => 'Markdown',
        'reply_markup'        => Keyboard::remove(['selective' => false]),
        'text'                => $text,
    ];

    $command_result = Request::sendMessage($data);
  }

That's all.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment