Alexa skills kit, trouble getting session attributes to persist - session

I have been working on a skill where I am using Login With Amazon account linking so I can grab the user email address and name to use in my skill. I am doing something similar to the scoreKeeper sample, using the eventHandlers.js and the storage.js for saving items to a database. In the eventHandlers.onLaunch I am successfully getting the profile name and email address from Amazon and I save it to the session.attributes like this:
var profile = JSON.parse(body);
speechOutput="Hello, " + profile.name.split(" ")[0] + ".";
var sessionAttributes = {};
sessionAttributes = { name: profile.name, email: profile.email };
session.attributes = sessionAttributes;
console.log("Name in session:", session.attributes.name);
The console log shows the name so I know it is being saved in the session.attributes, but when I try to access the session.attributes in my storage.js or intentHandlers.js, it shows it as being empty. What am I missing? Thanks in advance. This has been driving me crazy.

I got this working by adding session to the callback of the response.ask function, like this:
ask: function (speechOutput, repromptSpeech, _session) {
this._context.succeed(buildSpeechletResponse({
session: _session,
output: speechOutput,
reprompt: repromptSpeech,
shouldEndSession: false
}));
},
It had session: this._session for saving the session, but that didn't seem to be working for me. Passing it as a variable did.

Let's say you want to obtain city name from the user and be able to access that value later in the Alexa session:
1) Pre-define your key/value pairs in the JSON response:
def build_response(session_attributes, speechlet_response):
return {
'version': '1.0',
'sessionAttributes': {
"session_attributes": {
'NameOfCity': city_name,
}
},
'response': speechlet_response
}
2) In global scope, declare the variable as an empty string:
city_name = "",
3) Whenever you update that variable within a function, make sure you reference that variable as global. For example:
def set_city_name_in_session(intent, session):
card_title = intent['name']
session_attributes = {}
should_end_session = False
if 'CityIntent' in intent['slots']:
global city_name
city_name = intent['slots']['CityIntent']['value']
4) When creating a function that needs to access this variable, pass the global variable as an argument into the function then, within the function, expose all session key/pair values like so:
def access_variables(intent, session, city_name):
card_title = intent['name']
session_attributes = {}
should_end_session = False
exposed_attributes = session['attributes']['session_attributes']
city_name_attribute_value = exposed_attributes.get('NameOfCity')
if (some_kind_of_condition):
do something awesome with city_name_attribute_value
To test, enter sample utterances into Service Simulator then check if values are persisting in your Lambda JSON response.

Related

Get the student´s submission id of a google classroom assignment

I want to return assignments in Google Classrom using
service().courseWork().studentSubmissions().return_(courseId=PASS_HERE_THE_COURSEID, courseWorkId=PASS_HERE_THE_COURSEWORDID, id=PASS_HERE_THE_SUBMISSION_ID)
I have the courseId and the courseWorkId, but don´t know how to get the id=PASS_HERE_THE_SUBMISSION_ID for each student.
Hope someone can help me.
You can use courses.courseWork.studentSubmissions.list to get a list of student submissions. You just need to provide the courseId and courseWorkId as a path parameter. You may also include additional query parameters in your request.
For example, you want to restrict returned student work to those owned by the student with the specified identifier. You need to set a specific identifier to userId as part of your query parameters
Note: You may also loop all the list of student submission to process each submission before returing it using courses.courseWork.studentSubmissions.return
The numeric identifier for the user
The email address of the user
The string literal "me", indicating the requesting user
Sample Response Body (JSON):
{
"studentSubmissions": [
{
object (StudentSubmission)
}
],
"nextPageToken": string
}
StudentSubmission contains all the information related to the student submission for the course work including the courseId, courseWorkId, id and userId.
StudentSubmission Resource (JSON):
{
"courseId": string,
"courseWorkId": string,
"id": string,
"userId": string,
"creationTime": string,
"updateTime": string,
"state": enum (SubmissionState),
"late": boolean,
"draftGrade": number,
"assignedGrade": number,
"alternateLink": string,
"courseWorkType": enum (CourseWorkType),
"associatedWithDeveloper": boolean,
"submissionHistory": [
{
object (SubmissionHistory)
}
],
// Union field content can be only one of the following:
"assignmentSubmission": {
object (AssignmentSubmission)
},
"shortAnswerSubmission": {
object (ShortAnswerSubmission)
},
"multipleChoiceSubmission": {
object (MultipleChoiceSubmission)
}
// End of list of possible types for union field content.
}
(UPDATE)
Regarding the error you have encountered when using courses.courseWork.studentSubmissions.return in Apps Script,
GoogleJsonResponseException: API call to classroom.courses.courseWork.studentSubmissions.return failed with error: #ProjectPermissionDenied The Developer Console project is not permitted to make this request.
It occurred because you are trying to modify a course work which is not created on a Developer Console project. Please refer here.
Sample Code:
var courseId = '2491255xxxxxx';
var courseWorkId = '2524434xxxxx'; // manually created in classroom.google.com
//1st TRY with error
var studentSubmissions = Classroom.Courses.CourseWork.StudentSubmissions.list(courseId, courseWorkId);
Logger.log(studentSubmissions.studentSubmissions[0].id);
//var ret = Classroom.Courses.CourseWork.StudentSubmissions.return({},courseId, courseWorkId, studentSubmissions.studentSubmissions[0].id);
//Logger.log(ret);
var assignment = {
title: "Test Assignment 3",
state: "DRAFT",
assigneeMode: "ALL_STUDENTS",
workType: "ASSIGNMENT"
};
//var newCourseWork = Classroom.Courses.CourseWork.create(assignment, courseId);
//2nd TRY without error
var newCourseWorkId = '2618921xxxxx';
var studentSubmissions2 = Classroom.Courses.CourseWork.StudentSubmissions.list(courseId, newCourseWorkId);
var ret = Classroom.Courses.CourseWork.StudentSubmissions.return({},courseId, newCourseWorkId, studentSubmissions2.studentSubmissions[0].id);
Logger.log(studentSubmissions2);
Logger.log(ret);
Logger.log(Classroom.Courses.CourseWork.get(courseId,newCourseWorkId));
Explanation:
During the first try, I tried to return a student submission course work which was created in https://classroom.google.com/. This case will encounter an error, since I am trying to modify a course work that is not associated with a developer console project. You can check if a course work has an associated developer console project using Classroom.Courses.CourseWork.get(), associatedWithDeveloper property should be true.
On the 2nd try, I created a draft course work first, then modify the created course work in https://classroom.google.com/. Once I finalized the changes and published the course work. I tried to return the student submission course work and it was successful (return should be null/empty). The reason why it succeed is because a developer console project is associated with the course work since I created the course work using Apps Script, hence I could also modify the student submission using Apps Script.

How do I store user input (the utterance) from Amazon Lex?

I am trying to store the user utterance from the Lex bot. I am currently using DynamoDB. I do not need to store the slot. I am using this information to build a transcript.
I tried using event['inputTranscript'] to access the user input, but I get an error message saying that the lambda is unhandled in my lex bot.
Please note that event = intent_request, for those of you familiar with AWS documentation. Also, this is a helper function in lambda. There is a response to Lex in another function (Not shown) which is called after
def write_dynamo(intent_request):
t = datetime.datetime.now
tString = datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
table = dynamodb.Table('<TABLENAME>')
ID = intent_request['userId'] + tString
intent_name = intent_request['currentIntent']['name']
response = table.put_item(
Item = {
'ID': ID,
'user': intent_request['userId'],
'time': tString,
'input': intent_request['inputTranscript']
})
return
Thank you for your time

e.source and e.range missing/unavailable

I have a basic installable trigger I am trying to use to send an email invite based on when a Sheet is edited (a specific checkbox is selected in my case) however when I try and access the range or source object from my event object I get [object Object] and undefined respectively. However I know the event object is working thanks to being able get the oldValue, value, triggerUid, and user.
function onEditCheck(e) {
var cells = e.range.getA1Notation();
var name = e.source.getActiveSheet().getName()
console.log('cells: ' + cells);
console.log('sheet name: ' + name);
console.log('id: ' + e.triggerUid);
console.log('edit: ' + e.value);
if(e.oldValue === 'false' && e.value === 'TRUE') {
sendEmail(e.user.getEmail(), e.range);
}
}
The only other reference to this issue I could find was this question here however I have had no luck with the permissions "solution" they found.
Any help or insight would be appreciated.
This is because necessary authorization wasn't granted to your script.
Add this somewhere in your code:
//SpreadsheetApp.getActive()
This will trigger the oAuth flow and request the permission to access Spreadsheets, which was missing.
Related:
IssueTracker
User response missing on Form submit
This worked for me:
function createTrigger(){
var tr=ScriptApp.newTrigger('onEditCheck').forSpreadsheet('My SSID').onEdit().create();
}
function onEditCheck(e) {
var cell = e.range.getA1Notation();
var name = e.range.getSheet().getName();
var data=Utilities.formatString('<br />Cell Edited: %s<br />Name of Sheet: %s<br />TriggerId: %s<br />Value: %s<br />Old Value: %s<br />',cell,name,e.triggerUid,e.value,e.oldValue);
var userInterface=HtmlService.createHtmlOutput(data);
SpreadsheetApp.getUi().showModelessDialog(userInterface, 'Testing')
}
By the way it's really handy to go to the trigger editor after creating the trigger and set notifications to immediate. That way you'll get notifications to failures pretty fast from Google Server.

How to Grab an image file from Parse

So i've tried looking over the documentation and cant make heads or tails of it... so i'm hoping someone here can help:
so i've created a ParseFile with an image stored in a byte[]. I've saved this parsefile and then assigned it into a parseObject. I have then saved the parseObject
profilePicFile = new ParseFile( "profilePic.png", bytes);
Task saveProfilePic = profilePicFile.SaveAsync();
yield return saveProfilePic;
user["Profile_Pic"] = profilePicFile;
Task updateUser = user.SaveAsync();
Then i've made a temporary button just to check that this works. I've assigned it a new script. Basically when I hit the button, I just want it to grab the user, and its profile_pic and tell me if there is something there.
ParseObject receivedUser = new ParseObject("ReceivedUser");
ParseQuery<ParseObject> query = ParseObject.GetQuery("User");
query.GetAsync("DwRfTQ66tA").ContinueWith(t =>
{
receivedUser = t.Result;
});
if (receivedUser.IsDataAvailable == true) {
print ("getting data");
byte[] data = receivedUser.Get<byte[]> ("Profile_Pic");
} else {
print ("no user");
}
}
Am I doing this right? Do i need to re-initialise anything? Do I need to add the other script component to this or use Getcomponent to get the user data? (I dont think so since the ParseUser object is supposed to be a static right?). Or does this script need to re-log in to grab data from Parse?
currently the error i'm getting is KeyNotFoundException.
I deff have a User Class on parse and a Profile_Pic column. I'm using the object ID as the reference. Is this correct?
Instead of
ParseObject.GetQuery("User")
you should be using:
ParseUser.Query

AngularJS setting headers on GET Request

I'm implementing a login authentication and the backend developer wants me to pass along the key value pairs in the header when i make a GET request. I'm new to AngularJS and I think my problem is the format of my header. I'm able to get a status 200 in Advanced Rest client (chrome extension for testing apis) with this format below. That is the raw format of the key value pairs if i put curly brackets around them or quotes or even a comma it throws an error so i'm very certain that should be the correct format.
identity: foo
password: bar
I've done every format possible to try to replicate it in the above example. So in my Code it goes like this, and i always get an error.
var config = {headers:{'identity': 'foo', 'password':'bar'}};
this.GetUser = function (config) {
return $http.get($rootScope.endPoint + '/user/email_token)', config);
};
you can do it like this:
$http.defaults.headers.common['identity'] = 'foo';
$http.defaults.headers.common['password'] = 'bar';
and call the api without additional properties
this.GetUser = function () {
return $http.get($rootScope.endPoint + '/user/email_token)');
};

Resources