php-telegram-bot / core

PHP Telegram Bot based on the official Telegram Bot API
MIT License
3.88k stars 953 forks source link

Raw Message Data #191

Closed deios0 closed 8 years ago

deios0 commented 8 years ago

I want to add Botan.io statistics to my bot. There is a piece of documentation from the site:

$messageObj = json_decode($message_json, true);
$messageData = $messageObj['message'];

$botan = new Botan($this->token);
$botan->track($messageData, 'Start');

How can I get $messageData with your SDK? Or perhaps you can recommend another statistic platform.

Thank you!

jacklul commented 8 years ago

This is how I integrated it in my bots:

changes in Telegram.php

    public function executeCommand($command)
    {
        $command_obj = $this->getCommandObject($command);

        if (!$command_obj || !$command_obj->isEnabled()) {
            //Failsafe in case the Generic command can't be found
            if ($command === 'Generic') {
                throw new TelegramException('Generic command missing!');
            }

            //Handle a generic command or non existing one
            $this->last_command_response = $this->executeCommand('Generic');
        } else {
            //execute() method is executed after preExecute()
            //This is to prevent executing a DB query without a valid connection
            $this->last_command_response = $command_obj->preExecute();

            $this->botanTrack($this->input, $command);
        }

        return $this->last_command_response;
    }

    /**
     * Botan.io track code
     *
     * @param $input
     * @param $command
     */
    private function botanTrack($input, $command)
    {
        $obj = json_decode($input, true);
        if (isset($obj['message']) && $obj['message']['from']['username'] != $this->bot_name && strtolower($command) != 'generic' && strtolower($command) != 'genericmessage') {
            $data = $obj['message'];

            if ($obj['message']['entities'][0]['type'] == 'bot_command') {
                $event_name = 'Command (/'.strtolower($command).')';
            } elseif ($obj['message']['chat']['type'] == 'private') {
                $event_name = 'Message';
            }
        } elseif (isset($obj['inline_query'])) {
            $data = $obj['inline_query'];
            $event_name = 'InlineQuery';
        } elseif (isset($obj['chosen_inline_result'])) {
            $data = $obj['chosen_inline_result'];
            $event_name = 'ChosenInlineResult';
        } elseif (isset($obj['callback_query'])) {
            $data = $obj['callback_query'];
            $event_name = 'CallbackQuery';
        }

        if (!empty($event_name) && !empty($data)) {
            $botan = new Botan();
            $botan->track($data, $event_name);
        }
    }

and this should be placed where Telegram.php is:

Botan.php

<?php

namespace Longman\TelegramBot;

class Botan
{
    protected $track_url = 'https://api.botan.io/track?token=#TOKEN&uid=#UID&name=#NAME';
    protected $shortener_url = 'https://api.botan.io/s/?token=#TOKEN&user_ids=#UID&url=#URL';

    protected $token = '';

    public function track($message, $event_name = 'Message')
    {
        $uid = $message['from']['id'];
        $url = str_replace(
            ['#TOKEN', '#UID', '#NAME'],
            [$this->token, $uid, urlencode($event_name)],
            $this->track_url
        );

        $options = [
            'http' => [
                'header'  => 'Content-Type: application/json',
                'method'  => 'POST',
                'content' => json_encode($message),
                'ignore_errors' => true
            ]
        ];

        $context = stream_context_create($options);
        $response = @file_get_contents($url, false, $context);
        $responseData = json_decode($response, true);

        return $responseData;
    }

    public function shortenUrl($url, $user_id)
    {
        $url = str_replace(
            ['#TOKEN', '#UID', '#URL'],
            [$this->token, $user_id, urlencode($url)],
            $this->shortener_url
        );

        $options = [
            'http' => [
                'ignore_errors' => true
            ]
        ];

        $context = stream_context_create($options);
        $response = @file_get_contents($url, false, $context);

        return $response === false ? $url : $response;
    }
}

Remember to set your track token in it.

Why silencing errors (@file_get_contents): very often botan API is overloaded and returns error, this does not affect your bot functionality and thats why you shouldn't care about those errors. Of course if you come into issues where it doesnt send statistics you should unsilence file_get_contents for debug purposes.

@akalongman @MBoretto @noplanman We could add build-in support for botan.io in the library, what you guys think?

MBoretto commented 8 years ago

I never use it so far, I have to say that I don't know exactly what it does (maybe you can explain a bit more the advantages ;) )

jacklul commented 8 years ago

Usage could be optional, but it's really good platform to track what commands are executed the most or what types or updates are used, in addition to access to the stats from botaniobot you can also view them on AppMetrica website.

MBoretto commented 8 years ago

Wow! seems interesting, I will support the introduction, seems also already done ;)

noplanman commented 8 years ago

Just had a quick look at it and I don't think it's a question any more if we're going to add it! Looks amazing!

@jacklul Would you like to create a new issue dedicated to this? That'd be great 😊

deios0 commented 8 years ago

@noplanman then should I wait for your implementation or do it myself?

@jackul thanks a lot again for your advice!

noplanman commented 8 years ago

@deios0 Feel free to implement this 👍 Maybe even join up with @jacklul and discuss it in #194

deios0 commented 8 years ago

@jacklul I used your code and got an error:

[2016-05-20 07:12:17] prod.ERROR: ErrorException: Undefined index: entities in /vendor/longman/telegram-bot/src/Telegram.php:533

and here is a code on 533:

if ($obj['message']['entities'][0]['type'] == 'bot_command') {
    $event_name = 'Command (/' . strtolower($command) . ')';
} elseif ($obj['message']['chat']['type'] == 'private') {
    $event_name = 'Message';
}

Do you have any ideas?

jacklul commented 8 years ago

@deios0 Well, that shouldn't happen, Telegram API request should contain entities field, for failsafe you can try replacing the line with

if ((isset($obj['message']['entities']) && $obj['message']['entities'][0]['type'] == 'bot_command') || substr($obj['message']['text'], 0, 1) == '/')

Currently working on official integration, if everything will work as expected I'm gonna push this to develop soon!

deios0 commented 8 years ago

Ok! Will implement your fix and wait for official integration)

jacklul commented 8 years ago

Implemented in https://github.com/akalongman/php-telegram-bot/commit/771a5061caff808df53ea1046367c58941906c91

Use https://github.com/akalongman/php-telegram-bot/issues/194 for discussion