Commit a8ea577f authored by MBoretto's avatar MBoretto

tracking works

parent 57ed52b8
......@@ -161,7 +161,6 @@ abstract class Command
return Request::sendMessage($data)->isOk();
}
/**
* Get update object
*
......
......@@ -10,6 +10,7 @@
namespace Longman\TelegramBot\Commands\SystemCommands;
use Longman\TelegramBot\Tracking;
use Longman\TelegramBot\Commands\SystemCommand;
/**
......@@ -23,8 +24,20 @@ class GenericmessageCommand extends SystemCommand
protected $name = 'Genericmessage';
protected $description = 'Handle generic message';
protected $version = '1.0.1';
protected $need_mysql = true;
/**#@-*/
/**
* Execution if MySQL is required but not available
*
* @return boolean
*/
public function executeNoDB()
{
//Do nothing
return true;
}
/**
* Execute command
*
......@@ -32,7 +45,15 @@ class GenericmessageCommand extends SystemCommand
*/
public function execute()
{
//System command, do nothing
//System command, fetch command to execute if track exist
$message = $this->getMessage();
$chat_id = $message->getChat()->getId();
$user_id = $message->getFrom()->getId();
//Fetch Track if exist
$command = (new Tracking($user_id, $chat_id))->getTrackCommand();
if (! is_null($command)) {
return $this->telegram->executeCommand($command, $this->update);
}
return true;
}
}
<?php
/**
* This file is part of the TelegramBot package.
*
* (c) Avtandil Kikabidze aka LONGMAN <akalongman@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Longman\TelegramBot\Commands\UserCommands;
use Longman\TelegramBot\Request;
use Longman\TelegramBot\Tracking;
use Longman\TelegramBot\Commands\UserCommand;
use Longman\TelegramBot\Entities\ForceReply;
use Longman\TelegramBot\Entities\ReplyKeyboardHide;
use Longman\TelegramBot\Entities\ReplyKeyboardMarkup;
/**
* User "/survery" command
*/
class SurveyCommand extends UserCommand
{
/**#@+
* {@inheritdoc}
*/
protected $name = 'survey';
protected $description = 'Survery for bot users';
protected $usage = '/survey';
protected $version = '0.1.0';
protected $need_mysql = true;
/**#@-*/
/**
* Execute command
*
* @return boolean
*/
public function execute()
{
$update = $this->getUpdate();
$message = $this->getMessage();
$chat = $message->getChat();
$user = $message->getFrom();
$text = $message->getText(true);
$chat_id = $chat->getId();
$user_id = $user->getId();
//Preparing Respose
$data = [];
if ($chat->isGroupChat() || $chat->isSuperGroup()) {
//reply to message id is applied by default
$data['reply_to_message_id'] = $message_id;
//Force reply is applied by default to so can work with privacy on
$data['reply_markup'] = new ForceReply([ 'selective' => true]);
}
$data['chat_id'] = $chat_id;
//tracking
$path = new Tracking($user_id, $chat_id, $this->getName());
$path->startTrack();
//cache data from the tracking session if any
$session = $path->GetData();
if (!isset($session['state'])) {
$state = '0';
} else {
$state = $session['state'];
}
//state machine
//entrypoint of the machine state if given by the track
//Every time the step is achived the track is updated
switch ($state) {
case 0:
if (empty($text)) {
$session['state'] = '0';
$path->updateTrack($session);
$data['text'] = 'Type your name:';
$result = Request::sendMessage($data);
break;
}
$session['name'] = $text;
$text = '';
// no break
case 1:
if (empty($text)) {
$session['state'] = 1;
$path->updateTrack($session);
$data['text'] = 'Type your surname:';
$result = Request::sendMessage($data);
break;
}
$session['surname'] = $text;
++$state;
$text = '';
// no break
case 2:
if (empty($text) || !is_numeric($text)) {
$session['state'] = '2';
$path->updateTrack($session);
$data['text'] = 'Type your age:';
if (!empty($text) && !is_numeric($text)) {
$data['text'] = 'Type your age, must be a number';
}
$result = Request::sendMessage($data);
break;
}
$session['age'] = $text;
$text = '';
// no break
case 3:
if (empty($text) || !($text == 'M' || $text == 'F')) {
$session['state'] = '3';
$path->updateTrack($session);
$keyboard = [['M','F']];
$reply_keyboard_markup = new ReplyKeyboardMarkup(
[
'keyboard' => $keyboard ,
'resize_keyboard' => true,
'one_time_keyboard' => true,
'selective' => true
]
);
$data['reply_markup'] = $reply_keyboard_markup;
$data['text'] = 'Select your gender:';
if (!empty($text) && !($text == 'M' || $text == 'F')) {
$data['text'] = 'Select your gender, choose a keyboard option:';
}
$result = Request::sendMessage($data);
break;
}
$session['gender'] = $text;
$text = '';
// no break
case 4:
if (is_null($message->getLocation())) {
$session['state'] = '4';
$path->updateTrack($session);
$data['text'] = 'Insert your home location (need location object):';
$data['reply_markup'] = new ReplyKeyBoardHide(['selective' => true]);
$result = Request::sendMessage($data);
break;
}
$session['longitude'] = $message->getLocation()->getLongitude();
$session['latitude'] = $message->getLocation()->getLatitude();
// no break
case 5:
if (is_null($message->getPhoto())) {
$session['state'] = '5';
$path->updateTrack($session);
$data['text'] = 'Insert your picture:';
$result = Request::sendMessage($data);
break;
}
$session['photo_id'] = $message->getPhoto()[0]->getFileId();
// no break
case 6:
$path->stopTrack();
$out_text = '/Survey result:' . "\n";
unset($session['state']);
foreach ($session as $k => $v) {
$out_text .= "\n" . ucfirst($k).': ' . $v;
}
$data['photo'] = $session['photo_id'];
$data['reply_markup'] = new ReplyKeyBoardHide(['selective' => true]);
$data['caption'] = $out_text;
$result = Request::sendPhoto($data);
break;
}
return $result->isOk();
}
}
......@@ -182,6 +182,7 @@ class Telegram
public function enableMySQL(array $credential, $table_prefix = null)
{
$this->pdo = DB::initialize($credential, $this, $table_prefix);
TrackingDB::initializeTracking();
$this->mysql_enabled = true;
}
......
<?php
/**
* This file is part of the TelegramBot package.
*
* (c) Avtandil Kikabidze aka LONGMAN <akalongman@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Longman\TelegramBot;
use Longman\TelegramBot\Command;
use Longman\TelegramBot\Request;
use Longman\TelegramBot\TrackingDB;
use Longman\TelegramBot\Entities\Update;
/**
* Class Tracking
*/
class Tracking
{
/**
* Track has been fetched true false
*
* @var bool
*/
protected $is_fetched = false;
/**
* All information fetched from the database
*
* @var array
*/
protected $track = null;
/**
* Data stored inside the track
*
* @var array
*/
protected $data = null;
/**
* Telegram user id
*
* @var int
*/
protected $user_id;
/**
* Telegram chat_id
*
* @var int
*/
protected $chat_id;
/**
* Group name let you share the session among commands
* Call this as the same name of the command if you don't need to share the tracking
*
* @var strint
*/
protected $group_name;
/**
* Command to be execute if the track is active
*
* @var string
*/
protected $command;
/**
* Tracking contructor initialize a new track
*
* @param int $user_id
* @param int $chat_id
* @param string $name
* @param string $command
*/
public function __construct($user_id, $chat_id, $group_name = null, $command = null)
{
if (is_null($command)) {
$command = $group_name;
}
$this->user_id = $user_id;
$this->chat_id = $chat_id;
$this->command = $command;
$this->group_name = $group_name;
}
/**
* Check if the track already exist
*
* @return bool
*/
protected function trackExist()
{
//Track info already fetched
if ($this->is_fetched) {
return true;
}
$track = TrackingDB::selectTrack($this->user_id, $this->chat_id, 1);
$this->is_fetched = true;
if (isset($track[0])) {
//Pick only the first element
$this->track = $track[0];
if (is_null($this->group_name)) {
//Track name and command has not been specified. command has to be retrieved
return true;
}
//a track with the same name was already opened store the data
if ($this->track['track_name'] == $this->group_name) {
$this->data = json_decode($this->track['data'], true);
return true;
}
//a track with a differet name has been opened unsetting the DB one and reacreatea a new one
TrackingDB::updateTrack(['is_active' => 0], ['chat_id' => $this->chat_id, 'user_id' => $this->user_id]);
return false;
}
$this->track = null;
return false;
}
/**
* Check if the tracke already exist
*
* Check if a track has already been created in the database. If the track is not found, a new track is created. startTrack fetch the data stored in the database
*
* @return bool
*/
public function startTrack()
{
if (!$this->trackExist()) {
$status = TrackingDB::insertTrack($this->command, $this->group_name, $this->user_id, $this->chat_id);
$this->is_fetched = true;
}
return true;
}
/**
* Store the array/variable in the database with json_encode() function
*
* @param array $data
*/
public function updateTrack($data)
{
//track must exist!
if ($this->trackExist()) {
$fields['data'] = json_encode($data);
TrackingDB::updateTrack($fields, ['chat_id' => $this->chat_id, 'user_id' => $this->user_id]);
//TODO verify query success before convert the private var
$this->data = $data;
}
}
/**
* Delete the track from the database
*
* Currently the Track is not deleted but just unsetted
*
* @TODO should return something
*
* @param array $data
*/
public function stopTrack()
{
if ($this->trackExist()) {
TrackingDB::updateTrack(['is_active' => 0], ['chat_id' => $this->chat_id, 'user_id' => $this->user_id]);
}
}
/**
* Retrieve the command to execute from the track
*
* @param string
*/
public function getTrackCommand()
{
if ($this->trackExist()) {
return $this->track['track_command'];
}
return null;
}
/**
* Retrive the data store in the track
*
* @param array $data
*/
public function getData()
{
return $this->data;
}
}
<?php
/**
* This file is part of the TelegramBot package.
*
* (c) Avtandil Kikabidze aka LONGMAN <akalongman@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Longman\TelegramBot;
use Longman\TelegramBot\DB;
/**
* Class TrackingDB
*/
class TrackingDB extends DB
{
/**
* Initilize tracking table
*/
public static function initializeTracking()
{
if (!defined('TB_TRACK')) {
define('TB_TRACK', self::$table_prefix . 'track');
}
}
/**
* Tracking contructor initialize a new track
*
* @param int $user_id
* @param int $chat_id
* @param bool $limit
*
* @return array
*/
public static function selectTrack($user_id, $chat_id, $limit = null)
{
if (!self::isDbConnected()) {
return false;
}
try {
$query = 'SELECT * FROM `' . TB_TRACK . '` ';
$query .= 'WHERE `is_active` = 1 ';
$query .= 'AND `chat_id` = :chat_id ';
$query .= 'AND `user_id` = :user_id ';
$tokens = [':chat_id' => $chat_id, ':user_id' => $user_id];
if (!is_null($limit)) {
$query .=' LIMIT :limit';
}
$sth = self::$pdo->prepare($query);
$sth->bindParam(':user_id', $user_id, \PDO::PARAM_INT);
$sth->bindParam(':chat_id', $chat_id, \PDO::PARAM_INT);
$sth->bindParam(':limit', $limit, \PDO::PARAM_INT);
$sth->execute();
$results = $sth->fetchAll(\PDO::FETCH_ASSOC);
} catch (PDOException $e) {
throw new TelegramException($e->getMessage());
}
return $results;
}
/**
* Insert the track in the database
*
* @param string $track_command
* @param string $track_name
* @param int $user_id
* @param int $chat_id
*
* @return bool
*/
public static function insertTrack($track_command, $track_group_name, $user_id, $chat_id)
{
if (!self::isDbConnected()) {
return false;
}
try {
$sth = self::$pdo->prepare('INSERT INTO `' . TB_TRACK . '`
(
`is_active`, `track_command`, `track_name`, `user_id`, `chat_id`, `data`, `created_at`, `updated_at`
)
VALUES (
:is_active, :track_command, :track_name, :user_id, :chat_id, :data, :date, :date
)
');
$active = 1;
$data = json_encode('');
$created_at = self::getTimestamp();
$sth->bindParam(':is_active', $active);
$sth->bindParam(':track_command', $track_command);
$sth->bindParam(':track_name', $track_group_name);
$sth->bindParam(':user_id', $user_id);
$sth->bindParam(':chat_id', $chat_id);
$sth->bindParam(':data', $data);
$sth->bindParam(':date', $created_at);
$status = $sth->execute();
} catch (PDOException $e) {
throw new TelegramException($e->getMessage());
}
return $status;
}
/**
* Update a specific track
*
* @param array $fields_values
* @param array $where_fields_values
*
* @return bool
*/
public static function updateTrack(array $fields_values, array $where_fields_values)
{
return self::update(TB_TRACK, $fields_values, $where_fields_values);
}
/**
* Insert the track in the database
*
* @param string $table
* @param array $fields_values
* @param array $where_fields_values
*
* @todo this function is generic should be moved in DB.php
*
* @return bool
*/
public static function update($table, array $fields_values, array $where_fields_values)
{
if (!self::isDbConnected()) {
return false;
}
//Auto update the field update_at
$fields_values['updated_at'] = self::getTimestamp();
//Values
$update = '';
$tokens = [];
$a = 0;
foreach ($fields_values as $field => $value) {
if ($a) {
$update .= ', ';
}
++$a;
$update .= '`'.$field.'` = :'.$a;
$tokens[':'.$a] = $value;
}
//Where
$a = 0;
$where = '';
foreach ($where_fields_values as $field => $value) {
if ($a) {
$where .= ' AND ';
} else {
++$a;
$where .= 'WHERE ';
}
$where .= '`'.$field .'`='.$value ;
}
$query = 'UPDATE `'.$table.'` SET '.$update.' '.$where;
try {
$sth = self::$pdo->prepare($query);
$status = $sth->execute($tokens);
} catch (PDOException $e) {
throw new TelegramException($e->getMessage());
}
return $status;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment