php-telegram-bot / core

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

Reply to chat member when he writes two messages in a row #652

Closed land0r closed 6 years ago

land0r commented 6 years ago

Required Information

Expected behaviour

I need some custom functions for my bot. What I need? Example, user write two messages in a row (one and at once another) - two messages from one chat member standing nearby. Bot reply to the second message: "Please, put thoughts in one message and use 'Edit' function or wait when another members write".

I need to ensure that my chat is not spammed with messages in a row, and wrote strictly one message at a time. Bot need to check that the last two messages are not messages from one user. Answers to other users do not count. A simple message and reply to another user's message does not cause bot warning, but two simple messages in a row cause bot notice to spammer.

Advices

Please, give me advice how to solve this task.

Hitmare commented 6 years ago

Use GenericMessageCommand.php

Set Privacy of the Bot off ,

In the GenericMessageCommand.php you 'just' have to check if the Sender of the Message is the same of the last Message and then send a message of your choise if so

noplanman commented 6 years ago

You can do that by writing the conditions in your GenericmessageCommand. When a new message gets written, you can check to see when the previous one was created and then act accordingly.

Edit: D'oh, just realised I misread your issue 🙈 Will leave the code below for reference anyway.


Note: The code below is only to get the time from the last message the same user wrote, regardless of messages in between.

Here some code that might help you on your way:

$message  = $this->getMessage();
$chat_id  = $message->getChat()->getId();
$user_id  = $message->getFrom()->getId();
$date_msg = date('Y-m-d H:i:s', $message->getDate());

$sth = DB::getPdo()->prepare('
    SELECT TIMESTAMPDIFF(MINUTE, `date`, :date_msg)
    FROM ' . TB_MESSAGE . '
    WHERE `chat_id` = :chat_id
      AND `user_id` = :user_id
    ORDER BY `date` DESC
    LIMIT 1
');
$sth->execute([
    ':date_msg' => $date_msg,
    ':chat_id'  => $chat_id,
    ':user_id'  => $user_id,
]);
$diff_in_minutes = $sth->fetchColumn();
land0r commented 6 years ago

@Hitmare @noplanman thanks for your feedback

But I don't use database and the creation of a database is highly undesirable. Іs there another way in this case?

noplanman commented 6 years ago

Are we talking about purely message texts? Or could they also be photos and documents sent etc?

land0r commented 6 years ago

@Hitmare @noplanman we talking about only text messages, not stickers, docs, photos. If user write 2 text messages standing nearby bot need to reply to spammer warning message

noplanman commented 6 years ago

Hmm, unfortunately there is no way of just "retrieving" a chat message, so there is no way of knowing who the last one belongs to.

Best would be to use the DB, but as I understand, that's not possible.

There is a very horrible alternative that comes to mind though, to forward the previous message to a different chat and then check the author/user of the forwarded message, i.e. the previous message.

$message    = $this->getMessage();
$message_id = $message->getMessageId();
$chat_id    = $message->getChat()->getId();
$user_id    = $message->getFrom()->getId();

$forwarded_message = Request::forwardMessage([
    'chat_id'      => $user_id, // or any chat you choose...
    'from_chat_id' => $chat_id,
    'message_id'   => $message_id - 1, // the previous message
]);

$previous_message_user_id = $forwarded_message->getResult()->getForwardFrom()->getId();

Now you can compare that with the current $user_id and see if it's the same user.

I repeat though, this is a pretty nasty solution, as it forwards a message EVERY time a user writes one. With multiple chats using your bot this is way overkill in messaging.

If you really don't want to use the DB, maybe just writing some simple data to a file?

land0r commented 6 years ago

@noplanman I think there was only one option left - create file and write last N (10, 25, 100) messages. After receiving a new message bot will compared authors of two last messages (like in code above, with DB).

What are you think about this? This library can work with files using specific library method?

noplanman commented 6 years ago

@frontier-code What you are trying to implement is quite difficult 😕

There is no integrated method for this, you'll have to search for some external library or make it more simple using just file_get_contents and file_put_contents. Yes you can emulate the required behaviour using files that are written directly from the GenericmessageCommand class, but it's not 100% proof.

Imagine if a user writes a lot of messages, your bot will probably start lagging behind to delete them or at some point there might be issues when multiple users write a lot of messages.

Maybe this doesn't even apply though, I don't know.

land0r commented 6 years ago

@noplanman OK, I will try how my option will work. I really don't understand why we can't get message by ID in bot API, it's really awful. Or do we can that? I read docs and didn't see that the functions have some parameters like $this->getMessage( $id );, etc

noplanman commented 6 years ago

Using this library, you can easily get the message ID of the current message inside the command:

$message_id = $this->getMessage()->getMessageId();

Or when sending a message:

$message_response = Request::sendMessage(...);

$message_id = $message_response->getResult()->getMessageId();

What doesn't work, is to get an existing message from a chat when the chat_id and message_id are known, which is a bit unfortunate...