I am trying to write some code that submits a ticket automatically with information from a page I created in Apps Script. I have tried numerous examples, but I can't seem to get my code to work.
var headers = {
'Content-type': 'application/json',
'Authorization': 'Basic ' + Utilities.base64Encode(API_KEY + ':X')
};
//Puts together the ticket according to the freshdesk api.
//var payload = '{"helpdesk_ticket":{"description":"' + message + '","subject":"' + subject + '","email":"' + arr[0][0] + '","priority":"' + ticketPriority + '","status":2}}';
//var payload = '{"helpdesk_ticket":{"description": message ,"subject": subject,"email": arr[0][0],"priority": ticketPriority,"status":2}}';
var payload = '{"helpdesk_ticket":{"description":"TEST","subject":"TEST","email":"test#test.com","priority":1,"status":2}}';
//Adds the extensions that are needed to post a new ticket to the end of the url
var url = ENDPOINT + '/helpdesk/tickets.json';
var options = {
'method': 'post',
'headers': headers,
'payload': payload,
muteHttpExceptions: true
};
var response = UrlFetchApp.fetch(url, options);
This is what I currently have. I have gotten it to work once, but only when I do not have any variables being assigned to the 'description' or 'subject' header (the line with the payload variables that is uncommented. When I use that line, a ticket is successfully created). I am not sure why my first or second lines with the payload variables would not work. The variable 'message' is just a String with some new line characters '\n' in it. Does anyone know why this might be happening?
Solved by building the message variable with HTML code and using the 'description_html' property instead of 'description'.
Related
I'm going to start by saying it's immensely frustrating half knowing how to do something but never quite being able to finish; this is another one of those projects for me.
Scenario: Using a Google Sheet and Apps Script I am attempting to update several User records in Zendesk using their API.
I think i probably have most if it right (i stand to be corrected of course) with the following script however I just cannot get it to update any records. I suspect it might be to do with how the array is presented (an area I sadly don't know enough about).
function updateManyUsers(){
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
var [headers, ...rows] = sheet.getDataRange().getValues();
var data = {}
var items = []
rows.forEach(function(r) {
var obj={}
r.forEach(function (c, j) {
obj[headers[j]] = c
})
var data = {}//moved
data['users'] = obj // moved this inside your loop
items.push(data) // pushed the object into the items array
})
Logger.log("Log JSON Stringify Items: " + JSON.stringify(items))
items.forEach(function(i) { // added this to loop over objects in items
var url = 'https://itsupportdesk1611575857.zendesk.com/api/v2/users/update_many.json'; //https://developer.zendesk.com/api-reference/ticketing/users/users/#update-user
var user = 'myemailaddresshere/token';
var pwd = 'mytoken';
var options = {
'method' : 'PUT',
'headers': {
'Authorization': "Basic " + Utilities.base64Encode(user + ':' + pwd)
},
'payload' : JSON.stringify(i),
'contentType': 'application/json',
'muteHttpExceptions': true
};
UrlFetchApp.fetch(url, options);
Logger.log(i)
var response = UrlFetchApp.fetch(url, options);
Logger.log(response);
})
}
I've gone through as much as I can following the documentation, I know i had the end points incorrect and the method(?) too (set to Post instead of Push). I have gone through varying error messages that I have tried to act upon and this is my current one:
This is an image of the data in my sheet
Suplimental: In order to get better at this i would like to put myself on a learning path but am unsure what the path is; most of my automation work and scripting is done using Google Apps script so would people recommend a JavaScript course? I alter between that and Python not knowing what would suit me best to get a better understanding of this kind of issue.
Many thanks in advance.
From your endpoint in your script, I thought that you might have wanted to use "Batch update". Ref If my understanding is correct, the following sample curl in the official document can be used. Ref
curl https://{subdomain}.zendesk.com/api/v2/users/update_many.json \
-d '{"users": [{"id": 10071, "name": "New Name", "organization_id": 1}, {"external_id": "123", "verified": true}]}' \
-H "Content-Type: application/json" -X PUT \
-v -u {email_address}:{password}
If this sample curl command is converted to Google Apps Script using your script, how about the following modification?
Modified script:
function updateManyUsers2() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
var [headers, ...rows] = sheet.getDataRange().getDisplayValues();
var users = rows.map(r => {
var temp = {};
headers.forEach((h, j) => {
if (r[j] != "") temp[h] = r[j];
});
return temp;
});
var url = 'https://itsupportdesk1611575857.zendesk.com/api/v2/users/update_many.json';
var user = 'myemailaddresshere/token';
var pwd = 'mytoken';
var options = {
'method': 'PUT',
'headers': {
'Authorization': "Basic " + Utilities.base64Encode(user + ':' + pwd)
},
'payload': JSON.stringify({ users }),
'contentType': 'application/json',
'muteHttpExceptions': true
};
var response = UrlFetchApp.fetch(url, options);
Logger.log(response.getContentText());
}
Note:
From the official document, it says Bulk or batch updates up to 100 users.. So, when you want to use more data, please modify the above script. Please be careful about this.
If an error occurs, please check the values of users, user and pwd, again.
Reference:
fetch(url, params)
As an example, I need the batch request in the following scenario:
After using Gmail.Users.Threads.list(..) I would like to do several Gmail.Users.Threads.get(threadId,..) operations in a batch.
I am talking about something similar to gapi.client.newBatch(); call in javascript gmail api.
First in apps script, one needs to enable the Gmail v1 Api in Advanced Google Services as described here.
Then using the Gmail Api in google apps script looks like this:
The suggestions are:
Users : UsersCollection
newAutoForwarding() : AutoForwarding
newBatchDeleteMessagesRequest() : BatchDeleteMessagesRequest
newBatchModifyMessagesRequest() : BatchModifyMessagesRequest
newDraft() : Draft
newFilter() : Filter
newFilterAction() : FilterAction
newFilterCriteria() : FilterCriteria
newForwardingAddress() : ForwardingAddress
newImapSettings() : ImapSettings
newLabel() : Label
newLabelColor() : LabelColor
newMessage() : Message
newMessagePart() : MessagePart
newMessagePartBody() : MessagePartBody
newMessagePartHeader() : MessagePartHeader
newModifyMessageRequest() : ModifyMessageRequest
newModifyThreadRequest() : ModifyThreadRequest
newPopSettings() : PopSettings
newSendAs() : SendAs
newSmimeInfo() : SmimeInfo
newSmtpMsa() : SmtpMsa
newVacationSettings() : VacationSettings
newWatchRequest() : WatchRequest
There is no newBatch() suggested.
How about this answer? I couldn't find the method of batch request for Gmail.Users.Threads.get(). And at Google Apps Script, there are no methods for requesting the batch request. So it is required to implement the method. The flow of batch request is as follows.
Create the request body for the batch request.
Requst the body to the endpoint of POST https://www.googleapis.com/batch using multipart/mixed.
The access token is required to be used for only this post.
The sample script for this flow is as follows.
Sample script :
Flow :
Retrieve thread list using Gmail.Users.Threads.list().
Create the request body for Gmail.Users.Threads.get().
In this case, Gmail.Users.Threads.get() of Advanced Google Services cannot be used, so it is required to directly use the API.
Post the created body using multipart/mixed.
Parse the response.
Script :
function myFunction() {
var userId = "me"; // Please modify this, if you want to use other userId.
var threadList = Gmail.Users.Threads.list(userId).threads;
var body = threadList.map(function(e){
return {
method: "GET",
endpoint: "https://www.googleapis.com/gmail/v1/users/" + userId + "/threads/" + e.id
}
});
var url = "https://www.googleapis.com/batch";
var boundary = "xxxxxxxxxx";
var contentId = 0;
var data = "--" + boundary + "\r\n";
for (var i in body) {
data += "Content-Type: application/http\r\n";
data += "Content-ID: " + ++contentId + "\r\n\r\n";
data += body[i].method + " " + body[i].endpoint + "\r\n\r\n";
data += "--" + boundary + "\r\n";
}
var payload = Utilities.newBlob(data).getBytes();
var options = {
method: "post",
contentType: "multipart/mixed; boundary=" + boundary,
payload: payload,
headers: {'Authorization': 'Bearer ' + ScriptApp.getOAuthToken()},
muteHttpExceptions: true,
};
var res = UrlFetchApp.fetch(url, options).getContentText();
var dat = res.split("--batch");
var result = dat.slice(1, dat.length - 1).map(function(e){return e.match(/{[\S\s]+}/g)[0]});
Logger.log(result.length)
Logger.log(result)
}
Note :
The parsed response is an array. Each element in the array is corresponding to each element in the request body.
In this sample script, the thread list is retrieved by Gmail.Users.Threads.list("me").threads. If you want to use some threads, please modify the request body.
Reference :
Batching Requests
If I misunderstand your question, I'm sorry.
I'm trying to remove the value of a custom field on an asana task via a PUT request.
Based on the original json data I sent over to create the task with a custom field value and the documentation here this is my best guess for how this should look:
let data = {custom_fields: { ASANA_CUSTOM_FIELD_ID_NUMBER: null }}; //struggling here
updateTask(ASANA_TASK_ID_NUMBER, data);
function updateTask(id, data) {
return put(`https://app.asana.com/api/1.0/tasks/${ASANA_TASK_ID_NUMBER}`, data);
}
function put(url, data) {
return makeRequest({
"url": url,
"headers": {"Authorization": "Bearer " + accessCode()},
"type": "PUT",
"data": data
})
}
But I get the error:
status:400 Bad request
custom_fields: Value cannot be an array: []
Which seems verbose enough to solve except I've tried every format i can come up with and I've had no luck working it out. I know that the put function works fine for updating other fields for a task and I see the same error with an actual number other than null.
You will need to send your content in JSON rather than urlencoded data. This is a bit of a bug in Asana API in my opinion. They say that they support form-encoded content however it doesn't like it when you try to send an object as it thinks it's an array.
I'm not sure why, but setting custom fields seems to be different from the rest of the API requests.
Here is some code that works for setting it, you can probably figure out how to apply this to whatever language you're using:
function SetCustomField(taskId, fieldId, value) {
// not sure why, but to set the custom task you have to tell it your content type is json,
// then send json as a string instead of letting it serialize it for you
var headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer API-KEY'
};
var formData = '{"data": { "custom_fields": { "' + fieldId + '": ' + value + '} } }';
var options = {
'method': 'put',
'headers': headers,
'payload': formData
};
var response = UrlFetchApp.fetch('https://app.asana.com/api/1.0/tasks/' + taskId, options);
//Logger.log(response.getContentText());
}
I don't know my JavaScript. So I am using someone else's:
var CONSUMER_KEY = 'xxxx'; // Register your app with Twitter.
var CONSUMER_SECRET = 'xxxx'; // Register your app with Twitter.
function getTwitterUserFollowers(id) {
// Encode consumer key and secret
var tokenUrl = "https://api.twitter.com/oauth2/token";
var tokenCredential = Utilities.base64EncodeWebSafe(
CONSUMER_KEY + ":" + CONSUMER_SECRET);
// Obtain a bearer token with HTTP POST request
var tokenOptions = {
headers: {
Authorization: "Basic " + tokenCredential,
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"
},
method: "post",
payload: "grant_type=client_credentials"
};
var responseToken = UrlFetchApp.fetch(tokenUrl, tokenOptions);
var parsedToken = JSON.parse(responseToken);
var token = parsedToken.access_token;
// Authenticate Twitter API requests with the bearer token
var apiUrl = 'https://api.twitter.com/1.1/users/show.json?screen_name='+id;
var apiOptions = {
headers: {
Authorization: 'Bearer ' + token
},
"method": "get"
};
var responseApi = UrlFetchApp.fetch(apiUrl, apiOptions);
var result = "";
if (responseApi.getResponseCode() == 200) {
// Parse the JSON encoded Twitter API response
var tweets = JSON.parse(responseApi.getContentText());
return tweets.followers_count
}
Logger.log(result);
}
source: http://sarahmarshall.io/post/70812214349/how-to-add-twitter-follower-counts-to-a-google
Sarah Marshall provides a pretty awesome how-to on using a Google Sheets script with the Twitter API to get follower counts for a list of Twitter user names. But it times out after about 100 user names:
Service invoked too many times for one day: urlfetch. (line 21, file "Code")
I'm wondering how I can get around the rate limit, or account for it, and return follower counts for more than 100 user names. Any ideas?
The function you are using does too many things: it both obtains a token and uses it to retrieve followers. So, if you are invoking it 100 times, you obtain a token 100 times (and notably, time out on the line obtaining it); but you need it once. You should store the token somewhere, e.g., in the spreadsheet itself since you already have your private data in the script associated with it. Example:
function getToken() {
// Obtain a bearer token with HTTP POST request
var tokenOptions = {
headers: {
Authorization: "Basic " + tokenCredential,
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"
},
method: "post",
payload: "grant_type=client_credentials"
};
var responseToken = UrlFetchApp.fetch(tokenUrl, tokenOptions);
var parsedToken = JSON.parse(responseToken);
var token = parsedToken.access_token;
SpreadsheetApp.getActiveSpreadsheet().getSheetByName('SheetWithToken').getRange('A1').setValue(token);
}
The last line stores the token string in cell A1 of the sheet named SheetWithToken. You'd invoke this function once, manually from the Script Editor.
The following function does the rest: it can be invoked as a custom function =getFollowers(A2) from the spreadsheet. Custom functions, like other spreadsheet functions, are re-evaluated only when the parameter changes. Thus, if the column with IDs (say, A) has a thousand of entries, you can paste the custom function gradually, for a handful at once.
function getFollowers(id) {
// Authenticate Twitter API requests with the bearer token
var token = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('SheetWithToken').getRange('A1').getValue();
var apiUrl = 'https://api.twitter.com/1.1/users/show.json?screen_name='+id;
var apiOptions = {
headers: {
Authorization: 'Bearer ' + token
},
"method": "get"
};
var responseApi = UrlFetchApp.fetch(apiUrl, apiOptions);
var result = "";
if (responseApi.getResponseCode() == 200) {
// Parse the JSON encoded Twitter API response
var tweets = JSON.parse(responseApi.getContentText());
return tweets.followers_count
}
}
You could even hardcode your access token into the second function, instead of fetching it from the spreadsheet. Twitter's tokens do not expire.
Another thing to consider is to recast the function getFollowers so that it accepts an array of IDs and loops through them, returning an array of follower counts. I don't think this would help, though: you would still have to worry about rate-limit on Twitter side, and at the same time be limited to 30 second execution time limit for custom functions.
In NetSuite, I'm trying to create a form Portlet POST data to a RESTlet in JSON. I've checked the documentation and internet and all the examples I've been able to find are GET requests or they post to a backend Suitelet instead.
I've come to a point where I can make the request reach the RESTlet but it's not being formatted in JSON, so I get the following error:
Account: xxxxxxxxxxxxx
Environment: Production Date & Time: 6/11/2015 5:09 pm
Execution Time: 0.06s
Script Usage: 0
Script: gw_SS_FormBackend
Type: RESTlet
Function: postWMForm
Error: UNEXPECTED_ERROR
SyntaxError: Empty JSON string (null$lib#3)
I'm using the following code to set the submit button and it's working fine:
var headers = new Array();
headers['User-Agent-x'] = 'SuiteScript-Call';
headers['Authorization'] =
'NLAuth nlauth_account=' + cred.account +
', nlauth_email=' + cred.email +
', nlauth_signature=' + cred.password +
', nlauth_role=' + cred.role;
headers['Content-Type'] = 'application/json';
portlet.setSubmitButton(nlapiRequestURL(getRESTletURL(), null, headers, 'POST'), 'Submit', '_hidden');
My problem is I don't know how to convert the form data to JSON before submitting it.
I'd appreciate any help.
Why would you want to use a RESTlet? If you are in a portlet then you already have a valid NS session so you'd be better off using a Suitelet. A Suitelet you know is set up to handle JSON would be called thus:
nlapiRequestURL(suiteletURL', JSON.stringify{test:'it', when:new Date(), by:'Brett'}), {"content-type":'application/json'}, function(resp){console.log(resp.getBody());}, 'POST');
and your Suitelet code might include something like:
var body = request.getBody();
nlapiLogExecution('DEBUG', 'posted body', body);
var asJSON = JSON.parse(body);
var user = nlapiGetContext().getUser(); // system already knows who this is.
...
var obj = {
success:true,
stuff: asProcessed
};
response.setContentType('JAVASCRIPT');
response.writeLine( JSON.stringify(obj) );
Not quite as clean as a RESTlet but you avoid having to hack the credentials.
you can use JSON.stringify() function.
var headers = new Array();
headers['User-Agent-x'] = 'SuiteScript-Call';
headers['Authorization'] =
'NLAuth nlauth_account=' + cred.account +
', nlauth_email=' + cred.email +
', nlauth_signature=' + cred.password +
', nlauth_role=' + cred.role;
headers['Content-Type'] = 'application/json';
var myJsonHeader = JSON.stringify(headers);
portlet.setSubmitButton(nlapiRequestURL(getRESTletURL(), null, myJsonHeader, 'POST'), 'Submit', '_hidden');
Regards