telegram bot api - send additional data with replay keyboard - telegram

I'm working on telegram bot api and I sendReplayKeyboard with my message text to user. When a user click on a button, telegram sends a post with below structure to my webhook. Here is json structure of post:
{
"update_id": *******,
"message": {
"message_id": ***,
"from": {
"id": *****,
"is_bot": false,
"first_name": "*****",
"username": "******",
"language_code": "en-US"
},
"chat": {
"id": *****,
"first_name": "******",
"username": "*****",
"type": "private"
},
"date": 1518716587,
"text": "Button Text"
}
}
My problem is telegram does not accept any additional data for replay keyboard button. So, I have to check message.text with string and this is not a good practice. For example if the button has emoji, the emoji code must be in the check. Also, I have different menu type and I need to find out type of clicked button, but I have just text of the button. So I need to assign id and type to each button. But I don't know how can I do it.
Here is the post data that my bots sends to user:
$keyboard = array(
'resize_keyboard' => true,
'keyboard' => array(
array(
array(
"text" => "Button Text"
//There is not any `id` or `type`,...
)
)
)
);
$post_fields = array(
'chat_id' => **********
'text' => ************,
'reply_markup' => json_encode($keyboard)
);
Note: I don't want to InlineKeyboard and I need to use RelplayKeyboard.
If it's not possible, is there any alternative way? For example put additional data in button text and hide it from user.

It seems you need to save each user stat, so you can elect suitable reaction to similar text of button.
Also note that emoji is not horrible! and you don't need emoji code!
You just need to compare text that include emoji with a predefined string:
if('راهنما 💡'===$receivedText)
doSomeMagic();

Related

Find and delete Discord webhook message

I'm using a Discord webhook to send information which may later be invalidated, so I want to be able to delete it. To do this i use these endpoints:
First i make a post request to send a message:
POST /webhooks/{webhook.id}/{webhook.token}
And then i want to do a delete request to remove the message again:
DELETE /webhooks/{webhook.id}/{webhook.token}/messages/{message.id}
However I don't have the ID of the message i want to delete, since no response is given to the first POST request which is always an empty 204 response. Is it possible to get the message id?
Any help would be appreciated.
Per this reddit post:
If you need to reference a message ID of a webhook message you sent, you can add ?wait=true to the end of the URL which will give you the message data (including the ID) instead of a 204 (No Content) when you don't include the query parameter.
So if you send your normal POST request to your url like this: POST /webhooks/{webhook.id}/{webhook.token}, add ?wait=true to the end of that. Then you will get back data like this:
{
"id": "MESSAGEID",
"type": 0,
"content": "This is a test",
"channel_id": "CHANNELID",
"author": {
"bot": true,
"id": "AUTHORID",
"username": "USERNAME",
"avatar": "AVATARID",
"discriminator": "0000"
},
"attachments": [],
"embeds": [],
"mentions": [],
"mention_roles": [],
"pinned": false,
"mention_everyone": false,
"tts": false,
"timestamp": "2021-11-13T18:10:24.412000+00:00",
"edited_timestamp": null,
"flags": 0,
"components": [],
"webhook_id": "WEBHOOKID"
}

Deeplinking into a telegram bot

I have a simple use case. When a user clicks the link below,
T.me/MycompanynameBot?start=Microsoft
I want to show him 3 inline buttons corresponding to 3 Telegram channels within Microsoft. Is this possible?
The key is the bot must be able to retrieve the parameters from the URL.
Thank you.
Yes it's possible to retrieve bot parameter via answerCallbackQuery
Alternatively, the user can be redirected to the specified Game URL. For this option to work, you must first create a game for your bot via #Botfather and accept the terms. Otherwise, you may use links like:
t.me/your_bot?start=XXXX
that open your bot with a parameter.
Here is an example I made for you :
{
"ok": true,
"result": [{
"update_id": 89590932,
"message": {
"message_id": 5978,
"from": {
"id": 223110107,
"is_bot": false,
"first_name": "Ğąme",
"last_name": "Ǿver!",
"username": "GameO7er",
"language_code": "en"
},
"chat": {
"id": 223110107,
"first_name": "Ğąme",
"last_name": "Ǿver!",
"username": "GameO7er",
"type": "private"
},
"date": 1579094448,
"text": "/start Microsoft",
"entities": [{
"offset": 0,
"length": 6,
"type": "bot_command"
}]
}
}]
}
As you can see type=bot_command so you can parse the message if (type == "bot_command") and get text and substring /start from the original text or what ever you want to do.
In many cases I detect users with the parameters for example when I wanna to know who invited this user to bot I share the link in this format:
t.me/NameBot?start=ReferUserID
for example :
t.me/NameBot?start=223110107
is my ID and I can see how many user I've invited to the bot.
Hope be useful.

telegram inline bot - InlineQueryResultCachedPhoto does not show title and description

I'm using telegram bot api for implementing an inline bot. For sending query result to the user, I'm using answerInlineQuery method in this way. This is just an example for showing a photo that exist on telegram server to user:
$results = array(
array(
"type" => "photo",
"id" => "1",
"photo_file_id" => the file id,
"title" => "test title",
"description" => "test description",
"caption" => "test caption",
"parse_mode" => "HTML"
),
);
$postFields["results"] = json_encode($results);
$postFields["cache_time"] = 0;
//send $postFields to telegram bot api server with curl
This works and after user sending inline query, one image shows as the result list. But the problem is two fields title and description does not show in the result list, even these are exist in telegram api documentation here.
What's is the problem and whay these two fields does not present in the result list?

Adding more fields to Meteor user accounts

I am using mrt add accounts-ui-bootstrap-dropdown and mrt add accounts-password to get a simple login page running on my app.
The accounts users gives me a nice hash containing ids, createdAt, emails, etc.
If I wanted to add other fields in this hash so I can make use of them later, how would I do that? For example, I want then to also enter their given name and surname:
"given_name": "John", "surname": "Doe"
Users are special objects in meteor ; you don't want to add fields in the user but in the users profile.
From the doc :
By default the server publishes username, emails, and profile.
If you want to add properties like surname when you create the account, you should use in the Account.onCreateUser server-side hook : http://docs.meteor.com/#accounts_oncreateuser
Accounts.onCreateUser(function(options, user) {
//pass the surname in the options
user.profile['surname'] = options.surname
return user
}
If you want to update a user after, you can do it from the client that way :
Meteor.users.update({_id:Meteor.user()._id}, { $set: {what you want to update} });
By default, the users base will allow that (the current user may update itself). If you don't trust your users and want to ensure that everything is properly update, you can also forbid any updates from the client and make them via a Meteor.call() and proceed to the checkings server-side. But this would be sad.
Edit :
As said in the comments, adding options via the standard account-ui won't be possible. You'll only be able to update the user after the registration. To add options when you subscribe, you'll have to make you own form.
I won't insult you by writing html markup, but here is what you want to have after the submit event (and after the various checking) :
var options = {
username: $('input#username')[0].value,
emails: [{
address: $('input#email')[0].value,
verified: false
}],
password: $('input#password')[0].value,
profile: {
surname: $('input#surname')
},
};
Accounts.createUser( options , function(err){
if( err ) $('div#errors').html( err.message );
});
You only need the account-base package ; not the account-ui.
Login with the social networks is cake :
Meteor.loginWithFacebook({
requestPermissions: ['email', 'user_birthday', 'user_location']
}, function(error){loginCallBack(error);});
About the answer ram1 made :
This is not the way meteor works. You do not "POST" a form. You want all your client / server communication done via the websocket. The equivalent of what you are talking about is making a "Meteor.call('myserverfunction', myarguments, mycallback)" of a server method from the client and you pass the arguments you want the server to use.
But this is not the way you will get the best of meteor. There is the philosophy you want to work with :
you have datas in your local mini mongo you got from the server
you update locally those datas in your base / view
meteor do his magic to transmit those updates to the server
there the server can answer : ok, updates saved, this is seamless for you. Or answer : nop ! reverse the changes (and you can implement an error notification system)
(it can answer no because you don't have the permission to update this field, because this update break a rule you did set up...)
All you do is setting permissions and controls on the databases server-side. That way, when an honest client make an update, he sees the result instantly ; way before it has been pushed to the server and send to the other clients. This is latency compensation, one of the seven principles of meteor.
If you modify a data via Meteor.call, you will do that :
send an update to the server
the server checks and update the base
the server send the update to the clients (including you)
your local base updates and your view update => you see your update
=> this is what you had in yesterday app ; meteor allow you to build a today app. Don't apply the old recipes :)
The accepted answer has the HOW right, but the WHERE is outdated information. (Yes, this would be better as a comment on the answer, but I can't do that yet.)
From the Meteor 1.2 documentation:
The best way to store your custom data onto the Meteor.users collection is to add a new uniquely-named top-level field on the user document.
And regarding using Meteor.user.profile to store custom information:
🔗Don’t use profile
There’s a tempting existing field called profile that is added by
default when a new user registers. This field was historically
intended to be used as a scratch pad for user-specific data - maybe
their image avatar, name, intro text, etc. Because of this, the
profile field on every user is automatically writeable by that user
from the client. It’s also automatically published to the client for
that particular user.
Basically, it's probably fine to store basic information such as name, address, dob, etc in the profile field, but not a good idea to store anything beyond that as it will, by default, be writeable by the client and vulnerable to malicious users.
I had the same problem and managed to do it only with Accounts.createUser:
Accounts.createUser({
email: email,
password: password,
profile: {
givenName: 'John',
surname: 'Doe',
gender: 'M'
}
}
Thats very simple way and it works. Just add your desired variables in the profile section and it should be ready. Hope it helps someone.
I ended up using https://atmospherejs.com/joshowens/accounts-entry which offers an extraSignUpFields config option.
From the documentation (https://github.com/ianmartorell/meteor-accounts-ui-bootstrap-3/blob/master/README.md):
Custom signup options
You can define additional input fields to appear in the signup form, and you can decide wether to save these values to the profile object of the user document or not. Specify an array of fields using Accounts.ui.config like so:
Accounts.ui.config({
requestPermissions: {},
extraSignupFields: [{
fieldName: 'first-name',
fieldLabel: 'First name',
inputType: 'text',
visible: true,
validate: function(value, errorFunction) {
if (!value) {
errorFunction("Please write your first name");
return false;
} else {
return true;
}
}
}, {
fieldName: 'last-name',
fieldLabel: 'Last name',
inputType: 'text',
visible: true,
}, {
fieldName: 'gender',
showFieldLabel: false, // If true, fieldLabel will be shown before radio group
fieldLabel: 'Gender',
inputType: 'radio',
radioLayout: 'vertical', // It can be 'inline' or 'vertical'
data: [{ // Array of radio options, all properties are required
id: 1, // id suffix of the radio element
label: 'Male', // label for the radio element
value: 'm' // value of the radio element, this will be saved.
}, {
id: 2,
label: 'Female',
value: 'f',
checked: 'checked'
}],
visible: true
}, {
fieldName: 'country',
fieldLabel: 'Country',
inputType: 'select',
showFieldLabel: true,
empty: 'Please select your country of residence',
data: [{
id: 1,
label: 'United States',
value: 'us'
}, {
id: 2,
label: 'Spain',
value: 'es',
}],
visible: true
}, {
fieldName: 'terms',
fieldLabel: 'I accept the terms and conditions',
inputType: 'checkbox',
visible: true,
saveToProfile: false,
validate: function(value, errorFunction) {
if (value) {
return true;
} else {
errorFunction('You must accept the terms and conditions.');
return false;
}
}
}]
});
The official Meteor Guide provides a comprehensive answer with an example code:
The best way to store your custom data onto the Meteor.users collection is to add a new uniquely-named top-level field on the user document.
https://guide.meteor.com/accounts.html#custom-user-data

How to "Add guest" to event via google calendar API?

could you please give me a hint on how to share a single event via google calendar api?
That is I'd like to invite other users to see the event programmatically without sharing the whole calendar. To mimic the "Add guests" UI action
As Claudio mentioned, you need to use the Google Calendar Advanced API for this.
You'll want to use a patch because you don't want to replace all the other data on the calendar invite. However, even in the case of patch, since the attendees lives in an array, if you attempt to pass a patch such as this:
{
attendees: [ { email: "new#example.com"} ]
}
... it'll replace all old invitees (i.e. it'll remove anyone that was on the invite before you called patch). To fix this, you must first get the current invitees, add a new person to the array, and then send a patch.
You can see a detailed example of this in this answer which also explains how to use Google Apps Scripting to ensure an email is sent to the user when adding them to a calendar event (see the addGuestAndSendEmail() method in that post).
You can use the API to add people to the attendees collection:
https://developers.google.com/google-apps/calendar/v3/reference/events/update
refer the following request.
method: POST
endpoint: https://www.googleapis.com/calendar/v3/calendars/primary/events?sendUpdates=all
here, sendUpdates means when you add any guest so he would get an invitation mail used based on scenario.
Input Json:
{
"kind": "calendar#event",
"etag": "etag",
"status": "confirmed",
"summary": "JayKara",
"description": "eqwbdjhwhhwhhwrhjehrhejhfj",
"location": "America",
"creator": {
"email": "#mail.com",
"self": true
},
"organizer": {
"email": "#mail.com",
"self": true
},
"start": {
"date": "2019-12-23"
},
"end": {
"date": "2019-12-24"
},
"originalStartTime": {
"date": "2019-12-24"
},
"visibility": "public",
"attendees": [
{
"email": "****#mail.com" //this guys are the guest
}
]
}.
After that there is no patch method required your guest guys will receive an invitation whenever update event
Cheers!

Resources