Closed JTD420 closed 3 years ago
Am I supposed to add a route for the webhook to work?
I have the config and .env setup with my token and tried setting the webhook url to my domain/webhook but no luck there!
Hello! This error tells that webhook url returns not found. To setup a webhook you need a route for that:
// WebhookController.php
...
public function webhook()
{
TeleBot::bot('your_bot')->handleUpdate();
}
...
// routes/web.php
Route::post('/webhook', [WebhookController::class, 'webhook']);
Be sure you correctly set your bot token and webhook url in config or .env:
// config/telebot.php
...
'your_bot' => [
'token' => '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11',
'webhook' => [
'url' => 'https://your-app.url/webhook'
]
]
...
Then when you run php artisan telebot:webhook -S
your webhook should be set.
Also, be sure that your webhook url is accessible for telegram servers. If you want to work with your bot localy, use php artisan telebot:polling -S
instead.
I think this guideline should be documented better or/and library should create routes by itself. Thanks for request!
Oh, also as I understand you are not able to even get webhook info. In this case, I assume there is something wrong with your token.
Oh, also as I understand you are not able to even get webhook info. In this case, I assume there is something wrong with your token.
Thanks for your fast response and help! - I was able to get the artisan commands working by installing an earlier version of Laravel on a clean OS with properly configured permissions and the code you provided above! (Was running Laravel 8, now switched to 6.x and seems to be working far more stable.)
I think this guideline should be documented better or/and library should create routes by itself. Thanks for request!
Yes I agree! The documentation seems a little bit confusing and hard to work out the different steps to take while using Laravel vs the Standalone guides..
Once I'm able to verify the steps needed to get it working, I'd be more than happy to give updating the documentation a try. :)
I've been messing around trying to follow the documentation and see if I could figure out how to get it all working but I'm stumped and have a few questions if you don't mind!
How do I add commands to the bot? I get the following error after trying to add a command and register it in the handler section of my config file..
WeStacks\TeleBot\Exception\TeleBotMehtodException : Given update handler type "app\Telegram\Commands\StartCommand" is not valid update handler
at /opt/bitnami/apache/htdocs/vendor/westacks/telebot/src/Exception/TeleBotMehtodException.php:14
10| }
11|
12| public static function wrongHandlerType(string $type)
13| {
> 14| return new TeleBotMehtodException("Given update handler type \"{$type}\" is not valid update handler", 404);
15| }
16| }
17|
And lastly, how do I respond to "non-commands"?
Example: User initiates bot with a command /start
Bot runs the Start Command which has logic to respond to user with "Hello, what's your name?" User is now expected to respond e.g "Brad" Bot then responds "Hi, Brad! Nice to meet you."
In above scenario the user is not providing a "/" or command but rather just responding to an already executed command. How would I handle this?
Thanks again for your help! Great to see a well supported and documented php/laravel Telegram Bot Framework 💯
For bot commands - check out #3. It seems like something is wrong with your namespace - app\Telegram\Commands\StartCommand
. App
should be capitalised in Laravel
Non commands working almost the same as commands - you should extend your handler from UpdateHandler
class instead of CommandHandler
and specify the trigger function as shown in docs. For you it should be something like this:
<?php
namespace Somewhere\InYour\App;
use WeStacks\TeleBot\Interfaces\UpdateHandler;
class NameMessageHandler extends UpdateHandler
{
public static function trigger(Update $update)
{
if (!$update->is('message')) return false; // Check if update is a message
$user = User::where('telegram_id', $update->from()->id)->first();
return ($user && $user->input == 'name_message'); // Checking user input state, which you should set after executing the command as you described
}
public function handle()
{
$name = $this->update->message->text;
$this->sendMessage([
'text' => "Hello, {$name}! Nice to meet you."
]);
}
}
The idea here is simple - you store what user should input in the database and then validate it inside the handler.
Also I think my example kinda rough, User model probably should be used not only inside one handler, so in order not to provoke unnecessary calls to the database you should add a closure handler in first position of handlers array:
function ($update) {
$user = User::where('telegram_id', $update->from()->id)->first();
if (!$user) {
// Create user if needed
}
...
Auth::login($user);
}
Then you will be able to access user anywhere using:
$user = Auth::user();
Also I'm not sure if laravel checks if there is already loged in user, so in long polling this may not work, need to test it out.
For bot commands - check out #3. It seems like something is wrong with your namespace -
app\Telegram\Commands\StartCommand
.App
should be capitalised in LaravelNon commands working almost the same as commands - you should extend your handler from
UpdateHandler
class instead ofCommandHandler
and specify the trigger function as shown in docs. For you it should be something like this:<?php namespace Somewhere\InYour\App; use WeStacks\TeleBot\Interfaces\UpdateHandler; class NameMessageHandler extends UpdateHandler { public static function trigger(Update $update) { if (!$update->is('message')) return false; // Check if update is a message $user = User::where('telegram_id', $update->from()->id)->first(); return ($user && $user->input == 'name_message'); // Checking user input state, which you should set after executing the command as you described } public function handle() { $name = $this->update->message->text; $this->sendMessage([ 'text' => "Hello, {$name}! Nice to meet you." ]); } }
The idea here is simple - you store what user should input in the database and then validate it inside the handler.
Hi, Thanks again for your help. That's my bad, I thought the namespace needed to be the same case as the folder. Changing it to a capital "App" as you suggested fixed the problem of registering my commands! :)
I'm still a little bit confused though, if I'm being honest... To begin with, so now I have the "StartCommand
" registered and showing up if I type "/
" on telegram along with the command names and descriptions so it's clearly communicating with the server now which is great!
What I don't understand is why if I send "/start" or "/s" I don't get a reply from the bot saying "hello world" like it seems it would from the handle() function..?
Have I missed something there needed to get it to work?
Also I think my example kinda rough, User model probably should be used not only inside one handler, so in order not to provoke unnecessary calls to the database you should add a closure handler in first position of handlers array:
function ($update) { $user = User::where('telegram_id', $update->from()->id)->first(); if (!$user) { // Create user if needed } ... Auth::login($user); }
Then you will be able to access user anywhere using:
$user = Auth::user();
Also I'm not sure if laravel checks if there is already loged in user, so in long polling this may not work, need to test it out.
I'm also not entirely sure how this part works? Are we basically creating a user in the DB if their telegram_id doesn't exist in there already along with the messages the user sends to us and then querying against it to determine what was sent?
If that's how it works, then I think that's incredibly smart, and something that definitely needs to be documented better! I was not aware that was a feature of this project...
Can you explain the Auth::login($user);
part?
I know laravel comes with a user scaffolding etc but I didn't think it was being used here.
Also;
you should add a closure handler in first position of handlers array: What file and where do you mean when you refer to the handlers array? Not the one in
Config/TeleBot.php
?
Thanks again for your help! In the meanwhile, I'll get started now on updating the documentation, with what I know and have done so far! -Brad :)
I've submitted a pull-request with the changes I've made to the documentation so far.
I've still not figured out why the StartCommand isn't sending hello world
back to the user but is registering the name and description on the telegram servers but once I figure out what I've missed, I'll add those steps to the documentation aswell so hopefully it's more clear how to get up and running! :D
-Brad
I'm also not entirely sure how this part works? Are we basically creating a user in the DB if their telegram_id doesn't exist in there already along with the messages the user sends to us and then querying against it to determine what was sent?
If that's how it works, then I think that's incredibly smart, and something that definitely needs to be documented better! I was not aware that was a feature of this project...
This actualy not the part of the project, it's a feature of Laravel itself - I just showed an example how you may use it to solve your task - we just attach telegram_id
to any Authenticatable
model and then use it as authorised user for our handlers, so we don't execute database query for each Telegram handler trigger function. The way handlers work is a simple foreach loop, so this is my optimization tip - it will slow down an application if you run User::get()
in each handler's trigger function, so its a good practice to avoid it.
What I don't understand is why if I send "/start" or "/s" I don't get a reply from the bot saying "hello world" like it seems it would from the handle() function..?
Have I missed something there needed to get it to work?
I think you forgot to setup a webhook or long polling. Notice that you can't run a webhook for local domains, so try out testing with polling if you run app localy.
What file and where do you mean when you refer to the handlers array? Not the one in
config/telebot.php
?
Yes, in config/telebot.php
. You may import it from other file in someway to make config cleaner.
I'm also not entirely sure how this part works? Are we basically creating a user in the DB if their telegram_id doesn't exist in there already along with the messages the user sends to us and then querying against it to determine what was sent? If that's how it works, then I think that's incredibly smart, and something that definitely needs to be documented better! I was not aware that was a feature of this project...
This actualy not the part of the project, it's a feature of Laravel itself - I just showed an example how you may use it to solve your task - we just attach
telegram_id
to anyAuthenticatable
model and then use it as authorised user for our handlers, so we don't execute database query for each Telegram handler trigger function. The way handlers work is a simple foreach loop, so this is my optimization tip - it will slow down an application if you runUser::get()
in each handler's trigger function, so its a good practice to avoid it.What I don't understand is why if I send "/start" or "/s" I don't get a reply from the bot saying "hello world" like it seems it would from the handle() function..? Have I missed something there needed to get it to work?
I think you forgot to setup a webhook or long polling. Notice that you can't run a webhook for local domains, so try out testing with polling if you run app localy.
What file and where do you mean when you refer to the handlers array? Not the one in
config/telebot.php
?Yes, in
config/telebot.php
. You may import it from other file in someway to make config cleaner.
I'm on my phone right now so sorry if reply is poorly formatted!
Thanks for clarifying, I will try and add your suggestions to my code and see if I can get the commands working!
I did actually setup a webhook address and included it in my routes... (Using a web-domain with https enabled and configured so DNS points to my web server...) So not sure why it's not working as one would expect...
Take a look at my pull request, specifically the guide.md file because I included my routes/web.php webhook code there aswell as the StartCommand.php code and how it's being called in the handlers array in TeleBot.php config file so maybe you'll spot where I messed up?
I think we should add your suggestion for using Laravels authenticateable model to store the telegram_id into the documentation aswell as I feel it would help a lot of users with many different uses!
Thanks again 💯🙌
I think we should add your suggestion for using Laravels authenticateable model to store the telegram_id into the documentation aswell as I feel it would help a lot of users with many different uses!
This is totaly depends on how developer designing his app, database and bot, so I don't think that this needs to be in the docs. There are many ways to solve this task: cache user, store it in singleton, use the middleware for webhook request, etc; I just showed the first thing I thought about for task you described using Laravel's features.
By the way this is common task for bot development, so I will try to think about more automated sollution for this
Starting from version 1.5.0 route for webhook is being generated automatically.
Hi,
I cant seem to get the webhook artisan command to work.. I can get the help command for it but it fails to execute no matter the options I try!
The error is more or less the same each time:
Any help appreciated! :)