php-telegram-bot / core

PHP Telegram Bot based on the official Telegram Bot API
MIT License
3.86k stars 951 forks source link

[question] Please provide an example #384

Closed seyfer closed 7 years ago

seyfer commented 7 years ago

https://github.com/akalongman/php-telegram-bot#mysql-storage-recommended

Please, provide some use-case or example to this part of the documentation. Any working example to understand why a developer would save messages and how it's possible to use them later.

Is it helpful for creating a step by step process? For example some initialization. Need example.

seyfer commented 7 years ago

The MySQL database must be active!

Why? I have chosen another lib just because of this MySQL requirement. Here is irazasyed/telegram-bot-sdk and it's getUpdates mode doesn't require MySQL.

noplanman commented 7 years ago

Hi @seyfer

The MySQL requirement is necessary to handle the getUpdates properly. By saving each update request, we can easily only get the latest updates. Just using the getUpdates method directly, without the offset parameter will give you all the latest unhandled updates. So you need to save the ID of the latest update somewhere, else the same results will be returned with each call.

Using the telegram-bot-sdk, how exactly do you fetch the latests updates with getUpdates?

Theoretically, if you remember which update ID offset you're on, you wouldn't require the MySQL database, but then you'd be saving it in a file or some other place. Keeping track of all updates and messages in a database gives you the versatility of using that data for other operations, statistics for example (if you don't use botan).

Also, things like conversations with the bot wouldn't be possible, as the state of the conversation needs to be remembered somewhere.

Hope this explains it a bit. Feel free to ask more questions! :smiley:

seyfer commented 7 years ago

@noplanman , thank you for an answer.

I agree with a case for custom statistics.

With telegram-bot-sdk I'm developing bot like in stateless mode. When bot starts it will receive in cycle 50 messages pack and process it one by one. It doesn't matter what update ID is latest, because if it's a command - it will be processed as a command. Another text - as text. No needs to remember this ID in a usual situation (or I can't see it). When bot stops and starts again - it continues processing next messages.

For processing conversations, I'm using special processors classes with custom logic. For example, if I need initialization process with several steps I'm doing InitializationModeProcessor with custom logic. User start it with /init command and it will be active until finish or reset (by /start). While InitMode is active I could store needed information in DB or Redis, etc. (current step of the process and accumulated info)

While running bot receiving updates and answering it immediately, so it always knows userId, chatId and messageId at the moment when it needs to answer.

How MySQL helps to build conversations in akalongman/php-telegram-bot? I can't see it, that's why I'm asking for example.

noplanman commented 7 years ago

Take a look at the /survey command. All user input is saved into the notes field in the database in JSON format.

Of course you could use any other storage option, it doesn't have to be MySQL, but we chose it for convenience and because most (shared) hosts have it available with no extra installation necessary.

start it with /init command and it will be active until finish or reset

So your script is always running in the background? What if the user (or 1000s of users) starts the conversation and never ends it?

jacklul commented 7 years ago

Using the telegram-bot-sdk, how exactly do you fetch the latests updates with getUpdates?

@noplanman , I think setting offset to something really high (like '999999999999') will return unanswered updates from the API, that's how I assumed this worked when I tested it sometime ago, can't speak for sure though! It might be worth a while looking into this, so we could have non-db getUpdates (also having sqlite state.db file might work too!)

Also, in a topic: does the current conversation implementation allows getting values from conversions of different commands? It might be useful in some cases (when conversation migrates to different command, might be worth having something like migrate($new_chat_id) implemented!

noplanman commented 7 years ago

Had a quick look into the other library and found this.

It basically calls getUpdates twice, first to fetch the updates, second to set the offset and mark the requests as handled.

Regarding the conversations, once you have access to the DB you can get any info you want. Or what do you mean?

seyfer commented 7 years ago

What if the user (or 1000s of users) starts the conversation and never ends it?

It depends on logic which will be implemented. This 1000s userIds could be stored in storage forever or been cleaned after some period of time. Or I didn't get the problem?

Thank you for /survey example, I have missed it. Now I see Conversation class and ConversationDB. Nice implementation. I'm doing the same, but by myself and I'm not bounded to MySQL. I can't see a way to use my own adapter because there is no Interface usage in code, it's too bounded.

Had a quick look into the other library and found this.

Their latest branch is develop, which will lead to v3 soon.

seyfer commented 7 years ago

@noplanman latest version getUpdates is this one.

noplanman commented 7 years ago

@seyfer The code has moved here and it's essentially the same. Not that it makes a big difference though.

I see they have changed their code base quite a lot since their initial version!

I can't see a way to use my own adapter

Unfortunately so... We need a rewrite of that at some point, to make it more flexible.

seyfer commented 7 years ago

My proposal is something like that:

StorageAdapterInterface
- MySQLAdapter
- RedisAdapter
etc.

StorageInterface
- ConversationStorage
- ConversationStorage::setAdapter(StorageAdapterInterface)

Conversation
- Conversation::setStorage(StorageInterface)

This structure will separate infrastructure dependencies from domain logic and give a possibility to use own implementations of Interfaces.

noplanman commented 7 years ago

@seyfer We've moved all example command to the example-bot repository, where we will also be creating example to illustrate all bot features.

As for your latest comments, still nothing has been done 😕

I'll link this issue to your other one (#170) and close off here.