How to understand what message from the telegram bot answered the user? - laravel

I use Laravel Framework and Telegram Bot SDK. I looked at a lot of guides, and all say how easy it is to create a command and get an answer, but I can’t understand how to create dialogs between the user and the bot. In my webhook I can do for example:
$message = Telegram::getWebhookUpdates()->getMessage();
if ($message->getText() == 'something')
foreach (Service::get() as $item => $value){
if($value->name == $message->getText()) {
$credential = Credential::find($value->id);
if($credential) {
Telegram::sendMessage([
'chat_id' => $message->getChat()->getId(),
'text' => 'Enter the data'
]);
}
}
}
}
Telegram::commandsHandler(true);
And after the user sends the data (in numerical format) I need to process the response. But how can I check the message text with a conditional statement, to know that this is the answer to my previous message, if it is any number. For example:
$message = Telegram::getWebhookUpdates()->getMessage();
if($message->getText() == '/start'){
...
}
elseif($message->getText() == **HERE USER RESPONSE WITH DATA**){
...
}
This is only part of the functionality, there are still different commands, variations of keyboards, and therefore I need to understand how to correctly process incoming messages in order to know which particular question I received the answer.
P.S. I found solutions that say that you need to create a database table with message history and based on this do handlers. Are there any other ways?

You can do it by ForceReply in Telegram Bots API. If user's message is a reply, you should find out which message a user replied to. Just check message's text using it's message id. If it's the first question, it means it has been answered and now you can send the second question.
PS: The solutions that you found is probably the better way to do the job. Just create a database table with message history.

Related

Laravel 9, send notification with preferredLocale

I am creating a bilingual application in which I have implemented database and e-mail notifications.
A notification is, for example, information that a user has started a new conversation. Unfortunately, notifications sent to the database are sent in the language of the user who sends them (set language: App::setLocale(Auth()->user->locale);) and not in the language of the recipient.
I use:
use Illuminate\Contracts\Translation\HasLocalePreference;
class User extends Model implements HasLocalePreference
{
/**
* Get the user's preferred locale.
*
* #return string
*/
public function preferredLocale()
{
return $this->locale;
}
}
Oddly enough, email notifications work this way.
I translate notifications like this:
$customer->notify(new NewMessageNotification($message, trans('notifications.new_message', ['user' => $user->name])));
I tried this way, but it didn't change anything:
https://setkyar.medium.com/fixing-laravels-notification-locale-issue-9ad74c2652ca
Although now I'm wondering if it wouldn't be better to save in the key base and translate only when reading, so that all received notifications are translated when changing the language. The only question is how to do it then.
If i understand well, you want to send notification based on destination language and not based on sender one. If yes, preferredLocale may not works, but you can try to define the language on notification trigger like this:
$customer->notify(new NewMessageNotification($message, trans('notifications.new_message', ['user' => $user->name]))->locale('pt'));
I found that I save to the database in both languages ​​and when reading, I check the language set by the user to display the appropriate version.
On second thought, it seems more logical to have notifications displayed in the currently set language rather than when sent.

use ForceReply option to get input from user without reply interface in telegram

We know that there is ForceReply option to get input from user in telegram api.
Telegram said :
Upon receiving a message with this object, Telegram clients will
display a reply interface to the user (act as if the user has selected
the bot‘s message and tapped ’Reply'). This can be extremely useful if
you want to create user-friendly step-by-step interfaces without
having to sacrifice privacy mode.
Now I used irazasyed/telegram-bot-sdk to make my telegram bot. in that package to create a force_reply interface we should do like this :
$forceReply = Keyboard::forceReply(['force_reply' => true]);
$this->replyWithMessage([
'text' => 'Please enter your name ?',
'reply_markup' => $forceReply
]);
Result is like :
But in usages in other bot for example PollBot that uses this option , when shows a question and want to get answer , reply interface does not show.
I want to do same.I know that if I set value of force_reply to false it done but I do not know after that how can I detect that text that user entered is related to which my question.
what do I do really ?
What I've done for my last bot is:
I created a table for user history which holds some info about users like their username and chat_id, I also keep track of a user's last state in last_state column
So when asking a question from a user, I update her state field in DB with current state, Then upcoming answer is for the question in user's last state, Let me go with a short-simple example.
A:Propmpt question x for user with chat_id n
B:Update state of user whose chat_id is n equal to x in DB
C:Get the answer
D:Get chat_id and then fetch her last_state from DB, the state indicares the question
Now you know which question she's answering to
Check this bot developed by me: #TunnelCSBot

Application wide subscription to a channel

Quick question about Pusher.js.
I've started working on a notifications functionality today and wanted to do this with Pusher.js, since I used it for my chat.
I'm working in Laravel. What I want to achieve is an application wide subscription to a channel. When a user registrates a channel is being made for him "notifications_channel", which I store in the database. I know how to register a user to a channel, but once he leaves that page, the room vacates. That's not really what I'm looking for, since I'd like to send the user notifications no matter where he is on the platform.
I couldn't really find anything like this in the documentation, so I thought maybe one of you guys know how to do so.
Here are some snippets of what I do:
When the user registrates I fire this:
$generateChannel = User::generateNotificationsChannel($request['email']);
This corresponds to this in my model:
public static function generateNotificationsChannel($email){
$userID = User::getIdByMail($email);
return self::where('email', $email)->update(['notifications_channel' => $userID."-".str_random(35)]);
}
It's fairly basic, but for now that's all I need.
So for now, when the user logs in the Index function of my HomeController is being fired, which gathers his NotificationsChannel from the database and sends it to the view.
public function index()
{
$notificationsChannel = User::getUserNotificationsChannel(\Auth::user()->id);
return view('home', compact('notificationsChannel', $notificationsChannel));
}
Once we get there I simply subscribe the user to that channel and bind him to any events linked to the channel:
var notifications = pusher.subscribe('{{$notificationsChannel}}');
channel.bind('new-notification', notifyUser);
function notifyUser(data){
console.log(data);
}
So as you can see, for now it's pretty basic. But my debug console shows me that the channel vacates as soon as the user leaves /home.
So the question is, how do I make him subscribed to the channel, no matter where he is on the platform?
Any and all help would be deeply appreciated!
Thanks in advance.
I've found a fix to this issue, I've decided to send the notifications-channel to my Master layout, which I use to extend all views after the user has logged in. In my master layout I subscribe the user to his own notifications channel.
For people who might be interested in how I did it:
I altered the boot function of my AppServiceProvider which you can find in \app\Providers\AppServiceProvider. The code looks like this:
public function boot()
{
view()->composer('layouts.app', function($view){
$channel = User::getUserNotificationsChannel(\Auth::user()->id);
$view->with('data', array('channel' => $channel));
});
}
In my Master layout I simply subscribed the user by grabbing the channel name.

Joomla Error Messages for Specific User Group

I'm trying to set up customer error messages for different user groups in Joomla 3.6. We have locked content on the front-end of our site, currently there is a generic message that tells the user to login to see it, however we recently adjusted our user groups to create multiple levels of access so even after logging in there may still be content the user can't see. In those instances I need to be able to show a message specific to that user group rather than a generic "please login".
I have used Language Overrides for custom messages before but there's no option I've found to have it show to specific groups. I don't know a lot about code, and Google revealed no existing answers for this.
This might be something to get you going:
$groups = JUserHelper::getUserGroups((int) $user->user_id);
if(in_array(8, $groups))
{
$level = 'admin';
} elseif (in_array(4, $groups)) {
$level = 'globalmoderator';
} elseif (in_array(3, $groups)) {
$level = 'moderator';
} elseif (in_array(2, $groups)) {
$level = 'user';
} else {
$level = 'guest';
}
Without some programming it'll not be easy for you to achieve. But in short, you can create a pretty simple plugin, which will capture certain Joomla events.
For example, Joomla has onUserLogin even, which allows you to do different stuff, when user logs in. Your custom plugin can capture this even, check for some parameters and then add a group specific message to the queue. More over, you can get current message queue, parse or empty it and then add group specific message.
You can do the same for any other Joomla event like onUserLogout, onUserLoginFailure and so on. There're plenty events to choose from.
As for message specific groups, you can add your own generic messages similar to this:
COM_USERS_ERROR_LOGIN_GUEST
COM_USERS_ERROR_LOGIN_REGISTERED
COM_USERS_ERROR_LOGIN_ADMIN
Then you just take "COM_USERS_ERROR_LOGIN_" string and add a group name (or ID, when language is non-English) to it. That's it.
The task doesn't seem too complex, but you still have to know some coding to create a plugin, which will capture Joomla events. There's no other way to do this.
Try to use articles for messages and filter it with permissions for user groups.

How to deal with non existent emails

I am making an app that allow to register to a newsletter and then manage it.
There is the normal validation if the field is empty, if is email type, unique ecc..
But how can i check if the email really exists?
If someone enter a fake mail, that mail is entered in the database, and this can mess up the database. And there are other annoyance.
Is possible to check if the mail really exists?
Otherwise it is possible to automatically delete an unregistered user after 10 days?
You can create a rule to check if the e-mail format is valid:
$validator = Validator::make(
Input::all(),
array('email' => 'required|email')
);
if ($validator->fails())
{
return "This is not a valid e-mail";
}
But this will only check for the format (name#domain.tld), because there is no way to know if an e-mail address really exists.
Well... this is not entirely true, there is a way: send an e-mail to that address and if you don't get an error message, the address exists, probably.
The best way to do what you need is, when a user creates an account in your system, send him/her a confirmation e-mail, with a link where he/she should click to validate that address. If the account is not validated for x days you delete it. This is a question that might help you on that: Laravel 4: how to make confirmation email?.
About your last question: create an Artisan Command that checks for unvalidated accounts and delete them. Take a look at the docs, it's easy, Laravel does almost all the job for you. And you can run this command once a day using cron or task manager:
php /var/www/your-site-dir/artisan check:accounts
EDIT:
This question will show you how to create a command: Creating and using Laravel 4 commands
And in the method fire() you should do something like:
public function fire()
{
$dt = Carbon\Carbon::now();
User::where('activated', false)
->where('created_at', '<', $dt->subDays(10))
->delete();
}
There are some APIs you can use to verify the validity and existence of emails, but I am not sure how good they are. The free ones usually limit you to something like 10 an hour which probably would not be nearly enough for you, depending on how busy your site is.
Check out http://verify-email.org/register/levels.html
If you are worried about the sheer amount of emails being entered, you could probably log $_SERVER['REMOTE_ADDR'], which would be the client's IP address in the DB on emails and check to make sure that is unique as well before you save additional records to the table.
As far as how to actually validate the existence and validity of the entered email yourself, I believe you'd have to use fsockopen and issue smtp commands to servers. I did find this php class which attempts to do what we are talking about http://www.webdigi.co.uk/blog/wp-content/uploads/2009/01/smtpvalidateclassphp.txt
I doubt it works, but should get you a nice starting point.

Resources