InlineQueryResultArticle of answerInlineQuery in Telegram Bot API with Google Apps Script - google-apps-script

I'm using google apps script for Telegram Bot API & I'm having problem with InlineQueryResultArticle in answerInlineQuery method.
function answerInlineQuery(iqid, result){
var data = {
method: "post",
payload: {
method: "answerInlineQuery",
inline_query_id: iqid,
results:JSON.stringify(result)
}
}
}
Here is the format of result :-
var result= {
InlineQueryResultArticle:[
{type:'article',id: iqid, title:"RESULT 1", input_message_content:"TEXT 1"},
{type:'article',id: iqid, title:"RESULT 2", input_message_content:"TEXT 2"}
]
};
answerInlineQuery(iqid, result);
I have turned on Inline Mode in #BotFather. My bot is also receiving inline queries and for every request I can see my inline query id properly & I can also see the result receiving as [object Object].
But, the problem is I'm not getting any results.
REF: In answerinlinequery, the results should be a JSON-serialized array of results for the inline query using any of these results.
Can anyone point out where am I going wrong ?

The id field for a InlineQueryResultArticle must be unique for each result. However you are setting the id as iqid for both results.
You should replace them with custom ids.
var result= {
InlineQueryResultArticle:[
{type:'article',id: "1", title:"RESULT 1", input_message_content:"TEXT 1"},
{type:'article',id: "2", title:"RESULT 2", input_message_content:"TEXT 2"}
]
};

After many attempts I found solution:
Here there are an inline answer with three results
****Be careful :change value of document_file_id with a sample file_id from your bot else you will see an error
//your bot token placed here
const token = "";
tgmsg('answerInlineQuery', {
"inline_query_id": update['inline_query']['id'],
"results": JSON.stringify([
//inline result of an article with thumbnail photo
{
"type": "article",
"id": "1",
"title": "chek inline keybord ",
"description": "test ",
"caption": "caption",
"input_message_content": {
"message_text": "you can share inline keyboard to other chat"
},
"thumb_url": "https://avatars2.githubusercontent.com/u/10547598?v=3&s=88"
},
//inline result of an article with inline keyboard
{
id: "nchfjdfgd",
title: 'title',
description: "description",
type: 'article',
input_message_content: {
message_text: "inline is enabled input_message_content: {message_text: message_text}message_text"
},
reply_markup: {
"inline_keyboard": [
[{
"text": "InlineFeatures.",
"callback_data": "inline_plugs_1118095942"
}],
[{
"text": "OtherFeatures.",
"callback_data": "other_plugs_1118095942"
}]
]
}
},
//inline result of a cached telegram document with inline keyboard
{
id: "nchgffjdfgd",
title: 'title',
description: "description",
//change this on with the value of file_id from telegram bot api
document_file_id: "BQACAgQAAxkBAAIBX2CPrD3yFC0X1sI0HFTxgul0GdqhAALjDwACR4pxUKIV48XlktQNHwQ",
type: 'document',
caption: "caption ghh hhdd",
reply_markup: {
"inline_keyboard": [
[{
"text": "InlineFeatures.",
"callback_data": "inline_plugs_1118095942"
}],
[{
"text": "OtherFeatures.",
"callback_data": "other_plugs_1118095942"
}]
]
}
}
])
})
function tgmsg(method, data) {
var options = {
'method': 'post',
'contentType': 'application/json',
'payload': JSON.stringify(data)
};
var responselk = UrlFetchApp.fetch('https://api.telegram.org/bot' + token + '/' + method, options);
}

Related

Parsing objects of a JSON for input validation

I want to use a database of valid ICAO and IATA airport codes for a discord bot input in typescript. However, I am not quite sure how to call the "icao" and "iata" contstructor of all objects, as each one is defined differently and there are thousands: e.g.:
"00AK": {
"icao": "00AK",
"iata": "",
"name": "Lowell Field",
"city": "Anchor Point",
"state": "Alaska",
"country": "US",
"elevation": 450,
"lat": 59.94919968,
"lon": -151.695999146,
"tz": "America\/Anchorage"
},
"00AL": {
"icao": "00AL",
"iata": "",
"name": "Epps Airpark",
"city": "Harvest",
"state": "Alabama",
"country": "US",
"elevation": 820,
"lat": 34.8647994995,
"lon": -86.7703018188,
"tz": "America\/Chicago"
},
The bot uses the following to provide the METAR of a specific airport:
name: 'metar',
description: 'Provides the METAR report of the requested airport',
category: CommandCategory.UTILS,
executor: async (msg) => {
const splitUp = msg.content.replace(/\.metar\s+/, ' ').split(' ');
if (splitUp.length <= 1) {
await msg.reply('please provide an ICAO airport code.');
return Promise.resolve();
}
const icaoArg = splitUp[1];
if (icaoArg.length !== 4) {
await msg.reply('please provide an ICAO airport code.');
return Promise.resolve();
}
request({
method: 'GET',
url: `https://avwx.rest/api/metar/${icaoArg}`,
headers: {
Authorization: process.env.METAR_TOKEN },
}, async (error, response, body) => {
const metarReport = JSON.parse(body);å
const metarEmbed = makeEmbed({
title: `METAR Report | ${metarReport.station}`,
description: makeLines([
'**Raw Report**',
metarReport.raw,
,
'**Basic Report:**',
`**Time Observed:** ${metarReport.time.dt}`,
`**Station:** ${metarReport.station}`,
`**Wind:** ${metarReport.wind_direction.repr} at ${metarReport.wind_speed.repr}kts`,
`**Visibility:** ${metarReport.visibility.repr}${metarReport.units.visibility}`,
`**Temperature:** ${metarReport.temperature.repr}C`,
`**Dew Point:** ${metarReport.dewpoint.repr}C`,
`**Altimeter:** ${metarReport.altimeter.value.toString()} ${metarReport.units.altimeter}`,
]),
fields: [
{
name: 'Unsure of how to read the raw report?',
value: 'Type \'**.metarhow**\' to learn how to read raw METARs',
inline: false
},
],
footer: { text: 'This METAR report may not accurately reflect the weather in the simulator. However, it will always be similar to the current conditions present in the sim.' },
});
await msg.channel.send({ embeds: [metarEmbed] });
});
},
};
Currently, if a user provides an ICAO that's not valid the bot crashes, or if they provide a valid IATA, the discord api throws the user an error to provide a valid ICAO code. How would I go about cross referencing the user argument with the JSON so the bot does not crash when inputting an invalid ICAO? Thanks

How to Retrieve (not create) Tasks from Asana using Apps Script & Personal Access Token

I am attempting to retrieve, but not create, tasks from Asana using Google Apps Script.
Using the Asana API Explore, I have constructed a URL that returns the data I desire: https://app.asana.com/api/1.0/tasks?opt_fields=name,assignee_status&assignee=987654321987654&completed_since=2018-02-22&limit=100&workspace=456789123456
This URL returns the desired data, in the following format:
{
"data": [
{
"id": 147258369147258,
"assignee_status": "inbox",
"name": "An example task name"
},
{
"id": 963852741963852,
"assignee_status": "upcoming",
"name": "And second example task name."
},
//etc...
]
}
With that URL as a model, I have created a Personal Access Token and executed the following function within Apps Script:
function getTasks5() {
// Asana Personal Token
var bearerToken = "Bearer " + "asdf123456789asdf456789456asdf";
//Request
var request = {
data: {
opt_fields: ["name", "assignee_status"],
assignee: "987654321987654",
completed_since: "2018-02-22",
limit: "100",
workspace: "456789123456"
}
};
// Request options
var options = {
method: "GET",
headers: {
"Authorization": bearerToken
},
contentType: "application/json",
payload: JSON.stringify(request)
};
var url = "https://app.asana.com/api/1.0/tasks";
var result = UrlFetchApp.fetch(url, options);
var reqReturn = result.getContentText();
Logger.log(reqReturn);
}
Instead of returning the desired data as the aforementioned URL does, the function creates an unnamed task in Asana, which is undesirable. It also returns this response containing undesired data:
{
"data": {
"id": 123456789123456,
"created_at": "2018-02-22T20:59:49.642Z",
"modified_at": "2018-02-22T20:59:49.642Z",
"name": "",
"notes": "",
"assignee": {
"id": 987654321987654,
"name": "My Name Here"
},
"completed": false,
"assignee_status": "inbox",
"completed_at": null,
"due_on": null,
"due_at": null,
"projects": [],
"memberships": [],
"tags": [],
"workspace": {
"id": 456789123456,
"name": "Group Name Here"
},
"num_hearts": 0,
"num_likes": 0,
"parent": null,
"hearted": false,
"hearts": [],
"followers": [
{
"id": 987654321987654,
"name": "My Name Here"
}
],
"liked": false,
"likes": []
}
}
Is it possible to simply GET a list of tasks in the manner exemplified by my first JSON example above without creating a task, and without resorting to using OAuth? If so, what changes to the Apps Script function need to be made?
Alright, the problem was with the approach I was taking. Rather than format the request with a payload (which infers a POST request), I needed to structure it more traditionally as a GET request, like so:
var requestUrl = "https://app.asana.com/api/1.0/tasks?opt_fields=name,assignee_status&assignee=123456789123&completed_since=2018-02-22&limit=100&workspace=987654321987";
var headers = {
"Authorization" : "Bearer " + AUTH_TOKEN
};
var reqParams = {
method : "GET",
headers : headers,
muteHttpExceptions: true
};
Then I was able to perform:
UrlFetchApp.fetch(requestUrl, reqParams);
And obtain the data I was after.

MongoDB, NodeJS: updating an embedded document with new members

Using: MongoDB and native nodeJS mongoDB driver.
I'm trying to parse all the data from fb graph api, send it to my API and then save it to my DB.
PUT handling in my server:
//Update user's data
app.put('/api/users/:fbuser_id/:category', function(req, res) {
var body = JSON.stringify(req.body);
var rep = /"data":/;
body = body.replace(rep, '"' + req.params.category + '"' + ':');
req.body = JSON.parse(body);
db.fbusers.update({
id: req.params.fbuser_id
}, {
$set: req.body
}, {
safe: true,
multi: false
},
function(e, result) {
if (e) return next(e)
res.send((result === 1) ? {
msg: 'success'
} : {
msg: 'error'
})
});
});
I'm sending 25 elements at a time, and this code just overrides instead of updating the document.
Data I'm sending to the API:
{
"data": [
{
"category": "App page",
"name": "SoundCloud",
"id": "7919071058",
"created_time": "2013-09-16T18:16:59+0000"
},
{
...and so on
}
]
}
Basically my API changes "data" key from sent json to the category name, f.e.:
PUT to /api/users/000/likes will change the "data" key to "likes":
{
"likes": [
{
"category": "App page",
"name": "SoundCloud",
"id": "7919071058",
"created_time": "2013-09-16T18:16:59+0000"
},
{
...and so on
}
]
}
Then this JSON is put to the db.
Hierarchy in mongodb:
{
"_id": ObjectID("556584c8e908f0042836edce"),
"id": "0000000000000",
"email": "XXXX#gmail.com",
"first_name": "XXXXXXXX",
"gender": "male",
"last_name": "XXXXXXXXXX",
"link": "https://www.facebook.com/app_scoped_user_id/0000000000000/",
"locale": "en_US",
"name": "XXXXXXXXXX XXXXXXXXXX",
"timezone": 3,
"updated_time": "2015-05-26T18:11:59+0000",
"verified": true,
"likes": [
{
"category": "App page",
"name": "SoundCloud",
"id": "7919071058",
"created_time": "2013-09-16T18:16:59+0000"
},
{
"category": "App page",
"name": "SoundCloud",
"id": "7919071058",
"created_time": "2013-09-16T18:16:59+0000"
},
{
....and so on
}
]
}
So the problem is that my api overrides the field (in this case "likes") with newly sent data, instead of appending it to already existing data document.
I am pretty sure that I should be using other parameter than "$put" in the update, however, I have no idea which one and how to pass parameters to it programatically.
Use $push with the $each modifier to append multiple values to the array field.
var newLikes = [
{/* new item here */},
{/* new item here */},
{/* new item here */},
];
db.fbusers.update(
{ _id: req.params.fbuser_id },
{ $push: { likes: { $each: newLikes } } }
);
See also the $addToSet operator, it adds a value to an array unless the value is already present, in which case $addToSet does nothing to that array.

retrieving data using Ember

as I go deeper into EmberJS, I got into this context where I need to use HTTP request. As a start, I tried to retrieve JSON data so I made a test page that returns JSON and I also verified that it is in JSON by deserializing it. No errors were encountered but there is no output at all. Below are the details of my code
application.js
App = Ember.Application.create({});
App.ApplicationAdapter = DS.RESTAdapter.extend({
host: 'http://172.19.20.30/EmberTest/testApi.aspx'
});
event.js
App.Event = DS.Model.extend({
title: DS.attr('string'),
body: DS.attr('string')
});
router.js
App.Router.map(function () {
this.resource('events', {path: '/'});
});
App.EventsRouter = Ember.Route.extend({
model: function () {
return App.Event.find();
}
});
JSON output from host
{ "events": [{ "id": 1, "title": "test title", "body": "test body" },{ "id": 2, "title": "another title", "body": "another body" }] }
HTML
<script type="text/x-handlebars" data-template-name="events">
this is an example
{{#each e in model}}
<label>{{e.title}}</label><br />
{{/each}}
</script>
what could possibly be missing in my code? comments, opinions, suggestions are greatly appreciated
Looks like the return JSON is wrong.. it should be singular:
{ "event": [{ "id": 1, "title": "test title", "body": "test body" },{ "id": 2, "title": "another title", "body": "another body" }] }
When you do a find with Ember Data it should have the model name:
this.store.find('event') So Ember-data know where the return map to.
This will generate a URL http://host:port/event
If you are changing host it should just be the base URL you are changing and not absolute. So in your case:
App.ApplicationAdapter = DS.RESTAdapter.extend({
host: 'http://172.19.20.30/EmberTest'
});
Then the URL will become http://172.19.20.30/EmberTest/events

BackboneJS How to fetch specific value from API JSON file

I have a BackboneJS Application where I want to fetch a specific value from a JSON API.
The JSON file has this structure:
"data": {
"title": "some title",
"startDate": "some start date",
"endDate": "some enddate",
"description": "description blablabla ",
"contest_id": 10,
}
I want to fetch the "contest_id". So I have this Backbone Model:
CompetitionQuestion.CompetitionQuestionModel = Backbone.Model.extend({
url: function() {
return App.APIO + '/i/contest/' + this.contest_id;
},
defaults: {
"data": []
}
});
This gives me /i/contest/undefined Why is that?? I cant do:
return App.APIO + '/i/contest/' + this.data.contest_id;
Can someone tell me what I'm doing wrong?