<?php
function sendTelegram($data, $method = 'sendMessage', $headers = [])
{
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_POST => 1,
CURLOPT_HEADER => 0,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => 'https://api.telegram.org/bot' . TOKEN . '/' . $method,
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_HTTPHEADER => array_merge(array("Content-Type: application/json"))
]);
$result = curl_exec($curl);
curl_close($curl);
return (json_decode($result, 1) ? json_decode($result, 1) : $result);
}
class StringCompareJaroWinkler
{
public function compare($str1, $str2)
{
return $this->JaroWinkler($str1, $str2, $PREFIXSCALE = 0.1);
}
private function getCommonCharacters($string1, $string2, $allowedDistance)
{
$str1_len = mb_strlen($string1);
$str2_len = mb_strlen($string2);
$temp_string2 = $string2;
$commonCharacters = '';
for ($i = 0; $i < $str1_len; $i++) {
$noMatch = True;
// compare if char does match inside given allowedDistance
// and if it does add it to commonCharacters
for ($j = max(0, $i - $allowedDistance); $noMatch && $j < min($i + $allowedDistance + 1, $str2_len); $j++) {
if ($temp_string2[$j] == $string1[$i]) {
$noMatch = False;
$commonCharacters .= $string1[$i];
if (is_array($temp_string2)) {
$temp_string2[$j] = '';
}
}
}
}
return $commonCharacters;
}
private function Jaro($string1, $string2)
{
$str1_len = mb_strlen($string1);
$str2_len = mb_strlen($string2);
// theoretical distance
$distance = (int) floor(min($str1_len, $str2_len) / 2.0);
// get common characters
$commons1 = $this->getCommonCharacters($string1, $string2, $distance);
$commons2 = $this->getCommonCharacters($string2, $string1, $distance);
if (($commons1_len = mb_strlen($commons1)) == 0)
return 0;
if (($commons2_len = mb_strlen($commons2)) == 0)
return 0;
// calculate transpositions
$transpositions = 0;
$upperBound = min($commons1_len, $commons2_len);
for ($i = 0; $i < $upperBound; $i++) {
if ($commons1[$i] != $commons2[$i])
$transpositions++;
}
$transpositions /= 2.0;
// return the Jaro distance
return ($commons1_len / ($str1_len) + $commons2_len / ($str2_len) + ($commons1_len - $transpositions) / ($commons1_len)) / 3.0;
}
private function getPrefixLength($string1, $string2, $MINPREFIXLENGTH = 4)
{
$n = min(array($MINPREFIXLENGTH, mb_strlen($string1), mb_strlen($string2)));
for ($i = 0; $i < $n; $i++) {
if ($string1[$i] != $string2[$i]) {
// return index of first occurrence of different characters
return $i;
}
}
// first n characters are the same
return $n;
}
private function JaroWinkler($string1, $string2, $PREFIXSCALE = 0.1)
{
$JaroDistance = $this->Jaro($string1, $string2);
$prefixLength = $this->getPrefixLength($string1, $string2);
return $JaroDistance + $prefixLength * $PREFIXSCALE * (1.0 - $JaroDistance);
}
}
function update($param = '', $set = '')
{
global $update, $user, $userStore;
if (empty($user->$param) and $user->$param != 0) {
return $user;
}
$user->$param = $set;
$userStore->updateOrInsert((array) $user, false);
return $user;
}
function getHistory($title = 'launch')
{
$file = file_get_contents(dirname(dirname(__FILE__)) . '/History_rus.txt');
if ($file === false) {
return 'error';
}
preg_match('~:: ' . $title . '\n(.*?)\n\n~uis', $file, $result);
$result = $result['1'];
preg_match_all('~(<<choice |)\[\[(.*?)]](>>|) \| (<<choice |)\[\[(.*?)]](>>|)~uim', $result, $button);
$i = 0;
for ($i = 0; $i < count($button['0']); $i++) {
$buttons['0'][$i] = str_replace('<<choice ', '', $button['0'][$i]);
$buttons['0'][$i] = str_replace('>>', '', $buttons['0'][$i]);
$buttons['0'][$i] = str_replace('[[', '', $buttons['0'][$i]);
$buttons['0'][$i] = str_replace(']]', '', $buttons['0'][$i]);
$buttons['0'][$i] = trim($buttons['0'][$i]);
preg_match('~(.*?) \| (.*?)$~ui', $buttons['0'][$i], $buttonArr);
unset($buttonArr['0']);
$code = '';
foreach ($buttonArr as $buttonValues) {
$code .= "\r\n" . '$button[] .= \'' . trim($buttonValues) . '\';';
}
$result = str_replace($button['0'][$i], "\r\n" . $code, $result);
}
preg_match_all('~\[\[delay (.*?)\|(.*?)]]~ui', $result, $delay);
$i = 0;
foreach ($delay['0'] as $value) {
$result = str_replace($value, "\r\n" . 'sleeps(\'' . $delay['1'][$i] . '\', \'' . $delay['2'][$i] . '\');', $result);
$i++;
}
//$result = preg_replace('~\[\[delay ([^|]+)\|([A-z]+)]]~ui', '', $result);
//$result = preg_replace('~<<silently>><<set \$([^>>]+)>><<endsilently>>~', '', $result);
$result = str_replace('~<<silently>>', '', $result);
$result = str_replace('<<endsilently>>', '', $result);
$result = str_replace('<<silently>>', '', $result);
$result = str_replace('<<endsilently>>', '', $result);
$result = str_replace('<<else>>', "\r\n" . '}else{' . "\r\n", $result);
$result = str_replace('<<endif>>', "\r\n" . '}' . "\r\n", $result);
preg_match_all('~<<if ([^>>]+)>>~', $result, $rs);
$values = [];
$i = 0;
foreach ($rs['1'] as $value) {
$value = str_replace('is', '==', $value);
$value = str_replace('eq', '==', $value);
$value = str_replace('$', '$user->', $value);
$value = "\r\n" . 'if(' . $value . '){' . "\r\n";
$values[] = $value;
$result = str_replace($rs['0'][$i], $value, $result);
$i++;
}
preg_match_all('~<<elseif ([^>>]+)>>~', $result, $rs2);
$values = [];
$i = 0;
foreach ($rs2['1'] as $value) {
$value = str_replace('is', '==', $value);
$value = str_replace('$', '$user->', $value);
$value = "\r\n" . '}elseif(' . $value . '){' . "\r\n";
$values[] = $value;
$result = str_replace($rs2['0'][$i], $value, $result);
$i++;
}
preg_match_all('~\[\[(.*?)]]~ui', $result, $add);
if (!empty($add['1'])) {
$i = 0;
foreach ($add['0'] as $id => $value) {
if (preg_match('~\|~ui', $value)) {
continue;
} else {
if (!file_exists(dirname(dirname(__FILE__)) . '/history/ru/' . $add['1'][$i] . '.php')) {
getHistory($add['1'][$i]);
}
$result = str_replace($value, "\r\n" . 'include $_SERVER[\'DOCUMENT_ROOT\'].\'/history/ru/' . $add['1'][$i] . '.php\';', $result);
}
$i++;
}
}
preg_match_all('~<<set (.*?)>>~ui', $result, $set);
if (!empty($set)) {
$i = 0;
foreach ($set['1'] as $value) {
//pre(htmlspecialchars($set['0'][$i]));
//$result = str_replace($set['0'][$i], '', $result);
if (preg_match('~= ""~ui', $value)) {
$result = str_replace($set['0'][$i], '', $result);
$i++;
continue;
}
preg_match('~\$(.*?) = ([^\n]+)~ui', $value, $IhateThis);
if (preg_match('~\$(.*?) ([\-|\+]+) ([0-9]+)~ui', $IhateThis['2'], $wtf)) {
//pre(['wtf' => $wtf]);
$setter = '($user->' . $wtf['1'] . $wtf['2'] . $wtf['3'] . ')';
$val = $wtf['1'];
} else {
//pre($IhateThis);
$setter = " '$IhateThis[2]'";
$val = $IhateThis['1'];
}
$result = str_replace($set['0'][$i], "\r\n" . 'update(\'' . $val . '\',' . $setter . ');' . "\r\n", $result);
$i++;
}
}
preg_match_all('~<<\$([^>]+)>>~ui', $result, $arrays);
$i = 0;
foreach ($arrays['0'] as $value) {
$result = str_replace($value, '\'.$user->' . $arrays['1'][$i] . '.\'', $result);
$i++;
}
$line = explode("\r\n", $result);
$result = '';
foreach ($line as $value) {
$value = trim(htmlspecialchars($value));
if (empty($value)) {
continue;
}
if (!preg_match('~^(if|sleep|}|\$|include|update)~ium', $value)) {
$value = '$str .=\'' . $value . '\';';
}
$result .= "\r\n $value";
}
$result = '<?php' . $result;
file_put_contents(dirname(dirname(__FILE__)) . '/history/ru/' . $title . '.php', htmlspecialchars_decode($result));
}
function buttons($text = '', $status = false)
{
preg_match('~(.*?)\|(.*?)$~ui', $text, $array);
return $status ? $array['2'] : $array['1'];
}
function sleeps($time = '', $nextape = '')
{
global $user, $str, $userStore;
$s = $time;
if (preg_match('~m~ui', $time)) {
$multiplicity = 60;
$time = intval(str_replace('m', '', $time));
} else {
$multiplicity = 1;
$time = intval(str_replace('s', '', $time));
}
$str .= "\r\n" . '[Занят]';
$user = (object) $user;
$user->pause = time() + ($time * $multiplicity);
$user->stage = $nextape;
getHistory($nextape);
$user->status = 2;
$userStore->updateOrInsert((array) $user, false);
return $user;
}
function main_index($user, $data = null)
{
global $str, $button, $userStore;
if (empty($user)) {
return 'error user';
}
if (!file_exists(dirname(dirname(__FILE__)) . '/history/ru/' . $user->stage . '.php')) {
getHistory($user->stage);
}
require_once dirname(dirname(__FILE__)) . '/history/ru/' . $user->stage . '.php';
if ($user->status == 1 and !empty($data)) {
// Ловим и обрабатываем сообщения
$i = 1;
$a = [];
$var = '';
$jw = new StringCompareJaroWinkler();
foreach ($button as $value) {
if ($data->message->text == buttons($value)) {
$var = $i;
break;
}
$a[] = $jw->compare($data->message->text, buttons($value));
$i++;
}
if (empty($var)) {
// Нет правильного ответа
if ($a['0'] - $a['1'] > 20 and $a['0'] >= 40) {
// Первый вариант перевешивает второй на 20% и он имеет схожесть больше 50%
$var = 1;
} elseif ($a['1'] - $a['0'] > 20 and $a['1'] >= 40) {
// Второй вариант перевешивает первый на 20% и он имеет схожесть больше 50%
$var = 2;
}
}
if (!empty($var)) {
// Есть правильный ответ или очень схожий
$var -= 1;
$user->stage = buttons($button[$var], true);
//$user->status = '1';
$userStore->updateOrInsert((array) $user, false);
$str = '';
$button = [];
main_index($user);
return 'send';
} else {
// Ответ не распознан
$send_data = [
'text' => 'Я не понял тебя',
'chat_id' => $data->message->chat->id
];
$keyboard = [];
$j = 0;
foreach ($button as $values) {
$keyboard['keyboard'][$j][] = ['text' => buttons($values)];
$j += 1;
}
$keyboard['resize_keyboard'] = true;
$keyboard['one_time_keyboard'] = true;
$keyboard['selective'] = true;
$send_data['reply_markup'] = json_encode($keyboard);
sleep(1);
sendTelegram($send_data);
}
} elseif (empty($data) or $user->status == 0) {
// Движемся по сюжету (бот рассказывает)
if ($user->status == 0) {
if ($user->status != 2) {
$user->status = 1;
}
$userStore->updateOrInsert((array) $user, false);
}
$strArray = explode("\n", $str);
$count = count($strArray);
$i = 1;
foreach ($strArray as $value) {
$send_data = [
'chat_id' => $user->_id,
'action' => 'typing'
];
sendTelegram($send_data, 'sendChatAction');
usleep((mb_strlen($value, 'UTF-8') * 50000));
$send_data = [
'text' => $value,
'chat_id' => $user->_id
];
if ($i == 1 and $i != $count) {
$keyboard = [
'remove_keyboard' => true
];
$send_data['reply_markup'] = json_encode($keyboard);
}
$send_data['disable_notification'] = true;
if ($i == $count and !empty($button)) {
$send_data['disable_notification'] = false;
$keyboard = [];
$j = 0;
foreach ($button as $values) {
$keyboard['keyboard'][$j][] = ['text' => buttons($values)];
$j += 1;
}
$keyboard['resize_keyboard'] = true;
$keyboard['one_time_keyboard'] = true;
$keyboard['selective'] = true;
$send_data['reply_markup'] = json_encode($keyboard);
}
sendTelegram($send_data);
$i++;
}
} elseif ($user->status == 2) {
// Статус ждуна, человек занят
$send_data = [
'text' => '[Занят]',
'chat_id' => $user->_id
];
sleep(1);
sendTelegram($send_data);
} else {
// Нам написали во время рассказа, игнорируем
$send_data = [
'text' => 'Игнор',
'chat_id' => $user->_id
];
sendTelegram($send_data);
}
}
function delTree($dir)
{
$files = array_diff(scandir($dir), array('.', '..'));
foreach ($files as $file) {
(is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file");
}
return rmdir($dir);
}