botman io + laravel not continue conversations - php

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.

Related

irazasyed/telegram-bot-sdk get update object on commands

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

Laravel + Pusher Expected parameter 2 to be an array, string given in live chat

I've been following this blog post by pusher in their official site for building basic chat app with laravel + pusher.
I've followed every step thoroughly according to the blog, I'd search here and there as some details were not mentioned there.
I can send the message between users (save in DB table) but not updating in realtime in users end.
The below is the error message I get when I press send message button:
Here are the snippets from my code file that I have written.
Events/MessageSent.php
use App\User;
use App\Message;
class MessageSent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $user;
public $message;
public function __construct(User $user, Message $message)
{
$this->message = $message;
$this->user = $user;
}
public function broadcastOn()
{
return new PrivateChannel('chat');
}
}
Broutes/channels.php
Broadcast::channel('chat', function ($user) {
return Auth::check();
});
web.php
Auth::routes();
Route::get('/', 'ChatsController#index');
Route::get('messages', 'ChatsController#fetchMessages');
Route::post('messages', 'ChatsController#sendMessage');
ChatsController.php
use App\Events\MessageSent;
use App\Message;
use Illuminate\Http\Request;
use Auth;
class ChatsController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function index()
{
return view('chat');
}
public function fetchMessages()
{
return Message::with('user')->get();
}
public function sendMessage(Request $request)
{
$user = Auth::user();
$message = $user->messages()->create([
'message' => $request->message,
]);
broadcast(new MessageSent($user, $message))->toOthers();
return ['status' => 'Message Sent!'];
}
}
I'm using laravel version 5.5, pusher 6.1.
The blog post is written for laravel 5.4 and pusher 2.6.
Is version difference causing this issue ?
Thanks for the help.
The solution is to downgrade the pusher version.
composer require pusher/pusher-php-server ^4.1
will still be looking for the appropriate answer for latest version.

Laravel Botman issue - Can't call functions from the same class after nesting inside botman class

I am trying to use the native buttons and questions feature in Botman inside laravel, however i am struggling to understand how to chain functions without using static functions. I have it working where everything is a static function, however i want to use all the information gathered to send an email.
// initialization function
public function handle()
{
$botman->hears("{message}", function($botman, $message) {
$this->selectHelpQuery($botman);
});
}
// ask question function
public function selectHelpQuery($botman)
{
$question = Question::create("How can i help you, would you like to know about the following:")
->fallback("Unable to help at this time, please try again later")
->callbackId("choose_query")
->addButtons([
Button::create("button1")->value("val1"),
Button::create("button2")->value("val2"),
]);
$botman->ask($question, function (Answer $answer, $botman) {
// Detect if button was clicked:
if ($answer->isInteractiveMessageReply()) {
if($answer->getValue() == "val1")
{
$this->contactFollowUp($botman); //** not working
} else {
$this->contactNoFollowUp($botman); //** not working
}
}
});
}
// other functions.....
However without declaring the contactFollowUp() function as static and accessing it by using the classname BotManController::contactFollowUp($botman) However if i do this i have issues with accessing and setting data for use in other functions. Specifically i get a Method contactFollowUp does not exist error.
So, after finding some github code examples i have managed to work out the issue. It is to do with the way the botman framework is structured. To achive linked conversations you have to use a function from the botman framework called startConversation() to envoke this you need to reference bot which is from the extended base class Conversation. So you will need an entry point and then the conversation you want to link to like so:
*note you will need the default entry point of run() for each conversation.
//BotManController.php
<?php
namespace App\Http\Controllers\Chatbot;
use App\Http\Controllers\Controller;
use BotMan\BotMan\BotMan;
use Illuminate\Http\Request;
use BotMan\BotMan\Messages\Incoming\Answer;
use BotMan\BotMan\Messages\Outgoing\Actions\Button;
use BotMan\BotMan\Messages\Outgoing\Question;
class BotManController extends Controller
{
/**
* start the conversation on intitlization
*/
public function handle()
{
$botman = app("botman");
$botman->hears("{message}", function($botman, $message) {
$botman->startConversation(new BotManStart);
});
$botman->listen();
}
}
Then
// BotManStart.php
<?php
namespace App\Http\Controllers\Chatbot;
use BotMan\BotMan\BotMan;
use Illuminate\Http\Request;
use BotMan\BotMan\Messages\Incoming\Answer;
use BotMan\BotMan\Messages\Outgoing\Actions\Button;
use BotMan\BotMan\Messages\Outgoing\Question;
use BotMan\BotMan\Messages\Conversations\Conversation;
class BotManStart extends Conversation
{
public function run()
{
$this->selectHelpQuery();
}
public function selectHelpQuery()
{
$question = Question::create("How can i help you, would you like to know about the following: ")
->fallback("Unable to help at this time, please try again later")
->callbackId("choose_query")
->addButtons([
Button::create("Button 1")->value("button1"),
Button::create("Button 2")->value("button2"),
]);
$this->ask($question, function (Answer $answer) {
if ($answer->isInteractiveMessageReply()) {
switch ($answer->getValue()) {
case "button1":
$this->bot->startConversation(new BotManConversation1());
break;
case "button2":
$this->bot->startConversation(new BotManConversation2());
break;
}
}
});
}
}

Receive Notificatoin Pusher + Echo in Laravel

I am trying to receive notification using echo + pusher. I can post to pusher and pusher console receive the event and channel but i can't get this data on laravel. I read many documents, but none of them work for me.
WebNotification Class // Notification file
private $subscription;
public function __construct($data)
{
$this->subscription = $data;
}
public function via($notifiable)
{
return ['database','broadcast'];
}
public function toBroadcast($notifiable)
{
return new BroadcastMessage([
'data' => $this->subscription,
'count' => $notifiable->unreadNotifications->count()
]);
}
Account Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\Notifiable;
class account extends Model
{
use Notifiable;
public function receivesBroadcastNotificationsOn()
{
return 'accounts.'.$this->id;
}
}
MyNotification // To call event to send data to pusher
public function DatabaseNot(){
$user = Account::where('id', Cookie::get('uid'))->first();
$data = collect(['title'=>'Hello Title', 'body'=>'my body']);
$user->notify(new WebNotification($data));
return view('layout.test',['user'=>$user]);
}
Pusher log
Channel: private-accounts.23, Event: Illuminate\Notifications\Events\BroadcastNotificationCreated
I call Echo in resorces/js/app.js
Echo.private('App.accounts.23')
.notification((notification) => {
console.log(notification.type);
});
I did not get any response from this.
I already add csrf token in meta, I compiled js code using NPM run watch. I tried many other ways, no one provide clear document, its so confusing.

Having some trouble understanding Facades and Service Providers

I've been reading the documentation up and down now, still not sure what I'm doing wrong. In my opinion the documentation is very difficult to understand for a beginner.
Anyway, I'm trying to make something akin to the Auth::user() method, where it returns additional data about a logged in user that I will be needing for this application.
I have this helper class here:
namespace App\Helpers;
use Auth;
use Illuminate\Http\Request;
use App\Models\Grouping\User;
use App\Models\Grouping\Client;
use App\Models\Grouping\Rank;
class ClientUser {
public function __construct($request) {
$this->request = $request;
}
public function client() {
return Client::find($this->request->session()->get('client_id'));
}
public function auth() {
if (Auth::check()) {
// Get the client
$client = $this->client();
// Get the client's user
$user = $client->users()->find(Auth::user()['id']);
// Get the rank of the logged in user
$rank = Rank::find($user->pivot->rank_id);
return [
'user' => $user,
'rank' => $rank,
'client' => $client
];
}
return null;
}
}
This is responsible for doing what I described, returning additional data that I can't get through Auth::user(). Now I'm trying to register this class in the AuthServiceProvider
public function register()
{
// Register client auth
$request = $this->app->request;
$this->app->singleton(ClientUser::class, function ($app) {
return new ClientUser($request);
});
}
Now what I don't understand is how I'm supposed to make this globally accessible throughout my app like Auth::user() is.
The problem with just making "importing" it is that it needs the request object, which is why I'm passing it through the service container.
Now here's where I'm stuck. I'm not able to access app in my controller or anywhere, and I can't define a Facade because a Facade expects you to return a string of the bound service that it should "alias?"
Change your service provider like this :
$this->app->bind('client.user', function ($app) {
return new ClientUser($app->request);
});
Create another class extended from Illuminate\Support\Facades\Facade.
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class ClientUserFacade extends Facade {
public static function getFacadeAccessor(){
return "client.user";
}
}
Add 'ClientUser => ClientUserFacade::class in alias key of app.php

Categories