defstudio / telegraph

Telegraph is a Laravel package for fluently interacting with Telegram Bots
MIT License
702 stars 116 forks source link

Perhaps we can optimize the implementation of the `action` and `param` method of Button in Keyboard #576

Closed MoLeft closed 1 week ago

MoLeft commented 7 months ago

Under normal circumstances, when creating a Keyboard, we might write it like this:

$keyboard = Keyboard::make()->row([
    Button::make('A button')->action('keyboard_callback_method')->param('data', 'test')
]);
$result = $this->chat->message("keyboard example")->keyboard($keyboard)->send();

We can then use this->data->get('data') in keyboard_callback_method to get the value of data. When making the request to the Telegram URL, it might transform into this format:

action:keyboard_callback_method|data:test

However, I've noticed an issue with this. Telegram doesn't allow this value to exceed 64 characters in length, so we can't use it to pass a lot of data.

In Laravel , I've implemented three methods like this to handle large amounts of data:

class Handler extends WebhookHandler
{

    protected function put($args): string
    {
        $key = md5(serialize($args));
        if (cache()->get($key)) {
            return $key;
        }
        cache()->put($key, $args);
        return $key;
    }

    protected function get($key, $default = null)
    {
        if(cache()->has($key) === false) return $default;
        return cache()->get($key);
    }

    protected function update($key, $data): void
    {
        if(cache()->has($key) === false) return;
        $origin_data = cache()->get($key);
        cache()->put($key, array_replace($origin_data, $data));
    }

}

This allows us to set and get data like this:

// set data
$data = $this->put([
    'message_id' => $messageId,
    'model' => $this->chat
]);
$keyboard = Keyboard::make()->row([
    Button::make('A button')->action('keyboard_callback_method')->param('data', $data)
]);
$result = $this->chat->message("keyboard example")->keyboard($keyboard)->send();

// get data
data = $this->get($this->data->get('data'));

Although this seems like a solution, it's still not perfect. I hope Telegram can come up with a more ideal solution.

fabio-ivona commented 7 months ago

Hi @MoLeft I think you are moving toward a solution to the problem, but I think cache is not the best way in this case: what would happen if cache gets cleared before the webhook response is received?

maybe using Telegraph storage system for a stronger persistence?

feel free to open a PR for this and we can work on it ;)