Как реализовать диалоговый бот на PHP?

Начал программировать на PHP не так давно, и начал писать проект Telegram Bot-а.
Столкнулся с проблемой реализации диалогового окна, и меня возник вопрос. В задании, мы должны узнать 2 входных параметра у человека. 1 - ссылка на канал, 2 - число. Эти параметры человек должен вводить в чат, после того, как сам бот скажет ему это делать. И тут у меня возникла сама проблема.
Конструкция "elseif", работает таким способом, что если выполнилась одна ветка, то по определению другие выполняться не будут. И соответственно, после ввода пользователем ссылки, мы должны спрашивать число. Если введенные пользователем данные прошли валидацию, то бот переходит к следующему шагу и задает второй вопрос.

Вопрос заключается в следующем. Когда пользователь ввёл ссылку, а потом число, как мы можем сохранять эти 2 параметра глобально? Т.е записывать эти параметры навсегда, дабы вызывать их в любом участке кода.
Единственные логический ответ мне пришёл с использованием БД, и записывать введённые данные туда. Но на сколько я знаю, в PHP можно сохранять все данные в сессию, это я бы и хотел реализовать.

Пример кода:
$saveChannelLink = '';
$saveChannelNumber = '';

if ($message === '/start') {
    $method = 'sendMessage';
    $send_data = [
        'text' => "Привет! Я бот для анализа активности подписчиков в каналах, чатах и группах."
    ];
}
# Проверяем, вводит ли пользователь ссылку.
elseif (strpos($message, 'http') === 0) {
    $saveChannelLink = $message;

    $method = 'sendMessage';
    $send_data = [
        'text' => "Отлично! Отправь мне число:"
    ];
}
elseif (is_numeric($message)) {
    $saveChannelNumber = $message;
    $method = 'sendMessage';
            $send_data = [
            'text' => "Отлично! Ссылка: " . $saveChannelLink . "\nЧисло: " . $saveChannelNumber
        ];


Как я уже объяснял выше, сама конструкция elseif не готова к тому, дабы сохранять 2 параметра, и этот код вообще никак не будет сохранять и выводить ссылку. Т.к в поле $message после ввода ссылки, уже будет число,потому что пользователь 2-ым параметром вводит именно его. Какие пути решения существуют дабы обойти это? Заранее спасибо за ответы!
  • Вопрос задан
  • 350 просмотров
Решения вопроса 2
ipatiev
@ipatiev Куратор тега PHP
Потомок старинного рода Ипатьевых-Колотитьевых
$data = json_decode(file_get_contents('php://input'), TRUE);

Вот тут в $data у вас не только сообщение, но и много другой информации. В частности, айди юзера.
я думаю, что этот айди можно использовать в качестве идентификатора сессии, передавая в session_id() перед вызовом session_start()
Во всяком случае можно попробовать
если сессия не взлетит, то эмулировать её на любом другом хранилище, используя идентификатор юзера чтобы сохранять состояние бота для него

Попробовал, сессия через юзер айди не работает потому что идентификатор телеграма не подходит под стандарт идентификатора сессии.
Если эмулировать (просто добив до нужной длины) то сессия начинает работать.
Ответ написан
Комментировать
delphinpro
@delphinpro Куратор тега PHP
frontend developer
Но на сколько я знаю, в PHP можно сохранять все данные в сессию, это я бы и хотел реализовать.


Реализуйте. https://www.php.net/manual/ru/book.session.php

в самом начале кода:

session_start();

Потом в любом месте

//записать
$_SESSION['link'] = 'https://...';
$_SESSION['number'] = 123;

//прочитать
$link = $_SESSION['link'];
$number = $_SESSION['number'];
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@alekssamos
Программист любитель
Я не проверял. Точно как пишется не помню, но идея рабочая.

<?php

class SqliteStore {
	protected $db;
	public function __construct($tableName, $filePath = 'db.sqlite') {
		$this->db = new SQLite3($filePath);
		$this->tableName = $this->db->escapeString($tableName);
		if (is_numeric($tableName[0])) {
			$details = sprintf(
				"sqlite will choke on table names that start w/ a number.  yours starts w/ '%s'",
				$tableName[0]
			);
			throw new Exception($details);
		}
		
		//wrap in try/catch & ignore warnings as workaround to lack of 'if not exists' in sqlite version
		try {
			$sql = "create table $tableName ( key text primary key, value text, tm INT )";
			@$this->db->query( $sql );
		} catch ( Exception $e ) {
			// var_dump($e);
		}
	}
	
	public function get($key, $defvalue = '') {
		$sql = sprintf(
			"SELECT value FROM %s WHERE key = '%s';", 
			$this->tableName, $key
		);
		$result = $this->db->query($sql)->fetchArray(SQLITE3_ASSOC);
		if ($result) {
			$result = $result['value'];
		} else { $result = $defvalue; }
		return $result;
	}
	
	public function set($key, $value){
		$time = time();
		$sql = sprintf(
			"REPLACE INTO %s (key, value, tm) VALUES ('%s', '%s', %d);", 
			$this->tableName, $this->db->escapeString($key), $this->db->escapeString($value), $time
		);
		
		//allow exceptions to bubble up
		$this->db->exec($sql);
	}
	
	public function delete($key){
		$sql = sprintf(
			"DELETE FROM %s WHERE key = '%s';", 
			$this->tableName, $this->db->escapeString($key)
		);
		
		//allow exceptions to bubble up
		$this->db->exec($sql);
	}
	
	public function deleteOld($seconds){
		$time = time();
		$sql = sprintf(
			"DELETE FROM %s WHERE (%d - tm > %d);", 
			$this->tableName, $time, $seconds
		);
		
		//allow exceptions to bubble up
		$this->db->exec($sql);
	}
	
	public function delete_old($seconds){
		return $this->deleteOld($seconds);
	}
}


$ss = new SqliteStore('tg');
$data = json_decode(file_get_contents('php://input'), TRUE);
$message = trim($data["message"]["text"]);
$chat_id = $data["chat"]["id"];
if ($message === '/start') {
    $method = 'sendMessage';
    $send_data = [
        'text' => "Привет! Я бот для анализа активности подписчиков в каналах, чатах и группах."
    ];
}
# Проверяем, вводит ли пользователь ссылку.
elseif (strpos($message, 'http') === 0) {
    $ss->set('saveChannelLink'.$chat_id, $message);

    $method = 'sendMessage';
    $send_data = [
        'text' => "Отлично! Отправь мне число:"
    ];
}
elseif (is_numeric($message)) {
    $ss->set('saveChannelNumber'.$chat_id, $message);
    $method = 'sendMessage';
    $saveChannelLink = $ss->get('saveChannelLink'.$chat_id);
    $saveChannelNumber = $ss->get('saveChannelNumber'.$chat_id);
    $send_data = [
        'text' => "Отлично! Ссылка: " . $saveChannelLink . "\nЧисло: " . $saveChannelNumber
    ];

echo json_encode($send_data);
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы