Skip to content

Instantly share code, notes, and snippets.

@believer-ufa
Last active August 29, 2015 14:26
Show Gist options
  • Save believer-ufa/c1189dfbedb63a90ebfd to your computer and use it in GitHub Desktop.
Save believer-ufa/c1189dfbedb63a90ebfd to your computer and use it in GitHub Desktop.
Telegram bot example on Laravel
<?php namespace QuranOnline\Http\Controllers;
use Curl\Curl;
use DB;
use Log;
use QuranOnline\Models\Telegram\User;
use QuranOnline\Services\TelegramQuranBot;
class Telegram extends Controller {
private $quran_bot; /* @var $this->quran_bot QuranOnline\Services\TelegramQuranBot */
private $request;
function __construct(TelegramQuranBot $bot_service)
{
parent::__construct();
$this->quran_bot = $bot_service;
}
/**
* Функция используется для отладки, позволяет скинуть текущий объект запроса в лог-файл
*/
function dumpRequest()
{
ob_start();
var_dump($this->request);
$debug_out = ob_get_contents();
ob_end_clean();
Log::debug($debug_out);
}
function QuranOnlineBot()
{
$this->request = json_decode(file_get_contents('php://input'));
$this->user = User::where('telegram_id',$this->request->message->from->id)->first();
if (is_null($this->user))
{
$this->user = new User([
'telegram_id' => $this->request->message->from->id,
'name' => property_exists($this->request->message->from, 'first_name') ? $this->request->message->from->first_name : null,
'family' => property_exists($this->request->message->from, 'last_name') ? $this->request->message->from->last_name : null,
'nick' => property_exists($this->request->message->from, 'username') ? $this->request->message->from->username : null,
]);
$this->user->save();
}
//$this->dumpRequest();
$this->processMessage(
$this->quran_bot->processCommand($this->request, $this->user)
);
return 'thanks!';
}
private function processMessage($answer)
{
if ($answer)
{
$curl = new Curl();
$params = [
'chat_id' => $this->request->message->chat->id,
'disable_web_page_preview' => true,
];
if (is_array($answer)) {
$params = array_merge($params, $answer);
} else {
$params['text'] = $answer;
}
if (property_exists($this->request->message, 'text') AND $params['text'])
{
DB::table('telegram_messaging_history')->insert([
'user_id' => $this->user->id,
'question' => $this->request->message->text,
'answer' => $params['text'],
]);
}
$curl->get('https://api.telegram.org/bot123928604:AAFy6JsOgnjPGp615TnQhbJenz4f82r2UCY/sendMessage', $params);
}
}
}
<?php
namespace QuranOnline\Services;
use QuranOnline\Helpers\Text;
use QuranOnline\Models\Quran\Ayat;
use QuranOnline\Models\Quran\Sura;
/**
* Класс работы бота для программы "Телеграмм"
*/
class TelegramQuranBot {
private $request;
private $user; /* @var $this->user \QuranOnline\Models\Telegram\User */
function processCommand($request, $user)
{
$this->request = $request;
$this->user = $user;
if (! property_exists($this->request->message, 'text')) {
return '';
}
$first_word = explode(' ',$this->request->message->text)[0];
switch ($first_word)
{
case '/start':
case (preg_match('/^(привет|здорова|хай|здравствуй).*$/iu', $first_word) ? true : false):
return $this->commandHelloJahil();
case '/start':
case (preg_match('/^.*(салям|салам).*$/iu', $first_word) ? true : false):
return $this->commandHelloMuslim();
case '/help':
return $this->commandHelp();
case '/search':
case 'искать':
case 'Искать':
case 'найти':
case 'Найти':
case 'поиск':
case 'Поиск':
return $this->commandSearch();
// case '/settings':
// case 'настройки':
// return $this->commandSettings();
case '/ayat':
case 'аят':
case 'Аят':
return $this->commandAyat();
case '/sura':
case 'сура':
case 'Сура':
return $this->commandSura();
case 'Завершить':
case 'завершить':
case 'Отмена':
case 'отмена':
case '/cancel':
return $this->cancelOperations();
case 'далее':
case 'Далее':
case '/next':
case '>':
return $this->nextOperation();
case 'назад':
case 'Назад':
case '/previous':
case '<':
return $this->previousOperation();
default:
return 'Прошу прощения, но я не понял, что вам от меня нужно. Пожалуйста, постарайтесь уточнить ваш запрос.';
}
}
private function commandHelloJahil()
{
return "Добрый день, {$this->user->name}!\n\nНа данный момент, с моей помощью вы можете искать аяты в Священном Коране, а также получать текст нужного аята."
. "\n\nЧтобы что-то найти, просто напишите мне что-нибудь вроде \"найти Мухаммад\", и я найду все аяты в Священном Коране, в которых упоминается слово \"Мухаммад\"."
. "\n\nЧтобы прочитать текст нужного аята, напишите мне \"аят 1 2\" (или \"/ayat 1 2\", если бот в группе), и я найду текст второго аята первой суры."
. "\n\nВот так всё просто :) Всего хорошего вам, и пусть Аллах покроет вас Своей милостью :)";
}
private function commandHelloMuslim()
{
return "Уа алейкум ассаламу уа рахматуллахи уа баракятух, {$this->user->name}!\n\nНа данный момент, с моей помощью вы можете искать аяты в Священном Коране, а также получать текст нужного аята."
. "\n\nЧтобы что-то найти, просто напишите мне что-нибудь вроде \"найти Мухаммад\", и я найду все аяты в Священном Коране, в которых упоминается слово \"Мухаммад\"."
. "\n\nЧтобы прочитать текст нужного аята, напишите мне \"аят 1 2\" (или \"/ayat 1 2\", если бот в группе), и я найду текст второго аята первой суры."
. "\n\nВот так всё просто :) Всего хорошего вам, и пусть Аллах покроет вас Своей милостью :)";
}
private function commandHelp()
{
return 'Ас-саляму алейкум! Данный бот может помочь вам изучить Священный Коран.';
}
private function commandSearch()
{
$search_query = explode(' ', $this->request->message->text);
if (count($search_query) > 1)
{
unset($search_query[0]);
$search = implode(' ', $search_query);
$ayats = $this->searchInQuran($search);
if ($ayats->count())
{
$this->user->state = 'search';
$this->user->search = $search;
$this->user->search_num = 0;
$this->user->save();
return $this->navigationReply(
'Мне удалось найти ' . Text::chislitelnie($ayats->count(), [ 'вхождение', 'вхождения', 'вхождений' ]) . ' по данному запросу.'
. "\n\nПосмотреть результаты поиска в более удобном виде вы всегда можете по данному адресу: quran-online.ru/search?search=".urlencode($search)
. ", а сейчас - первый результат в поиске: " . $this->showFindedAyat($ayats->first(), $search)
//. "\n\n Переключайтесь между результатами поиска: /next, /previous, /cancel"
. "\n\nПереключайтесь между результатами поиска: \n/next - следующий\n/previous - предыдущий\n/cancel - завершить поиск"
);
} else {
return 'Прошу прощения, но по данному запросу я ничего не нашел в Священном Коране, ни в одном из переводов :(';
}
}
else
{
return 'Вы можете воспользоваться функцией поиска по Священному Корану. '
. 'Чтобы сделать это, введите команду: "найти [слово или словосочетание]" (или "/search слово", если бот в группе), '
. 'и я найду для вас аяты, содержащие указанное слово.';
}
}
private function commandSura()
{
$search_query = explode(' ', $this->request->message->text);
if (count($search_query) > 1)
{
unset($search_query[0]);
$search = implode(' ', $search_query);
if (is_numeric($search))
{
$sura = Sura::findOrNew($search);
}
else
{
$sura = Sura::where('name','like',"%{$search}%")->orWhere('translit','like',"%{$search}%")->first();
}
if ($sura AND $sura->exists)
{
$ayat_texts = $this->showAyatTexts($sura->id, 1);
$ayat_texts .= "\n\nНавигация по аятам суры: \n/next - следующий\n/previous - предыдущий\n/cancel - завершить чтение";
$this->user->state = 'quran';
$this->user->sura = $sura->id;
$this->user->ayat = 1;
$this->user->save();
return $this->navigationReply($ayat_texts);
}
else
{
return 'К сожалению, я не нашел указанную вами суру в Священном Коране.';
}
}
else
{
return 'Вы можете попросить меня показать вам текст первого аята нужной суры.'
. ' Чтобы сделать это, просто введите фразу "сура бакара" (или "/sura бакара", если бот в группе), и я верну вам текст первого аята данной суры.';
}
}
private function commandAyat()
{
$search_query = explode(' ', $this->request->message->text);
if (count($search_query) === 3)
{
if (!is_numeric($search_query[1]) OR !is_numeric($search_query[2]))
{
return 'Пожалуйста, при указании аята, используйте числовые значения для номера суры и номера аята.';
}
if ($search_query[1] < 1 OR $search_query[1] > 114)
{
return 'Номер суры должен быть в промежутке от 1 до 114.';
}
if ($search_query[2] > Sura::maxAyat($search_query[1]))
{
return 'Указанная вами сура не имеет такого аята';
}
$ayat_texts = $this->showAyatTexts($search_query[1], $search_query[2]);
$ayat_texts .= "\n\nНавигация по аятам суры: \n/next - следующий\n/previous - предыдущий\n/cancel - завершить чтение";
$this->user->state = 'quran';
$this->user->sura = $search_query[1];
$this->user->ayat = $search_query[2];
$this->user->save();
return $this->navigationReply($ayat_texts);
}
else
{
return 'Вы можете попросить меня показать вам текст нужного аята.'
. ' Чтобы сделать это, просто введите фразу "аят 14 10" (или "/ayat 14 10", если бот в группе), и я верну вам текст десятого аята четырнадцатой суры.';
}
}
private function cancelOperations()
{
switch ($this->user->state)
{
case 'search':
$this->user->state = null;
$this->user->search = null;
$this->user->search_num = null;
$this->user->save();
return 'Режим поиска по аятам был отключён.';
case 'quran':
$this->user->state = null;
$this->user->sura = null;
$this->user->ayat = null;
$this->user->save();
return 'Режим чтения Корана был отключён.';
default:
return 'В данный момент у вас нет активных операций, поэтому и завершать вам нечего :)';
}
}
private function nextOperation()
{
switch ($this->user->state)
{
case 'search':
$search_results = $this->searchInQuran($this->user->search);
$search_results_count = $search_results->count();
if ($this->user->search_num < ($search_results_count-1))
{
$this->user->search_num = $this->user->search_num + 1;
$this->user->save();
$human_num = $this->user->search_num + 1;
$ayat = $search_results->skip($this->user->search_num)->take(1)->first();
$text = "Результат поиска №{$human_num} из {$search_results_count}:";
$text .= $this->showFindedAyat($ayat, $this->user->search);
$text .= "\n\nНавигация: /next /previous /cancel";
return $this->navigationReply($text);
} else {
return 'Данный аят - последний в списке найденных аятов по данному запросу.';
}
case 'quran':
if ($this->user->ayat < (Sura::maxAyat($this->user->sura)))
{
$this->user->ayat = $this->user->ayat + 1;
$this->user->save();
$ayat_texts = $this->showAyatTexts($this->user->sura, $this->user->ayat);
$ayat_texts .= "\n\nНавигация: /next /previous /cancel";
return $this->navigationReply($ayat_texts);
} else {
return 'Данный аят последний в этой суре.';
}
default:
return 'В данный момент у вас нет активных операций, поэтому операция "далее" бессмысленна.';
}
}
private function previousOperation()
{
switch ($this->user->state)
{
case 'search':
$search_results = $this->searchInQuran($this->user->search);
$search_results_count = $search_results->count();
if ($this->user->search_num > 0)
{
$this->user->search_num = $this->user->search_num - 1;
$this->user->save();
$human_num = $this->user->search_num + 1;
$ayat = $search_results->skip($this->user->search_num)->take(1)->first();
$text = "Результат поиска №{$human_num} из {$search_results_count}:";
$text .= $this->showFindedAyat($ayat, $this->user->search);
$text .= "\n\nНавигация: /next /previous /cancel";
return $this->navigationReply($text);
} else {
return 'Данный аят - первый в списке найденных аятов по данному запросу.';
}
case 'quran':
if ($this->user->ayat > 1)
{
$this->user->ayat = $this->user->ayat - 1;
$this->user->save();
$ayat_texts = $this->showAyatTexts($this->user->sura, $this->user->ayat);
$ayat_texts .= "\n\nНавигация: /next /previous /cancel";
return $this->navigationReply($ayat_texts);
} else {
return 'Это первый аят данной суры.';
}
default:
return 'В данный момент у вас нет активных операций, поэтому операция "назад" бессмысленна.';
}
}
private function commandSettings()
{
switch ($this->user->state)
{
case 'search':
return 'В данный момент модуль поиска не имеет настроек.';
case 'quran':
if ($this->user->ayat > 1)
{
$this->user->ayat = $this->user->ayat - 1;
$this->user->save();
$ayat_texts = $this->showAyatTexts($this->user->sura, $this->user->ayat);
$ayat_texts .= "\n\nНавигация: /next /previous /cancel";
return $this->navigationReply($ayat_texts);
} else {
return [
'text' => 'Настройте режимы отображения текстов аятов. Какой перевод вам следует отключить или включить?',
];
}
default:
return 'Чтобы настроить какой-либо из режимов работы бота, сначала войдите в него.';
}
}
private function searchInQuran($search)
{
$ayats = Ayat
::where('text','LIKE',"%{$search}%")
->where('translate.enabled',1)
->where('translate.big_translate',0)
->join('quran_translates as translate','translate.id','=','quran_ayats.translate_id')
->orderBy('quran_ayats.translate_id')
->orderBy('quran_ayats.sura')
->orderBy('quran_ayats.ayat');
return $ayats;
}
private function showFindedAyat($ayat, $search)
{
$text = "\n\nАят quran-online.ru/{$ayat->sura}:{$ayat->ayat} ({$ayat->translate->name}):\n\n";
$text .= preg_replace("/({$search})/ius", "*$1*", strip_tags($ayat->text));
return $text;
}
private function showAyatTexts($sura, $ayat)
{
$ayats = Ayat::where('sura', $sura)
->where('ayat', $ayat)
->join('quran_translates','quran_ayats.translate_id','=','quran_translates.id')
->where('quran_translates.enabled','=',true)
//->where('quran_translates.id','!=',2)
->orderBy('quran_translates.id')
->get();
$text = '';
if ($ayats->count() > 0) {
$text = "Сура {$ayats[0]->ssura->name}, аят quran-online.ru/{$ayats[0]->sura}:{$ayats[0]->ayat}\n\n";
foreach($ayats as $ayat) {
$text .= "{$ayat->translate->name}: ";
$text .= str_limit(trim(html_entity_decode(strip_tags($ayat->text))),800, '... (текст обрезан из-за большой длины, полная версия доступна на сайте)');
$text .= "\n\n";
}
}
return $text;
}
private function navigationReply($answer)
{
return [
'text' => $answer,
'reply_markup' => json_encode([
'keyboard' =>
false,
//[ [ '<', '>', 'Отмена' ] ],
//'one_time_keyboard' => true,
//'hide_keyboard' => true,
'selective' => true,
])
];
}
}
// Данный роут принимает обновления от бота в Телеграме
Route::post('telegram-updates/[secret-code]', 'Telegram@QuranOnlineBot');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment