Telegram bot inline keyboard via AppScript - javascript

I am making a Telegram bot using Appscript and I want to copy/send message with an inline_keyboard but when I send the URL I get an invalid parameter error and I don't know what is wrong, because everything worked until I add the reply_markup parameter.
function enviarMnesjePruebaCanal() {//ENVIAR MENSAJE
var urlusuarioconid = "tg://userid?=" + miID
var keyboard = {
"inline_keyboard": [
[
{
"text": "Usuario",
"url": urlusuarioconid
}
]
]
};
var url = telegramUrl + '/sendMessage?chat_id=' + miID + '&text=' + "texto" + "&reply_markup=" + JSON.stringify(keyboard);
Logger.log(url);
UrlFetchApp.fetch(url);
}
`
This is my code and this is what I send to telegram and what I get back:
(I have deleted the data of my bot and my id for obvious reasons, but that part is ok because when I run it without the last part it sends me the message)
I have already tried several things and they all give the same problem, I don't know if anyone can help me or see what could be happening. Thanks!

The issue is caused by the reply_markup containing non-url tokens.
You should encode that part of the url using encodeURIComponent()
Change the code to:
function enviarMnesjePruebaCanal() {
var myID = 123456;
var urlusuarioconid = "tg://userid?=" + myID
var keyboard = {
"inline_keyboard": [
[
{
"text": "Usuario",
"url": urlusuarioconid
}
]
]
};
var url = telegramUrl + '/sendMessage?chat_id=' + myID + '&text=' + "texto" + "&reply_markup=" + encodeURIComponent(JSON.stringify(keyboard));
Logger.log(url);
var response = UrlFetchApp.fetch(url);
Logger.log(response.getContentText());
}
The important change here is adding the encodeURIComponent:
encodeURIComponent(JSON.stringify(keyboard))

Related

Post image to Instagram from a Javascript using Instagram API

Instagram Graph API:
https://developers.facebook.com/docs/instagram-api/
Content Publishing:
https://developers.facebook.com/docs/instagram-api/guides/content-publishing/
My code Javascript in Google App Script:
function InstagramPost() {
const id = '123456789';
const image = 'https://www.w3schools.com/images/w3schools_green.jpg';
const text = 'Hello%20World';
const access_token = 'TESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTEST';
const container = 'https://graph.facebook.com/v11.0/' + id + '/media?image_url=' + image + '&caption=' + text + '&access_token=' + access_token;
const response = UrlFetchApp.fetch(container);
const creation = response.getContentText();
Logger.log(creation);
}
The return in my Logger of my container to Post via Instagram API request comes as follows:
{
"data": [
{
"id": "11111111111111111"
},
{
"id": "22222222222222222"
},
{
"id": "33333333333333333"
}
],
"paging": {
"cursors": {
"before": "QWOURQWNGEWRONHWENYWPETGNWQPGNPGNWEPGNWEPGNWEPNGWPENGPWEG",
"after": "WIWEPGNEPBNWE´GNÉ´BNWE´BNWÉBWNEB´WENBNWEBWEBEWBWE"
},
"next": "https://graph.facebook.com/v11.0/11111111111111111/media?access_token=PQWNFWPQINPWNBQPWNBQPWNBPQWNVQWPNVPQWVNPQWPVNQPWNVQPWVNQPWNVPQWNVQPWNVQPWVNQASASLGÇAJKSGLJAAÇSNAÇKNSVÇLKNASBÇANSBÇAS"
}
}
To make the final call for post image it is necessary to use an creation_id=:
const sendinstagram = 'https://graph.facebook.com/v11.0/' + id + '/media_publish?creation_id=' + creation + '&access_token=' + access_token;
UrlFetchApp.fetch(sendinstagram);
If the return from the container is several id in sequence, how do I know which one to define for the call?
Note: I can't loop to try every id because Instagram has a daily limit of 25 calls and posts, so if I did that I would end up with my calls just trying to post a single image.
First, we create IG Container by hitting the endpoint.
POST https://graph.facebook.com/v11.0/{ig-user-id}/media?image_url={image-url}&caption={caption}&access_token={access-token}
Once you have the IG container ID then we again make a POST request to post the Image.
POST https://graph.facebook.com/v11.0/{ig-user-id}/media_publish?creation_id={creation-id}&access_token={access-token}
I think you have to include the version in container and sendinstagram which is v11.0 (latest as if now).
I found the correct way to publish images:
var formData = {
'image_url': image,
'caption': text,
'access_token': access_token
};
var options = {
'method' : 'post',
'payload' : formData
};
const container = 'https://graph.facebook.com/v11.0/' + instagram_business_account + '/media';
const response = UrlFetchApp.fetch(container, options);
const creation = response.getContentText();
var data = JSON.parse(creation);
var creationId = data.id
var formDataPublish = {
'creation_id': creationId,
'access_token': access_token
};
var optionsPublish = {
'method' : 'post',
'payload' : formDataPublish
};
const sendinstagram = 'https://graph.facebook.com/v11.0/' + instagram_business_account + '/media_publish';
UrlFetchApp.fetch(sendinstagram, optionsPublish);

Connecting moodle api through web service

Let me explain: My purpose is to create moodle users from a web app.
I am implementing a web app on Tomcat 8.0.15.0. That is, I use java servlets on the server side. Many JSP files and javascript, with much of it in jQuery, resides on the client side.
On the other hand, on another server, I have a test moodle installation. Via site-administration> plugins> web services> external services, I created a ws that enables the core_user_create_users function. Also created a token to access this ws, and put the admin user as authorized user.
And then, typed the following URL on Chrome:
https://mysyte.com/webservice/rest/server.php?wstoken=780f8b3a1164163d4dc00a757071194e&wsfunction=core_user_create_users&moodlewsrestformat=json&users[0][username]=testuser&usr[ [email] =john#smith.com&users [0] [password] = XXXXXX
And it worked. It returned a blank page, with the text
[{"id": 1, "username": "testuser"}]
Thus creating a user in moodle.
My question is: How can I do this from java?, or from javascript?, or from jQuery even better.
And if not, from PHP, I guess I would have no problem calling it from java, or javascript, or jQuery.
My Wrong Hint: In another part of the application I used, in javascript, the call $.getJSON() successfully. That's why I thought would also serve me in this case. But no success now, when the mozilla debugger reaches the call, it hangs.
Any feedback will be most welcome.
The call looks like
function create_moodle_user(username,firstname,lastname,email,password) {
var url = "https://mysyte.com/webservice/rest/server.php?"
+ "wstoken=780f8b3a1164163d4dc00a757071194e" + "&"
+ "wsfunction=core_user_create_users" + "&"
+ "moodlewsrestformat=json" + "&"
+ "users[0][username]=" + username + "&"
+ "users[0][firstname]=" + firstname + "&"
+ "users[0][lastname]=" + lastname + "&"
+ "users[0][email]=" + email + "&"
+ "users[0][password]=" + password;
$.getJSON(url, function(data) { // should return [{"id":4,"username":"testuser"}]
// this point is never reached
if (data.length < 64) {
}
else {
}
});
}
Finally, it worked by changing the call and the way how parameters were passed.
function create_moodle_user(u,f,l,e,fn) {
var domainname = 'https://my.moodle.site.com';
var data = {
wstoken: '780f8b3a1164163d4dc00a757071194e'
wsfunction: 'core_user_create_users'
moodlewsrestformat: 'json',
users: [
{
username:u,
password:'xxxxxxxx',
email:e,
firstname:f,
lastname:l
}
]
};
var response = $.ajax({
type: 'GET',
data: data,
url: domainname + '/webservice/rest/server.php'
});
// pass the function parameter
response.done(fn);
}
And this worked!
My problem now is to get user info, since I don't know how to get the response from core_user_get_users_by_field.
This is what I have:
function get_moodle_user(u,fn) {
var domainname = 'https://my.moodle.site.com';
var data = {
wstoken: '780f8b3a1164163d4dc00a757071194e'
wsfunction: 'core_user_get_users_by_field'
moodlewsrestformat: 'json',
field: 'username',
username:u
};
var response = $.ajax({
type: 'GET',
data: data,
url: domainname + '/webservice/rest/server.php'
});
console.log(response); // this does not show the result data
// pass the function parameter
response.done(fn);
}
Any ideas, please?

Bad Request: can't parse reply keyboard markup JSON object

I want to create button in my telegram bot by javascript and I working in script google.
But it didn't fetch.
My code:
function a() {
const opts = {
reply_to_message_id: '690534265',
reply_markup: {
resize_keyboard: true,
one_time_keyboard: true,
keyboard: [ ['test'], ['test1'] ]
}
};
MainKeyBoard(opts, 'afs', '690534265');
}
function MainKeyBoard(tasti, toxt, chid) {
var url = link + '/sendMessage?parse_mode=Markdown' +
'&chat_id=' + chid +
'&text=' + toxt +
'&reply_markup=' + tasti;
var respose = UrlFetchApp.fetch(url);
}
This is my error:
Request failed for https://api.telegram.org/bot745193421:<token>/sendMessage?parse_mode=Markdown&chat_id=690534265&text=afs&reply_markup=[object%20Object] returned code 400. Truncated server response: {"ok":false,"error_code":400,"description":"Bad Request: can't parse reply keyboard markup JSON object"} (use muteHttpExceptions option to examine full response)
I tried to add JSON.parse but error :
SyntaxError: Unexpected token: o
Since opts is an object when you are trying to concatenate it will use the toString() method which will just return [object Object] that you can see in the request.
In order to solve this issue serialize your object using JSON.stringify in your MainKeyboard function.
function MainKeyBoard(tasti, toxt, chid) {
var url = link + '/sendMessage?parse_mode=Markdown&chat_id=' + chid +
'&text=' + toxt + '&reply_markup=' + JSON.stringify(tasti);
var response = UrlFetchApp.fetch(url);
}

What is the right way to send JSON to clients?

I want to develop an app for Pebble. This app is going to tell you how long it takes from one place you set in options to another one taking in account traffic jams and stuff.
To achieve this I need to make a page that will return JSON. Pebble retrieves information using code like that:
var cityName = 'London';
var URL = 'http://api.openweathermap.org/data/2.5/weather?q=' + cityName;
ajax(
{
url: URL,
type: 'json'
},
function(data) {
// Success!
console.log('Successfully fetched weather data!');
},
function(error) {
// Failure!
console.log('Failed fetching weather data: ' + error);
}
);
I created a small page with a js script that gets needed information from Yandex API:
var route;
ymaps.ready(init);
var myMap;
function init(){
function getParameterByName(name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
results = regex.exec(location.search);
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
var time = 0;
var home = getParameterByName("h");
var work = getParameterByName("w");
ymaps.route([home, work],{avoidTrafficJams: true}).then(
function (router) {
route=router;
time = ((route.getTime())/60).toFixed(2);
var info = new Object;
info["home"] = home;
info["work"] = work;
info["time"] = ~~time+"m"+~~((time%1)*60)+"s";
JSON.stringify(info);
},
function (error) {
alert('Возникла ошибка: ' + error.message);
}
);
}
As you can see I can get a JSON string in the end. But how do I send it to clients when a request with right parameters is made?
I ended up using phantomjs and executing this js script on my php page.

Uncaught Error: Can't form encode an Object

I am trying to call some Parse CloudCode that I wrote for Mailgun, but when I call it from my iOS app this is what I get:
E2015-09-16T05:52:37.410Z]v4 after_save triggered for EmailConfirmations for user HjHSYVX56t:
Input: {"object":{"createdAt":"2015-09-
16T05:52:37.399Z","email1":"test#trever.me","email2":"test#trever.me","name1":"Test Test","name2":"Test Test","objectId":"KPLpKdZqSO","updatedAt":"2015-09-16T05:52:37.399Z"}}
Result: Uncaught Error: Can't form encode an Object
I get this from the Parse Console, does anyone know what that means exactly?
Thank you!
Here is my CloudCode:
// bring in Mailgun
var Mailgun = require('mailgun');
// init Mailgun
Mailgun.initialize('sandboxcf52f1abbe6f4bbe80c055aecc31f58f.mailgun.org', 'key-b29acfb8411921998764456e247c30fa');
Parse.Cloud.afterSave("EmailConfirmations", function(request) {
// This function runs on INSERT and DELETE operations.
// Check to ensure account is new.
if (!request.object.existed()) {
var email1 = request.object.get("email1");
var email2 = request.object.get("email2");
var name1 = request.object.get("name1");
var name2 = request.object.get("name2");
var tradeDateTime = request.object.get("tradeDateTime");
var body = "Hello " + name1 + "&" + name2 + ",\n\n Your trade on" + tradeDateTime +
"has been approved, and will need to be processed in Empower, or via an Expresso ticket. " +
"Please process as soon as possible to ensure a successful trade.";
var sender = "test#test.com";
var subject = "Trade Confirmation";
}
Mailgun.sendEmail(
{
to: [email1, email2],
from: sender,
subject: subject,
text: body
}, onMailComplete, onMailError);
function onMailComplete (httpResponse) {
console.log(httpResponse);
console.log("Email sent to " + email1 + "and" + email2);
}
function onMailError (httpResponse) {
console.error(httpResponse);
console.error("Uh oh, something went wrong");
}
} /* eo func def */
);
And this is the code where I'm calling the cloud function:
PFCloud.callFunctionInBackground("EmailConfirmations", withParameters: ["objectId": objectID, "email1" : emailCurrentUser, "email2" : emailCurrentUser, "name1" : fullnameCurrentUser, "name2" : fullnameCurrentUser])
I guess you tried to send an HTTP request passing object as parameter where it expected string. Use JSON.stringify(object) before passing it.
For more info see: https://parse.com/questions/result-uncaught-error-cant-form-encode-an-object
EDIT:
Now i totally.. don't understand what's going on. You should re-read the Parse Cloud guide because you are mixing afterSave hooks with cloud function calls and those are different things.
I guess your cloud code should look like this:
// bring in Mailgun
var Mailgun = require('mailgun');
// init Mailgun
Mailgun.initialize('sandboxcf52f1abbe6f4bbe80c055aecc31f58f.mailgun.org', 'key-b29acfb8411921998764456e247c30fa');
Parse.Cloud.define("EmailConfirmations", function(request) {
var email1 = request.params.email1;
var email2 = request.params.email2;
var name1 = request.params.name1;
var name2 = request.params.name2;
var tradeDateTime = request.params.tradeDateTime;
var body = "Hello " + name1 + "&" + name2 + ",\n\n Your trade on" + tradeDateTime +
"has been approved, and will need to be processed in Empower, or via an Expresso ticket. " +
"Please process as soon as possible to ensure a successful trade.";
var sender = "test#test.com";
var subject = "Trade Confirmation";
Mailgun.sendEmail({
to: [email1, email2],
from: sender,
subject: subject,
text: body
}, onMailComplete, onMailError);
function onMailComplete (httpResponse) {
console.log(httpResponse);
console.log("Email sent to " + email1 + "and" + email2);
}
function onMailError (httpResponse) {
console.error(httpResponse);
console.error("Uh oh, something went wrong");
}
} /* eo func def */
);
And in the swift function call you can skip the objectID but you should add tradeDateTime of type NSDate

Categories