How can I sendMessage with reply_markup(telegram bot) - telegram

I deploy my project on heroku using express+request.I can reply text,but failed to reply with markup.I've been working on this proble for almost 2 days,but I can't fix it.
app.post("/",async(req,final)=>{
const body=req.body
console.log(JSON.stringify(body))
if(body.message){
const form={
text:req.body.message.text,
msgid:req.body.message.message_id,
uid:req.body.message.from.id,
chatid:req.body.message.chat.id
}
if(form.text.indexOf("/start")!=-1){
sendMessage(form.chatid,form.msgid,"Welcome")
}else{
let reply_markup={}
reply_markup.inline_keyboard=[]
let inlineRow=[]
inlineRow.push({
text:"one",
callback_data:"/one:"+body.message.text
})
inlineRow.push({
text:"two",
callback_data:"/two:"+body.message.text
})
let inlineRow1=[]
inlineRow1.push({
text:"three",
callback_data:"/three:"+body.message.text
})
inlineRow1.push({
text:"four",
callback_data:"/four:"+body.message.text
})
reply_markup.inline_keyboard.push(inlineRow)
reply_markup.inline_keyboard.push(inlineRow1)
sendMsgButton(form.chatid,"Click a button",reply_markup)
}
}
final.send("SUCCESS")
})
function sendMsgButton(chat_id,text,reply_markup){
request({
url:"https://api.telegram.org/botAPITOken/",
method:"POST",
form:{
"method": "sendMessage",
"chat_id": chat_id,
"parse_mode":"Markdown",
"reply_markup":reply_markup,
"text":text
}
},(err,res,body)=>{
console.log("SendMessage",body)
})
}
Someone knows what's wrong with my code?
Please help me/(ㄒoㄒ)/~~

Your request to API should have next format:
{
chat_id: data.chatId,
text: data.text,
reply_markup: {
inline_keyboard: [[{ text: 'Stop', callback_data: "string" }]],
},
}
You should also specify what kind of error you are getting from Telegram API.
Also, there are limitations in callback_data, it cannot be more than 64 bytes. You can use any online service to check the string size you pass into callback data
Also, your URL should like https://api.telegram.org/botAPITOken/sendMessage.

Related

How to use Sign-In User ID to send push notifications

I have some users signed into my actions-on-google app via Google Sign-In ( https://developers.google.com/actions/identity/google-sign-in )
I want to sent push notifications to one of those users.
For getting push notifications work with actions in the first place, I tried this sample: https://github.com/actions-on-google/dialogflow-updates-nodejs/blob/master/functions/index.js but I only can get this to work without this commit: https://github.com/actions-on-google/dialogflow-updates-nodejs/commit/c655062047b49e372da37af32376bd06d837fc7f#diff-1e53ef2f51bd446c876676ba83d7c888
It works fine, but I think const userID = conv.user.id; returns the deprecated Anonymous User ID. The commit suggests to use const userID = conv.arguments.get('UPDATES_USER_ID'); which returns undefined.
I use this nodejs code to send the push notifications.
const request = require('request');
const {JWT} = require('google-auth-library');
const serviceAccount = require('./service-account.json');
let jwtClient = new JWT(
serviceAccount.client_email, null, serviceAccount.private_key,
['https://www.googleapis.com/auth/actions.fulfillment.conversation'],
null
);
jwtClient.authorize((authErr, tokens) => {
let notification = {
userNotification: {
title: process.argv[2],
},
target: {
userId: USERID,
intent: 'tell_latest_status',
// Expects a IETF BCP-47 language code (i.e. en-US)
locale: 'en-US'
},
};
request.post('https://actions.googleapis.com/v2/conversations:send', {
'auth': {
'bearer': tokens.access_token,
},
'json': true,
'body': {
'customPushMessage': notification, 'isInSandbox': true
},
}, (reqErr, httpResponse, body) => {
console.log(httpResponse.statusCode + ': ' + httpResponse.statusMessage);
});
});
I simply can't get this to work with the const userID = conv.arguments.get('UPDATES_USER_ID'); version, because as I said
When I use conv.user.profile.payload.sub as suggested here: https://developers.google.com/actions/identity/user-info the AoG API returns "SendToConversation response: Invalid user id for target."
Is there any way to make this work with Google Sign-In?
Has anyone made this work? I mean with the UPDATES_USER_ID field?
I already created an issue on the samples repo: https://github.com/actions-on-google/dialogflow-updates-nodejs/issues/15 but I was sent here.
Thanks!
While researching why I sometimes got undefined I found an answer on this question that solved my issue.
I've found solution for this problem. While getting UPDATES_USER_ID
conv.arguments.get() only works for first attempt. So, while building
your action you must save it. If you didn't store or save, you can
reset your profile and try again, you will be able to get.
You can reset your user profile for the action here.

Error: Unrecognized operator: $nearSphere in meteor js

i have simple code in meteor js for find near by garages within 10 Kilometres the query works fine in my mongodb database if run it manually in robomongo it works fine but when i run it in my routes it throws an error. like this.
Error: Unrecognized operator: $nearSphere in meteor jsi
i see some blogs they said you need to call a server side method for this. so i use below code to call a server side route.
Router.route('/search/:name',
{name:'searchlist',
data:function(){
var searchedParams = this.params.name.split('-');
var lat = searchedParams.pop();
var lng = searchedParams.pop(1);
return {searchValue: Centers.find({ coordinates: { $nearSphere: { $geometry: { type: "Point", coordinates: [lng,lat] }, $maxDistance: 10000 } } })}
}
}, { where: "server" }
);
if anyone have idea please help.
You're mixing definitions for client and server side routes.
Server-side route should look like this:
Router.route('/search/:name', function(...){...}, { where: 'server' });
Client-side route could look like this:
Router.route('/search/:name, { ... });
Thus, your route is actually client-side route and minimongo doesn't have support for $nearSphere operator as noted here: https://github.com/meteor/meteor/blob/devel/packages/minimongo/NOTES
First, look at Styx answer and make the route a client route by eliminating this part:
', { where: "server" }'
Now that the router is available to the client, let's fix the $nearSphere issue, by changing the operator to $near. Use the following code:
Centers.find(
{
geoloc: {
$near: {
$geometry: {
type: "Point",
coordinates: [lng, lat]
}
}
}
}
);
Give it a try and let me know if it works.

Error while instanciating Restivus "Cannot find name 'Restivus' "

I imported restivus using :
meteor add nimble:restivus
And while using Restivus I encounter this error on meteor startup :
"Cannot find name 'Restivus' ".
I can although GET requests but I wonder if it impacts the behavior of the app.
Here is the code used :
if (Meteor.isServer) {
// Global API configuration
var Api = new Restivus({
apiPath: 'api/',
prettyJson: true
});
}
When receiving POSTs my request.body and my bodyParams are empty :
Api.addRoute(':id/test', {
post: function () {
var id = this.urlParams.id;
console.log("Body contains : ");
console.log(this.bodyParams);
return {
status: 'success',
url : 'post test from id: '+id,
body : this.bodyParams
};
}
});
Does anyone know how to make this error disappear and if this is linked to the POST body problem ?
If you use Meteor 1.4+ you can try to import Restivus to your file with something like this:
import Restivus from 'nibmle:restivus';
The problem with post body being empty was caused by the request I made :
I wasn't specifying the Content-type header.
Once I specified the "Content-Type": "application/json" it worked.
The "Cannot find 'Restivus' " Error is still here though.
Your code looks ok. Here is some code from a server-only file that I am using:
// Global API configuration
var Api = new Restivus({
useDefaultAuth: true,
prettyJson: true,
apiPath: 'restAPI/',
defaultHeaders: { 'Content-Type': 'application/json;encoding="UTF-8"' }
});
// Generates: GET, POST on /api/items and GET, PUT, DELETE on
// /api/items/:id for the Items collection
Api.addCollection(Policy);
Perhaps you should move your code to the server directory? I am on Meteor 1.3.4.

meteor autocomplete server-side

I'm writing a meteor app and I'm trying to add an autocomplete feature to a search box. The data is very large and is on the server, so I can't have it all on the client. It's basically a database of users. If I'm not wrong, the mizzao:autocomplete package should make that possible, but I can't seem to get it to work.
Here's what I have on the server:
Meteor.publish('autocompleteViewers', function(selector, options) {
Autocomplete.publishCursor(viewers.find(selector, options), this);
this.ready();
});
And here are the settings I use for the search box on the client:
getSettings: function() {
return {
position: 'bottom',
limit: 5,
rules: [{
subscription: 'autocompleteViewers',
field: '_id',
matchAll: false,
options: '',
template: Template.vLegend
}],
};
}
But I keep getting this error on the client:
Error: Collection name must be specified as string for server-side search at validateRule
I don't really understand the problem. When I look at the package code, it just seems like it's testing whether the subscription field is a string and not a variable, which it is. Any idea what the problem could be? Otherwise is there a minimum working example I could go from somewhere? I couldn't find one in the docs.
Error: Collection name must be specified as string for server-side search at validateRule
You get this error because you don't specify a Collection name in quotes.
getSettings: function() {
return {
position: 'bottom',
limit: 5,
rules: [{
subscription: 'autocompleteViewers',
field: '_id',
matchAll: false,
collection: 'viewers', // <- specify your collection, in your case it is a "viewers" collection.
options: '',
template: Template.vLegend
}],
};
}
For more information please read here.
Hope this helps!

Update Mongo on the client using document ID, but limiting search with another field

When updating a document which contains an array of objects, I have this function:
Template.editCompetition.events = {
'click button.promote': function() {
Competitions.update({_id: Session.get('competition_id'), 'players.user_id': this.user_id}, {$set: {'players.$.supervisor': true}});
},
};
I am seeing the error:
Uncaught Error: Not permitted. Untrusted code may only update documents by ID.
My document looks like this:
{
_id: 'aaaabbbbb',
title: 'ccccdddddd',
players: [
{
username: 'wwwww',
user_id: 'xxxxx',
supervisor: false
},
{
username: 'yyyyy',
user_id: 'zzzzz',
supervisor: false
}]
}
Isn't my query updating the document by the ID, but also searching for that array position to use the .$ notation.
How can I achieve this without using a method, which seems a bit hacky...?
You are also trying to use the player.user_id as second parameter for update query
Other option you can have to use Meteor.method.
Move Collection update code to Meteor server side method and call it from client side
On Server side,
Meteor.methods({
`update_players`: function(competition_id){
user_id = this.userId
Competitions.update({_id: competition_id, 'players.user_id': user_id}, {$set: {'players.$.supervisor': true}});
}
})
In in above code, understand use of how we fetched current userId with this.userId
and now from your click handler call this meteror method
Meteor.call('update_players')
Hope this helps

Resources