Javascript facebook bot function - javascript

I used to program in C++ but I'm trying to program a facebook bot in Javascript.
I have a function Options that creates option buttons. The buttons are programmed like this (1):
"buttons": [{
"type": "web_url",
"url": "https://www.messenger.com",
"title": "Use"
}]
But since I have lots of them I would like to create a function to create buttons.
I've tried to create a Button function like that:
function PLButton(type, title, payload) {
"type": type,
"title": title,
"payload": payload
}
And then substitute the code above (1) by this:
"buttons": [{PLButton("postback", "Drop", "PRESS_CANCEL")}]
But it doesn't work.

The object literal syntax and function body syntax are not interchangeable, but you can next an object literal within a function. If you want to construct and return an object, you need to combine your two attempts:
function PLButton(type, title, payload) {
return {
"type": type,
"title": title,
"payload": payload
};
}
The object literal syntax ({x: 1}) does something akin to creating a map (a dict-mode object) which the function can then return. This sort of helper is pretty common, since an object is easier to extend later than a list of loose parameters.

var initialButtonList = {"buttons": [{
"type": "web_url",
"url": "https://www.messenger.com",
"title": "Use"
}]}
function PLButton(type, title, payload) {
var newButton={//create newButton as object that holds key-value pairs
"type": type,
"title": title,
"payload": payload
};
return newButton;
}
initialButtonList.buttons.push(PLButton("postback", "Drop", "PRESS_CANCEL"));
//initialButtonList will now have the newly added button as well;

Solved!
I've just created a function like that:
function PLButton(tipo, titulo, accao){
var Butt = {type:tipo, title: titulo, payload: accao};
return Butt;
}
And incede the funcion Options :
"buttons": [PLButton("postback", "Use", "PRESS_USE_SCISOR"), PLButton("postback", "Drop", "PRESS_DROP_SCISOR")],

Related

Getting parameters from an Azure Function to use in function.json bindings

I am new to Azure Functions and I'm having trouble with some of the basics, in particular how to pass parameter data to function.json so that I can write a blob to Azure Blob Storage using the Storage Connector.
My question is, how do I specify a parameter within the httpTrigger function that can be used by the outputBlobContents binding below?
My setup is pretty simple (but doesn't work yet):
function.json:
{
"bindings": [
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "res"
},
{
"type": "blob",
"direction": "out",
"name": "outputBlobContents",
"path": "uploaded_files/{destinationFilename}",
"connection": "MY_STORAGE"
}
]
}
index.ts:
import { AzureFunction, Context, HttpRequest } from "#azure/functions"
const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
context.bindingData.destinationFilename = "testfile.pdf";
context.bindings.outputBlobContents = context.req.body;
const responseMessage = "uploaded file";
context.res = {
status: 201,
body: responseMessage
};
};
export default httpTrigger;
In my example code I am trying assign destinationFilename to the context.bindingData object, but this does not work. I've read through all the documentation but it's not very clear about what the bindingData object actually is or how named parameters work in general. How do I tell the blob storage connector where to store the file?
Simply put, any form of json input will be obtained as a parameter. Inside the function is impossible. If you want to use it inside the function, please choose to directly use the sdk of Azure Storage.
Since you use httptrigger, you can send a request body in json format, like this:
{
"destinationFilename":"something"
}
After that, output binding can get the value.

angular 5: setting (click) value from an object not working

I have a nav menu that is rendered using a navigation.ts json file for the menu items. When it gets to the navitem component it uses a ngIf to check if the item from the navigation file has a "function" key and if it does, the desired behavior is for it to use the string value from item.function in the object to fill the value for the (click) event.
In reality, the console throws an error saying "_co.item.function is not a function"
HTML
<span class="nav-link" *ngIf="item.function" (click)="item.function()" matRipple>
<mat-icon class="nav-link-icon" *ngIf="item.icon">{{item.icon}}</mat-icon>
<span class="nav-link-title" [translate]="item.translate">{{item.title}}</span>
<span class="nav-link-badge" *ngIf="item.badge" [translate]="item.badge.translate"
[ngStyle]="{'background-color': item.badge.bg,'color': item.badge.fg}">
{{item.badge.title}}
</span>
</span>
Navigation.ts
[{
"id": "accounting",
"title": "Accounting",
"type": "collapse",
"children": [
{
"id" : "salesmenSalesLocation",
"title": "Salesmen Sales Location",
"type": "item",
"function": "handleSelect(ReportTypes.SalesmenSalesLocations)"
},
{
"id": "laggingLedgerEntries",
"title": "Lagging Ledger Entries",
"type": "item",
"function": "handleSelect(ReportTypes.LaggingLedgerEntries)"
}
]}]
I have also tried it as (click)="item.function" with no success.
I'm assuming you can change the data source here, because otherwise I don't see any good solution.
A string is not a function, and while you can turn it into one with eval that is a bad idea. What you should really do instead is just pass in a value that tells the function what to use.
Change your data to something like this:
{
"id" : "salesmenSalesLocation",
"title": "Salesmen Sales Location",
"type": "item",
"reportTypeSource": "SalesmenSalesLocations"
},
{
"id": "laggingLedgerEntries",
"title": "Lagging Ledger Entries",
"type": "item",
"reportTypeSource": "LaggingLedgerEntries"
}
Then pass that value to your function and use that to tell it where to look:
handleSelect (reportTypeSource: string) {
const reportType = ReportTypes[reportTypeSource]
// continue as before
}
And call it in your HTML like this:
(click)="handleSelect(item.reportTypeSource)"
Problem lies here:
"function": "handleSelect(ReportTypes.LaggingLedgerEntries)"
And here:
(click)="item.function()"
You cannot simply pass a string and expect the component to execute a function and also know exactly what to do. Here you need to pass the actual function.
Your setup looks over-config'd. I would tear the config down and put the logic into the component itself. Don't be afraid to have more template as well, if anything it makes things more legible (as opposed to the config)
Does that function exist in the component or just the model? If it is just on the model it won't work. (click) is looking for a method on the component. It is, ostensibly just a string in this instance.

Failing to add a key and value to a javascript object

I'm new to JavaScript and Node etc but enjoying the experience of developing - last serious development i did was in the 90s - I used to be a 370 assembler programmer back 30 years ago!
I've been stuck on this all day.
My issue is that I am trying to add a new element to the entries in an array of objects. I have simplified my code here in the hope that I am doing something blindingly stupid and obviously wrong though I have tried this in javascript in the browser and I know I am barking up the right tree.
What I am trying to do is add a new key/value pair to the collectibles returned. I have simplified the code here but in essence the value is coming for a different collection. the issue is that the lines that set the new keys are having no effect on my objects in the array collectibles. I have tried several methods all of which I believe should work.
I can read the key/values in the returned array of objects and I can also set existing keys to new values, but setting a new key is not working.
Here is my code:
var sendJsonResponse = function (res, status, content) {
res.status(status);
res.json(content);
};
var mongoose = require("mongoose");
var Coll = mongoose.model("collectible");
var Img = mongoose.model("image");
module.exports.collectiblesList = function (req, res) {
var firstImage_ids = [];
var imageDir = "https://s3.amazonaws.com/xxxxxxxxxxx/images/";
var defaultImage = imageDir + "default.jpg";
// get the collectibles
Coll.find(req.body).exec(function (err, collectibles) {
if (!collectibles) {
// not found
sendJsonResponse(res, 404, {"message": "no collectibles found"});
return;
}
if (err) {
console.log(collectible);
sendJsonResponse(res, 400, err);
return;
}
//found the collectibles
// now find the list of images we need to pull (each collectible can have multiple images
collectibles.forEach(function (collectible, index) {
if (collectible.image_ids) {
firstImage_ids.push(collectible.image_ids[0]);
collectibles[index].imageUrl = defaultImage; // this is the line that has no effect.
collectible.imageUrl = defaultImage; // tried this too.
collectible["imageUrl"] = defaultImage; // and this. :-(
console.log(collectible);
}
});
sendJsonResponse(res, 200, collectibles);
});
};
Using Postman to test this API. This is what is being returned:
[
{
"_id": "5a43c61134aaea2025158cab",
"name": "A-0_5",
"title": "Occoneechee Lodge 104: A-0_5",
"issueDate": null,
"quantity": null,
"event_id": null,
"type": "A - Arrowhead patches",
"tag_ids": [
"5a401a17b720186ab61c649e"
],
"description": "Elangomat, no name",
"organisation_id": "5a413340b720186ab61c661e",
"supercedes_id": null,
"sortName": "A-000.5",
"image_ids": [
"5a41685ab720186ab61c663d"
],
"deleted": false,
"schemaVersion": "1.0"
},
{
"_id": "5a43c63334aaea2025158cac",
"name": "A-1",
"title": "Occoneechee Lodge 104: A-1",
"issueDate": null,
"quantity": null,
"event_id": null,
"type": "A - Arrowhead patches",
"tag_ids": [
"5a401a17b720186ab61c649e"
],
"description": "Service",
"organisation_id": "5a413340b720186ab61c661e",
"supercedes_id": null,
"sortName": "A-001",
"image_ids": [
"5a41685ab720186ab61c663e"
],
"deleted": false,
"schemaVersion": "1.0"
}]
i.e. it contains no imageUrl keys.
thanks for the assist.
WWW
GT
I might have misunderstood. But if your issue is that collectibles[i].imageUrl is later on returning undefined/null, then i believe it's simply because you need to add
collectibles.save();
after setting the collectibles[i].imageUrl value. you can add that line after the foreach loop, before the json response.
collectibles.forEach(function (collectible, index) {
if (collectible.image_ids) {
firstImage_ids.push(collectible.image_ids[0]);
collectible.imageUrl = defaultImage;
}
});
collectibles.save(); //here, this saves the changes done to the mongoose object.
sendJsonResponse(res, 200, collectibles);
I solved it in the end after a lot of effort. This article explains (but i don't fully yet follow the explanation)
I found that the object has more metadata in it and the actual object is in _doc, so the first (and i suspect frowned upon solution) is to update the code to:
collectible._doc.imageUrl = defaultImage;
The better way was to simply add imageUrl to the mongoose model and leave _doc out of it. The issue there is that this is not a field i intend to populate in the mongoDB.

Parse push notification shows empty geo-queries

This is similar to but it's a continuation to Parse geo-queries always empty
I have device installations working correctly, and i've created a customized class "test_users" that contains the location data. each instance in the "Installation" class holds a pointer to the "test_users" instance, with column name "test" below** you can see below, and when I clicked on the pointer value, it will go to that "test_user" instance.
and "test_users" class
I have the following javascript code to Query the channel and location to send push notification:
$http({
"url": "https://api.parse.com/1/push",
"method": "POST",
"data": {
"data": { "alert": "test!! ",
"sound": "beep.caf",
"badge": "Increment",
"uid":user_uid,
"date":date,
"time":time
},
"where": {
"channel": category,
"test": {
"$inQuery": {
"location": {
"$nearSphere": {
"__type": "GeoPoint",
"latitude": 37.7150 ,
"longitude": -117.1625
},
"$maxDistanceInMiles": 20
}
}
}
}
},
"headers": {
"X-Parse-Application-Id": "######",
"X-Parse-REST-API-Key": "#######",
"Content-Type": "application/json"
},
"params":
{
"uid" : user_uid,
"date": date,
"time": time
}
});
However, no push notification is created, and when i check the analytics, i see this
Any thoughts on where I made the query mistake? or anything wrong with "test_users" class? Update: On a different experiment, I also created a _User class just like the parse.com push notification doc did (and have "Installation" instance storing a pointer to the _User instance), and got same empty geo-query result.

Iteration in handlebar using backbone

I'm using backbone and handlebars for templating and i'm new to this.
My current json is in the below format and the code works fine.
[
{
"id": "10",
"info": {
"name": "data10"
}
},
{
"id": "11",
"info": {
"name": "data11"
}
}
]
But when i change my json structure to something like shown below i'm having difficulty in getting things to be populated.
{
"total_count": "10",
"dataElements": [
{
"id": "10",
"info": {
"name": "data10"
}
},
{
"id": "11",
"info": {
"name": "data11"
}
}
]
}
How can i populate name, info and total_count keeping the current code structure ?
JSFiddle : http://jsfiddle.net/KTj2K/1/
Any help really appriciated.
A few things that you need to do in order for this to work.
Replace Backbone's core 'reset' on your collection with a custom one that understands the data you are passing to it. For example:
reset: function (data) {
this.totalCount = data.total_count;
Backbone.Collection.prototype.reset.call(this, data.dataElements);
}
Now when you reset your collection, it will pull the total_count out of the object you are resetting it with, and use Backbone's core reset with the dataElement array. Keep in mind you may have to do a similar thing with 'parse' if you're intending on pulling this from the server.
I'd recommend that (if your example looks anything like the real code you're working with) you reset your collection before getting to rendering.
var dataCollectionList = new dataCollection();
dataCollectionList.reset(jsonData);
var App = new AppView({model : dataCollectionList});
Now in your view's "render" method you can grab the 'totalCount' property off the collection -
render : function() {
//Should spit the total count into the element, just as an example
this.$el.append(this.model.totalCount);
//or console.log it
console.log(this.model.totalCount);
return this;
}
Voila. Side note - as someone who works with Backbone a lot, it drives me nuts when people set an attribute of something like "model" (i.e. peopleModel, itemModel, etc) and it ends up being a backbone collection. It's much clearer to name it after what it is - though some MVC purists may disagree a bit.
Also, in this code block:
_.each(this.model.models, function (myData) {
$(this.el).append(new ItemView({model:myData}).render().el);
}, this);
You don't need to do _.each(this.model.models.......). Since you're working with a collection, the collection has a built in 'each' method.
this.model.each(function (myData) { ..... } , this);
Quite a bit cleaner.

Categories

Resources