I was using irazasyed/telegram-bot-sdk for a Telegram bot in Laravel. I just wanted to access the update object on my StartCommand class and send a welcome message to a user with his name. The StartCommand class looks like this:
<?php
namespace App\TelegramCommands;
use Telegram\Bot\Commands\Command;
class StartCommand extends Command
{
protected $name = "start";
protected $description = "Lets you get started";
public function handle()
{
$this->replyWithMessage(['text' => 'Welcome ']);
}
}
And the route (which is inside api.php) is:
Route::post('/'.env('TELEGRAM_BOT_TOKEN').'/webhook', function (Request $request) {
$update = Telegram::commandsHandler(true);
return 'ok';
});
I just wanted to access users data when he sends /start command and replay with a message like, "Welcome [his name]". Thank you in advance.
I just have got the answer. It was mainly adding the following to the handle method of StartCommand class:
$update= $this->getUpdate();
So the final file will look like:
<?php
namespace App\TelegramCommands;
use Telegram\Bot\Commands\Command;
class StartCommand extends Command
{
protected $name = "start";
protected $description = "Lets you get started";
public function handle()
{
$update= $this->getUpdate();
$name = $update['message']['from']['first_name'];
$this->replyWithMessage(['text' => 'Welcome '.$name]);
}
}
A good tutorial is here
Related
I am trying to start a conversation in laravel 7 and botman 2 with telegram. All works fine as but unable to continue the conversations. When I am trying to answer any previous question of the conversation it assuming to start the new conversation and not asking the 2nd question of the conversation thread.
The telegram webhook url i set is :
/api/telegram-bot
My routes/api.php
Route::post('/telegram-bot', 'TelegramController#bot');
TelegramController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Template
use App\Channel;
use Config;
use BotMan\BotMan\BotMan;
use BotMan\BotMan\BotManFactory;
use BotMan\BotMan\Drivers\DriverManager;
use App\Conversations\BankingConversation;
class TelegramController extends Controller{
public function bot(){
$config = [
"telegram" => [
"token" => "{MY_BOT_TOKEN}",
'conversation_cache_time' => 30
]
];
DriverManager::loadDriver(\BotMan\Drivers\Telegram\TelegramDriver::class);
$botman = BotManFactory::create($config);
$botman->hears('(hi|hello|start)', function (BotMan $bot) {
$bot->startConversation(new BankingConversation , \BotMan\Drivers\Telegram\TelegramDriver::class );
});
$botman->fallback(function($bot) {
$bot->reply('Sorry, I did not understand you. Just type start to continue.');
});
$botman->listen();
}
}
and finally the BankingConversation
<?php
namespace App\Conversations;
use Illuminate\Foundation\Inspiring;
use BotMan\BotMan\Messages\Incoming\Answer;
use BotMan\BotMan\Messages\Outgoing\Question;
use BotMan\BotMan\Messages\Outgoing\Actions\Button;
use BotMan\BotMan\Messages\Conversations\Conversation;
class BankingConversation extends Conversation
{
protected $fullname;
protected $email;
public function askFullname()
{
$welcome = 'Hey ';
$this->ask($welcome.' What is your name ?', function(Answer $answer) {
// Save result
$this->fullname = $answer->getText();
$this->say('Nice to meet you '.$this->fullname);
$this->askEmail();
});
}
public function askEmail()
{
$this->ask('One more thing - what is your email?', function(Answer $answer) {
// Save result
$this->email = $answer->getText();
$this->say('Great - that is all we need, '.$this->firstname);
});
}
public function run()
{
// This will be called immediately
$this->askFullname();
}
}
Whenever is am typing hi/hello/start it's asking me first question of conversation "Hey What is your name ?"
But after replying to the question it's going to fallback and returning "Sorry, I did not understand you. Just type start to continue."
What is the mistake i am doing here ?
You have not specified the cache driver.
update section of your code.
DriverManager::loadDriver(\BotMan\Drivers\Telegram\TelegramDriver::class);
$botman = BotManFactory::create($config, new \BotMan\BotMan\Cache\LaravelCache());
Botman uses cache to maintain the conversation.
I'am trying to send a Telegram message with Telegram Bot (longman/telegram-bot) and Laravel Lumen jobs.
So, first I'am install a Telegram bot with composer require longman/telegram-bot and add to composer.json "Longman\\TelegramBot\\": "vendor/longman/telegram-bot/src". Then create a job
<?php
namespace App\Jobs;
use Longman\TelegramBot\Request;
use Longman\TelegramBot\Telegram;
use Longman\TelegramBot\Exception\TelegramException;
class ProcessTelegramMessageJob extends Job
{
const TELEGRAM_API_KEY = 'BOTKEY';
const TELEGRAM_BOT_NAME = 'BOTNAME';
protected $telegram;
protected $data;
public function __construct($data)
{
$this->data = $data;
try {
$this->telegram = new Telegram(self::TELEGRAM_API_KEY, self::TELEGRAM_BOT_NAME);
$this->telegram->handle();
} catch (TelegramException $e) {}
}
public function handle()
{
$data = [
'chat_id' => $this->data['user_id'],
'text' => $this->data['message'],
];
$result = Request::sendMessage($data);
}
}
But, when job try to dispatch, I see in log Call to a member function getBotUsername() on null in ...vendor/longman/telegram-bot/src/Request.php. As I understand Request is not see Telegram instance.
How to fix this error?
Thanks in advance!
PS Dump of telegram object
O:28:"Longman\TelegramBot\Telegram":16:{s:10:"*version";s:6:"0.52.0";s:10:"*api_key";s:45:"Api key here";s:15:"*bot_username";s:13:"Bot name here";s:9:"*bot_id";s:9:"470649282";s:8:"*input";s:116:"{"id":1,"url":"cib","_pos":1,"is_vis":true,"deleted_at":null,"checked":false,"data":{"id":1,"_node":1,"head":"CIB"}}";s:17:"*commands_paths";a:1:{i:0;s:98:"/var/www/www-root/data/www/domain.com/vendor/longman/telegram-bot/src/Commands/SystemCommands";}s:9:"*update";O:35:"Longman\TelegramBot\Entities\Update":9:{s:2:"id";i:1;s:3:"url";s:3:"cib";s:4:"_pos";i:1;s:6:"is_vis";b:1;s:10:"deleted_at";N;s:7:"checked";b:0;s:4:"data";a:3:{s:2:"id";i:1;s:5:"_node";i:1;s:4:"head";s:3:"CIB";}s:8:"raw_data";a:7:{s:2:"id";i:1;s:3:"url";s:3:"cib";s:4:"_pos";i:1;s:6:"is_vis";b:1;s:10:"deleted_at";N;s:7:"checked";b:0;s:4:"data";a:3:{s:2:"id";i:1;s:5:"_node";i:1;s:4:"head";s:3:"CIB";}}s:12:"bot_username";s:13:"Bot name here";}s:14:"*upload_path";N;s:16:"*download_path";N;s:16:"*mysql_enabled";b:0;s:6:"*pdo";N;s:18:"*commands_config";a:0:{}s:14:"*admins_list";a:0:{}s:24:"*last_command_response";O:43:"Longman\TelegramBot\Entities\ServerResponse":4:{s:2:"ok";b:1;s:6:"result";b:1;s:8:"raw_data";a:2:{s:2:"ok";b:1;s:6:"result";b:1;}s:12:"bot_username";N;}s:16:"*botan_enabled";b:0;s:15:"*run_commands";b:0;}
according to their Request documentation, your request needs to include $telegram instance first, check the code below
$result = Request::initialize($this->telegram)->sendMessage($data);
EDIT:
Corrected my answer with a working solution, explained why in the comments
<?php
namespace App\Jobs;
use Longman\TelegramBot\Request;
use Longman\TelegramBot\Telegram;
use Longman\TelegramBot\Exception\TelegramException;
class ProcessTelegramMessageJob extends Job
{
const TELEGRAM_API_KEY = 'BOTKEY';
const TELEGRAM_BOT_NAME = 'BOTNAME';
protected $telegram;
protected $data;
public function __construct($data)
{
$this->data = $data;
try {
$this->telegram = new Telegram(self::TELEGRAM_API_KEY, self::TELEGRAM_BOT_NAME);
$this->telegram->handle();
$data = [
'chat_id' => $this->data['user_id'],
'text' => $this->data['message'],
];
$result = Request::sendMessage($data);
} catch (TelegramException $e) {}
}
public function handle()
{
//
}
}
When I run the test in the console, I am getting HTML and CSS code. The other tests are running fine I have issue only with this one... Can any one help?
thank you
This is my DemoFeature
namespace app\tests\fixtures;
use yii\test\ActiveFixture;
class DemoFixture extends ActiveFixture{
public $modelClass = '\website\models\DemoForm';
}
and this is my DemoTest
namespace app\tests\unit;
use app\tests\fixtures\DemoFixture;
use website\models\DemoForm;
class DemoTest extends \Codeception\Test\Unit{
protected function _before() {
parent::_before();
}
public function _fixtures() {
return ['demo' => DemoFixture::className()];
}
protected function _after() {
}
public function testDemoProcess(){
$demo = new DemoForm;
$demo->name = 'Sample Name';
$demo->company = 'cloudadic'.rand(115, 54785);
$demo->email = 'demo'.rand(115, 547).'#example.com';
$demo->message = 'Sample Company';
$this->assertTrue($demo->save());
}
}
To start from the conclusion, I get this error:
[ErrorException]
Argument 1 passed to SomeValidatorTest::__construct() must be an instance of App\Services\Validators\SomeValidator, none given, called in ....vendor/phpunit/phpunit/src/Framework/TestSuite.php on line 475 and defined
In Laravel app, I have a script called "SomeValidator.php" which looks like this:
<?php namespace App\Services\Validators;
use App\Services\SomeDependency;
class SomeValidator implements ValidatorInterface
{
public function __construct(SomeDependency $someDependency)
{
$this->dependency = $someDependency;
}
public function someMethod($uid)
{
return $this->someOtherMethod($uid);
}
}
which runs without error.
Then the test script, SomeValidatorTest.php looks like this:
<?php
use App\Services\Validators\SomeValidator;
class SomeValidatorTest extends TestCase
{
public function __construct(SomeValidator $validator)
{
$this->validator = $validator;
}
public function testBasicExample()
{
$result = $this->validator->doSomething();
}
}
The error shows up only when the test script is ran through './vendor/bin/phpunit' The test class seems to be initiated without the dependency stated and throws an error. Does anyone know how to fix this? Thanks in advance.
You cannot inject classes into the tests (as far as i know), given that they are not resolved automatically by laravel/phpUnit.
The correct way is to make (resolve) them through laravel's app facade. Your test script should look like this:
<?php
class SomeValidatorTest extends TestCase
{
public function __construct()
{
$this->validator = \App::make('App\Services\Validators\SomeValidator');
}
public function testBasicExample()
{
$result = $this->validator->doSomething();
}
}
Source: http://laravel.com/docs/5.1/container
Laravel 4 ships with the php artisan routes command. This shows a list of registered routes on the command line. Instead of showing the registered routes on the command line, I would like to get its values within a controller.
The following method does exactly what I want:
Illuminate\Foundation\Console\RoutesCommand()
Unfortunately this is a protected method, so it doesn't work when I try something like this:
$rc = new Illuminate\Foundation\Console\RoutesCommand(new Illuminate\Routing\Router);
print_r($rc->getRoutes());
How can I access this method to display the registered routes in my Laravel 4 app?
Or even better; how can I access methods of any autoloaded service provider?
You can get all routes like this:
$routes = App::make('router')->getRoutes();
foreach($routes as $name => $route)
{
//do your stuff
}
I believe you would have to create a class that extends Illuminate\Foundation\Console\RoutesCommand and then you can run the method using print_r($this->getRoutes());
Here is a sample of how you can call an Artisan command from inside a Controller:
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\Output;
use Illuminate\Console\Application as ConsoleApplication;
class MyOutput extends Output {
protected $contents = '';
protected function doWrite($message, $newline)
{
$this->contents .= $message . ($newline ? "\n" : '');
}
public function __toString()
{
return $this->contents;
}
}
class MyController extends BaseController {
public function getRoutes()
{
$app = app();
$app->loadDeferredProviders();
$artisan = ConsoleApplication::start($app);
$command = $artisan->find('routes');
$input = new ArrayInput(array('command' => 'routes'));
$output = new MyOutput();
$command->run($input, $output);
return '<pre>' . $output . '</pre>';
}
}
In this case, the Artisan command is routes and we are not passing any parameter to it.