The launch (New Session), unhandled, and Amazon default intents (cancel, help, stop) are working properly when I test them in the service simulator, but any one that I write doesn't seem to work. Below is an example of a test intent:
var handlers = {
'NewSession': function() {
this.emit(':tell', 'Hello');
'Test': function() {
this.emit(':tell','This intent is working');
},
'Unhandled': function() {
this.emit(':tell','Sorry, I don\'t know what to do');
},
'AMAZON.HelpIntent': function(){
this.emit(':ask', 'What can I help you with?', 'How can I help?');
},
'AMAZON.CancelIntent': function(){
this.emit(':tell', 'Okay');
},
'AMAZON.StopIntent': function(){
this.emit(':tell', 'Goodbye');
},
exports.handler = function(event,context){
var alexa = Alexa.handler(event,context);
alexa.registerHandlers(handlers);
alexa.execute();
};
The code snippet for the intents:
"intents": [
{
"name": "AMAZON.CancelIntent",
"samples": []
},
{
"name": "AMAZON.HelpIntent",
"samples": []
},
{
"name": "AMAZON.StopIntent",
"samples": []
},
{
"name": "ColorIntent",
"samples": [],
"slots": [
{
"name": "Test",
"samples": [
"Test me"
],
"slots": []
No matter what I do, I can't get the test intent to work and return "This intent is working'. Please help!
Maybe it's because your first invocation always gets handled by the NewSession handler, which then responds with 'Hello' and ends the session.
I see two ways to activate your Test handler, i.e. to get your Skill to respond with 'This intent is working':
You create a multi-turn conversation by ending your NewSession handler with this.emit(':ask', 'Hello! What do you want to do next?');, and then uttering 'Test me'.
You replace your NewSession handler with a LaunchRequest handler, and invoke your Skill with 'Alexa, tell tie picker to test me'.
Hope that helps! :)
By the way, because I can't comment everywhere yet: You can log your lambda's state, e.g. for debugging, by using console.log( 'Test handler invoked');, and then looking up the logs in AWS CloudWatch.
Related
I have working cross-platform extension which I converted for Safari using xcrun safari-web-extension-converter PATH. Goal of extension is to bookmark any URL into my website account (https://ourdomain.in).
My extension is perfectly working fine for Chrome but for Safari version, everything works well if user allows access permission for every website.
The issue is, even though I have proper optional_permissions and used chrome.permissions.request() method to ask user-consent for ourdomain.in, and we see user allowed access, still tab.url comes blank for chrome.tabs.onUpdated every time.
Here is the case in detail, when user presses extension button, we are checking user is logged into its account or not by opening our website URL into another tab.
var openSignin = function openSignin() {
console.log('hey');
chrome.tabs.create({ url: _config.baseURL + '?extension=1', active: false });
};
When this AUTH tab is loaded, following method will be called as it happens in Chrome which in turn extracts public and private tokens generated when any user logs into our website.
chrome.tabs.onUpdated.addListener(function (tabID, changeInfo, tab) {
if (tab.status == 'complete' && tab.url.startsWith(_config.baseURL)) {
chrome.tabs.executeScript(tab.id, { code: 'localStorage.getItem("PUBLIC")' }, function (r) {
localStorage['PUBLIC'] = JSON.parse(r[0]);
chrome.tabs.executeScript(tab.id, { code: 'localStorage.getItem("PRIVATE")' }, function (r) {
localStorage['PRIVATE'] = JSON.parse(r[0]);
if (localStorage['PRIVATE'] && tab.url === _config.baseURL + '?extension=1') {
chrome.tabs.remove(tabID);
}
});
});
}
});
The issue lies here is that until user does not grant for "Always Allow on Every Website" (I mean grant permission for https://ourdomain.in/extension?extension=1), chrome.tabs.onUpdate is giving tab.url = "" and it does not give proper URL value so our conditions don't match and know that particular user is signed in or not.
Following is our manifest.json where I have event used optional_permissions:
{
"name": "EXT NAME",
"description": "DESCRIPTION",
"manifest_version": 2,
"version": "1.0.181",
"minimum_chrome_version": "23",
"offline_enabled": true,
"browser_action" : {
"default_icon" : {
"64": "logo/icon.png"
},
"default_title" : "Add here"
},
"background" : {
"scripts" : [
"background.js"
]
},
"content_scripts": [{
"js": [ "content.js" ],
"matches": [ "<all_urls>" ]
}],
"icons": {
"16": "logo/icon_small.png",
"64": "logo/icon.png"
},
"permissions" : [
"https://*.ourdomain.in/*",
"activeTab",
"gcm",
"storage",
"notifications",
"identity",
"contextMenus",
"tabs",
"idle"
],
"externally_connectable": {
"matches": ["https://*.ourdomain.in/*"]
},
"optional_permissions": ["activeTab", "tabs", "storage", "contextMenus", "*://*.ourdomain.in/*"],
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
"web_accessible_resources": [
"corner.css",
"js/init.js",
"content.js",
"js/jquery.min.js",
"js/taggle.min.js",
"js/typeahead.bundle.min.js",
"ext.html.js",
"assets/*"
],
"commands": {
"_execute_browser_action": {
"suggested_key": {
"default": "Ctrl+Shift+S",
"mac": "Command+Shift+S"
},
"description": "Send a link to DOMAIN!"
}
}
}
And following is the code for permission request which is implemented in click event handler of extension button.
chrome.browserAction.onClicked.addListener(function (tab) {
var reqPerm = {
permissions: ["activeTab", "tabs", "storage", "contextMenus"],
origins: ['https://ourdomain.in/']
};
chrome.permissions.request(reqPerm, function (granted) {
if (granted) {
return go(tab.url);
} else {
console.log("Requested not granted.");
chrome.tabs.sendMessage(tabID, { action: 'signin', text: 'Please allow stash.ai to proceed.' });
}
});
});
Here I am able to see Privacy dialog and I do press Allow for the Day.
Now if I see in Safari > Preferences > Websites > Stash Extension, I am clearly able to see ourdomain.in -> Allowed which proves prompt worked as expected I believe.
Still when new tab is opened for authentication, the above mentioned code for chrome.tabs.onUpdate is executed and gives tab.url = ''. This definitely works when Allow for Every website is turned on.
And other thing is, when I open https://ourdomain.in, my extension icon still shows disabled and on click of the icon it again asks me for the permission. If on this tab, I do give permission, everything works smooth.
Thus, chrome.permissions.request() is no use if I have to manually give permission from tab.
Please let me know any suggestions here.
The answer was so simple, I have to change my reqPerm like,
var reqPerm = {
permissions: ["activeTab", "tabs", "storage", "contextMenus"],
origins: ['https://ourdomain.in/*']
};
So every endpoint in ourdomain.in works.
I am exploring if I can use cypress for end-to-end testing or not in angular? I am super beginner in it.
Cypress has some server() instance for XHR.
Question:
Suppose I am testing the login page so I can write test cases for querying elements and do the validation. In this process the browser will be making some API call, will it possible to write test cases for validating what was the statusCode the API had retured? What was XHR API response etc?
of course. With cypress you can spy the requests or mock them.
I have written a quick example to show you both methods:
describe("test", () => {
it("spy", () => {
cy.server();
cy.route("POST", /.*queries.*/).as("request")
cy.visit("https://docs.cypress.io/")
.get("#search-input").type("1234567890")
.wait("#request").then(xhr => {
expect(xhr.status).to.eq(200)
})
})
it("mock", () => {
cy.server();
const obj = JSON.parse(`
{
"results": [{
"hits": [{
"hierarchy": {
"lvl2": null,
"lvl3": null,
"lvl0": "Podcasts",
"lvl1": null,
"lvl6": null,
"lvl4": null,
"lvl5": null
},
"url": "https://stackoverflow.com",
"content": "mocked",
"anchor": "sidebar",
"objectID": "238538711",
"_snippetResult": {
"content": {
"value": "mocked",
"matchLevel": "full"
}
},
"_highlightResult": {
"hierarchy": {
"lvl0": {
"value": "Podcasts",
"matchLevel": "none",
"matchedWords": []
}
},
"content": {
"value": "mocked",
"matchLevel": "full",
"fullyHighlighted": false,
"matchedWords": ["testt"]
}
}
}
]
}
]
}
`);
cy.route("POST", /.*queries.*/, obj)
cy.visit("https://docs.cypress.io/")
.get("#search-input").type("1234567890")
.get("#algolia-autocomplete-listbox-0").should("contain", "mocked")
})
})
The spy example receives the raw XHR object and thus you are able to check the status code and so on.
The mock example shows you how you can mock any ajax request.
Please note: Currently you can not spy & mock fetch requests. But as far as I know they are rewriting the network layer in order to make this possible. Let me know if you need further assistance
i want to get data from nested json.
My json looks like as given below
{
"id": 2,
"cover_image": "http://13.233.31.123/media/homepage-banner.jpg",
"name": " Website",
"tagline": " IT Right",
"status": "ACTIVE",
"client_name": "Company",
"start_date": null,
"end_date": null,
"technology_frontend": "HTML, CSS, JAVASCRIPT\r\nCMS: WORDPRESS",
"technology_backend": "PHP",
"description": "We provide robust and high quality Custom Web Development.\r\nCodism is a global technology and business services consulting firm. We are specialized in servicing business market needs specializing in Web Design and Development, Online marketing and IT Consulting Services to commercial and government customers. We provide staffing and end-to end consulting services for organizations.",
"gallery": [
{
"project": 2,
"image": "http://localhost/media/gallery_image/homepage-banner.jpg"
},
{
"project": 2,
"image": "http://localhost/media/projects/gallery_image/software-development.jpg"
},
{
"project": 2,
"image": "http://localhost/media/projects/gallery_image/New_FRS_Image_Mobile_app_development.jpg"
}
]
}
I want to get all the images of gallery. I am not getting how i can do that if i am doing console.log(this.state.gallery[0]) it is showing first object but while i am doing console.log(this.state.gallery[0].image) giving error. my i found somewhere like use state as given gallery: {
images: []
} so my state is like this. how should i use map to get all details please help. thanks in advance
I hope you are doing mistake while setState
your state should be like
this.state = { data : {} }
when you setState on componentDidMount or anywhere so do something like
this.setState({ data : jsonData )};
after that you can use data on your render method for rendering the images.
this.state.data.galley.map(item => <Image source={{item.image}/>);
if your jsonData is an array and you want to render first object of array so do like
this.state = {data: []};
this.setState({data:jsonData)};
this.state.data[0].galley.map(item => <Image source={{item.image}/>);
if your jsonData is an array and you want to render all nested images so do like this.
this.state = {data: []};
this.setState({data:jsonData)};
this.state.data.map(data => data.galley.map(item => <Image source={{item.image}/>));
If you want to have all the images of your state, you can do something like this.
When you use the setState, you can try setState({...yourJson}) to create a new object of your json in your state.
Try to parse the JSON first like
.then((responseData) => {
newData = JSON.parse(responseData);
this.setState({ data: newData });
this.setState({ ... newData.gallery });
})
Pretty straightforward (I hope). I'd like to be able to use the API endpoint and have it only return specified fields. I.E. something like this
http://localhost:1337/api/reference?select=["name"]
Would ideally return something of the form
[{"name": "Ref1"}]
Unfortunately that is not the case, and in actuality it returns the following.
[
{
"contributors": [
{
"username": "aduensing",
"email": "standin#gmail.com",
"lang": "en_US",
"template": "default",
"id_ref": "1",
"provider": "local",
"id": 1,
"createdAt": "2016-07-28T19:39:09.349Z",
"updatedAt": "2016-07-28T19:39:09.360Z"
}
],
"createdBy": {
"username": "aduensing",
"email": "standin#gmail.com",
"lang": "en_US",
"template": "default",
"id_ref": "1",
"provider": "local",
"id": 1,
"createdAt": "2016-07-28T19:39:09.349Z",
"updatedAt": "2016-07-28T19:39:09.360Z"
},
"updatedBy": {
"username": "aduensing",
"email": "standin#gmail.com",
"lang": "en_US",
"template": "default",
"id_ref": "1",
"provider": "local",
"id": 1,
"createdAt": "2016-07-28T19:39:09.349Z",
"updatedAt": "2016-07-28T19:39:09.360Z"
},
"question": {
"createdBy": 1,
"createdAt": "2016-07-28T19:41:33.152Z",
"template": "default",
"lang": "en_US",
"name": "My Question",
"content": "Cool stuff, huh?",
"updatedBy": 1,
"updatedAt": "2016-07-28T19:45:02.893Z",
"id": "579a5ff83af4445c179bd8a9"
},
"createdAt": "2016-07-28T19:44:31.516Z",
"template": "default",
"lang": "en_US",
"name": "Ref1",
"link": "Google",
"priority": 1,
"updatedAt": "2016-07-28T19:45:02.952Z",
"id": "579a60ab5c8592c01f946cb5"
}
]
This immediately becomes problematic in any real world context if I decide to load 10, 20, 30, or more records at once, I and end up loading 50 times the data I needed. More bandwidth is used up, slower load times, etc.
How I solved this:
Create custom controller action (for example, 'findPaths')
in contributor/controllers/contributor.js
module.exports = {
findPaths: async ctx => {
const result = await strapi
.query('contributor')
.model.fetchAll({ columns: ['slug'] }) // here we wait for one column only
ctx.send(result);
}
}
Add custom route (for example 'paths')
in contributor/config/routes.json
{
"method": "GET",
"path": "/contributors/paths",
"handler": "contributor.findPaths",
"config": {
"policies": []
}
},
Add permission in admin panel for Contributor entity, path action
That's it. Now it shows only slug field from all contributor's records.
http://your-host:1337/contributors/paths
Here is how you can return specific fields and also exclude the relations to optimize the response.
async list (ctx) {
const result = await strapi.query('article').model.query(qb => {
qb.select('id', 'title', 'link', 'content');
}).fetchAll({
withRelated: []
}).catch(e => {
console.error(e)
});
if(result) {
ctx.send(result);
} else {
ctx.send({"statusCode": 404, "error": "Not Found", "message": "Not Found"});
}
}
I know this is old thread but I just run into exactly same problem and I could not find any solution. Nothing in the docs or anywhere else.
After a few minutes of console logging and playing with service I was able to filter my fields using following piece of code:
const q = Post
.find()
.sort(filters.sort)
.skip(filters.start)
.limit(filters.limit)
.populate(populate);
return filterFields(q, ['title', 'content']);
where filterFields is following function:
function filterFields(q, fields) {
q._fields = fields;
return q;
}
It is kinda dirty solution and I haven't figured out how to apply this to included relation entites yet but I hope it could help somebody looking for solution of this problem.
I'm not sure why strapi does not support this since it is clearly capable of filtering the fields when they are explicitly set. it would be nice to use it like this:
return Post
.find()
.fields(['title', 'content'])
.sort(filters.sort)
.skip(filters.start)
.limit(filters.limit)
.populate(populate);
It would be better to have the query select the fields rather than relying on node to remove content. However, I have found this to be useful in some situations and thought I would share. The strapi sanitizeEntity function can include extra options, one of which allows you only include fields you need. Similar to what manually deleting the fields but a more reusable function to do so.
const { sanitizeEntity } = require('strapi-utils');
let entities = await strapi.query('posts').find({ parent: parent.id })
return entities.map(entity => {
return sanitizeEntity(entity, {
model: strapi.models['posts'],
includeFields: ['id', 'name', 'title', 'type', 'parent', 'userType']
});
});
This feature is not implemented in Strapi yet. To compensate, the best option for you is probably to use GraphQL (http://strapi.io/documentation/graphql).
Feel free to create an issue or to submit a pull request: https://github.com/wistityhq/strapi
You can use the select function if you are using MongoDB Database:
await strapi.query('game-category').model.find().select(["Code"])
As you can see, I have a model called game-category and I just need the "Code" field so I used the Select function.
In the current strapi version (3.x, not sure about previous ones) this can be achieved using the select method in custom queries, regardless of which ORM is being used.
SQL example:
const restaurant = await strapi
.query('restaurant')
.model.query((qb) => {
qb.where('id', 1);
qb.select('name');
})
.fetch();
not very beautiful,but you can delete it before return.
ref here:
https://strapi.io/documentation/developer-docs/latest/guides/custom-data-response.html#apply-our-changes
const { sanitizeEntity } = require('strapi-utils');
module.exports = {
async find(ctx) {
let entities;
if (ctx.query._q) {
entities = await strapi.services.restaurant.search(ctx.query);
} else {
entities = await strapi.services.restaurant.find(ctx.query);
}
return entities.map(entity => {
const restaurant = sanitizeEntity(entity, {
model: strapi.models.restaurant,
});
if (restaurant.chef && restaurant.chef.email) {
**delete restaurant.chef.email;**
}
return restaurant;
});
},
};
yeah,I remember another way.
you can use the attribute in xx.settings.json file.
ref:
model-options
{
"options": {
"timestamps": true,
"privateAttributes": ["id", "created_at"], <-this is fields you dont want to return
"populateCreatorFields": true <- this is the system fields,set false to not return
}
}
You can override the default strapi entity response of:-
entity = await strapi.services.weeklyplans.create(add_plan);
return sanitizeEntity(entity, { model: strapi.models.weeklyplans });
By using:-
ctx.response.body = {
status: "your API status",
message: "Your own message"
}
Using ctx object, we can choose the fields we wanted to display as object.
And no need to return anything. Place the ctx.response.body where the response has to be sent when the condition fulfilled.
It is now 2023, and for a little while it has been possible to do this using the fields parameter:
http://localhost:1337/api/reference?fields[0]=name&fields[1]=something
event = Google::Apis::CalendarV3::Event.new({
"summary":"appointment",
"description":"placeholder",
"start": {
"date_time":'2016-05-28T08:00:00',
"time_zone":'Europe/Brussels',
},
"end": {
"date_time":'2016-05-28T09:00:00',
"time_zone":'Europe/Brussels',
},
'reminders': {
'useDefault': false,
'overrides': [
{'minutes': 840, 'method': 'popup'}
]
},
"color_id": "11"
})
result = service.insert_event('primary', event)
I am trying to insert a calendar event via the ruby API. This code gives the following error:
/usr/local/rvm/gems/ruby-2.3.1/gems/google-api-client-0.9.6/lib/google/apis/core/http_command.rb:211:in `check_status': cannotUseDefaultRemindersAndSpecifyOverride: Cannot specify both default reminders and overrides at the same time. (Google::Apis::ClientError)
Any help is greatly appreciated.
It may be a little late but I was having the same problem and I found a workaround.
Create the event without the reminders. Once you have the event created with the initializer set the reminders like this:
event.reminders = Google::Apis::CalendarV3::Event::Reminders.new(
use_default: false,
overrides: [
Google::Apis::CalendarV3::EventReminder.new(reminder_method:"popup", minutes: reminder_minutes),
Google::Apis::CalendarV3::EventReminder.new(reminder_method:"email", minutes: reminder_minutes)
]
)
That is working for me!