php-telegram-bot / core

PHP Telegram Bot based on the official Telegram Bot API
MIT License
3.89k stars 955 forks source link

Cannot create custom commands #187

Closed mitchelvanbever closed 8 years ago

mitchelvanbever commented 8 years ago

Hi Guys, first off thanks for the good work.

However I'm running into an issue. I have tried following the tutorial in the wiki on how to create custom commands.

I'm trying to use a custom directory. However when I try to hook this custom path, none of the preset commands work and no response on my custom command. I have followed the naming conventions TestCommand.php etc.

Whenever I add my own TestCommand.php to your src in /vendor/autoload, none of the preset, nor my own command work.

Please help me. Excuse me for my bad grammar and markup.

Thanks in advance!

in my bot.php

$commands_path = __DIR__ .'/../Commands/';
$telegram->addCommandsPath($commands_path);

In my TestCommand.php in /../Commands/

<?php
namespace Longman\TelegramBot\Commands;

require __DIR__ . '/../vendor/autoload.php';

use Longman\TelegramBot\Request;
use Longman\TelegramBot\Entities\Update;

class TestCommand extends Command
{
    protected $name = 'test';                      //your command's name
    protected $description = 'Send test message'; //Your command description
    protected $usage = '/test';                    // Usage of your command
    //protected $version = '1.0.0';                  
    protected $enabled = true;
    //protected $public = true;

    public function execute()
    {
        $update = $this->getUpdate();                //get Updates
        $message = $this->getMessage();              // get Message info

        //$chatId = '9767300';

        $chat_id = $message->getChat()->getId();     //Get Chat Id
        $message_id = $message->getMessageId();      //Get message Id
        //$text = $message->getText(true);           //Get recieved text

        $data = array();                             // prepapre $data
        $data['chat_id'] = $chat_id;                 //set chat Id
        $data['reply_to_message_id'] = $message_id;  //set message Id
        $data['text'] = 'This is just a Test...';    //set reply message

        $result = Request::sendMessage($data);       //send message

        return $result;
     }
}

?>
jacklul commented 8 years ago

My first bet is wrong definition:

Use class TestCommand extends UserCommand class TestCommand extends SystemCommand class TestCommand extends AdminCommand instead, depending on the type of the command.

MBoretto commented 8 years ago

https://github.com/akalongman/php-telegram-bot/wiki/Create-your-own-commands

mitchelvanbever commented 8 years ago

@jacklul Thanks for your quick reaction. If I change the definition to UserCommand, should I create a new folder within my custom Commands folder, called UserCommands (as seen in the src of the API).

@MBoretto That's the tutorial I followed. Couldn't get it to work.

jacklul commented 8 years ago

@jacklul Thanks for your quick reaction. If I change the definition to UserCommand, should I create a new folder within my custom Commands folder, called UserCommands (as seen in the src of the API).

No, I don't think subdirectories are scanned for commands.

mitchelvanbever commented 8 years ago

@jacklul Ok thanks again for the quick reply. Changing the definitions did nothing for me. I have also tried to copy EchoCommand for the src to my custom directory however still no luck. Is it also possible to add custom commands to the src files of the API (so bypassing the custom command directory option, since it was marked as optional step in the WIKI)? <-- Confirmed to not work, as changes to the src wil make it so none of the preset command work.

jacklul commented 8 years ago

Did you double check the custom commands path? It should be in the same folder as hook.php or getUpdatesCLI.php when using $commands_path = __DIR__ . '/Commands/';

However, In the code you provided there is $commands_path = __DIR__ .'/../Commands/';, which exits the directory containing hook.php or getUpdatesCLI.php.

Why are you placing require __DIR__ . '/../vendor/autoload.php'; in command file?

This is how my test command looks like and works in custom commands folder:

<?php

namespace Longman\TelegramBot\Commands\UserCommands;

use Longman\TelegramBot\Commands\UserCommand;
use Longman\TelegramBot\Request;

class TestCommand extends UserCommand
{
    protected $name = 'test';
    protected $description = 'test';
    protected $usage = '/test';
    protected $version = '1';

    public function execute()
    {
        return Request::sendMessage(['chat_id' => $this->getMessage()->getChat()->getId(), 'text' => 'test123']);
    }
}
mitchelvanbever commented 8 years ago

My directory is as follows, www/MAINBOTFOLDER in this folder there are three different directories ; BOT, Commands, Vendor.

So that's why I have $commands_path = DIR .'/../Commands/';

If I don't run require DIR . '/../vendor/autoload.php';, I get the following error "Fatal error: Class 'Longman\TelegramBot\Commands\UserCommand' not found etc.."

Thanks for your TestCommand.php could you elaborate on where you're commands folder is within your project?

jacklul commented 8 years ago

I think you're using bad folders structure.

Try to adjust your structure to the following:

-ROOT
 |-commands
   |-TestCommand.php
 |-bot
   |-src
     |-Telegram.php
     |-(...)
   |-vendor
 |-hook.php / getUpdatesCLI.php
mitchelvanbever commented 8 years ago

I don't understand, should I move the src folder from /vendor/longman/telegram-bot to /root/bot ? As well as the vendor folder?

mitchelvanbever commented 8 years ago

currently my folder structure is

-root
  |-Commands
  |-Bot
  |-Vendor
|- bot.php (which contains code from hook.php)
jacklul commented 8 years ago

I just posted you mine structure, for comparison.

Have you tried setting the custom commands path as full path? Example: $commands_path = '/home/root/www/bot/Commands/';

mitchelvanbever commented 8 years ago

Yes have tried that. Could it have something to with permissions on the files? Is it normal behaviour for the API to lose preset commands as soon as you add the custom commands_path?

jacklul commented 8 years ago

Still the thing that you have to place require __DIR__ . '/../vendor/autoload.php'; in command file is a bit weird.

I'm out of ideas.

mitchelvanbever commented 8 years ago

If I don't put the require part in, I get the : Fatal error: Class 'Longman\TelegramBot\Commands\UserCommand' not found in / error.

But it could be that the namespace couldn't be defined either since it comes before the require part..

Thanks for your help and quick response though!

jacklul commented 8 years ago

If I don't put the require part in, I get the : Fatal error: Class 'Longman\TelegramBot\Commands\UserCommand' not found in / error.

All I'm saying is that if everything is installed correcly you shouldn't have to do this.

noplanman commented 8 years ago

@MrBamBam The require only needs to be in your hook.php file, nowhere else! If you get the error, it means that the path in your hook.php is wrong. Could you paste your hook.php file for us to check? (remember to remove the API key and bot name!)

mitchelvanbever commented 8 years ago

@noplanman

here is my bot.php which contains the hook.php stuff.

<?php
    error_reporting(E_ALL);
    ini_set('display_errors', '1');     

    // Load composer
    require __DIR__ . '/vendor/autoload.php';

    $API_KEY = 'something';
    $BOT_NAME = 'something';
    $commands_path = __DIR__ .'/Commands/';

    $update = file_get_contents('php://input');
    $update = json_decode($update, TRUE);

    $chatId = $update["message"]["chat"]["id"];
    $message = $update["message"]["text"];

    try
    {
        $telegram = new Longman\TelegramBot\Telegram($API_KEY, $BOT_NAME);
        $telegram->enableAdmins(['something']);
        $telegram->addCommandsPath($commands_path);
        $telegram->handle();
    }

    catch(Longman\TelegramBot\Exception\TelegramException $e)
    {

    }

?>
noplanman commented 8 years ago

Hmmm, strange. This should work. So basically the problem is that the custom commands don't work, right? The default commands all work fine?

mitchelvanbever commented 8 years ago

the default commands work as long as I don't set my "$telegram->addCommandsPath($commands_path);"

custom commands don't work when I set my custom command path.

sorry for the mistake before.

noplanman commented 8 years ago

Try to activate the logs (in your bot.php) and see if something comes up:

$telegram->setLogRequests(true);
$telegram->setLogPath($BOT_NAME . '.log');
$telegram->setLogVerbosity(3);
Logger::initialize('TelegramException.log');
mitchelvanbever commented 8 years ago

it does not give me anything. But running bot.php tells me why ; Fatal error: Class 'Logger' not found in. So I guess you guys are right about the fact that I did not install de API properly or something..?

edit 18-05-2016 11:20: Strange thing is I do have a TelegramException.log, which only contains a few errors from the days before. Not containing any errors on the current commands directory.

mitchelvanbever commented 8 years ago

First of all thanks for taking the time to reply to this issue. I now know that this might not have been the appropriate place to post this question since I firmly believe that the issue has to do with my file structure or composer, running on my synology server, not in any way shape or form I blame this beautiful API.

Okay I got the logger to produce a log under the name 'mybotname'.log by removing "//Logger::initialize('TelegramException.log');" from the file that contains the hook. It doesn't however state any errors as far as I could tell. It only shows the info on the message that was sent to- and from the bot. When I don't add my Commandspath the bot reply's with command not found, when I add the CommandsPath, the bot won't produce a response.

Also checked my autoload_psr.php to be sure. Nothing seems out of the ordinary there.

<?php

// autoload_psr4.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'Longman\\TelegramBot\\' => array($vendorDir . '/longman/telegram-bot/src'),
);

Also edited my directory to be look like the one that @jacklul suggested (uses).

Still no luck.

mitchelvanbever commented 8 years ago

Okay, created an instance of Logger $logger = new Longman\TelegramBot\Logger();

Now I got my logs up and running.

Situation; sending /echo to the bot Triggers; `2016-05-18 18:26:16 exception 'Longman\TelegramBot\Exception\TelegramException' with message 'Input is empty!' in /root/www/bot/src/telegram.php/vendor/longman/telegram-bot/src/Telegram.php:414 Stack trace:

0 /root/www/bot/src/telegram.php(45): Longman\TelegramBot\Telegram->handle()

1 {main}

No response (not even the errorCommand usage: /echo .`)

Situation; sending /test to the bot Triggers; no exception or response

noplanman commented 8 years ago

I now know that this might not have been the appropriate place to post this question

This is absolutely the perfect place to post the question 😃👍

So weird that you get an empty input using the /echo command. Does any command give you anything back at all? What PHP version are you running?

I really don't think the file structure is the problem, since mine is exactly as yours was initially...

mitchelvanbever commented 8 years ago

@noplanman Thanks for clarifying!

As long as I don't set $telegram->addCommandsPath($commands_path); every preset UserCommand works. I.E /weather /echo /help. As soon as I set $telegram->addCommandsPath($commands_path);, there is no response on any command which contain TestCommand.php and EchoCommand.php. (I Copied EchoCommand.php from vendor/../../src/Commands/UserCommands to my custom dir).

mitchelvanbever commented 8 years ago

@noplanman my PHP version is PHP version: 5.5.30

p.s since you use the same structure as I did, I rolled back to my old filestructure.

noplanman commented 8 years ago

@MrBamBam Right, PHP version should be fine.

Do your Apache system logs say anything? Just SSH into your DiskStation and check in the /var/log/ folder for the httpd logs.

Could it have something to with permissions on the files?

Possible I guess, just make sure they have the same rights as your other bot files (which they probably already do)

mitchelvanbever commented 8 years ago

@noplanman just upgraded my DSM to 6.0 which provided me with PHP 5.6.20.

Which one of the logs would like me to check? The user-acces_log show no POST's from TelegramBot.

Permissions are indeed already the same as the others.

noplanman commented 8 years ago

I thought the Apache access and error logs, to see if there is maybe an error occurring before it even hits the Telegram library.

Would you mind sharing your setup a bit more?

I'll try to set up a bot on my DS too when I have the chance to, to see if I can get it to run normally.

mitchelvanbever commented 8 years ago

@noplanman Nope nothing regarding the telegram Bot in the apache logs.

Mmm not really sure what info would be useful.

Note that the bot does work. I can receive incoming messages and send messages with it. It is just that when I try to add a custom commands path, with these two lines : $commands_path = __DIR__ .'/../Commands/'; $telegram->addCommandsPath($commands_path); , the bot stops responding.

Those preset commands, should they work after you've added the addCommandsPath? Or are the preset Commands replaced by the commands in you're custom Commands folder? If so, this would probably indicate that the bot works fine, however that the Custom Commands are just not working (probably because of the class not found thing).

Thanks for the help thus far!

noplanman commented 8 years ago

I've set up a bot on my virtual DS3615xs (using XPEnology), which is running DSM 5.2-5592 with PHP 5.5.26 and it's working perfectly!

Are you sure that the permissions are correct? In your DSM, enable the output of PHP errors: Web Services -> PHP Settings, check the box Enable display_errors

In your browser, just open https://link-to-bot/hook.php (or bot.php as you have it) directly. What output do you get there?

In a nutshell, the bot first looks for the called command in the custom folders, then in the internal one. (Check the new command structure to get more info!)

mitchelvanbever commented 8 years ago

@noplanman First of all thanks for all the effort you put in to help me resolve this issue! It is greatly appreciated!

I'm not a 100% sure about the permissions, but as far as I could tell every folder/file had r+w permissions.
In DSM 6 web services is gone from the settings menu.

I'm running this error_reporting(E_ALL); ini_set('display_errors', '1'); in bot.php. Whenever I open bot.php in the browser there are no errors. (except for the previous error from the logger which I fixed by adding ; $logger = new Longman\TelegramBot\Logger();.

mitchelvanbever commented 8 years ago

Found one error concerning the telegrambot in the user-error_log FastCGI: server "/php-fpm-handler" stderr: PHP message: PHP Fatal error: Class 'Longman\\TelegramBot\\Commands\\UserCommand' not found in /root/www/Bot/Commands/TestCommand.php

noplanman commented 8 years ago

Could you post your TestCommand.php? Seems to be something wrong there.

mitchelvanbever commented 8 years ago
<?php
namespace Longman\TelegramBot\Commands\UserCommands;

use Longman\TelegramBot\Commands\UserCommand;
use Longman\TelegramBot\Request;

class TestCommand extends UserCommand
{
    protected $name = 'test';
    protected $description = 'test';
    protected $usage = '/test';
    protected $version = '1';

    public function execute()
    {
        return Request::sendMessage(['chat_id' => $this->getMessage()->getChat()->getId(), 'text' => 'test123']);
    }
}

?>
mitchelvanbever commented 8 years ago

wow it works, it was due to a file in my custom Commands folder that wasn't done yet. I moved the file, now the only two in the Commands folder are EchoCommand and TestCommand both of those work now.

Thank you all for investing the time to investigate this matter with me.

noplanman commented 8 years ago

You're not gonna get away that easily 😉

What did you change to make it work? I'm curious to learn in case something like this happens again.

Also, so that if somebody else has this issue, at least there is a solution around!

mitchelvanbever commented 8 years ago

@noplanman haha it's the least I can do.

But really I'm not certain when it started working. However I will post the steps/alterations I have made since opening the issue and where I think it came back to life!

  1. Compared my file structure with suggestions you guys have made and with other projects on my NAS. I now have the following structure:
|-ROOT
 |-bot.php (containing hook etc)
 |-Commands
   |-TestCommand.php
 |-Bot
   |-set.php
   |-unset.php
 |-composer (added this folder, moved composer.json/composer.lock/composer.phar from ROOT to here)
   |-composer.json
   |-vendor
      |-autoload.php
      |-longman
        |-telegram-bot
         |-src

Guess #1 Missed the composer Folder which made my autoload.php not load the right directory(since composer didn't exist)?

  1. Upgraded my DSM to 6.0 which implemented an upgrade of PHP to a newer version.
  2. Changed permissions on newly created composer folder
  3. Moved a W.I.P Command from the Command folder to the root directory

_Guess #2 _ Error generated by my W.I.P command was causing havoc.

After testing the bot after step 4 I noticed the bot replied as it should. Even on the preset commands.

Hope this helps, if there any further questions or inquiries please don't be hesitant to ask. I will answer to the best of my knowledge.

Again thanks for all the help, time and effort @noplanman, @jacklul , @MBoretto ! 💯

noplanman commented 8 years ago

Missed the composer Folder which made my autoload.php not load the right directory

I think this (or the permissions maybe) is the most likely. Next time, we'll make sure that the project is set up correctly using composer 👍

Thanks for enduring and great that it's working now 🎉

mitchelvanbever commented 8 years ago

No problem at all! Thank you guys for the great framework and the great support!